Accessing DailyMile API with AFNetworking 2.0
Asked Answered
F

1

0

So I'm making a JSON request from an https site (after retrieving the auth token) and like a dozen other problems with AFNetworking on stack overflow, I'm getting this error:

Error Domain=NSCocoaErrorDomain Code=3840 "The operation couldn’t be completed. (Cocoa error 3840.)" (JSON text did not start with array or object and option to allow fragments not set.) 

UserInfo=0x8dc2860 {NSDebugDescription=JSON text did not start with array or object and option to allow fragments not set.}

The code I'm using to make this request is like such:

AFHTTPRequestSerializer *requestSerializer = [AFHTTPRequestSerializer serializer];
[requestSerializer setValue:@"application/json" forHTTPHeaderField:@"Accept"];

//Set auth header...
NSString *accessToken = [[[self.dailymileAuthentication oauthClient] accessToken] accessToken];
[requestSerializer setAuthorizationHeaderFieldWithToken:accessToken];

AFHTTPRequestOperationManager *requestManager = [AFHTTPRequestOperationManager manager];

[requestManager setRequestSerializer:requestSerializer];
[requestManager setResponseSerializer:[AFJSONResponseSerializer serializer]];

[requestManager GET:[profileURL description]
         parameters:nil
            success:^(AFHTTPRequestOperation *operation, id response) {
                NSLog(@"JSON: %@", response);
            }
            failure:^(AFHTTPRequestOperation *operation, NSError *error) {
                NSLog(@"Error: %@", error);
            }];

The URL is: https://api.dailymile.com/people/me.json

I'm working out of a public GitHub repo if anyone is interested in checking out the full codebase (note: you don't need to to understand the problem, this is just optional): https://github.com/thepost/Dailymile-iOS

What do I need to do to make an authenticated JSON request?

I have no idea if I'm using AFNetworking correctly or not. To be honest, there isn't a lot of documentation out there for AFNetworking 2 yet.

Flavia answered 9/12, 2013 at 20:27 Comment(7)
Where does the error occur, in the request or in the response serialization? And just a note: perhaps you find a lower level API better suited (me too). Those super convenient network request methods only force you to examine every bit of the sources to understand what's going on anyway.Catnip
api.dailymile.com/people/me.json is returning 404 for me when I visit in the browser.Archle
@moby you have to login to dailymile.com, then visiting that API URL should give you your profile in JSON.Flavia
@Catnip the error occurs in the failure block. I agree, I don't think I even need AFNetworking anymore. NSURLSession has replaced a lot of the shortcomings in iOS, I've never used it but am looking over it here: raywenderlich.com/51127/nsurlsession-tutorialFlavia
I'm surprised by your comment about AFNetworking 2.0 lacking documentation. Have you not seen cocoadocs.org/docsets/AFNetworking/2.0.3 ?Urian
@matt, I'm going to respectfully concur with others. AFNetworking 2.0 does not lack documentation. It looks rather nice, and I'm glad it's there. But it hasn't helped me (and others) figure out how to solve problems. So something's not connecting. It may just be stupid users. Multiple times, I've been burned by the need to chase up and down the class chains to put the fragments together into a bigger picture.Waltz
The documentation is great, and the API IS really simple to use. It's not mentally challenging, and in my case all it needed was 1 line added. So it can cause hurdles in cases like mine where I didn't know what the missing pieces were. Like Travis I think it could do with some more examples from practical use cases. The documentation on "what" it does is great, the examples on "how" to use it perhaps needs more though. Maybe we can help and submit any working use case to Mattt and he can add it if he likes?Flavia
U
1

I'm not sure what the confusion is about; the error is quite clear:

Error Domain=NSCocoaErrorDomain Code=3840 "The operation couldn’t be completed. (Cocoa error 3840.)" (JSON text did not start with array or object and option to allow fragments not set.) UserInfo=0x8dc2860 {NSDebugDescription=JSON text did not start with array or object and option to allow fragments not set.}

The JSON response from DailyMile is not valid, as it doesn't have an array or object as its root value.

If the value is indeed JSON, and should be parsed as JSON, you can set the readingOptions of the responseSerializer to allow fragments.

What I suspect, however, is that your API endpoint is not actually returning JSON, but a plain text response with the wrong Content-Type header.

Urian answered 10/12, 2013 at 15:47 Comment(5)
You're right in that it's not returning JSON, but that's not the confusion. It's rightly returning an HTML body with an error message, because it interprets it as an unauthenticated request. The confusion is how to make an authenticated request. How to make a GET request when an access token is needed...Flavia
This is more to do with the DailyMile API than AFNetworking. A quick look over their API documentation reveals that they're implementing OAuth incorrectly. Instead of a header, they're expecting an oauth_token parameter, e.g. https://api.dailymile.com/people/me.json?oauth_token=<ACCESS_TOKEN>Urian
Errr wow. This is why I shouldn't work on networking calls. Or maybe it's why I should do MORE on networking :-| Thanks! That's working out ok now with the access token as a parameterFlavia
I'm dealing with a similar problem myself. What happens, is that a programmer error or misunderstanding of how to use AFNetworking on the front side result in an error being returned on the back side. For a while, you try to figure out what's wrong on the back side, without realizing the real problem was on the front side.Waltz
Hey Travis (or anyone else), if your problem is also specific with using AFNetworking with the Dailymile API, the library I was working on is usable now: github.com/thepost/Dailymile-iOSFlavia

© 2022 - 2024 — McMap. All rights reserved.