Last active
July 7, 2018 13:41
-
-
Save digoreis/bc1cbf2bf678a943cc2601111191b3d3 to your computer and use it in GitHub Desktop.
Simple DSL in Swift to Networking
This file contains hidden or 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 Cocoa | |
public typealias RestKitSuccess = (HTTPURLResponse, Data?) -> Void | |
public typealias RestKitFailure = (HTTPURLResponse, RestKitError) -> Void | |
public protocol RestKitProcess { | |
func process(_ request: URLRequest) -> URLRequest | |
} | |
public enum RestKitError: Error { | |
case httpError(Int) | |
} | |
public class RestKit { | |
public let methodHttp : RestKitMethod | |
public var urlString : String = "" | |
public var params = [RestKitParam]() | |
public var headers = [RestKitHeader]() | |
public var body: RestKitBody = .none | |
public var successCallback: RestKitSuccess? | |
public var failureCallback: RestKitFailure? | |
public var process: [RestKitProcess] = [RestKitProcess]() | |
public var task: URLSessionDataTask? | |
private let session: URLSession | |
public static func create(method: RestKitMethod, session: URLSession = URLSession.shared) -> RestKit { return RestKit(method: method, session: session) } | |
init(method: RestKitMethod, session: URLSession) { self.methodHttp = method ; self.session = session} | |
public var completeURL: String { return self.urlString.appending(params.reduce("?", { return "\($0)&\($1.generate())" })) } | |
} | |
public enum RestKitHeader { | |
case custom(String,String) | |
case authorization(String) | |
case basicAuth(String,String) | |
public func generate() -> (key: String,value: String) { | |
switch self { | |
case .custom(let k,let v): return (key: k, value: v) | |
case .authorization(let v): return (key: "Authorization", value: v) | |
case .basicAuth(let user,let passcode): | |
let crypto = "\(user):\(passcode)" | |
let final = Data(crypto.utf8).base64EncodedString() | |
let v = "Basic \(final)" | |
return (key: "Authorization", value: v) | |
} | |
} | |
} | |
public enum RestKitBody { | |
case body(Data) | |
case none | |
public func toData() -> Data? { | |
switch self { | |
case .body(let value): return value | |
case .none: return nil | |
} | |
} | |
public func toString() -> String { | |
switch self { | |
case .body(let value): return String(data: value, encoding: .utf8) ?? "" | |
case .none: return "" | |
} | |
} | |
} | |
public enum RestKitMethod : CustomStringConvertible { | |
case get,post,put,delete,head | |
public var description: String { | |
switch self { | |
case .get: return "GET" | |
case .post: return "POST" | |
case .put: return "PUT" | |
case .delete: return "DELETE" | |
case .head: return "HEAD" | |
} | |
} | |
} | |
public enum RestKitParam { | |
case stringValue(String,String) | |
case intValue(String,Int) | |
} | |
public extension RestKitParam { | |
func generate() -> String { | |
switch self { | |
case .stringValue(let key, let value): | |
let keyString = key | |
let valueString = value.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed) ?? value | |
return "\(keyString)=\(valueString)" | |
case .intValue(let key, let value): | |
let keyString = key | |
let valueString = "\(value)" | |
return "\(keyString)=\(valueString)" | |
} | |
} | |
} | |
public extension RestKit { | |
public func url(_ url: String) -> RestKit { | |
self.urlString = url | |
return self | |
} | |
public func param(_ param: RestKitParam) -> RestKit { | |
self.params.append(param) | |
return self | |
} | |
public func body<T : Encodable>(_ body: T) -> RestKit { | |
let encoder = JSONEncoder() | |
if let data = try? encoder.encode(body) { | |
self.body = .body(data) | |
} | |
return self | |
} | |
public func header(_ header: RestKitHeader) -> RestKit { | |
self.headers.append(header) | |
return self | |
} | |
public func success(_ callback: @escaping RestKitSuccess) -> RestKit { | |
self.successCallback = callback | |
return self | |
} | |
public func failure(_ callback: @escaping RestKitFailure) -> RestKit { | |
self.failureCallback = callback | |
return self | |
} | |
} | |
public extension RestKit { | |
public func execute() -> Void { | |
guard let url = URL(string: completeURL) else { return } | |
var request = URLRequest(url: url) | |
request.httpMethod = String(describing: self.methodHttp) | |
request.httpBody = self.body.toData() | |
request = self.headers.reduce(request, { (result, header) -> URLRequest in | |
var newRequest = request | |
let h = header.generate() | |
newRequest.addValue(h.value, forHTTPHeaderField: h.key) | |
return newRequest | |
}) | |
request = self.process.reduce(request, { (result, process) -> URLRequest in | |
return process.process(result) | |
}) | |
self.task = self.session.dataTask(with: request) { (responseData, response, responseError) in | |
guard let response = response, let httpResponse = response as? HTTPURLResponse else { return } | |
self.task = nil | |
if let _ = responseError { | |
self.failureCallback?(httpResponse,.httpError(httpResponse.statusCode)) | |
return | |
} | |
self.successCallback?(httpResponse,responseData) | |
} | |
self.task?.resume() | |
} | |
} | |
struct Proposal: Codable { | |
let title: String | |
} | |
let baseURL = "https://data.swift.org/swift-evolution/proposals" | |
var rest = RestKit.create(method: .get) | |
.url(baseURL) | |
.success({ response, proposals in | |
let str = String(data: proposals!, encoding: .utf8) ?? "Proposals empty" | |
print(str) | |
}) | |
.failure { (response, error) in | |
print(response) | |
} | |
rest.execute() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
//
// ViewController.swift
// TestForRestKit
//
// Created by Rodrigo Reis on 13/04/18.
// Copyright © 2018 Rodrigo Reis. All rights reserved.
//
import UIKit
extension Date {
func toMillis() -> Int64 {
return Int64(self.timeIntervalSince1970 * 1000)
}
}
class ViewController: UIViewController {
}