swift-corelibs-foundation: [SR-2429] Regression: HTTPURLResponse allHeaderFields is now case-sensitive
Previous ID | SR-2429 |
Radar | rdar://27925651 |
Original Reporter | alexsporn (JIRA User) |
Type | Bug |
Status | Resolved |
Resolution | Done |
Environment
Xcode Version 8.0 beta 6 (8S201h)
Additional Detail from JIRA
Votes | 27 |
Component/s | Foundation |
Labels | Bug |
Assignee | @airspeedswift |
Priority | Medium |
md5: 2495a8cbf7aef0a067f006a363dbbfce
Issue Description:
HTTPURLResponse normalizes header names following RFC 2616 as described in https://developer.apple.com/reference/foundation/httpurlresponse/1417930-allheaderfields
Access to these header values is case-insensitive as described in the documentation. This is broken in the latest Xcode8 beta6. The access is now case-sensitive.
Additionally the “ETag” header name is normalized to “Etag” instead of “ETag” as described in RFC 2616
This works correctly on Xcode8 beta4
Steps to Reproduce:
Run following Swift code:
let url = URL(string: "http://www.apple.com")!
let headers = [
"ETag" : "123456",
"content-type": "application/json",
]
let urlResponse = HTTPURLResponse(url: url,
statusCode: 200,
httpVersion: nil,
headerFields: headers)
print("ETag: \(urlResponse?.allHeaderFields["ETag"])")
print("Etag: \(urlResponse?.allHeaderFields["Etag"])")
print("ETAG: \(urlResponse?.allHeaderFields["ETAG"])")
print("etag: \(urlResponse?.allHeaderFields["etag"])")
print("content-type: \(urlResponse?.allHeaderFields["content-type"])")
print("Content-Type: \(urlResponse?.allHeaderFields["Content-Type"])")
print("CONTENT-TYPE: \(urlResponse?.allHeaderFields["CONTENT-TYPE"])")
Same code in Objective-C works as expected:
NSURL *url = [[NSURL alloc] initWithString:@"http://www.apple.com"];
NSDictionary *headers = @{
@"ETag": @"123456",
@"content-type": @"application/json",
};
NSURL *url = [[NSURL alloc] initWithString:@"http://www.apple.com"];
NSDictionary *headers = @{
@"ETag": @"123456",
@"content-type": @"application/json",
};
NSHTTPURLResponse *response = [[NSHTTPURLResponse alloc] initWithURL:url
statusCode:200
HTTPVersion:nil
headerFields:headers];
NSLog(@"Headers: %@", response.allHeaderFields);
NSLog(@"ETag: %@", response.allHeaderFields[@"ETag"]);
NSLog(@"Etag: %@", response.allHeaderFields[@"Etag"]);
NSLog(@"etag: %@", response.allHeaderFields[@"etag"]);
NSLog(@"ETAG: %@", response.allHeaderFields[@"ETAG"]);
NSLog(@"content-type: %@", response.allHeaderFields[@"content-type"]);
NSLog(@"Content-Type: %@", response.allHeaderFields[@"Content-Type"]);
NSLog(@"CONTENT-TYPE: %@", response.allHeaderFields[@"CONTENT-TYPE"]);
Expected Results:
Headers: Optional([AnyHashable("Content-Type"): application/json, AnyHashable("Etag"): 123456])
ETag: Optional(123456)
Etag: Optional(123456)
ETAG: Optional(123456)
etag: Optional(123456)
content-type: Optional(application/json)
Content-Type: Optional(application/json)
CONTENT-TYPE: Optional(application/json)
Actual Results:
Headers: Optional([AnyHashable("Content-Type"): application/json, AnyHashable("Etag"): 123456])
ETag: nil
Etag: Optional(123456)
ETAG: nil
etag: nil
content-type: nil
Content-Type: Optional(application/json)
CONTENT-TYPE: nil
Version:
Version 8.0 beta 6 (8S201h)
About this issue
- Original URL
- State: closed
- Created 8 years ago
- Comments: 23 (18 by maintainers)
Hi everyone,
There’s no way for us to keep
HTTPURLResponse.allHeaderFields
from being bridged to Swift as a case-sensitive dictionary, so this bug could only be fixed indirectly.To provide a way to do a case-insensitive lookup from Swift, Foundation has added a
HTTPURLResponse.value(forHTTPHeaderField:)
method. The Swift documentation forHTTPURLResponse
now recommends using this method instead ofallHeaderFields
to look up headers by name.This new method is available in the OSes released with Swift 5.1 (macOS 10.15/iOS and tvOS 13.0/watchOS 6.0). To backwards deploy on older OSes, using
(response.allHeaderFields as NSDictionary)[someHeaderName]
is a supported workaround that is expected to continue working in future OSes. The method was not included in Swift 5.1 or 5.2’s Corelibs Foundation, but as of SR-12300, it’s now in nightly snapshots and will probably be in Swift 5.3’s Corelibs Foundation.This bug has therefore been fixed by providing an alternate Swift-compatible API for the task. In the future, please use
value(forHTTPHeaderField:)
or, if necessary, theas NSDictionary
workaround to look up headers case-insensitively.Thanks!