How do I set the data for a “PUT” request with AFN

2019-01-23 22:21发布

问题:

I have started to use AFNetworking and it works well when it gets to making simple "GET"-request. However now I am trying to do a "POST"-request. I use the code below to do the "GET" request. When looking at the puthPath of AFHTTPClient there is no way to set the data to use for the body. My guess is that there is another way of fixing this. I have been looking at the AFHTTPOperation as a way of fixing this. However I am not getting this to work. The problem is that I do not know how to use it with Basic Authentication.

Could somebody give me a hint of how to do a simple "POST"-request with AFNetworking?

AFHTTPClient* client = [AFHTTPClient clientWithBaseURL:ServerURL];
[client setAuthorizationHeaderWithUsername:self.username 
                                  password:self.password];

NSString* resourcePath = [NSString stringWithFormat:@"/some/resource/%@", 
                          endPath];

[client getPath:resourcePath 
     parameters:nil 
        success:^(AFHTTPRequestOperation *operation, id responseObject) {
            // Success code omitted
        } 
        failure:^(AFHTTPRequestOperation *operation, NSError *error) {
            // Some error handling code omitted
        }
 ];

回答1:

I did not find any easy way to do this. But I did as recommended and created my own sub-class of AFHTTPClient. In the subclass I implemented the methods below. This makes it possible to perform both POST-request & PUT-requests with my own data.

- (void)postPath:(NSString *)path 
  parameters:(NSDictionary *)parameters 
        data:(NSData*)data
     success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success
     failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure;
{
    NSURLRequest *request = [self requestWithMethod:@"POST" path:path     parameters:parameters data:data];
    AFHTTPRequestOperation *operation = [self HTTPRequestOperationWithRequest:request success:success failure:failure];
    [self enqueueHTTPRequestOperation:operation];
}

- (void)putPath:(NSString *)path 
     parameters:(NSDictionary *)parameters 
           data:(NSData*)data
        success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success
        failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure;
{
    NSURLRequest *request = [self requestWithMethod:@"PUT" path:path parameters:parameters data:data];
    AFHTTPRequestOperation *operation = [self HTTPRequestOperationWithRequest:request success:success failure:failure];
[self enqueueHTTPRequestOperation:operation];
}

-(NSMutableURLRequest*)requestWithMethod:(NSString *)method 
                                    path:(NSString *)path 
                              parameters:(NSDictionary *)parameters 
                                 data:(NSData*)data;
{
    NSMutableURLRequest* request = [super requestWithMethod:method 
                                                      path:path 
                                                parameters:parameters];

    [request setHTTPBody:data];

    return request;
}


回答2:

With AFNetworking 2.0, I just copy code from

- (AFHTTPRequestOperation *)PUT:(NSString *)URLString
                 parameters:(id)parameters
                    success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success
                    failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure;

and add a

[request setHTTPBody:data];

Here is it:

NSString* str = [bookDetailLink objectForKey:@"Body"];
NSData* data = [str dataUsingEncoding: NSUTF8StringEncoding];
    NSMutableURLRequest *request = [self.manager.requestSerializer requestWithMethod:@"PUT" URLString:bookingDetailUrl parameters:nil error:nil];

[request setHTTPBody:data];
AFHTTPRequestOperation *operation = [self.manager HTTPRequestOperationWithRequest:request
                                                                  success:^(AFHTTPRequestOperation *op, NSHTTPURLResponse *response) {
                                                                      NSLog(@"%@", response);
                                                                  }
                                                                  failure:^(AFHTTPRequestOperation *op, NSError *error) {
                                                                      NSLog(@"%@", error);
                                                                  }];

[self.manager.operationQueue addOperation:operation];

I am integrating Skyscanner API to our iOS app using AFNetworking.



回答3:

With AFNetworking 1.3.2 the following code works for me:

NSData *imageData = UIImageJPEGRepresentation(thumb, 0.85F);

AFHTTPClient *httpClient = [[AFHTTPClient alloc]
    initWithBaseURL:[NSURL URLWithString:@"https://example.com/"]];
NSMutableURLRequest *request = [httpClient
    requestWithMethod:@"PUT" path:@"/foo" parameters:nil];
[request setHTTPBody:imageData];
[request setValue:@"image/jpeg" forHTTPHeaderField:@"Content-Type"];

AFHTTPRequestOperation *operation = [httpClient 
    HTTPRequestOperationWithRequest:request
        success:^(AFHTTPRequestOperation *op, NSHTTPURLResponse *response) {
            NSLog(@"%@", response);
        }
        failure:^(AFHTTPRequestOperation *op, NSError *error) {
            NSLog(@"%@", error);
        }];
[operation start];

This results in a PUT request with correct headers, Content-Lenght and general RESTfulness :-)