public typealias NetworkCompletion = ((_ result: Response) -> Void)? public enum Method: String { case OPTIONS, GET, HEAD, POST, PUT, PATCH, DELETE, TRACE, CONNECT } public class Request { fileprivate var headers: [String: String] = ["Content-Type": "application/json"] fileprivate var task : URLSessionDataTask! public init() { } public func send(method: Method, url: String, parameter: [String: Any], completion: NetworkCompletion) { if method == .GET { requestData(method: method, url: url, queryParameters: parameter, completion: completion) } else { requestData(method: method, url: url, bodyParameters: parameter, completion: completion) } } public func setHeaders(key:String, value:String) { headers = [key: value] } public func cancelTask() { guard task != nil else {return} task.cancel() } /** MARK: - Private Methods */ private func requestData(method: Method, url:String, queryParameters: [String: Any]? = nil, bodyParameters: [String: Any]? = nil, completion: NetworkCompletion) { let url = URL(string: url, relativeTo: URL(string:"https://api.github.com/"))! do { let request = try createURLRequest(url: url, method: method.rawValue, queryParameters: queryParameters, bodyParameters: bodyParameters, headers: headers) task = URLSession.sessionDefault.dataTask(with: request, completionHandler: { (data, response, error) in return self.parseTo(data, request: request, response: response, error: error, completion: completion) }) task.resume() } catch { completion?(Response(request: nil, response: nil, data: nil, result: Result.failure(error))) } } private func createURLRequest(url: URL, method: String, queryParameters: [String: Any]?, bodyParameters: [String: Any]?, headers: [String: String]?) throws -> URLRequest { var actualURL: URL = url if let queryParameters = queryParameters { var components = URLComponents(url: url, resolvingAgainstBaseURL: true)! components.queryItems = queryParameters.map { (key, value) in URLQueryItem(name: key, value: value as? String) } actualURL = components.url! } print(actualURL) var request = URLRequest(url: actualURL) request.httpMethod = method if let bodyParameters = bodyParameters { request.httpBody = try JSONSerialization.data(withJSONObject: bodyParameters, options: []) } if let headers = headers { for (field, value) in headers { request.addValue(value, forHTTPHeaderField: field) } } return request } private func parseTo(_ data: Data?, request: URLRequest, response:URLResponse?, error: Error?, completion: NetworkCompletion) { //todo: Não ficou bom isso guard error == nil else { completion?(Response(request: request, response: response as? HTTPURLResponse, data: nil, result: Result.failure(error!))) return } //todo: e nem isso guard data != nil else { completion?(Response(request: request, response: response as? HTTPURLResponse, data: nil, result: Result.failure(error!))) return } completion?(Response(request: request, response: response as? HTTPURLResponse, data: data, result: Result.success(data))) } }