Просмотр исходного кода

Fixed up emptyResponseAllowed logic (#2770 and #2772)

* Fix emptyResponseAllowed logic.

* Update empty response logic and test.

* Whitespace cleanup.

* Add doc comment for URLRequest extension.

* Make all Results into AFResults for consistency.
Jon Shier 6 лет назад
Родитель
Сommit
b16877cdef

+ 0 - 32
Alamofire.xcodeproj/project.pbxproj

@@ -301,15 +301,6 @@
 		4CFB02FB1D7D2FA20056F249 /* valid_data.json in Resources */ = {isa = PBXBuildFile; fileRef = 4CFB02EC1D7D2FA20056F249 /* valid_data.json */; };
 		4CFB02FC1D7D2FA20056F249 /* valid_data.json in Resources */ = {isa = PBXBuildFile; fileRef = 4CFB02EC1D7D2FA20056F249 /* valid_data.json */; };
 		4CFB02FD1D7D2FA20056F249 /* valid_data.json in Resources */ = {isa = PBXBuildFile; fileRef = 4CFB02EC1D7D2FA20056F249 /* valid_data.json */; };
-		4CFB02FE1D7D2FA20056F249 /* empty.data in Resources */ = {isa = PBXBuildFile; fileRef = 4CFB02EE1D7D2FA20056F249 /* empty.data */; };
-		4CFB02FF1D7D2FA20056F249 /* empty.data in Resources */ = {isa = PBXBuildFile; fileRef = 4CFB02EE1D7D2FA20056F249 /* empty.data */; };
-		4CFB03001D7D2FA20056F249 /* empty.data in Resources */ = {isa = PBXBuildFile; fileRef = 4CFB02EE1D7D2FA20056F249 /* empty.data */; };
-		4CFB03011D7D2FA20056F249 /* invalid.data in Resources */ = {isa = PBXBuildFile; fileRef = 4CFB02EF1D7D2FA20056F249 /* invalid.data */; };
-		4CFB03021D7D2FA20056F249 /* invalid.data in Resources */ = {isa = PBXBuildFile; fileRef = 4CFB02EF1D7D2FA20056F249 /* invalid.data */; };
-		4CFB03031D7D2FA20056F249 /* invalid.data in Resources */ = {isa = PBXBuildFile; fileRef = 4CFB02EF1D7D2FA20056F249 /* invalid.data */; };
-		4CFB03041D7D2FA20056F249 /* valid.data in Resources */ = {isa = PBXBuildFile; fileRef = 4CFB02F01D7D2FA20056F249 /* valid.data */; };
-		4CFB03051D7D2FA20056F249 /* valid.data in Resources */ = {isa = PBXBuildFile; fileRef = 4CFB02F01D7D2FA20056F249 /* valid.data */; };
-		4CFB03061D7D2FA20056F249 /* valid.data in Resources */ = {isa = PBXBuildFile; fileRef = 4CFB02F01D7D2FA20056F249 /* valid.data */; };
 		4CFB03071D7D2FA20056F249 /* empty_string.txt in Resources */ = {isa = PBXBuildFile; fileRef = 4CFB02F21D7D2FA20056F249 /* empty_string.txt */; };
 		4CFB03081D7D2FA20056F249 /* empty_string.txt in Resources */ = {isa = PBXBuildFile; fileRef = 4CFB02F21D7D2FA20056F249 /* empty_string.txt */; };
 		4CFB03091D7D2FA20056F249 /* empty_string.txt in Resources */ = {isa = PBXBuildFile; fileRef = 4CFB02F21D7D2FA20056F249 /* empty_string.txt */; };
@@ -448,9 +439,6 @@
 		4CFB02EA1D7D2FA20056F249 /* empty_data.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = empty_data.json; sourceTree = "<group>"; };
 		4CFB02EB1D7D2FA20056F249 /* invalid_data.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = invalid_data.json; sourceTree = "<group>"; };
 		4CFB02EC1D7D2FA20056F249 /* valid_data.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = valid_data.json; sourceTree = "<group>"; };
-		4CFB02EE1D7D2FA20056F249 /* empty.data */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = empty.data; sourceTree = "<group>"; };
-		4CFB02EF1D7D2FA20056F249 /* invalid.data */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = invalid.data; sourceTree = "<group>"; };
-		4CFB02F01D7D2FA20056F249 /* valid.data */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = valid.data; sourceTree = "<group>"; };
 		4CFB02F21D7D2FA20056F249 /* empty_string.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = empty_string.txt; sourceTree = "<group>"; };
 		4CFB02F31D7D2FA20056F249 /* utf32_string.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = utf32_string.txt; sourceTree = "<group>"; };
 		4CFB02F41D7D2FA20056F249 /* utf8_string.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = utf8_string.txt; sourceTree = "<group>"; };
@@ -784,7 +772,6 @@
 			isa = PBXGroup;
 			children = (
 				4CFB02E91D7D2FA20056F249 /* JSON */,
