Skip to content
This repository has been archived by the owner on Aug 20, 2018. It is now read-only.

'Cancel' for PromiseKit option 2 #10

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions Cartfile
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
github "mxcl/PromiseKit" ~> 6.3
#github "mxcl/PromiseKit" ~> 6.3
github "dougzilla32/PromiseKit" "PMKCancel"
github "mxcl/OMGHTTPURLRQ" ~> 3.2
github "PromiseKit/Foundation" ~> 3.1
#github "PromiseKit/Foundation" ~> 3.1
github "dougzilla32/Foundation" "PMKCancel"
#github "PromiseKit/Cancel" ~> 1.0
github "dougzilla32/Cancel" ~> 1.0
5 changes: 3 additions & 2 deletions Cartfile.resolved
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
github "AliSoftware/OHHTTPStubs" "6.1.0"
github "PromiseKit/Foundation" "3.1.0"
github "dougzilla32/Cancel" "1.0.0"
github "dougzilla32/Foundation" "1d0f84d4ae50db696feeb050f9dd9ebb90fd59be"
github "dougzilla32/PromiseKit" "a0217bd7b69af68237dcdeee0197e63259b9d445"
github "mxcl/OMGHTTPURLRQ" "3.2.5"
github "mxcl/PromiseKit" "6.3.3"
1 change: 1 addition & 0 deletions PMKOMGHTTPURLRQ.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,7 @@
OMGHTTPURLRQ,
OHHTTPStubs,
PMKFoundation,
PMKCancel,
);
name = "Embed Carthage Frameworks";
outputPaths = (
Expand Down
154 changes: 154 additions & 0 deletions Sources/NSURLSession+OMG+Promise.swift
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import OMGHTTPURLRQ
import Foundation
#if !PMKCocoaPods
import PMKCancel
import PMKFoundation
import PromiseKit
#endif
Expand Down Expand Up @@ -168,3 +169,156 @@ extension URLSession {
}
}
}

//////////////////////////////////////////////////////////// Cancellation

extension URLSession {
/**
Makes a cancellable **GET** request to the provided URL.

let p = URLSession.shared.GET("http://example.com", query: ["foo": "bar"])
p.then { data -> Void in
//…
}
p.asImage().then { image -> Void in
//…
}
p.asDictionary().then { json -> Void in
//…
}

- Parameter url: The URL to request.
- Parameter query: The parameters to be encoded as the query string for the GET request.
- Returns: A cancellable promise that represents the GET request.
*/
public func GETCC(_ url: String, query: [String: Any]? = nil) -> CancellablePromise<(data: Data, response: URLResponse)> {
return startCC(try OMGHTTPURLRQ.get(url, query) as URLRequest)
}

/**
Makes a cancellable POST request to the provided URL passing form URL encoded
parameters.

Form URL-encoding is the standard way to POST on the Internet, so
probably this is what you want. If it doesn’t work, try the `+POST:JSON`
variant.

let url = "http://jsonplaceholder.typicode.com/posts"
let params = ["title": "foo", "body": "bar", "userId": 1]
URLSession.shared.POST(url, formData: params).asDictionary().then { json -> Void in
//…
}

- Parameter url: The URL to request.
- Parameter formData: The parameters to be form URL-encoded and passed as the POST body.
- Returns: A cancellable promise that represents the POST request.
*/
public func POSTCC(_ url: String, formData: [String: Any]? = nil) -> CancellablePromise<(data: Data, response: URLResponse)> {
return startCC(try OMGHTTPURLRQ.post(url, formData) as URLRequest)
}

/**
Makes a cancellable POST request to the provided URL passing multipart form-data.

let formData = OMGMultipartFormData()
let imgData = Data(contentsOfFile: "image.png")
formData.addFile(imgdata, parameterName: "file1", filename: "myimage1.png", contentType: "image/png")

URLSession.shared.POST(url, multipartFormData: formData).then { data in
//…
}

- Parameter url: The URL to request.
- Parameter multipartFormData: The parameters to be multipart form-data encoded and passed as the POST body.
- Returns: A cancellable promise that represents the POST request.
- SeeAlso: [https://github.com/mxcl/OMGHTTPURLRQ](OMGHTTPURLRQ)
*/
public func POSTCC(_ url: String, multipartFormData: OMGMultipartFormData) -> CancellablePromise<(data: Data, response: URLResponse)> {
return startCC(try OMGHTTPURLRQ.post(url, multipartFormData) as URLRequest)
}

/**
Makes a cancellable POST request to the provided URL passing JSON encoded
parameters.

Most web servers nowadays support POST with either JSON or form
URL-encoding. If in doubt try form URL-encoded parameters first.

let url = "http://jsonplaceholder.typicode.com/posts"
let params = ["title": "foo", "body": "bar", "userId": 1]
URLSession.shared.POST(url, json: params).asDictionary().then { json -> Void in
//…
}

- Parameter url: The URL to request.
- Parameter json: The parameters to be JSON-encoded and passed as the POST body.
- Returns: A cancellable promise that represents the POST request.
*/
public func POSTCC(_ url: String, json: [String: Any]? = nil) -> CancellablePromise<(data: Data, response: URLResponse)> {
return startCC(try OMGHTTPURLRQ.post(url, json: json) as URLRequest)
}

/**
Makes a cancellable PUT request to the provided URL passing JSON encoded parameters.

let url = "http://jsonplaceholder.typicode.com/posts"
let params = ["title": "foo", "body": "bar", "userId": 1]
URLSession.shared.PUT(url, json: params).asDictionary().then { json -> Void in
//…
}

- Parameter url: The URL to request.
- Parameter json: The parameters to be JSON-encoded and passed as the PUT body.
- Returns: A cancellable promise that represents the PUT request.
*/
public func PUTCC(_ url: String, json: [String: Any]? = nil) -> CancellablePromise<(data: Data, response: URLResponse)> {
return startCC(try OMGHTTPURLRQ.put(url, json: json) as URLRequest)
}

/**
Makes a cancellable DELETE request to the provided URL passing form URL-encoded
parameters.

let url = "http://jsonplaceholder.typicode.com/posts/1"
URLSession.shared.DELETE(url).then.asDictionary() { json -> Void in
//…
}

- Parameter url: The URL to request.
- Returns: A cancellable promise that represents the PUT request.
*/
public func DELETECC(_ url: String) -> CancellablePromise<(data: Data, response: URLResponse)> {
return startCC(try OMGHTTPURLRQ.delete(url, nil) as URLRequest)
}

/**
Makes a cancellable PATCH request to the provided URL passing the provided JSON parameters.

let url = "http://jsonplaceholder.typicode.com/posts/1"
let params = ["foo": "bar"]
NSURLConnection.PATCH(url, json: params).asDictionary().then { json -> Void in
//…
}
- Parameter url: The URL to request.
- Parameter json: The JSON parameters to encode as the PATCH body.
- Returns: A cancellable promise that represents the PUT request.
*/
public func PATCHCC(_ url: String, json: [String: Any]? = nil) -> CancellablePromise<(data: Data, response: URLResponse)> {
return startCC(try OMGHTTPURLRQ.patch(url, json: json) as URLRequest)
}

private func startCC(_ body: @autoclosure () throws -> URLRequest) -> CancellablePromise<(data: Data, response: URLResponse)> {
do {
var request = try body()

if request.value(forHTTPHeaderField: "User-Agent") == nil {
request.setValue(OMGUserAgent(), forHTTPHeaderField: "User-Agent")
}

return dataTaskCC(.promise, with: request)
} catch {
return CancellablePromise(error: error)
}
}
}

79 changes: 79 additions & 0 deletions Tests/TestNSURLSession.swift
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import PMKCancel
import PMKOMGHTTPURLRQ
import OHHTTPStubs
import PromiseKit
Expand Down Expand Up @@ -72,3 +73,81 @@ class NSURLSessionTests: XCTestCase {
OHHTTPStubs.removeAllStubs()
}
}

//////////////////////////////////////////////////////////// Cancellation

extension NSURLSessionTests {
func testCancel1() {
let json: NSDictionary = ["key1": "value1", "key2": ["value2A", "value2B"]]

OHHTTPStubs.stubRequests(passingTest: { $0.url!.host == "example.com" }) { _ in
return OHHTTPStubsResponse(jsonObject: json, statusCode: 200, headers: nil)
}

let ex = expectation(description: "")
URLSession.shared.GETCC("http://example.com").compactMap {
XCTFail()
try JSONSerialization.jsonObject(with: $0.data)
}.done {
XCTAssertEqual(json, $0 as? NSDictionary)
XCTFail()
}.catch(policy: .allErrors) {
$0.isCancelled ? ex.fulfill() : XCTFail()
}.cancel()
waitForExpectations(timeout: 1)
}

func testCancel2() {

// test that Promise<Data> chains thens
// this test because I don’t trust the Swift compiler

let dummy = ("fred" as NSString).data(using: String.Encoding.utf8.rawValue)!

OHHTTPStubs.stubRequests(passingTest: { $0.url!.host == "example.com" }) { _ in
return OHHTTPStubsResponse(data: dummy, statusCode: 200, headers: [:])
}

let ex = expectation(description: "")

afterCC(seconds: 0.1).then { () -> CancellablePromise<(data: Data, response: URLResponse)> in
let p = URLSession.shared.GETCC("http://example.com")
p.cancel()
return p
}.done {
XCTAssertEqual($0.data, dummy)
XCTFail()
}.catch(policy: .allErrors) {
$0.isCancelled ? ex.fulfill() : XCTFail()
}

waitForExpectations(timeout: 1)
}

func testCancelSyntax() {
let json: NSDictionary = ["key1": "value1", "key2": ["value2A", "value2B"]]

OHHTTPStubs.stubRequests(passingTest: {
$0.url!.host == "example.com"
}, withStubResponse: { _ in
OHHTTPStubsResponse(jsonObject: json, statusCode: 200, headers: nil)
})

let p = URLSession.shared.GETCC("http://example.com", query: [
"1": 1,
"2": 2
])

let ex = expectation(description: "")
p.compactMap {
p.cancel()
try JSONSerialization.jsonObject(with: $0.data)
}.done {
XCTAssertEqual(json, $0 as? NSDictionary)
XCTFail()
}.catch(policy: .allErrors) {
$0.isCancelled ? ex.fulfill() : XCTFail()
}
waitForExpectations(timeout: 1)
}
}