Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

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

Closed
marcolinux opened this Issue · 8 comments

5 participants

@marcolinux

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
js commented

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

@marcolinux

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);
        [....]
@mattt
Owner

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.

@marcolinux

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!

@mattt
Owner

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

@mattt mattt closed this
@runmad

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?

@tewha

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

@runmad

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
Something went wrong with that request. Please try again.