Last active
February 15, 2017 18:05
-
-
Save eMdOS/c515fdc63db8f1728fdc2c1b16ef05ad to your computer and use it in GitHub Desktop.
API service routing using based on Alamofire
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 | |
public enum APIError: Error { | |
case service(message: String) | |
} | |
extension APIError: CustomStringConvertible { | |
public var description: String { | |
switch self { | |
case .service(let message): | |
return message | |
} | |
} | |
} |
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 | |
import Alamofire | |
public protocol RouterProvider { | |
var path: String { get } | |
} | |
public enum Router<T>: URLRequestConvertible where T: RouterProvider { | |
case get(router: T, headers: [String: String]?) | |
case post(router: T, parameters: [String : Any], headers: [String: String]?) | |
public func asURLRequest() throws -> URLRequest { | |
var request = try URLRequest( | |
url: stringURL, | |
method: method | |
) | |
switch self { | |
case .get(_, let headers): | |
request.headers = headers | |
return try JSONEncoding.default.encode(request) | |
case .post(_, let parameters, let headers): | |
request.headers = headers | |
return try JSONEncoding.default.encode(request, with: parameters) | |
} | |
} | |
private var method: Alamofire.HTTPMethod { | |
switch self { | |
case .get: | |
return .get | |
case .post: | |
return .post | |
} | |
} | |
private var stringURL: String { | |
switch self { | |
case .get(let router, _): | |
return router.path | |
case .post(let router, _, _): | |
return router.path | |
} | |
} | |
} |
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 | |
import Alamofire | |
public typealias ServiceResponse = (succeeded: Any?, failed: Error?) | |
public typealias ServiceResponseHandler = ((ServiceResponse) -> Void) | |
public protocol Service { | |
var requestor: SessionManager { get } | |
var request: Request? { get set } | |
mutating func api(request: URLRequestConvertible, completion: ServiceResponseHandler?) | |
func cancel() | |
} | |
public extension Service { | |
public mutating func api(request: URLRequestConvertible, completion: ServiceResponseHandler?) { | |
Self.log(apiRequest: request, onState: .requesting) | |
self.request = requestor.request(request).validate().responseJSON { response in | |
if let jsonResponse = response.result.value, (response.result.error == nil) { | |
Self.log(apiRequest: request, onState: .succeeded) | |
completion?((succeeded: jsonResponse, failed: nil)) | |
} else if let error = response.result.error { | |
Self.log(apiRequest: request, onState: .failed) | |
completion?((succeeded: nil, failed: error)) | |
} | |
} | |
} | |
public func cancel() { | |
request?.cancel() | |
} | |
} | |
// MARK: - Logging | Debugging | |
fileprivate extension Service { | |
static func log(apiRequest request: URLRequestConvertible, onState state: RequestState) { | |
print("::") | |
print("::", state.rawValue.capitalized) | |
print("::", request.urlRequest?.url?.absoluteString ?? "... unknown URL") | |
print("::") | |
} | |
} | |
fileprivate enum RequestState: String { | |
case requesting, succeeded, failed | |
} |
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 | |
public extension URLRequest { | |
var headers: [String: String]? { | |
set { | |
allHTTPHeaderFields = newValue | |
} | |
get { | |
return allHTTPHeaderFields | |
} | |
} | |
} |
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
// Usage | |
// UserRouter.swift | |
enum UserRouter { | |
case signIn | |
case records(byID: String) | |
} | |
extension UserRouter: RouterProvider { | |
var path: String { | |
switch self { | |
case .signIn: | |
return baseURL + "/user/signIn" | |
case .records(let id): | |
return baseURL + "/user/records/\(id)" | |
} | |
} | |
} | |
fileprivate extension UserRouter { | |
var baseURL: String { | |
return "https://mock-api-service.com/v1" | |
} | |
} | |
// UserService.swift | |
protocol UserServiceProvider { | |
mutating func signIn(email: String, password: String, completionHandler: (_ succeeded: Bool) -> Void) | |
mutating func records(byID id: String, completionHandler: (_ succeeded: Bool) -> Void) | |
} | |
struct UserService: Service { | |
let requestor: SessionManager | |
var request: Request? | |
init(requestor: SessionManager) { | |
self.requestor = requestor | |
} | |
} | |
extension UserService: UserServiceProvider { | |
mutating func signIn(email: String, password: String, completionHandler: (Bool) -> Void) { | |
let parameters: Parameters = [ | |
"email": email, | |
"password": password | |
] | |
let headers: HTTPHeaders = [ | |
"Content-Type": "application/json" | |
] | |
api(request: Router<UserRouter>.post(router: .signIn, parameters: parameters, headers: headers)) { response in | |
// implementation | |
} | |
} | |
mutating func records(byID id: String, completionHandler: (Bool) -> Void) { | |
let headers: HTTPHeaders = [ | |
"secret-key": "mock-secret-key" | |
] | |
api(request: Router<UserRouter>.get(router: .records(byID: id), headers: headers)) { response in | |
// implementation | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment