How to intercept the response of AFNetworking request in Objective-C? - ios

As titled, and how to check HTTP status of response?
For example, if the server returns http status code 403, I need to send a recall mail request again to take new access token.

Take a look at the below. In the failure block, retry/resend your query X number of times. Be sure to add logic to end retries at some point, so you don't end up with an infinite loop.
AFHTTPRequestOperationManager *operationManager = [AFHTTPRequestOperationManager manager];
[operationManager POST:url
parameters:object
success:^(AFHTTPRequestOperation *operation, id responseObject) {
}
failure:^(AFHTTPRequestOperation *operation, NSError *error) {
if (operation.response.statusCode == 403) {
// retry
}
}
];
This answer may also be helpful.

Related

AFNetworking: How do I measure HTTP request and response times?

Trying to debug AFNetworking in my application. I need to capture the time of both request and response time to get the duration.
The duration will help me to set a reasonable timeout for the GET operation. The default 60 seconds timeout is not enough.
How do I get the request and response time? Is it part of the AFHTTPRequestOperation object?
[[AFHTTPRequestOperationManager new] GET:#"http://www.example.com"
parameters:nil
success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"startTime={} endTime={}");
}
failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"startTime={} endTime={}");
}
];

Wrong content-type(old header sent) being received by server side

I updated afnetwork to 2.0 due to 64 bit. I made a mistake at first using AFHTTPRequestSerializer, but the server side accept Json only. The wried thing was it works fine for me even I used AFHTTPRequestSerializer, so I didn't notice this problem and released the error app to public. Then I keep receiving user complain and somehow I rebuild my app on my device, and local server can catch my wrong content-type(application/x-www.form-urlencoded). After I updated the AFHTTPRequestSerializer to AFJSONRequestSerializer, it doesn't fix the problem, but the user still keep sending wrong content-type to server even they updated the app. New user has no problem, only happen on old user.
Is this related to cache problem?
Server Log:
10:22:53 AM] Mark 1 contentType is: application/x-www-form-urlencoded, method is: POST headers are: Connection=keep-alive&Content-Length=1880739&Content-Type=application%2fx-www-form-urlencoded&Accept=*%2f*&Accept-Encoding=gzip%2c+deflate&Accept-Language=en%3bq%3d1&Cookie=ASP.NET_SessionId%3dbby5dlk5afmsnqnoqpprvqpw&Host
10:04:56 AM] contentType is: application/json, method is: POST header is: Connection=keep-alive&Content-Length=40352 4&Content-Type=application%2fjson &Accept=*%2f*&Accept-Encoding=gzip%2c+deflate&Accept-Language=en%3bq%3d1&Cookie=ASP.NET_SessionId%3dcw3gdkg3sff1f0j50z2rnism&Host
my code is
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
manager.requestSerializer = [AFJSONRequestSerializer serializer];
manager.responseSerializer = [AFJSONResponseSerializer serializer];
AFHTTPRequestOperation *operation = [manager POST:_url parameters:requestParams success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"operation success: %#\n %#", operation, responseObject);
NSDictionary *decoded = [self processResponce:responseObject failureBlock:failureBlock];
if (!decoded) return;
BOOL containsError = [self checkErrorStatus:decoded failureBlock:failureBlock];
if (containsError) return;
successBlock(decoded[#"Data"]);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
failureBlock(FailureTypeUnknown, [error localizedDescription]);
}];
[operation setUploadProgressBlock:^(NSUInteger bytesWritten, long long totalBytesWritten, long long totalBytesExpectedToWrite) {
progressBlock(bytesWritten,totalBytesWritten,totalBytesExpectedToWrite);
}];
as per your response, please set your manager's content type as below
manager.responseSerializer.acceptableContentTypes = [NSSet setWithObject:#"application/json"];

POSTing a nested NSDictionary using AFNetworking 2

Using the Postman extension for Chrome I can successfully POST some JSON. Using Charles to inspect the request, I see that the request data is as follows:
{
"query": {
"term": {
"user_id": "12345"
}
}
}
When I try to construct this same request using AFNetworking 2.4.1, I can see that the data is formatted as:
query[term][user_id]=12345
The server of course returns an error.
What part of the POST request am I getting wrong?
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
NSDictionary *parameters = #{#"query":#{#"term":#{#"user_id":#"12345"}}};
[manager POST:#"http://someURL" parameters:parameters success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"SUCCESS %#", responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"FAIL: %#", error);
}];
The short answer is:
manager.requestSerializer = [AFJSONRequestSerializer serializer];
From the documentation:
Requests created with requestWithMethod:URLString:parameters: &
multipartFormRequestWithMethod:URLString:parameters:constructingBodyWithBlock:
are constructed with a set of default headers using a parameter
serialization specified by this property. By default, this is set to
an instance of AFHTTPRequestSerializer, which serializes query
string parameters for GET, HEAD, and DELETE requests, or
otherwise URL-form-encodes HTTP message bodies.

