I'm trying to make a GET request setting a header called
X-User-Authorization
but I'm getting the following error:
Code=-1011 "Request failed: unauthorized (401)" AFNetwoking
-(void) listarGruposDeDistancia
{
NSMutableArray *listaDistancias = [[NSMutableArray alloc]init];
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
manager.requestSerializer = [AFHTTPRequestSerializer serializer];
manager.requestSerializer.allowsCellularAccess = YES;
[manager.requestSerializer setValue:#"valueHere" forHTTPHeaderField:#"X-User-Authorization"];
AFSecurityPolicy *policy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeNone];
policy.allowInvalidCertificates = YES;
manager.securityPolicy = policy;
NSString *url = #"https://url:3000/api/v0.1/groups/";
[manager GET:url
parameters:nil
success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#“success”);
}
[self concluirListaDistancias:listaDistancias];
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
}];
}
You're definitely getting a 401 back from the server - meaning you haven't constructed an appropriate HTTP request with authentication according to what the server requires. Review the documentation of the (service provider or in your case what appears to be a local packaged product), then use tools like curl and postman to construct an appropriate HTTP request. When you're confident the raw requests are working as expected, use something like requestb.in to test your AFNetworking request.
For what it's worth, X-User-Authorization isn't a pre-configured authorization header (The X- prefix implies it's a custom header attribute). Maybe you're looking for something more like Authorization: Bearer <token>?
Related
I'm attempting to set custom headers on a per-request basis using AFNetworking, but occasionally the headers will seemingly disappear after being set. Below is the code used to make a request...
+ (void) getWithURI: (NSString*) uri header: (NSDictionary*) header success: (NSString*) successCallback failure: (NSString*)errorCallback dispatch: (NSString*)dispatchedId
{
createManagerInstance();
AFHTTPRequestOperation* operation = [manager GET:uri
parameters:nil
success:^(AFHTTPRequestOperation *operation, id responseObject) {
[RestWrapper succeededWithJson:operation.responseString dispatchedId:dispatchedId successCallback:successCallback];
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
[RestWrapper failedWithJson:operation.responseString dispatchedId:dispatchedId errorCallback:errorCallback];
}];
NSMutableURLRequest* request = (NSMutableURLRequest*)operation.request;
for (NSString* key in header)
{
if([request valueForHTTPHeaderField:key] != nil)
{
[request setValue:header[key] forHTTPHeaderField:key];
}
else
{
[request addValue:header[key] forHTTPHeaderField:key];
}
}
NSLog(#"Headers: %#", request.allHTTPHeaderFields);
[operation start];
}
For 95% of my requests, they go through as anticipated. Sporadically, however, some will fail and indicate a header is missing. This has been confirmed by capturing the requests in question using Fiddler and seeing that the headers are actually missing. Despite this, the console log of request.allHTTPHeaderFields always shows the headers in place.
The only other thing I noticed is that in general Fiddler reports the caching policy as "max-age=0, private, must-revalidate" for each request. However, whenever a request loses the custom headers, it's caching policy is "no-cache".
This is because you're adding HTTP Header fields in wrong way.
You should add it before request. You may try something like this :
+ (void) getWithURI: (NSString*) uri header: (NSDictionary*) header success: (NSString*) successCallback failure: (NSString*)errorCallback dispatch: (NSString*)dispatchedId{
createManagerInstance();
manager.requestSerializer = [AFJSONRequestSerializer serializer];
[manager.requestSerializer setValue:header[key] forHTTPHeaderField:key];
AFHTTPRequestOperation* operation = [manager GET:uri
parameters:nil
success:^(AFHTTPRequestOperation *operation, id responseObject) {
[RestWrapper succeededWithJson:operation.responseString dispatchedId:dispatchedId successCallback:successCallback];
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
[RestWrapper failedWithJson:operation.responseString dispatchedId:dispatchedId errorCallback:errorCallback];
}];
[operation start];
}
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"];
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.
After trying nearly every response on the subject, I've come up without a working answer to my problem.
The problem: So I've implemented the uploading portion of my app using AFNetworking 2.0.3 after porting from AFNetworking 1.3:
-(void)commandWithParams:(NSMutableDictionary*)params onCompletion:(JSONResponseBlock)completionBlock {
NSData* uploadFile = nil;
if ([params objectForKey:#"file"]) {
uploadFile = (NSData*)[params objectForKey:#"file"];
[params removeObjectForKey:#"file"];
}
AFHTTPRequestOperationManager *manager = [[AFHTTPRequestOperationManager alloc] initWithBaseURL:[NSURL URLWithString:#"http://54.204.17.38"]];
manager.responseSerializer = [AFJSONResponseSerializer serilizer];
manager.responseSerializer.acceptableContentTypes = [NSSet setWithObject:#"application/json"];
AFHTTPRequestOperation *apiRequest = [manager POST:#"/API" parameters:params constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
if (uploadFile) {
[formData appendPartWithFileData:uploadFile name:#"file" fileName:#"photo.jpg" mimeType:#"image/jpeg"];
}
} success:^(AFHTTPRequestOperation *operation, id responseObject) {
completionBlock(responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
completionBlock([NSDictionary dictionaryWithObject:[error localizedDescription] forKey:#"error"]);
}];
[apiRequest start];
}
The error I get when using this code is "Request failed: unacceptable content-type: text/html" I know you might be wondering if the server is responding with proper JSON, and I have every reason to think it is after inspecting the response headers in my browser that say 'MIME type: application/json'. Also, I am using 'header('Content-type: application/json')' at the top of my API as well (PHP API). Now, if I change the serialization type to 'AFHTTPResponseSerializer' instead of 'AFJSONResponseSerializer', it will not spit out the JSON error, but it will give me a different error (a random unrecognized selector error).
Any thoughts on why I cannot seem to get a JSON response out of this method?
You can set the AFHTTPSessionManager to accept any MIME Type:
manager.responseSerializer.acceptableContentTypes = [NSSet setWithObject:#"text/html"];
Got it! So, turns out, unknowingly, although my API was returning valid JSON, matter examining the header response logged on the Xcode side of things (thru NSLog(#"Error: %#", error);), it was actually returning text/HTML because it wasn't actually hitting the correct file, it was getting re-routed by a header somewhere. After explicitly stating the API path to be /API/index.php and not just /API, it started returning the valid JSON! Next, after making sure the response was properly JSON serialized (using requestManager.responseSerializer = [AFJSONResponseSerializer serializer];), the app worked!
Hopefully this helps someone who was having the same issue :)
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"];