automatic capitalization of http headers in iOS?

How to pass "location"(all letters small-case) in HTTP headers of NSURLRequest or URLSession? I am coding like

let session = URLSession.shared

let request = NSMutableURLRequest(url: url!)

request.httpMethod = "GET"

request.addValue("XYZLocation", forHTTPHeaderField: "location")

print("Header : \(String(describing: request.allHTTPHeaderFields))") 


It's always printing Location: XYZLocation. Whereas I want location:XYZLocation. Why 'l' is always getting capitalized? Please help ASAP.

Replies

Saw the reply to your question in SO.

First of all, use the native Swift equivalent, URLRequest instead of NSMutableURLRequest. Second of all, if you look at the documentation of addValue, you can see that the header values are case insensitive to conform to HTTP RFC, so you should also be using case insensitive headers in your backend.


So, if you want to print with Location, you would have to go throughh all the fields in request.allHTTPHeaderFields and format the key with uppercase.

So, if you want to print with Location, you would have to go through all the fields in

request.allHTTPHeaderFields
and format the key with uppercase.

The way this is written it seems like you’re making a suggestion for how to access the headers in their original case rather than what MS_ios is looking for, that is, a way to set the headers with a specific case.

Despite that, the technique you proposed seems to work, which was a bit of a surprise to me. Specifically, this code:

var req = URLRequest(url: URL(string: "http://sully.local:12345/")!)
req.setValue("XYZLocation", forHTTPHeaderField: "location")
req.allHTTPHeaderFields?["location2"] = "XYZLocation2"
URLSession.shared.dataTask(with: req) { 
    …
}.resume()

produces headers like this on the wire:

Location: XYZLocation
location2: XYZLocation2

I wasn’t expecting that that would actually work.

… you should also be using case insensitive headers in your backend.

Yes!

@MS_ios, I want to be absolutely clear here: HTTP headers are specified to be case insensitive [1] so if you’ve created a server that differentiates between

location
and
Location
then you’re asking for problems down the line. The above seems to provide a workaround on current Apple platforms but it’s a very bad idea to rely on that indefinitely. You need to fix your server.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

[1] Specifically, see Section 3.2 of RFC 7230 which says, in its very first sentence:

Each header field consists of a case-insensitive field name followed by a colon …

You did implement it ! As always, I'm impressed.


I also thought MS_ios could generate the appropriate String for the

print("Header : \(String(describing: request.allHTTPHeaderFields))")

from request.allHTTPHeaderFields

If I simply print("Header :\(request.allHTTPHeaderFields)") , XCode 8.3.3 shows me a warning:"String interpolation produces a debug description for an optional value; did you mean to make this explicit?"

Thanks @eskimo for understanding my query correctly. 🙂 Will definitely make changes at server-side and make header case-insensitive. But again I have one doubt:

request.addValue("XYZLocation", forHTTPHeaderField: "loc")
print("Header : \(String(describing: request.allHTTPHeaderFields))")

Its printing all letters small loc:XYZLocation for me. So, why iOS is not canonicalizing it? Can you please give it a try?

Thanks.

So, why iOS is not canonicalizing it?

To be clear, the concern is that:

  • setValue(_:forHTTPHeaderField:)
    canonicalises the header case
  • addValue(_:forHTTPHeaderField:)
    does not

It actually gets even weirder than that. If you call ‘set’ and then call one or more ‘adds’, the case of the last add wins.

Honestly, I can’t explain this. I encourage you to file a bug about the inconsistency. File it against the behaviour of

URLRequest
and ask that, if that behaviour is deemed correct, that the documentation be updated to describe it.

Please post your bug number, just for the record.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"