I can't find where is the body of my request? In what property?
[[RKObjectManager sharedManager] postObject:object
path:path
parameters:parameters
success:success
failure:^(RKObjectRequestOperation *operation, NSError *error) {
NSLog(#"???");
}
Now how to print whole body of request? I'd like to see the path with header and parameters.
I was able to see output of everything via setting:
RKLogConfigureByName("RestKit/Network*", RKLogLevelTrace);
Body of your request is in object, as it is specified here: https://github.com/RestKit/RestKit#post-patch-and-delete-an-object
If you want to log your requests and responses you can use AFHTTPRequestOperationLogger.
Related
In my app i am making different calls and they work except one call, that returns just a string in response as SUCCESS. I am getting this error
"The operation couldn’t be completed. (Cocoa error 3840.)", NSLocalizedDescription=Loaded an unprocessable response (200) with content type 'application/json'}
How can i tell the restkit to access the "Content-Type: text/plain"
This is a post call.
Short answer: you can't. RestKit is designed to work with JSON objects only, and so it expects a JSON response (keeping with the RESTful paradigm).
However, you can definitely post objects using AFNetworking, which RestKit actually includes. I use AFNetworking for non-coreData-related correspondence. Here's a code sample on how to get the AFHTTPClient from RestKit and make a POST, expecting a text/plain response.
AFHTTPClient *httpClient = [RKObjectManager sharedManager].HTTPClient;
NSDictionary *requestObject = #{#"label1":data1, #"label2":data2};
[httpClient setParameterEncoding:AFJSONParameterEncoding];
[httpClient setDefaultHeader:#"Accept" value:#"text/plain"];
[httpClient postPath:urlPath parameters:requestObject success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSString *response = (NSString*)responseObject;
if([response isEqualToString:#"SUCCESS"]) NSLog(#"It worked!");
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
//failure code goes here
}];
If that's your only call expecting text/plain, change the Accept header back after you're done:
[httpClient setDefaultHeader:#"Accept" value:#"application/json"];
After trying nearly every response on the subject, I've come up without a working answer to my problem.
The problem: So I've implemented the uploading portion of my app using AFNetworking 2.0.3 after porting from AFNetworking 1.3:
-(void)commandWithParams:(NSMutableDictionary*)params onCompletion:(JSONResponseBlock)completionBlock {
NSData* uploadFile = nil;
if ([params objectForKey:#"file"]) {
uploadFile = (NSData*)[params objectForKey:#"file"];
[params removeObjectForKey:#"file"];
}
AFHTTPRequestOperationManager *manager = [[AFHTTPRequestOperationManager alloc] initWithBaseURL:[NSURL URLWithString:#"http://54.204.17.38"]];
manager.responseSerializer = [AFJSONResponseSerializer serilizer];
manager.responseSerializer.acceptableContentTypes = [NSSet setWithObject:#"application/json"];
AFHTTPRequestOperation *apiRequest = [manager POST:#"/API" parameters:params constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
if (uploadFile) {
[formData appendPartWithFileData:uploadFile name:#"file" fileName:#"photo.jpg" mimeType:#"image/jpeg"];
}
} success:^(AFHTTPRequestOperation *operation, id responseObject) {
completionBlock(responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
completionBlock([NSDictionary dictionaryWithObject:[error localizedDescription] forKey:#"error"]);
}];
[apiRequest start];
}
The error I get when using this code is "Request failed: unacceptable content-type: text/html" I know you might be wondering if the server is responding with proper JSON, and I have every reason to think it is after inspecting the response headers in my browser that say 'MIME type: application/json'. Also, I am using 'header('Content-type: application/json')' at the top of my API as well (PHP API). Now, if I change the serialization type to 'AFHTTPResponseSerializer' instead of 'AFJSONResponseSerializer', it will not spit out the JSON error, but it will give me a different error (a random unrecognized selector error).
Any thoughts on why I cannot seem to get a JSON response out of this method?
You can set the AFHTTPSessionManager to accept any MIME Type:
manager.responseSerializer.acceptableContentTypes = [NSSet setWithObject:#"text/html"];
Got it! So, turns out, unknowingly, although my API was returning valid JSON, matter examining the header response logged on the Xcode side of things (thru NSLog(#"Error: %#", error);), it was actually returning text/HTML because it wasn't actually hitting the correct file, it was getting re-routed by a header somewhere. After explicitly stating the API path to be /API/index.php and not just /API, it started returning the valid JSON! Next, after making sure the response was properly JSON serialized (using requestManager.responseSerializer = [AFJSONResponseSerializer serializer];), the app worked!
Hopefully this helps someone who was having the same issue :)
I have seen a lot of major changes with the RestKit framework in version 0.20.x for the iOS platform.
The one thing I haven't found so far on the web is an example of how to download a binary file with the new version of RestKit.
I need to send a JSON object to a REST service and expect a binary file in return. Would seem simple, wouldn't it but for some reason RestKit only expects JSON (and the common internet content types such as XML) to come back.
The JSON object essentially is a request object telling the service which image it should go and get for me.
Fortunately I have managed to use the underlying AFNNetworking framework to help me with this and leverage the RestKit serializer to produce the request object I needed.
MyRequestClass *request = // ... get my request class instance
RKObjectManager *manager = [RKObjectManager sharedManager];
NSMutableURLRequest *downloadRequest = [manager requestWithObject:request method:RKRequestMethodPOST path:ROUTE_URL_MY_SERVICE parameters:nil];
AFHTTPRequestOperation *requestOperation = [[AFImageRequestOperation alloc] initWithRequest:downloadRequest];
[requestOperation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
// Use my success callback with the binary data and MIME type string
callback(operation.responseData, operation.response.MIMEType, nil);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
// Error callback
callback(nil, nil, error);
}];
[manager.HTTPClient enqueueHTTPRequestOperation:requestOperation];
The documentation for AFNetworking notes that you should create subclass of AFHTTPClient and use it as a singleton per web-service.
If I have 2 endpoints at www.example.com, one that allows for 'application/json' in HTTP_ACCEPT and another that needs text/html, what parameter would I configure in my singleton AFHTTPClient class so that it configures the correct HTTP_ACCEPT value?
Implementation details:
#interface MyAFHTTPClient : AFHTTPClient
+ (MyAFHTTPClient *)sharedClient;
#end
[[MyAFHTTPClient sharedClient] getPath:#"endPoint_json"
parameters:nil
success:^(AFHTTPRequestOperation *operation, id responseObject) {
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
}]
At a later time, I need to invoke the html endpoint:
[[MyAFHTTPClient sharedClient] getPath:#"endPoint_html"
parameters:nil
success:^(AFHTTPRequestOperation *operation, id responseObject) {
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
}]
It seems that both of these calls cause "HTTP_ACCEPT"=>"application/json" when the server receives the request.
getPath:... and all of those convenience methods construct a request with requestWithMethod:path:parameters:, and then pass that into HTTPRequestOperationWithRequest:success:failure:, which is then enqueued into an operation queue.
If you need to do a one-off request for HTML or the like, do these steps manually rather than using the convenience method: create the request, set the Accept (HTTP_ACCEPT) is not an HTTP header) header to text/html, and then create and enqueue the operation.
I am trying to post a sound to echo nest for file analysis. The POST method is no different than any other method, and I believe it's not echonest dependent.
Here is the documentation. I need the "upload" part.
http://developer.echonest.com/docs/v4/track.html
NSURLRequest *request = [self multipartFormRequestWithMethod:#"POST" path:[NSString stringWithFormat:#"track/upload", self.apiKey] parameters:dictionary constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
[formData appendPartWithFileData:data name:#"track" fileName:[path lastPathComponent] mimeType:#"multipart/form-data"];
}];
AFURLConnectionOperation *operation = [self HTTPRequestOperationWithRequest:request success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"done");
NSLog(#"response: %#", operation.responseString);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"error: %#", error.description);
NSLog(#"response: %#", operation.responseString);
NSLog(#"headers: %#", operation.request.allHTTPHeaderFields.description);
NSLog(#"operation url: %#", operation.request.URL.absoluteString);
}];
However, I have problems. Here is my response:
{"response": {"status": {"version": "4.2", "code": 4, "message": "track - Missing Parameter: track or url is required with a POST content-type of \"application/x-www-form-urlencoded\" or \"multipart/form-data\""}}}
I thought I have already given the "track" parameter to be the data I initialized. Can anyone help me?
I experienced same problem few weeks ago. And here is what i found.
AFNetworking makes slightly wrong multipart/form-data request.
In AFHTTPClient.m file,
static inline NSString * AFMultipartFormFinalBoundary() {
return [NSString stringWithFormat:#"%#--%#--%#%#", kAFMultipartFormCRLF, kAFMultipartFormBoundary, kAFMultipartFormCRLF, kAFMultipartFormCRLF];
}
They put kAFMultipartFormCRLF twice at the end of final boundary of a request.
But Echonest only except request with one CRLF at the end of multipart/form-data post request.
I don't know which one is exactly the righteous way in terms of HTTP protocol standard, but if you modify that code line (remove a kAFMultipartFormCRLF), i think your code would work well.
FYI, while writing this answer, I explored current AFNetworking Git repo, and found out that this defect has been fixed just 5 days ago. So i guess you can just use latest source code to fix the problem.