15

Before today's iOS 8.3 update I had my code working right, but after updating server started rejecting requests as it could not find JSON data.

I found that iOS is sending a wrong application/x-www-form-urlencoded text (not properly encoded as it seems a JSON object):

Wireshark screenshot showing wrong data

This is what I expected to be sent (and what was sent on 8.2): Wireshark screenshot showing expected object

As I said, this only happens on iOS 8.3 (I just tried on iOS simulator with 8.2 and it works).

I think the problem is in one of the classes that appear on these lines:

NSData *bodyData = [NSJSONSerialization dataWithJSONObject:requestDict options:0 error:nil];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
request.HTTPBody = bodyData;

I checked Apple documentation and none appears as modified recently.

Is someone suffering the same or knows what can lead to this?

Thanks.

Bartomeu Galmés
  • 263
  • 1
  • 5
  • 14
  • 1
    Try to indicate the http method like `[request setHTTPMethod:@"POST"]`, eventually, the request length `[request setValue:postLength forHTTPHeaderField:@"Content-Length"];` and the content type `[request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Current-Type"];` – Luca Iaco Apr 09 '15 at 08:46
  • 2
    It worked putting the `Content-Type` header with `"application/json"` value. Seems that I was adding the headers to the `NSURLSessionConfiguration` instead of the `NSMutableURLRequest`. Thanks!. – Bartomeu Galmés Apr 09 '15 at 13:16
  • I'll put as answer so we can close this issue – Luca Iaco Apr 09 '15 at 14:28
  • 1
    http://openradar.appspot.com/20489846 looks like a radar on this issue; [QuickRadar](http://www.quickradar.com/) makes duplicating radars very easy if you want to file a dupe. – Isaac Apr 10 '15 at 15:44
  • @LucaIaco Sorry to re-awaken an old question, but why `Current-Type` and not `Content-Type`? I've recently seen it in a codebase I've taken over and can't find anything indicating what it does? Are the two analogous? – George Green Jun 20 '16 at 14:38
  • @GeorgeGreen Hey, no worries. Yes sorry, In my old post I wrote "Current-Type" but I meant Content-Type, check my answer below in case – Luca Iaco Jun 20 '16 at 15:22
  • @LucaIaco, thanks for clarification. I only ask because I saw it in this project I'm working on, stuck it in Google and this was all that came up. Though maybe I'd missed a valuable header type :P – George Green Jun 20 '16 at 15:46

3 Answers3

11

I also have encountered this problem in one application.

It looks like it could be a bug introduced in iOS 8.3. From the official Framework Reference, it is said of the NSURLSessionConfiguration's HTTPAdditionalHeaders property:

This property specifies additional headers that are added to all tasks within sessions based on this configuration. For example, you might set the User-Agent header so that it is automatically included in every request your app makes through sessions based on this configuration.

From what I understand, a Content-Type set in this configuration should be automatically included in every request made through this session, which is no longer the case since 8.3. I've filed a radar.

UPDATE: The radar has been set as 'duplicate' of another so it's more likely a bug.

As Luca pointed out, the work around is to set the Content-Type directly on the request:

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

Source: https://developer.apple.com/library/mac/documentation/Foundation/Reference/NSURLSessionConfiguration_class/#//apple_ref/occ/instp/NSURLSessionConfiguration/HTTPAdditionalHeaders

Rufel
  • 2,630
  • 17
  • 15
  • The docs also state that headers on the request object take precedence over headers on the configuration. The implication here is that `NSMutableURLRequest` now sets `Content-Type` when it didn't used to. – Lily Ballard Apr 10 '15 at 01:59
  • 2
    Just got hit by this with the release of iOS 8.3 - setting the Content-Type on each url request instead of using the `NSURLSessionConfiguration` fixes the issue – Orion Edwards Apr 10 '15 at 05:40
  • Thanks for the workaround. That's a horrendous bug in a platform with multi-day app review timeframes. I wonder how many apps were broken in production due to this one. – stephent Apr 25 '15 at 22:35
7

I put the comment as answer here:

Try to indicate the http method like

[request setHTTPMethod:@"POST"]

and / or, the request length

[request setValue:postLength forHTTPHeaderField:@"Content-Length"]; 

and / or the content type

[request setValue:@"application/<YOUR CONTENT TYPE>"forHTTPHeaderField:@"Content-Type"];
Luca Iaco
  • 3,387
  • 1
  • 19
  • 20
  • Great. In some implementations this may be a quick way to do it: `NSDictionary *headers = session.configuration.HTTPAdditionalHeaders;` for (id key in headers.allKeys) { `[request addValue:[headers objectForKey:key] forHTTPHeaderField:key];` } – Arjan Apr 22 '15 at 10:45
0

It seems that iOS 8.3 introduces this. At my site we got found the problem that the (json)body was correctly not set inside the request.

When debugging try to debug the server-side also

traxion
  • 1
  • 1