-				4CFB02ED1D7D2FA20056F249 /* Property List */,
 				4CFB02F11D7D2FA20056F249 /* String */,
 			);
 			name = Responses;
@@ -801,16 +788,6 @@
 			path = JSON;
 			sourceTree = "<group>";
 		};
-		4CFB02ED1D7D2FA20056F249 /* Property List */ = {
-			isa = PBXGroup;
-			children = (
-				4CFB02EE1D7D2FA20056F249 /* empty.data */,
-				4CFB02EF1D7D2FA20056F249 /* invalid.data */,
-				4CFB02F01D7D2FA20056F249 /* valid.data */,
-			);
-			path = "Property List";
-			sourceTree = "<group>";
-		};
 		4CFB02F11D7D2FA20056F249 /* String */ = {
 			isa = PBXGroup;
 			children = (
@@ -1177,16 +1154,13 @@
 				4C743D051C22772D00BCB23E /* missing-dns-name-and-uri.cer in Resources */,
 				4C743CFB1C22772D00BCB23E /* randomGibberish.crt in Resources */,
 				4C743CFE1C22772D00BCB23E /* alamofire-signing-ca1.cer in Resources */,
-				4CFB03001D7D2FA20056F249 /* empty.data in Resources */,
 				4C743D001C22772D00BCB23E /* multiple-dns-names.cer in Resources */,
 				4C743D011C22772D00BCB23E /* signed-by-ca1.cer in Resources */,
-				4CFB03031D7D2FA20056F249 /* invalid.data in Resources */,
 				4C743D021C22772D00BCB23E /* test.alamofire.org.cer in Resources */,
 				4C743CF61C22772D00BCB23E /* certDER.cer in Resources */,
 				4C743CFD1C22772D00BCB23E /* alamofire-root-ca.cer in Resources */,
 				4C743CF91C22772D00BCB23E /* certPEM.cer in Resources */,
 				4CF627351BA7CC300011A099 /* unicorn.png in Resources */,
-				4CFB03061D7D2FA20056F249 /* valid.data in Resources */,
 				4C743CFA1C22772D00BCB23E /* certPEM.crt in Resources */,
 				4C743CF71C22772D00BCB23E /* certDER.crt in Resources */,
 				4CCB20711D4549E000C64D5B /* expired.badssl.com-root-ca.cer in Resources */,
@@ -1239,16 +1213,13 @@
 				4C743D311C22772F00BCB23E /* missing-dns-name-and-uri.cer in Resources */,
 				4C743D271C22772F00BCB23E /* randomGibberish.crt in Resources */,
 				4C743D2A1C22772F00BCB23E /* alamofire-signing-ca1.cer in Resources */,
-				4CFB02FE1D7D2FA20056F249 /* empty.data in Resources */,
 				4C743D2C1C22772F00BCB23E /* multiple-dns-names.cer in Resources */,
 				4C743D2D1C22772F00BCB23E /* signed-by-ca1.cer in Resources */,
-				4CFB03011D7D2FA20056F249 /* invalid.data in Resources */,
 				4C743D2E1C22772F00BCB23E /* test.alamofire.org.cer in Resources */,
 				4C743D221C22772F00BCB23E /* certDER.cer in Resources */,
 				4C743D291C22772F00BCB23E /* alamofire-root-ca.cer in Resources */,
 				4C743D251C22772F00BCB23E /* certPEM.cer in Resources */,
 				4C33A1391B5207DB00873DFF /* rainbow.jpg in Resources */,
-				4CFB03041D7D2FA20056F249 /* valid.data in Resources */,
 				4C743D261C22772F00BCB23E /* certPEM.crt in Resources */,
 				4C743D231C22772F00BCB23E /* certDER.crt in Resources */,
 				4CCB206F1D4549E000C64D5B /* expired.badssl.com-root-ca.cer in Resources */,
@@ -1280,16 +1251,13 @@
 				4C743D1B1C22772E00BCB23E /* missing-dns-name-and-uri.cer in Resources */,
 				4C743D111C22772E00BCB23E /* randomGibberish.crt in Resources */,
 				4C743D141C22772E00BCB23E /* alamofire-signing-ca1.cer in Resources */,
-				4CFB02FF1D7D2FA20056F249 /* empty.data in Resources */,
 				4C743D161C22772E00BCB23E /* multiple-dns-names.cer in Resources */,
 				4C743D171C22772E00BCB23E /* signed-by-ca1.cer in Resources */,
-				4CFB03021D7D2FA20056F249 /* invalid.data in Resources */,
 				4C743D181C22772E00BCB23E /* test.alamofire.org.cer in Resources */,
 				4C743D0C1C22772E00BCB23E /* certDER.cer in Resources */,
 				4C743D131C22772E00BCB23E /* alamofire-root-ca.cer in Resources */,
 				4C743D0F1C22772E00BCB23E /* certPEM.cer in Resources */,
 				4C33A13A1B5207DB00873DFF /* rainbow.jpg in Resources */,
-				4CFB03051D7D2FA20056F249 /* valid.data in Resources */,
 				4C743D101C22772E00BCB23E /* certPEM.crt in Resources */,
 				4C743D0D1C22772E00BCB23E /* certDER.crt in Resources */,
 				4CCB20701D4549E000C64D5B /* expired.badssl.com-root-ca.cer in Resources */,

+ 1 - 1
Source/ResponseSerialization.swift

@@ -69,7 +69,7 @@ extension ResponseSerializer {
     }
 
     public func emptyResponseAllowed(forRequest request: URLRequest?, response: HTTPURLResponse?) -> Bool {
-        return requestAllowsEmptyResponseData(request) ?? responseAllowsEmptyResponseData(response) ?? false
+        return (requestAllowsEmptyResponseData(request) == true) || (responseAllowsEmptyResponseData(response) == true)
     }
 }
 

+ 3 - 2
Source/URLRequest+Alamofire.swift

@@ -25,8 +25,9 @@
 import Foundation
 
 public extension URLRequest {
+    /// Returns the `httpMethod` as Alamofire's `HTTPMethod` type.
     var method: HTTPMethod? {
-        guard let httpMethod = httpMethod else { return nil }
-        return HTTPMethod(rawValue: httpMethod)
+        get { return httpMethod.flatMap(HTTPMethod.init) }
+        set { httpMethod = newValue?.rawValue }
     }
 }

+ 8 - 0
Tests/HTTPBin.swift

@@ -46,6 +46,14 @@ extension URLRequest {
 
         return request
     }
+
+    static func make(url: URL = URL(string: "https://httpbin.org/get")!, method: HTTPMethod = .get, headers: HTTPHeaders = .init()) -> URLRequest {
+        var request = URLRequest(url:url)
+        request.method = method
+        request.httpHeaders = headers
+
+        return request
+    }
 }
 
 extension Data {

+ 0 - 0
Tests/Resources/Responses/Property List/empty.data


+ 0 - 6
Tests/Resources/Responses/Property List/invalid.data

@@ -1,6 +0,0 @@
-this is not going
-"to" be happy json
-data at all
-{
-    "10": whoops
-}

+ 0 - 26
Tests/Resources/Responses/Property List/valid.data

@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
-	<key>CFBundleDevelopmentRegion</key>
-	<string>en</string>
-	<key>CFBundleExecutable</key>
-	<string>$(EXECUTABLE_NAME)</string>
-	<key>CFBundleIdentifier</key>
-	<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
-	<key>CFBundleInfoDictionaryVersion</key>
-	<string>6.0</string>
-	<key>CFBundleName</key>
-	<string>$(PRODUCT_NAME)</string>
-	<key>CFBundlePackageType</key>
-	<string>FMWK</string>
-	<key>CFBundleShortVersionString</key>
-	<string>4.0.0-beta.2</string>
-	<key>CFBundleSignature</key>
-	<string>????</string>
-	<key>CFBundleVersion</key>
-	<string>$(CURRENT_PROJECT_VERSION)</string>
-	<key>NSPrincipalClass</key>
-	<string></string>
-</dict>
-</plist>

+ 172 - 10
Tests/ResponseSerializationTests.swift

@@ -106,13 +106,52 @@ final class DataResponseSerializationTestCase: BaseTestCase {
         }
     }
 
