diff --git a/NetworkingTests/Webservice/WebserviceTests.swift b/NetworkingTests/Webservice/WebserviceTests.swift index aac4c2b..bf5c6eb 100644 --- a/NetworkingTests/Webservice/WebserviceTests.swift +++ b/NetworkingTests/Webservice/WebserviceTests.swift @@ -184,4 +184,44 @@ final class WebserviceTests: XCTestCase { waitForExpectations(timeout: 0.1, handler: nil) } + + struct CancelRequestBehavior: RequestBehavior { + func allowCompletion(data: Data?, response: URLResponse?, error: Error?) -> Bool { + return false + } + + func after(completion result: Result) { + switch result { + case .success: + XCTFail("should not get called") + case .failure(let error): + if case Webservice.Error.cancelled = error { + print("request cancelled") + } else { + XCTFail("incorrect error") + } + } + } + } + + func testCancelledBehavior() { + + let sessionMock = URLSessionDataTaskLoaderFake(data: nil, + response: HTTPURLResponse(url: URL.fake(), + statusCode: 200, + httpVersion: nil, + headerFields: nil), + error: nil) + + webservice = Webservice(baseURL: URL.fake(), + session: sessionMock, + defaultRequestBehavior: CancelRequestBehavior()) + + let resource = Resource(endpoint: "/", decoder: EmptyDecoder()) + + webservice.load(resource) { _ in + XCTFail("completion should not get called") + } + } } + diff --git a/Sources/Webservice/Requests/RequestBehavior.swift b/Sources/Webservice/Requests/RequestBehavior.swift index 091f4e2..2a801ae 100644 --- a/Sources/Webservice/Requests/RequestBehavior.swift +++ b/Sources/Webservice/Requests/RequestBehavior.swift @@ -4,16 +4,17 @@ public protocol RequestBehavior { func modify(urlComponents: URLComponents) -> URLComponents func modify(planned request: URLRequest) -> URLRequest func before(sending request: URLRequest) - func modifyResponse(data: Data?, response: URLResponse?, error: Error?) -> (Data?, URLResponse?, Error?) + func allowCompletion(data: Data?, response: URLResponse?, error: Error?) -> Bool func after(completion result: Result) + } public extension RequestBehavior { func modify(urlComponents: URLComponents) -> URLComponents { return urlComponents } func modify(planned request: URLRequest) -> URLRequest { return request } func before(sending: URLRequest) {} - + func allowCompletion(data: Data?, response: URLResponse?, error: Error?) -> Bool { return true } func modifyResponse(data: Data?, response: URLResponse?, error: Error?) -> (Data?, URLResponse?, Error?) { return (data, response, error) } func after(completion result: Result) {} @@ -74,4 +75,13 @@ private struct CompoundRequestBehavior: RequestBehavior { $0.after(completion: result) } } + + func allowCompletion(data: Data?, response: URLResponse?, error: Error?) -> Bool { + for behaviour in behaviors { + if !behaviour.allowCompletion(data: data, response: response, error: error) { + return false + } + } + return true + } } diff --git a/Sources/Webservice/Webservice.swift b/Sources/Webservice/Webservice.swift index ed364c7..559354e 100644 --- a/Sources/Webservice/Webservice.swift +++ b/Sources/Webservice/Webservice.swift @@ -14,6 +14,7 @@ public struct Webservice: ResourceRequestable { public enum Error: Swift.Error { case http(HTTP.StatusCode, Swift.Error?) case unknown(Swift.Error?) + case cancelled } private let baseURL: URL @@ -42,6 +43,12 @@ public struct Webservice: ResourceRequestable { requestBehavior.before(sending: request) session.dataTask(with: request) { data, response, error in + + guard requestBehavior.allowCompletion(data: data, response: response, error: error) else { + requestBehavior.after(completion: Result.failure(Error.cancelled)) + return + } + let (data, response, error) = requestBehavior.modifyResponse(data: data, response: response, error: error)