feature request: better handling of server return code in JSON #166

Closed
marcolinux opened this Issue Jan 9, 2012 · 8 comments

Comments

Projects
None yet
5 participants

Hello,
currently AFJSONRequestOperation in case of error, it is returning a NSError (coming from the super AFHTTPOperation) which is containing a localised string not in relation neither with the original error code, neither with the original server answer.

It would be nice if (at least) the JSON answer (if any) would be returned within the NSError description.
I modified a bit the code (just a quick proposal, surely need to be polished)

--- a/AFNetworking/AFJSONRequestOperation.m
+++ b/AFNetworking/AFJSONRequestOperation.m
@@ -126,7 +126,9 @@ static dispatch_queue_t json_request_operation_processing_queue() {
     if (self.error) {
         if (failure) {
             dispatch_async(dispatch_get_main_queue(), ^(void) {
 -                    failure(self, self.error);
+                    NSDictionary *userInfo = self.responseJSON;
+                   NSError *er = [[[NSError alloc] initWithDomain:AFNetworkingErrorDomain code:[self.response statusCode] userInfo:userInfo] autorelease];
+                    failure(self, er);
             });

As for return error code, this question is more theoretical, ie should we just return the HTTP error code, or stick with the NSURLError list?
For an HTTP answer -> 401 Unauthorized eventually I would expect a NSURLErrorUserAuthenticationRequired, but for other in the range ~400 there might not be a correspondent NSURLError.

js commented Jan 9, 2012

As of 200512c (or thereabout) the failure block is now declared as (void (^)(AFHTTPRequestOperation *operation, NSError *error))failure meaning that you can call operation.response.statusCode and operation.responseData to get that information

thanks for the suggestion, it is a sufficient workaround for the time being.
It is just a pity that it is breaking a little bit the encapsulation of the library, as (unless there is another way), you are forced to import an header and methods that could be kept private on the library itself.

#import "AFJSONUtilities.h"

 failure:^(__unused AFHTTPRequestOperation *operation, NSError *error) {
        NSInteger errorcode = operation.response.statusCode;
        NSError *error2;
        NSDictionary *d = AFJSONDecode(operation.responseData, &error2);
        [....]
Contributor

mattt commented Jan 9, 2012

Thanks for the suggestion. One of the drawbacks of the way the operations are typed in callbacks is that they hide the fact that they are usually a subclass of AFHTTPRequestOperation. In this case, your failure block would pass operation, which is an instance of an AFJSONRequestOperation. Unless I'm mistaken, you should be able to simply do operation.responseJSON, thus avoiding that ugliness. Let me know if that works for you.

thanks, that is working indeed and sufficiently clean for me (so for my perspective the issue is closed).
For everyone benefit, a cast is necessary for the fact you mentioned.

failure:^(__unused AFHTTPRequestOperation *operation, NSError *error) {
        NSDictionary *d1 = [(AFJSONRequestOperation*)operation responseJSON];
        [....]

thanks again for the prompt feedback!

Contributor

mattt commented Jan 10, 2012

Sure thing! Thanks for your feedback—I'll do what I can to improve the documentation of this soon.

@mattt mattt closed this Jan 10, 2012

Contributor

runmad commented Feb 19, 2014

I am just dealing with a 401 as well, and I was wondering why there was a decision made to return code -1011 instead of using the http error code as the NSError code?

Contributor

tewha commented Feb 24, 2014

There's no domain for HTTP status codes, right? If you want to use an existing domain, -1011 is a good pick.

Contributor

runmad commented Feb 24, 2014

How about NSURLErrorDomain ?
[NSError errorWithDomain:NSURLErrorDomain code:[((NSHTTPURLResponse*)task.response) statusCode] userInfo:nil]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment