diff --git a/APIKit/RequestType.swift b/APIKit/RequestType.swift index 7eeedf9c..6f538416 100644 --- a/APIKit/RequestType.swift +++ b/APIKit/RequestType.swift @@ -16,7 +16,7 @@ public protocol RequestType { var baseURL: NSURL { get } var method: HTTPMethod { get } var path: String { get } - var parameters: [String: AnyObject] { get } + var parameters: [String: AnyObject?] { get } /// You can add any configurations here /// @@ -45,7 +45,7 @@ public protocol RequestType { /// Default implementation of RequestType protocol public extension RequestType { - public var parameters: [String: AnyObject] { + public var parameters: [String: AnyObject?] { return [:] } @@ -78,15 +78,16 @@ public extension RequestType { } let URLRequest = NSMutableURLRequest() - + let paramObject = parametersToAnyObject(parameters) + switch method { case .GET, .HEAD, .DELETE: if parameters.count > 0 { - components.percentEncodedQuery = URLEncodedSerialization.stringFromDictionary(parameters) + components.percentEncodedQuery = URLEncodedSerialization.stringFromDictionary(paramObject) } default: do { - URLRequest.HTTPBody = try requestBodyBuilder.buildBodyFromObject(parameters) + URLRequest.HTTPBody = try requestBodyBuilder.buildBodyFromObject(paramObject) } catch { return .Failure(.RequestBodySerializationError(error)) } @@ -133,3 +134,12 @@ public extension RequestType { return .Success(response) } } + +/// Convert `var parameters: [String: AnyObject?]` (non-AnyObject) to AnyObject using NSNull +private func parametersToAnyObject(parameters: [String: AnyObject?]) -> [String: AnyObject] { + var object = [String: AnyObject]() + for (key, value) in parameters { + object[key] = value ?? NSNull() + } + return object +} diff --git a/APIKit/URLEncodedSerialization.swift b/APIKit/URLEncodedSerialization.swift index 503afd4a..c3f34fc3 100644 --- a/APIKit/URLEncodedSerialization.swift +++ b/APIKit/URLEncodedSerialization.swift @@ -62,6 +62,10 @@ public final class URLEncodedSerialization { public static func stringFromDictionary(dictionary: [String: AnyObject]) -> String { let pairs = dictionary.map { key, value -> String in + guard (value is NSNull) == false else { + return "\(escape(key))" + } + let valueAsString = (value as? String) ?? "\(value)" return "\(escape(key))=\(escape(valueAsString))" } diff --git a/APIKitTests/RequestCreateTaskInURLSessionTests.swift b/APIKitTests/RequestCreateTaskInURLSessionTests.swift index 0ce36f1a..71d2fd46 100644 --- a/APIKitTests/RequestCreateTaskInURLSessionTests.swift +++ b/APIKitTests/RequestCreateTaskInURLSessionTests.swift @@ -18,7 +18,7 @@ class RequestCreateTaskInURLSessionTest: XCTestCase { var baseURL: NSURL { return NSURL(string: b)! } var method: HTTPMethod { return m } var path: String { return p } - var parameters: [String: AnyObject] { return params } + var parameters: [String: AnyObject?] { return params } func responseFromObject(object: AnyObject, URLResponse: NSHTTPURLResponse) -> Response? { return nil } } diff --git a/APIKitTests/RequestTests.swift b/APIKitTests/RequestTests.swift index 5cd34310..6ae18dad 100644 --- a/APIKitTests/RequestTests.swift +++ b/APIKitTests/RequestTests.swift @@ -17,9 +17,10 @@ class RequestTests: XCTestCase { return "/" } - var parameters: [String: AnyObject] { + var parameters: [String: AnyObject?] { return [ "q": query, + "dummy": nil ] } @@ -35,7 +36,7 @@ class RequestTests: XCTestCase { func testJapanesesURLQueryParameterEncoding() { OHHTTPStubs.stubRequestsPassingTest({ request in - XCTAssert(request.URL?.query == "q=%E3%81%93%E3%82%93%E3%81%AB%E3%81%A1%E3%81%AF") + XCTAssert(request.URL?.query == "q=%E3%81%93%E3%82%93%E3%81%AB%E3%81%A1%E3%81%AF&dummy") return true }, withStubResponse: { request in return OHHTTPStubsResponse(data: NSData(), statusCode: 200, headers: nil) @@ -53,7 +54,7 @@ class RequestTests: XCTestCase { func testSymbolURLQueryParameterEncoding() { OHHTTPStubs.stubRequestsPassingTest({ request in - XCTAssert(request.URL?.query == "q=%21%22%23%24%25%26%27%28%290%3D~%7C%60%7B%7D%2A%2B%3C%3E%3F_") + XCTAssert(request.URL?.query == "q=%21%22%23%24%25%26%27%28%290%3D~%7C%60%7B%7D%2A%2B%3C%3E%3F_&dummy") return true }, withStubResponse: { request in return OHHTTPStubsResponse(data: NSData(), statusCode: 200, headers: nil)