AFNetworking Request API iOS - ios

I'm doing a request to the server and the server returns a JSON. AFNetworking framework returns a wrong formatted JSON.
This is what the server sends:
{"email":"XXXXXXX","firstName":"XXXXXX","lastName":"XXXXXXX","gender":"male","userToken":"XXXXXXXXXXX"}
This is what AFNetworking receives:
{
email = "XXXXXXX";
firstName = XXXXXX;
gender = male;
lastName = XXXXXXX;
token = XXXXXXXXXXXX;
}
My code:
AFHTTPClient *client = [[AFHTTPClient alloc] initWithBaseURL:[NSURL URLWithString:server_ip]];
NSURLRequest *request = [client requestWithMethod:#"POST" path:path parameters:params];
AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
NSLog(#"%#", JSON);
} failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) {
NSLog(#"Request Failed with Error: %#, %#", error, error.userInfo);
}];
[operation start];

The object you are printing out is the NSDictionary representation of the JSON received from the server.
If you want to see the raw JSON returned from the server, you should look at the responseString of the operation:
NSLog(#"%#", operation.responseString);

Related

AFNetworking, getting 401 with proper token

I'm making a request on https://www.ez-point.com/api/v1/ezpoints with a proper token using a Chrome Rest Client. I'm properly getting the result. However, when using AFNetworking, I'm getting a 401.
Here is my code snippet:
NSURL *url = [[NSURL alloc] initWithString:#"https://www.ez-point.com/api/v1/"];
AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:url ];
[httpClient setAuthorizationHeaderWithToken:#"xxxxxxxxxx"];
NSMutableURLRequest *request = [httpClient requestWithMethod:#"GET" path:#"/ezpoints" parameters:nil];
AFJSONRequestOperation *operation =
[AFJSONRequestOperation JSONRequestOperationWithRequest:request
success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
NSLog(#"%#", #"success");
}
failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) {
NSLog(#"%#", #"Error");
Here is the error:
2013-10-29 08:51:38.908 EZ-POINT[4944:c07] I restkit:RKLog.m:34 RestKit logging initialized...
2013-10-29 08:51:39.189 EZ-POINT[4944:c07] I restkit.network:RKObjectRequestOperation.m:180 GET 'https://www.ez-point.com/ezpoints'
2013-10-29 08:51:41.908 EZ-POINT[4944:c07] E restkit.network:RKObjectRequestOperation.m:209 GET 'https://www.ez-point.com/ezpoints' (401 Unauthorized) [2.7191 s]: Error Domain=AFNetworkingErrorDomain Code=-1011 "Expected status code in (200-299), got 401" UserInfo=0x1052ef40 {AFNetworkingOperationFailingURLRequestErrorKey=<NSMutableURLRequest https://www.ez-point.com/ezpoints>, NSErrorFailingURLKey=https://www.ez-point.com/ezpoints, NSLocalizedDescription=Expected status code in (200-299), got 401, AFNetworkingOperationFailingURLResponseErrorKey=<NSHTTPURLResponse: 0xac54520>}
2013-10-29 08:51:41.908 EZ-POINT[4944:c07] Error
Its working with the following code:
NSURL *url = [[NSURL alloc] initWithString:#"https://www.ez-point.com/api/v1/ezpoints"];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url];
[request setValue:#"4f62fab9c91c46ad971cc2ae4a32bb6f" forHTTPHeaderField:#"Authorization"];
AFJSONRequestOperation *operation =
[AFJSONRequestOperation JSONRequestOperationWithRequest:request
success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
NSLog(#"%#",[JSON objectForKey:#"status"]);
}
failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) {
NSLog(#"%#", #"Error");
}];
[operation start];

AFNetworking POST not working

I am trying to make a POST request using AFNetworking. I went through SO and found that I need to include httpClient.parameterEncoding = AFJSONParameterEncoding
It still doesn't work even after making that change. Anything else I am missing ? Here is the code
NSDictionary *subDictionaryUsers = [[NSDictionary alloc]initWithObjectsAndKeys:myObject.name,#"name", myObject.topic_description,#"description", nil];
NSString *_restPath = [NSString stringWithFormat:#"spaces.json/auth_token=%#",myObject.auth_token];
NSDictionary *params = [[NSDictionary alloc]initWithObjectsAndKeys:subDictionaryUsers,#"space",nil];
myAppAFNClient *httpClient = [myAppAFNClient sharedClient];
NSMutableURLRequest *request = [httpClient requestWithMethod:#"POST" path:_restPath parameters:params];
httpClient.parameterEncoding = AFJSONParameterEncoding;
[httpClient getJsonResponse:request notificationString:#"add.hydramixer.topics"];
myAppAFNClient.m
-(void)getJsonResponse:(NSURLRequest *)_request notificationString:(NSString *)notifString{
AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:_request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
if([notifString length] != 0){
// handling success
}
} failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON){
// handling errors
}];
[operation start];
}

AFNetworking application/json

Using iOS, I'm trying to communicate with a webservice that requests 3 headers followed by JSON POST data.
I've taken a look at the following AFNetworking snippet which converts a Dictionary to a JSON file. In this case I'm trying to POST both the headers and a JSON file. Let me know if you have any suggestions:
NSURL *url = [NSURL URLWithString:WalletKit_URL];
AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:url];
httpClient.parameterEncoding = AFJSONParameterEncoding;
NSDictionary *params = #{#"brand-id" : Brand_Id, #"api-key" : API_Key, #"Content-Type" : #"application/json"};
NSMutableURLRequest *request = [httpClient requestWithMethod:#"POST" path:#"" parameters:params];
AFHTTPRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSURLResponse *response, id JSON) {
NSLog(#"success");
} failure:^(NSURLRequest *request, NSURLResponse *response, NSError *error, id JSON) {
NSLog(#"error");
}];
You should add the HTTP header fields to the NSMutableURLRequest.
[request addValue:#"foobar" forHTTPHeaderField:#"X-Foo-Bar"];

AFNetworking with AFHTTPClient with AFJSONRequestOperation // MIME-Type Issues

I've been trying to get a grip on AFHTTPClient in the specific instance of dispatching a request to a REST-based service that requires OAuth authentication. I have no problem with creating the OAuth authentication using GTMOAuth.
I can also successfully marshall parameters to dispatch the request and obtain a well-formed JSON response using a hand-cobbled NSMutableURLRequest and both AFJSONRequestOperation and an NSURLConnection. Those latter two mechanics were my sanity check that I was touching the service correctly.
I get a response using
[AFHTTPClient HTTPRequestOperationWithRequest:request success:^(AFHTTPRequestOperation *operation, id responseObject)]
but no matter what — it's interpreted as text/plain. The returned object's class is __NCFData.
No bueno.
This bit of code doesn't want to return a response that's a dictionary of any sort.
- (IBAction) testFlickr {
// marshall parameters
NSString *urlStr = #"http://api.flickr.com/";
NSURL *url = [NSURL URLWithString:urlStr];
AFHTTPClient *client = [[AFHTTPClient alloc]initWithBaseURL:url];
[client registerHTTPOperationClass:[AFJSONRequestOperation class]];
[client setParameterEncoding:AFJSONParameterEncoding];
NSDictionary *params = [[NSDictionary alloc]initWithObjectsAndKeys:#"json", #"format", #"66854529#N00", #"user_id", #"1", #"jsoncallback", nil];
NSString *path = [[NSString alloc]initWithFormat:#"services/rest/?method=flickr.people.getPhotos"];
NSMutableURLRequest *af_request = [client requestWithMethod:#"GET" path:path parameters:params];
// flickrAuth instance variable is an instance of GTMOAuthAuthentication
[self.flickrAuth authorizeRequest:af_request];
[client setAuthorizationHeaderWithToken:[self.flickrAuth accessToken]];
[client setDefaultHeader:#"Accept" value:#"application/json"];
[client requestWithMethod:#"GET" path:path parameters:params];
LOG_FLICKR_VERBOSE(0, #"Can Authorize? %#", ([self.flickrAuth canAuthorize] ? #"YES":#"NO"));
LOG_FLICKR_VERBOSE(0, #"%#", client);
// first way of trying..
AFHTTPRequestOperation *af_operation = [client HTTPRequestOperationWithRequest:af_request success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSString *str = [[NSString alloc] initWithData:responseObject
encoding:NSUTF8StringEncoding];
LOG_FLICKR_VERBOSE(0, #"Weird af_operation semantics, but.. %#", str);
LOG_FLICKR_VERBOSE(0, #"Weird af_operation semantics returns %#", [responseObject class]);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
//
LOG_FLICKR_VERBOSE(0, #"Weird af_operation semantics, error.. %#", error);
}];
[af_operation start];
}
This request goes through okay. The response data itself is what I'd expect, but it is not any kind of dictionary class.
I'd rather keep to using methods of AFHTTPClient (as opposed to, for example, [AFJSONRequestOperation JSONRequestOperationWithRequest]) so I can use AFHTTPClient's Reachability methods and so forth.
Strangely (to me, at least) if I do the request like this:
NSMutableURLRequest *aj_request = [client requestWithMethod:#"GET" path:path parameters:params];
[self.flickrAuth authorizeRequest:aj_request];
AFJSONRequestOperation *aj_operation =
[AFJSONRequestOperation JSONRequestOperationWithRequest:af_request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
LOG_FLICKR_VERBOSE(0, #"AFJSONRequestOperation %#", JSON);
} failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) {
LOG_FLICKR_VERBOSE(0, #"AFJSONREquestOperation Error %#", error);
}];
[aj_operation start];
It fails with a "401" because it was expecting application/json in the response header and instead thinks it's received text/plain
But, if I do the request like this:
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[[NSURL alloc]initWithString:#"http://api.flickr.com/services/rest/?method=flickr.people.getPhotos&format=json&user_id=66854529#N00&nojsoncallback=1"]];
[self.flickrAuth authorizeRequest:request];
AFJSONRequestOperation *operation =
[AFJSONRequestOperation JSONRequestOperationWithRequest:request
success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
LOG_FLICKR_VERBOSE(0, #"Success Flickr =========\n%# %#", JSON, [JSON valueForKeyPath:#"photos.total"]);
/////handler(JSON, nil);
} failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) {
LOG_FLICKR(0, #"URL Was %#", url);
LOG_FLICKR(0, #"Failed Flickr ==========\n%# %#", error, JSON);
/////handler(nil, error);
}];
[operation start];
It works fine, including nice JSON, dictionary-formed data.
In the first instance, I'm using AFHTTPClient to produce the NSMutableURLRequest. In the second instance, I'm creating the NSMutableURLRequest on my own. In both cases I'm using AFJSONRequestOperation to dispatch the request leaving the only culprit for the problem to (besides myself..) AFHTTPClient.
In the first example that I can get to work, it's not returning JSON-y data.
In the second example AFHTTPClient seems to create an NSMutableURLRequest that blatantly fails — but (AFAICT) the same URL succeeds when that URL is created "by hand" using [NSMutableURLRequest requestWithURL].
I wonder — what am I missing when using AFHTTPClient?
Help?
In your first code example, it looks like you're doing NSMutableURLRequest *af_request = [client requestWithMethod:#"GET" path:path parameters:params]; and then setting default headers afterwards. Default headers only get applied to requests created after they were specified. Maybe that's where things are going amiss.
Also, that 401 error may be complaining about its content type, but 401 is an error status code, meaning that you're unauthenticated.
I ended up removing all the header parameters to isolate the problem, but it made no difference. Examining the response quite closely gave me a clue. While Flickr does return "JSON" it is not Lint-free, it seems and requires a tweak to one of the parameters. I had been sending jsoncallback=1 but it should be nojsoncallback=1. Once I fixed that parameter AFJSONRequestOperation handles the response correctly and parses the JSON.
My final code looks like this (for others, n.b. the nojsoncallback=1 parameter)
- (IBAction)testFlickrAFJSON:(id)sender
{
// marshall parameters
NSString *urlStr = #"http://api.flickr.com/";
NSURL *url = [NSURL URLWithString:urlStr];
//NSDictionary *params = [[NSDictionary alloc]initWithObjectsAndKeys:#"json", #"format", #"66854529#N00", #"user_id", nil];
NSDictionary *params = [[NSDictionary alloc]initWithObjectsAndKeys:#"json", #"format", #"66854529#N00", #"user_id", #"1", #"nojsoncallback", nil];
NSString *path = [[NSString alloc]initWithFormat:#"services/rest/?method=flickr.people.getPhotos"];
AFHTTPClient *client = [[AFHTTPClient alloc]initWithBaseURL:url];
NSMutableURLRequest *af_request = [client requestWithMethod:#"GET" path:path parameters:params];
[self.flickrAuth authorizeRequest:af_request];
LOG_FLICKR_VERBOSE(0, #"Can Authorize? %#", ([self.flickrAuth canAuthorize] ? #"YES":#"NO"));
AFJSONRequestOperation *af_operation_2 = [AFJSONRequestOperation JSONRequestOperationWithRequest:af_request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
LOG_FLICKR_VERBOSE(0, #"AFJSONRequestOperation Alt %#", JSON);
LOG_FLICKR_VERBOSE(0,#"AFJSONRequestOperation Alt response MIMEType %#",[response MIMEType]);
} failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) {
LOG_FLICKR_VERBOSE(0, #"AFJSONREquestOperation Alt Error %#", error);
NSHTTPURLResponse *resp = [[error userInfo] valueForKey:AFNetworkingOperationFailingURLResponseErrorKey];
LOG_FLICKR_VERBOSE(0,#"AFJSONRequestOperation Alt Error response MIMEType %#",[resp MIMEType]);
}];
[af_operation_2 start];
}

AFNetworking and POST Request

I'm getting this response in error.userInfo while making a POST request from AFNetworking.
Can anyone tell either I'm missing anything obvious or something need to fix at my server end?
Request Failed with Error: Error Domain=AFNetworkingErrorDomain
Code=-1016 "Expected content type {(
"text/json",
"application/json",
"text/javascript" )}, got text/html" UserInfo=0x6d7a730 {NSLocalizedRecoverySuggestion=index test,
AFNetworkingOperationFailingURLResponseErrorKey=, NSErrorFailingURLKey=http://54.245.14.201/,
NSLocalizedDescription=Expected content type {(
"text/json",
"application/json",
"text/javascript" )}, got text/html, AFNetworkingOperationFailingURLRequestErrorKey=http://54.245.14.201/>}, {
AFNetworkingOperationFailingURLRequestErrorKey = "http://54.245.14.201/>";
AFNetworkingOperationFailingURLResponseErrorKey = "";
NSErrorFailingURLKey = "http://54.245.14.201/";
NSLocalizedDescription = "Expected content type {(\n \"text/json\",\n \"application/json\",\n
\"text/javascript\"\n)}, got text/html";
NSLocalizedRecoverySuggestion = "index test"; }
And I'm using this code;
AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:url];
[httpClient registerHTTPOperationClass:[AFJSONRequestOperation class]];
[httpClient setDefaultHeader:#"Accept" value:#"application/json"];
NSDictionary *params = [NSDictionary dictionaryWithObjectsAndKeys:
#"Ans", #"name",
#"29", #"age",
nil];
NSMutableURLRequest *request = [httpClient requestWithMethod:#"POST" path:#"/" parameters:params];
AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request
success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
NSLog(#"Success");
NSLog(#"%#",JSON);
} failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) {
NSLog(#"Request Failed with Error: %#, %#", error, error.userInfo);
NSLog(#"Failure");
}];
[operation start];
[operation waitUntilFinished];
By default, AFJSONRequestOperation accepts only "text/json", "application/json" or "text/javascript" content-types from server, but you are getting "text/html".
Fixing on server would be better, but you can also add "text/html" content type as acceptable in your app:
[AFJSONRequestOperation addAcceptableContentTypes:[NSSet setWithObject:#"text/html"]];
It worked for me, hope this helps!
Did you send this POST request by AFHTTPClient? If so, you need to set operation class for it:
AFHTTPClient * client = [[AFHTTPClient alloc] initWithBaseURL:[NSURL URLWithString:#"http://localhost:8080"]];
// ...
[client registerHTTPOperationClass:[AFJSONRequestOperation class]];
[client setDefaultHeader:#"Accept" value:#"application/json"];
// ...
// EDIT: Use AFHTTPClient's POST method
NSDictionary *params = [NSDictionary dictionaryWithObjectsAndKeys:
#"Ans", #"name",
#"29", #"age", nil];
// POST, and for GET request, you need to use |-getPath:parameters:success:failure:|
[client postPath:#"/"
parameters:params
success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"RESPONSE: %#", responseObject);
// ...
}
failure:^(AFHTTPRequestOperation *operation, NSError *error) {
if (error)
NSLog(#"%#", [error localizedDescription]);
// ...
}
Set your values in this code and check if it works for you
AFHTTPClient *httpClient = [[AFHTTPClient alloc]initWithBaseURL:[NSURL URLWithString:kBASEURL]];
NSString *_path = [NSString stringWithFormat:#"groups/"];
_path = [_path stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSLog(#"%s %#",__PRETTY_FUNCTION__,_path);
NSMutableURLRequest *request = [httpClient requestWithMethod:#"POST"
path:_path
parameters:postParams];
[httpClient release];
AFJSONRequestOperation *operation = [AFJSONRequestOperation
JSONRequestOperationWithRequest:request
success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
if ([JSON isKindOfClass:[NSArray class]] || [JSON isKindOfClass:[NSDictionary class]]) {
completed(JSON);
}
else {
}
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
}
failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) {
NSLog(#" response %# \n error %# \n JSON %#",response,error,JSON);
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
errored(error);
}];
NSOperationQueue *queue = [[[NSOperationQueue alloc] init] autorelease];
[queue addOperation:operation];
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];

Resources