Skip to content

Instantly share code, notes, and snippets.

@eMdOS
Last active February 15, 2017 18:05
Show Gist options
  • Save eMdOS/c515fdc63db8f1728fdc2c1b16ef05ad to your computer and use it in GitHub Desktop.
Save eMdOS/c515fdc63db8f1728fdc2c1b16ef05ad to your computer and use it in GitHub Desktop.
API service routing using based on Alamofire
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
}
}
}
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
}
}
}
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
}
import Foundation
public extension URLRequest {
var headers: [String: String]? {
set {
allHTTPHeaderFields = newValue
}
get {
return allHTTPHeaderFields
}
}
}
// 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