Yahoo OAuth Error 401 Consumer Key Unknown

I am trying to get a request token from Yahoo by making a POST request to the following URL:
https://api.login.yahoo.com/oauth/v2/get_request_token
I am making the request in the following way:
int randomNumber = rand();
NSDictionary *parameters = #{#"oauth_consumer_key": YahooConsumerKey,
#"oauth_signature_method": #"plaintext",
#"oauth_signature": YahooConsumerSecret,
#"oauth_version": #"1.0",
#"xoauth_lang_pref": #"en_us",
#"oauth_callback": #"oob",
#"oauth_timestamp": [self getTimeStamp],
#"oauth_nonce": [NSString stringWithFormat:#"%d", randomNumber]};
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
[manager POST:#"https://api.login.yahoo.com/oauth/v2/get_request_token" parameters:parameters success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"JSON: %#", responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
}];
The problem is that I keep getting the error 401 with the explanation that the consumer key is unknown. I have pasted the consumer key from where I've created my project, so I really don't know what I am doing wrong. Any help will be appreciated. Thanks!
Your request looks good. Try appending #"%26" to your YahooConsumerSecret string. Here's your request link with the fix, it seems to be working!
When using plaintext as oauth_signature_method you need to append %26 at the end of your oauth_signature according to the Yahoo docs.

AFNetworking 2.0 Request w. Custom Header

Ive tried to avoid asking such a newb question on here, but im a Android dev learning IOS and I cant figure out for the life of me how to add a simple header to my post requests using AFNetworking 2.0. Below is my code so far which works if i want to make a request that doesnt require a header.Could anyone show me via adding to my snippet or providing a alternate one that does this? I came across this tut: http://www.raywenderlich.com/30445 that shows how to add a header under the "A RESTful Class" heading , but its for afnetworking 1.0 and is now depreciated as far as i can tell.
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
NSDictionary *parameters = #{#"uid": #"1"};
AFHT
[manager POST:#"http://myface.com/api/profile/format/json" parameters:parameters success:^(AFHTTPRequestOperation *operation, id responseObject) {
//NSLog(#"JSON: %#", responseObject);
self.feedArray = [responseObject objectForKey:#"feed"];
[self.tableView reloadData];
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
} ];
}
Under AFHTTPRequestOperationManager you will notice a property called requestSerializer. This is of type AFHTTPRequestSerializer, and requests made through the HTTP manager are constructed with the headers specified by this object.
So, try this:
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
[manager.requestSerializer setValue:#"SomeValue" forHTTPHeaderField:#"SomeHeaderField"]
//Make your requests
You can read the headers dictionary from the request serializer as follows:
manager.requestSerializer.HTTPRequestHeaders
Note that once you set a header this way, it will be used for all other operations!
[manager.requestSerializer setAuthorizationHeaderFieldWithUsername:#"staging" password:#"dustylendpa"];

Resources