Skip to content

Commit

Permalink
Fix errors on non-Darwin platforms
Browse files Browse the repository at this point in the history
HTTPURLResponse is part of FoundationNetworking instead of Foundation on non-Darwin platforms.
HTTPURLResponse.init is not accessible in FoundationNetworking, so init(url:statusCode:httpVersion:headerfields:) must be used to test for a missing date header.
HTTPURLResponse.value(forHTTPHeaderField:) is not present in the current release of FoundationNetworking, and allHeaderFields uses keys with different capitalization than the Foundation version. Fixes for both have been implemented in Swift 5.3.
Extraneous whitespace has been removed.
  • Loading branch information
Saklad5 committed Apr 24, 2020
1 parent 3ff1139 commit d7f5543
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 6 deletions.
22 changes: 16 additions & 6 deletions Sources/HTTPResponseDate/HTTPURLResponse+DateHeader.swift
Original file line number Diff line number Diff line change
@@ -1,17 +1,21 @@
import Foundation

#if canImport(FoundationNetworking)
import class FoundationNetworking.HTTPURLResponse
#endif

public extension HTTPURLResponse {
private static let dateFormatters = [
// GMT is required in all timestamps, but section 19.3 of RFC 2616 requires clients to convert timestamps incorrectly given with a different time zone into GMT.

// RFC 1123
"EEE, dd MMM yyyy HH:mm:ss z",

// RFC 850
"EEEE, dd-MMM-yy HH:mm:ss z",

// ANSI C's asctime() format
"EEE MMM d HH:mm:ss yyyy"
"EEE MMM d HH:mm:ss yyyy",
]
.lazy // It's very unlikely that any DateFormatter beyond the first will be necessary.
.map { formatString -> DateFormatter in
Expand All @@ -21,27 +25,33 @@ public extension HTTPURLResponse {
formatter.dateFormat = formatString
return formatter
}

/// The date that the response was sent.
/// - Note: This is parsed from the `date` header of the response according to [RFC 2616](https://tools.ietf.org/html/rfc2616#section-3.3.1).
var date: Date? {
// Servers are required to send a date header whenever possible. It isn't always possible.
let dateValue: String?

#if canImport(FoundationNetworking) && swift(<5.3) // See https://bugs.swift.org/browse/SR-12300
dateValue = allHeaderFields["date"] as? String
#else
if #available(iOS 13, macCatalyst 13, OSX 10.15, tvOS 13, watchOS 6, *) {
dateValue = value(forHTTPHeaderField: "date")
} else {
dateValue = allHeaderFields["Date"] as? String
}
#endif

guard let dateString = dateValue else {
return nil
}

for dateFormatter in Self.dateFormatters {
if let date = dateFormatter.date(from: dateString) {
return date
}
}

return nil
}
}
17 changes: 17 additions & 0 deletions Tests/HTTPResponseDateTests/HTTPResponseDateTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@ import Foundation
import HTTPResponseDate
import XCTest

#if canImport(FoundationNetworking)
import class FoundationNetworking.HTTPURLResponse
#endif

final class HTTPResponseDateTests: XCTestCase {
/// A set of dates along with an `HTTPURLResponse` for each supported `date` header representation of them.
///
Expand Down Expand Up @@ -153,7 +157,20 @@ final class HTTPResponseDateTests: XCTestCase {
}

func testMalformedTimestampParsing() {
#if canImport(FoundationNetworking) // HTTPURLResponse.init isn't present in FoundationNetworking
XCTAssertNil(
HTTPURLResponse(
url: URL(string: "example.com")!,
statusCode: 0,
httpVersion: nil,
headerFields: nil
)!
.date
)
#else
XCTAssertNil(HTTPURLResponse().date)
#endif

XCTAssertNil(
HTTPURLResponse(
url: URL(string: "example.com")!,
Expand Down

0 comments on commit d7f5543

Please sign in to comment.