Last active
May 28, 2017 22:42
-
-
Save a-voronov/d6368e7df0828e36c4aa157a6792d250 to your computer and use it in GitHub Desktop.
Lightweight Networking Abstraction Layer
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
// MARK: - Commons Level | |
protocol Cancellable { | |
func cancel() | |
} | |
enum Result<T, E: Error> { | |
case success(T) | |
case failure(E) | |
} | |
// MARK: - Api Service Level | |
enum ApiRequestParametersEncoding { | |
case json | |
case url | |
case form | |
} | |
enum ApiRequestMethod: String { | |
case head = "HEAD" | |
case get = "GET" | |
case post = "POST" | |
case put = "PUT" | |
case delete = "DELETE" | |
case patch = "PATCH" | |
} | |
class ApiRequest { | |
var url: () -> NSURL | |
var method: ApiRequestMethod | |
var params: [String: AnyObject] | |
var encoding: ApiRequestParametersEncoding | |
var headers: [String: String] | |
init( | |
url: @escaping () -> NSURL, | |
method: ApiRequestMethod, | |
encoding: ApiRequestParametersEncoding, | |
params: [String: AnyObject] = [:], | |
headers: [String: String] = [:] | |
) { | |
self.url = url | |
self.method = method | |
self.params = params | |
self.encoding = encoding | |
self.headers = headers | |
} | |
} | |
typealias ApiRequestProvider = () -> ApiRequest | |
struct ApiResponse<T> { | |
let value: T | |
let response: HTTPURLResponse? | |
} | |
struct ApiResponseError<E: Error>: Error { | |
let error: E | |
let response: HTTPURLResponse? | |
} | |
typealias ApiResponseCallback = (Result<ApiResponse<NSData?>, ApiResponseError<NSError>>) -> Void | |
protocol ApiService { | |
func makeRequest(request: ApiRequestProvider, callback: ApiResponseCallback) -> Cancellable | |
} | |
// MARK: - Api Router Level | |
protocol ApiRouter { | |
var request: ApiRequestProvider { get } | |
} | |
// MARK: - Promise Extension (https://gist.github.com/a-voronov/ad0d62f2f465dcd785016cb95d2f4578) | |
extension Promise: Cancellable {} | |
typealias ApiResponsePromise = Promise<ApiResponse<NSData?>, ApiResponseError<NSError>> | |
extension ApiService { | |
func makeRequest(request: ApiRequestProvider) -> ApiResponsePromise { | |
return Promise { (fulfill, reject, onCancel) in | |
let cancellableRequest = makeRequest(request: request) { result in | |
switch result { | |
case let .success(value): fulfill(value) | |
case let .failure(reason): reject(reason) | |
} | |
} | |
onCancel(cancellableRequest.cancel) | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
ApiService makeRequest implementation only needed and it can be anything, like NSURLSession or Alamofire library.
Validation, parsing and other stuff before giving back data can be wrapped into a nice pipeline if using promises