From d7f5543aebbb4375ff5432c3962e8b71b3b1d891 Mon Sep 17 00:00:00 2001 From: Jeremy Saklad Date: Fri, 24 Apr 2020 17:00:47 -0500 Subject: [PATCH] Fix errors on non-Darwin platforms 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. --- .../HTTPURLResponse+DateHeader.swift | 22 ++++++++++++++----- .../HTTPResponseDateTests.swift | 17 ++++++++++++++ 2 files changed, 33 insertions(+), 6 deletions(-) diff --git a/Sources/HTTPResponseDate/HTTPURLResponse+DateHeader.swift b/Sources/HTTPResponseDate/HTTPURLResponse+DateHeader.swift index 0bb3dcd..fe60b08 100644 --- a/Sources/HTTPResponseDate/HTTPURLResponse+DateHeader.swift +++ b/Sources/HTTPResponseDate/HTTPURLResponse+DateHeader.swift @@ -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 @@ -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 } } diff --git a/Tests/HTTPResponseDateTests/HTTPResponseDateTests.swift b/Tests/HTTPResponseDateTests/HTTPResponseDateTests.swift index 04e5248..822a8c4 100644 --- a/Tests/HTTPResponseDateTests/HTTPResponseDateTests.swift +++ b/Tests/HTTPResponseDateTests/HTTPResponseDateTests.swift @@ -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. /// @@ -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")!,