Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

HTTPURLResponse allHeaderFields Swift 3 Capitalisation

Converting to Swift 3 I noticed a strange bug occur reading a header field from HTTPURLResponse.

let id = httpResponse.allHeaderFields["eTag"] as? String

no longer worked.

I printed out the all headers dictionary and all my header keys seem to be in Sentence case.

According to Charles proxy all my headers are in lower case. According to the backend team, in their code the headers are in Title-Case. According the docs: headers should be case-insensitive.

So I don't know which to believe. Is anyone else finding in Swift 3 that their headers are now being turned into Sentence case by iOS? If so is this behaviour we want?

Should I log a bug with Apple or should I just make a category on HTTPURLResponse to allow myself to case insensitively find a header value.

like image 450
Mark Bridges Avatar asked Oct 20 '16 10:10

Mark Bridges


3 Answers

More efficient workaround:

(response.allHeaderFields as NSDictionary)["etag"]
like image 93
Guoye Zhang Avatar answered Oct 21 '22 18:10

Guoye Zhang


Due to a bug in Swift and a new solution in iOS 13, I made an extension:

Here is a link to gist.

public extension HTTPURLResponse {
    func valueForHeaderField(_ headerField: String) -> String? {
        if #available(iOS 13.0, *) {
            return value(forHTTPHeaderField: headerField)
        } else {
            return (allHeaderFields as NSDictionary)[headerField] as? String
        }
    }
}

like image 43
Alexander Bekert Avatar answered Oct 21 '22 16:10

Alexander Bekert


Update: this is a known issue.


allHeaderFields should return a case-insensitive dictionary because that is what the HTTP spec requires. Looks like a Swift error, I would file a radar or a bug report on .

Here is some sample code that reproduces the issue simply:

let headerFields = ["ETag" : "12345678"]
let url = URL(string: "http://www.example.com")!
let response = HTTPURLResponse(url: url, statusCode: 200, httpVersion: "HTTP/1.1", headerFields: headerFields)!

response.allHeaderFields["eTaG"] // nil (incorrect)
headerFields["eTaG"] // nil (correct)

(Adapted from this Gist from Cédric Luthi.)

like image 44
Aaron Brager Avatar answered Oct 21 '22 17:10

Aaron Brager