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

[Issue 740] Fixed crash when multipart form data was uploaded from in-memory data.

Background sessions do not support uploads from data for obvious reasons. Solution was to add a check to the encoding logic to check whether the session was configuration as a background session. Also added tests to verify the logic now works without crashing.
Christian Noon 10 лет назад
Родитель
Сommit
441a9dca04
2 измененных файлов с 66 добавлено и 1 удалено
  1. 3 1
      Source/Upload.swift
  2. 63 0
      Tests/UploadTests.swift

+ 3 - 1
Source/Upload.swift

@@ -286,7 +286,9 @@ extension Manager {
             let URLRequestWithContentType = URLRequest.URLRequest
             URLRequestWithContentType.setValue(formData.contentType, forHTTPHeaderField: "Content-Type")
 
-            if formData.contentLength < encodingMemoryThreshold {
+            let isBackgroundSession = self.session.configuration.identifier != nil
+
+            if formData.contentLength < encodingMemoryThreshold && !isBackgroundSession {
                 do {
                     let data = try formData.encode()
                     let encodingResult = MultipartFormDataEncodingResult.Success(

+ 63 - 0
Tests/UploadTests.swift

@@ -583,6 +583,69 @@ class UploadMultipartFormDataTestCase: BaseTestCase {
         }
     }
 
+    func testThatUploadingMultipartFormDataOnBackgroundSessionWritesDataToFileToAvoidCrash() {
+        // Given
+        let identifier = "com.alamofire.uploadtests.\(NSUUID().UUIDString)"
+
+        let manager = Manager(
+            configuration: NSURLSessionConfiguration.backgroundSessionConfigurationWithIdentifier(identifier),
+            serverTrustPolicyManager: nil
+        )
+
+        let URLString = "https://httpbin.org/post"
+        let french = "français".dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)!
+        let japanese = "日本語".dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)!
+
+        let expectation = expectationWithDescription("multipart form data upload should succeed")
+
+        var request: NSURLRequest?
+        var response: NSHTTPURLResponse?
+        var data: NSData?
+        var error: ErrorType?
+        var streamingFromDisk: Bool?
+
+        // When
+        manager.upload(
+            .POST,
+            URLString,
+            multipartFormData: { multipartFormData in
+                multipartFormData.appendBodyPart(data: french, name: "french")
+                multipartFormData.appendBodyPart(data: japanese, name: "japanese")
+            },
+            encodingCompletion: { result in
+                switch result {
+                case let .Success(upload, uploadStreamingFromDisk, _):
+                    streamingFromDisk = uploadStreamingFromDisk
+
+                    upload.response { responseRequest, responseResponse, responseData, responseError in
+                        request = responseRequest
+                        response = responseResponse
+                        data = responseData
+                        error = responseError
+
+                        expectation.fulfill()
+                    }
+                case .Failure:
+                    expectation.fulfill()
+                }
+            }
+        )
+
+        waitForExpectationsWithTimeout(defaultTimeout, handler: nil)
+
+        // Then
+        XCTAssertNotNil(request, "request should not be nil")
+        XCTAssertNotNil(response, "response should not be nil")
+        XCTAssertNotNil(data, "data should not be nil")
+        XCTAssertNil(error, "error should be nil")
+
+        if let streamingFromDisk = streamingFromDisk {
+            XCTAssertTrue(streamingFromDisk, "streaming from disk should be true")
+        } else {
+            XCTFail("streaming from disk should not be nil")
+        }
+    }
+
     // MARK: Combined Test Execution
 
     private func executeMultipartFormDataUploadRequestWithProgress(streamFromDisk streamFromDisk: Bool) {