Add support for retrieving headers in canonical form
This commit is contained in:
parent
2a7066873a
commit
0803012b7a
|
@ -192,6 +192,23 @@ public struct HTTPHeaders : Sequence, CustomStringConvertible {
|
|||
public func makeIterator() -> AnyIterator<(name: String, value: String)> {
|
||||
return AnyIterator(HTTPHeadersIterator(wrapping: storage.makeIterator()))
|
||||
}
|
||||
|
||||
/// Retrieves the header values for the given header field in "canonical form": that is,
|
||||
/// splitting them on commas as extensively as possible such that multiple values received on the
|
||||
/// one line are returned as separate entries. Also respects the fact that Set-Cookie should not
|
||||
/// be split in this way.
|
||||
public func getCanonicalForm(_ name: String) -> [String] {
|
||||
// It's not safe to split Set-Cookie on comma.
|
||||
let queryName = name.lowercased()
|
||||
if queryName == "set-cookie" {
|
||||
return self[name]
|
||||
}
|
||||
|
||||
if let result = storage[queryName] {
|
||||
return result.map { tuple in tuple.1.split(separator: ",").map { substring in String(substring).trimmingCharacters(in: .whitespaces) } }.reduce([], +)
|
||||
}
|
||||
return []
|
||||
}
|
||||
}
|
||||
|
||||
extension HTTPHeaders : Equatable {
|
||||
|
|
|
@ -28,6 +28,9 @@ extension HTTPHeadersTest {
|
|||
return [
|
||||
("testCasePreservedButInsensitiveLookup", testCasePreservedButInsensitiveLookup),
|
||||
("testWriteHeadersSeparately", testWriteHeadersSeparately),
|
||||
("testRevealHeadersSeparately", testRevealHeadersSeparately),
|
||||
("testSubscriptDoesntSplitHeaders", testSubscriptDoesntSplitHeaders),
|
||||
("testCanonicalisationDoesntHappenForSetCookie", testCanonicalisationDoesntHappenForSetCookie),
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
|
@ -70,4 +70,43 @@ class HTTPHeadersTest : XCTestCase {
|
|||
XCTAssertTrue(writtenBytes.contains("set-cookie: foo=bar\r\n"))
|
||||
XCTAssertTrue(writtenBytes.contains("set-cookie: buz=cux\r\n"))
|
||||
}
|
||||
|
||||
func testRevealHeadersSeparately() {
|
||||
let originalHeaders = [ ("User-Agent", "1"),
|
||||
("host", "2"),
|
||||
("X-SOMETHING", "3, 4"),
|
||||
("X-Something", "5")]
|
||||
|
||||
let headers = HTTPHeaders(originalHeaders)
|
||||
XCTAssertEqual(headers.getCanonicalForm("user-agent"), ["1"])
|
||||
XCTAssertEqual(headers.getCanonicalForm("host"), ["2"])
|
||||
XCTAssertEqual(headers.getCanonicalForm("x-something"), ["3", "4", "5"])
|
||||
XCTAssertEqual(headers.getCanonicalForm("foo"), [])
|
||||
}
|
||||
|
||||
func testSubscriptDoesntSplitHeaders() {
|
||||
let originalHeaders = [ ("User-Agent", "1"),
|
||||
("host", "2"),
|
||||
("X-SOMETHING", "3, 4"),
|
||||
("X-Something", "5")]
|
||||
|
||||
let headers = HTTPHeaders(originalHeaders)
|
||||
XCTAssertEqual(headers["user-agent"], ["1"])
|
||||
XCTAssertEqual(headers["host"], ["2"])
|
||||
XCTAssertEqual(headers["x-something"], ["3, 4", "5"])
|
||||
XCTAssertEqual(headers["foo"], [])
|
||||
}
|
||||
|
||||
func testCanonicalisationDoesntHappenForSetCookie() {
|
||||
let originalHeaders = [ ("User-Agent", "1"),
|
||||
("host", "2"),
|
||||
("Set-Cookie", "foo=bar; expires=Sun, 17-Mar-2013 13:49:50 GMT"),
|
||||
("Set-Cookie", "buz=cux; expires=Fri, 13 Oct 2017 21:21:41 GMT")]
|
||||
|
||||
let headers = HTTPHeaders(originalHeaders)
|
||||
XCTAssertEqual(headers.getCanonicalForm("user-agent"), ["1"])
|
||||
XCTAssertEqual(headers.getCanonicalForm("host"), ["2"])
|
||||
XCTAssertEqual(headers.getCanonicalForm("set-cookie"), ["foo=bar; expires=Sun, 17-Mar-2013 13:49:50 GMT",
|
||||
"buz=cux; expires=Fri, 13 Oct 2017 21:21:41 GMT"])
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue