AFNetworking version 2 content-type error
Asked Answered
H

5

4

I'm attempting to make an iphone app that will interact with a particular JIRA server. I've got the following code to log in:

NSURL *url = [[NSURL alloc] initWithString:@"https://mycompany.atlassian.net/rest/auth/latest/session/"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:@"POST"];
NSString *postString = [NSString stringWithFormat:@"{\"username\":\"%@\",\"password\":\"%@\"}", username, password];
[request setHTTPBody:[postString dataUsingEncoding:NSUTF8StringEncoding]];
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
[request setValue:@"application/json" forHTTPHeaderField:@"Accept" ];
operation.responseSerializer = [AFJSONResponseSerializer serializer];
[operation setCompletionBlockWithSuccess:
    ^(AFHTTPRequestOperation *operation, id responseObject) {
        NSLog(@"JSON: %@", responseObject);
    } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
    NSLog(@"ERROR: %@", error);

    }
 ];
 [operation start];

But it's giving me the following error having to do with Content-Type:

ERROR: Error Domain=AFNetworkingErrorDomain Code=-1011
"Request failed: unsupported media type (415)"
UserInfo=0x8cd6540
{
  NSErrorFailingURLKey=https://mycompany.atlassian.net/rest/auth/latest/session/,
  NSLocalizedDescription=Request failed: unsupported media type (415),
  NSUnderlyingError=0x8c72e70
  "Request failed: unacceptable content-type: text/html", 

I'm not sure what the problem is. I found this question, which I thought might be a similar problem, but the answers say to either use the AFJSONRequestOperation class (which I can't because I'm using AFNetworking version 2, which doesn't have that class), or to fix it on the server side (which I also can't for obvious reasons).

What can I fix this error when I can't fix the server side and I can't use AFJSONRequestOperation?

Hem answered 23/1, 2014 at 22:51 Comment(1)
Glad you solved your problem. BTW, it's inadvisable to build JSON with stringWithFormat (if password had certain characters in it, it would fail). Better to use NSDictionary *postDictionary = @{@"username":username,@"password":password}; and then use NSData *postBody = [NSJSONSerialization dataWithJSONObject:postDictionary options:0 error:&error]; to create the NSData for setHTTPBody. Or in AF 2.0 use POST and AFJSONRequestSerializer (in AF 1.x use AFHTTPClient with parameterEncoding of AFJSONParameterEncoding), and it will convert the dictionary to JSON for you.Edson
E
14

If using AFNetworking 2.0, you can use the POST method, which simplifies this a bit:

AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
manager.requestSerializer = [AFJSONRequestSerializer serializer];
NSDictionary *parameters = @{@"username":username, @"password":password};
[manager POST:@"https://mycompany.atlassian.net/rest/auth/latest/session/" parameters:parameters success:^(AFHTTPRequestOperation *operation, id responseObject) {
    NSLog(@"JSON: %@", responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
    NSLog(@"Error: %@", error);
}];

This does the creation of the request, setting its Content-Type according to the requestSerializer setting, and encodes the JSON for you. One of the advantages of AFNetworking is that you can get out of the weeds of constructing and configuring NSURLRequest objects manually.


By the way, the "Request failed: unacceptable content-type: text/html" error means that regardless of what you were expecting to receive (e.g. JSON), you received HTML response. This is very common: Many server errors (e.g. the server informing you that the request was malformed, etc.) generate HTML error messages. If you want to see that HTML, in your failure block, simply log the operation.responseString.

Edson answered 23/1, 2014 at 23:46 Comment(0)
H
2

It turns out the problem is that this one line:

[request setValue:@"application/json" forHTTPHeaderField:@"Accept" ];

Should be

[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type" ];

The error is now solved. (Edit: I should have both, see CouchDeveloper's comment.)

EDIT
Rob's solution is better, so I'm going with it. I had actually tried a similar solution to what he shows, but where he had the line,

manager.requestSerializer = [AFJSONRequestSerializer serializer];

I had the line:

[manager.requestSerializer
    setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];

...which didn't work. Kudos to Rob for getting it to work!

Hem answered 23/1, 2014 at 23:4 Comment(2)
You may need both: with the header "Accept" you specify what kind of media type you want to receive when there is a response. With header "Content-Type" you specify the media type which you are sending. The "Content-Type" header SHOULD (really should) be specified in your request.Sacken
@Sacken Thanks, that helps me comprehend this better.Hem
C
1

I had the same problem in AFNetworking 2.0 and the solution was that I had to make sure I set the AFHTTPRequestSerializer type (In case your request is JSON) the it should be like this.

AFHTTPSessionManager *myHTTPManager = ...
[myManager setRequestSerializer:[AFJSONRequestSerializer serializer]];

You have to set both AFHTTPResponseSerializer and AFHTTPRequestSerializer

Continuo answered 5/4, 2014 at 13:9 Comment(0)
U
0

if you are using default written class AFAppDotNetAPIClient and you face this error. Must add responseSerializer. see your shared method should look like -

+ (instancetype)sharedClient {

static AFAppDotNetAPIClient *_sharedClient = nil;
static dispatch_once_t onceToken;

dispatch_once(&onceToken, ^{
    _sharedClient = [[AFAppDotNetAPIClient alloc] initWithBaseURL:[NSURL URLWithString:AFAppDotNetAPIBaseURLString]];
    _sharedClient.securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeNone];
    _sharedClient.responseSerializer = [AFHTTPResponseSerializer serializer];
});
return _sharedClient;}
Undemonstrative answered 22/7, 2014 at 11:45 Comment(0)
O
0

Use this line of code.

operation.responseSerializer.acceptableContentTypes = [NSSet setWithObject:@"text/html"];
Overwrought answered 17/7, 2015 at 9:32 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.