-    func testThatDataResponseSerializerSucceedsWhenDataIsNilWithEmptyResponseStatusCode() {
+    func testThatDataResponseSerializerSucceedsWhenDataIsNilWithGETRequestAnd204ResponseStatusCode() {
         // Given
         let serializer = DataResponseSerializer()
+        let request = URLRequest.make(method: .get)
         let response = HTTPURLResponse(statusCode: 204)
 
         // When
-        let result = AFResult { try serializer.serialize(request: nil, response: response, data: nil, error: nil) }
+        let result = AFResult { try serializer.serialize(request: request, response: response, data: nil, error: nil) }
+
+        // Then
+        XCTAssertTrue(result.isSuccess)
+        XCTAssertNotNil(result.value)
+        XCTAssertNil(result.error)
+
+        if let data = result.value {
+            XCTAssertEqual(data.count, 0)
+        }
+    }
+
+    func testThatDataResponseSerializerSucceedsWhenDataIsNilWithGETRequestAnd205ResponseStatusCode() {
+        // Given
+        let serializer = DataResponseSerializer()
+        let request = URLRequest.make(method: .get)
+        let response = HTTPURLResponse(statusCode: 205)
+
+        // When
+        let result = AFResult { try serializer.serialize(request: request, response: response, data: nil, error: nil) }
+
+        // Then
+        XCTAssertTrue(result.isSuccess)
+        XCTAssertNotNil(result.value)
+        XCTAssertNil(result.error)
+
+        if let data = result.value {
+            XCTAssertEqual(data.count, 0)
+        }
+    }
+
+    func testThatDataResponseSerializerSucceedsWhenDataIsNilWithHEADRequestAnd200ResponseStatusCode() {
+        // Given
+        let serializer = DataResponseSerializer()
+        let request = URLRequest.make(method: .head)
+        let response = HTTPURLResponse(statusCode: 200)
+
+        // When
+        let result = AFResult { try serializer.serialize(request: request, response: response, data: nil, error: nil) }
 
         // Then
         XCTAssertTrue(result.isSuccess)
@@ -286,13 +325,52 @@ final class DataResponseSerializationTestCase: BaseTestCase {
         }
     }
 
-    func testThatStringResponseSerializerSucceedsWhenDataIsNilWithEmptyResponseStatusCode() {
+    func testThatStringResponseSerializerSucceedsWhenDataIsNilWithGETRequestAnd204ResponseStatusCode() {
+        // Given
+        let serializer = StringResponseSerializer()
+        let request = URLRequest.make(method: .get)
+        let response = HTTPURLResponse(statusCode: 204)
+
+        // When
+        let result = AFResult { try serializer.serialize(request: request, response: response, data: nil, error: nil) }
+
+        // Then
+        XCTAssertTrue(result.isSuccess)
+        XCTAssertNotNil(result.value)
+        XCTAssertNil(result.error)
+
+        if let string = result.value {
+            XCTAssertEqual(string, "")
+        }
+    }
+
+    func testThatStringResponseSerializerSucceedsWhenDataIsNilWithGETRequestAnd205ResponseStatusCode() {
         // Given
         let serializer = StringResponseSerializer()
+        let request = URLRequest.make(method: .get)
         let response = HTTPURLResponse(statusCode: 205)
 
         // When
-        let result = AFResult { try serializer.serialize(request: nil, response: response, data: nil, error: nil) }
+        let result = AFResult { try serializer.serialize(request: request, response: response, data: nil, error: nil) }
+
+        // Then
+        XCTAssertTrue(result.isSuccess)
+        XCTAssertNotNil(result.value)
+        XCTAssertNil(result.error)
+
+        if let string = result.value {
+            XCTAssertEqual(string, "")
+        }
+    }
+
+    func testThatStringResponseSerializerSucceedsWhenDataIsNilWithHEADRequestAnd200ResponseStatusCode() {
+        // Given
+        let serializer = StringResponseSerializer()
+        let request = URLRequest.make(method: .head)
+        let response = HTTPURLResponse(statusCode: 200)
+
+        // When
+        let result = AFResult { try serializer.serialize(request: request, response: response, data: nil, error: nil) }
 
         // Then
         XCTAssertTrue(result.isSuccess)
@@ -418,13 +496,56 @@ final class DataResponseSerializationTestCase: BaseTestCase {
         }
     }
 
-    func testThatJSONResponseSerializerSucceedsWhenDataIsNilWithEmptyResponseStatusCode() {
+    func testThatJSONResponseSerializerSucceedsWhenDataIsNilWithGETRequestAnd204ResponseStatusCode() {
         // Given
         let serializer = JSONResponseSerializer()
+        let request = URLRequest.make(method: .get)
         let response = HTTPURLResponse(statusCode: 204)
 
         // When
-        let result = AFResult { try serializer.serialize(request: nil, response: response, data: nil, error: nil) }
+        let result = AFResult { try serializer.serialize(request: request, response: response, data: nil, error: nil) }
+
+        // Then
+        XCTAssertTrue(result.isSuccess)
+        XCTAssertNotNil(result.value)
+        XCTAssertNil(result.error)
+
+        if let json = result.value as? NSNull {
+            XCTAssertEqual(json, NSNull())
+        } else {
+            XCTFail("json should not be nil")
+        }
+    }
+
+    func testThatJSONResponseSerializerSucceedsWhenDataIsNilWithGETRequestAnd205ResponseStatusCode() {
+        // Given
+        let serializer = JSONResponseSerializer()
+        let request = URLRequest.make(method: .get)
+        let response = HTTPURLResponse(statusCode: 205)
+
+        // When
+        let result = AFResult { try serializer.serialize(request: request, response: response, data: nil, error: nil) }
+
+        // Then
+        XCTAssertTrue(result.isSuccess)
+        XCTAssertNotNil(result.value)
+        XCTAssertNil(result.error)
+
+        if let json = result.value as? NSNull {
+            XCTAssertEqual(json, NSNull())
+        } else {
+            XCTFail("json should not be nil")
+        }
+    }
+
+    func testThatJSONResponseSerializerSucceedsWhenDataIsNilWithHEADRequestAnd200ResponseStatusCode() {
+        // Given
+        let serializer = JSONResponseSerializer()
+        let request = URLRequest.make(method: .head)
+        let response = HTTPURLResponse(statusCode: 200)
+
+        // When
+        let result = AFResult { try serializer.serialize(request: request, response: response, data: nil, error: nil) }
 
         // Then
         XCTAssertTrue(result.isSuccess)
@@ -593,6 +714,51 @@ final class DecodableResponseSerializerTests: BaseTestCase {
         XCTAssertNil(result.error)
     }
 
+    func testThatDecodableResponseSerializerSucceedsWhenDataIsNilWithGETRequestAnd204ResponseStatusCode() {
+        // Given
+        let serializer = DecodableResponseSerializer<Empty>()
+        let request = URLRequest.make(method: .get)
+        let response = HTTPURLResponse(statusCode: 204)
+
+        // When
+        let result = AFResult { try serializer.serialize(request: request, response: response, data: nil, error: nil) }
+
+        // Then
+        XCTAssertTrue(result.isSuccess)
+        XCTAssertNotNil(result.value)
+        XCTAssertNil(result.error)
+    }
+
+    func testThatDecodableResponseSerializerSucceedsWhenDataIsNilWithGETRequestAnd205ResponseStatusCode() {
+        // Given
+        let serializer = DecodableResponseSerializer<Empty>()
+        let request = URLRequest.make(method: .get)
+        let response = HTTPURLResponse(statusCode: 205)
+
+        // When
+        let result = AFResult { try serializer.serialize(request: request, response: response, data: nil, error: nil) }
+
+        // Then
+        XCTAssertTrue(result.isSuccess)
+        XCTAssertNotNil(result.value)
+        XCTAssertNil(result.error)
+    }
+
+    func testThatDecodableResponseSerializerSucceedsWhenDataIsNilWithHEADRequestAnd200ResponseStatusCode() {
+        // Given
+        let serializer = DecodableResponseSerializer<Empty>()
+        let request = URLRequest.make(method: .head)
+        let response = HTTPURLResponse(statusCode: 200)
+
+        // When
+        let result = AFResult { try serializer.serialize(request: request, response: response, data: nil, error: nil) }
+
+        // Then
+        XCTAssertTrue(result.isSuccess)
+        XCTAssertNotNil(result.value)
+        XCTAssertNil(result.error)
+    }
+
     func testThatDecodableResponseSerializerSucceedsWhenDataIsNilWithEmptyResponseConformingTypeAndEmptyResponseStatusCode() {
         // Given
         let serializer = DecodableResponseSerializer<Bool>()
@@ -640,10 +806,6 @@ final class DownloadResponseSerializationTestCase: BaseTestCase {
     private var jsonValidDataFileURL: URL { return url(forResource: "valid_data", withExtension: "json") }
     private var jsonInvalidDataFileURL: URL { return url(forResource: "invalid_data", withExtension: "json") }
 
-    private var plistEmptyDataFileURL: URL { return url(forResource: "empty", withExtension: "data") }
-    private var plistValidDataFileURL: URL { return url(forResource: "valid", withExtension: "data") }
-    private var plistInvalidDataFileURL: URL { return url(forResource: "invalid", withExtension: "data") }
-
     private var stringEmptyDataFileURL: URL { return url(forResource: "empty_string", withExtension: "txt") }
     private var stringUTF8DataFileURL: URL { return url(forResource: "utf8_string", withExtension: "txt") }
     private var stringUTF32DataFileURL: URL { return url(forResource: "utf32_string", withExtension: "txt") }