Created
July 22, 2021 23:49
-
-
Save gauthierm/0451d58a61d9d1a1eb84d5162b68d8b6 to your computer and use it in GitHub Desktop.
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 ElasticSwiftCore | |
import Foundation | |
import Network | |
import Logging | |
import NIOHTTP1 | |
/** | |
Class maintaining URLSession for a Host | |
*/ | |
class SessionManager: NSObject, URLSessionDelegate { | |
private let logger = Logger(label: "org.emrap.ElasticSwift.Networking.SessionManager") | |
private var session: URLSession? | |
public let url: URL | |
init(forHost url: URL, config: URLSessionConfiguration? = nil) { | |
self.url = url | |
super.init() | |
let config: URLSessionConfiguration = config ?? URLSessionConfiguration.ephemeral | |
let queue = OperationQueue() | |
session = URLSession(configuration: config, delegate: self, delegateQueue: queue) | |
} | |
func makeReqeust(_ httpRequest: HTTPRequest) -> URLRequest { | |
var components = URLComponents() | |
components.queryItems = httpRequest.queryParams | |
components.path = httpRequest.path | |
let url = components.url(relativeTo: self.url) | |
var request = URLRequest(url: url!) | |
request.httpMethod = httpRequest.method.rawValue | |
request.httpBody = httpRequest.body | |
for header in httpRequest.headers { | |
request.addValue(header.value, forHTTPHeaderField: header.name) | |
} | |
return request | |
} | |
func execute(_ request: URLRequest, onCompletion callback: @escaping (_ data: Data?, _ response: URLResponse?, _ error: Error?) -> Void) { | |
let dataTask = session?.dataTask(with: request, completionHandler: callback) | |
dataTask?.resume() | |
} | |
/** | |
Closes current URLSession after finishing any outstanding tasks. | |
*/ | |
func close() { | |
session?.finishTasksAndInvalidate() | |
} | |
/** | |
Terminates current URLSession without finishing any outstanding tasks. | |
*/ | |
func forceClose() { | |
session?.invalidateAndCancel() | |
} | |
deinit { | |
self.session?.invalidateAndCancel() | |
logger.debug("session invalidated") | |
} | |
} | |
public final class URLSessionAdaptor: ManagedHTTPClientAdaptor { | |
private let logger = Logger(label: "org.emrap.ElasticSwfit.Networking.URLSessionAdaptor") | |
let sessionManager: SessionManager | |
public required init(forHost host: URL, adaptorConfig: HTTPAdaptorConfiguration = URLSessionAdaptorConfiguration.default) { | |
let config = adaptorConfig as! URLSessionAdaptorConfiguration | |
sessionManager = SessionManager(forHost: host, config: config.urlSessionConfiguration) | |
} | |
public func performRequest(_ request: HTTPRequest, callback: @escaping (Result<HTTPResponse, Error>) -> Void) { | |
let urlRequest = sessionManager.makeReqeust(request) | |
sessionManager.execute(urlRequest) { data, response, error in | |
guard error == nil else { | |
return callback(.failure(error!)) | |
} | |
let responseBuilder = HTTPResponseBuilder() | |
.set(request: request) | |
if let response = response as? HTTPURLResponse { | |
responseBuilder.set(status: HTTPResponseStatus(statusCode: response.statusCode)) | |
let headerDic = response.allHeaderFields as! [String: String] | |
var headers = HTTPHeaders() | |
for header in headerDic { | |
headers.add(name: header.key, value: header.value) | |
} | |
responseBuilder.set(headers: headers) | |
} | |
if let resData = data { | |
responseBuilder.set(body: resData) | |
} | |
do { | |
let httpResponse = try responseBuilder.build() | |
return callback(.success(httpResponse)) | |
} catch { | |
return callback(.failure(error)) | |
} | |
} | |
} | |
public var host: URL { | |
return sessionManager.url | |
} | |
} | |
// MARK: - URLSessionAdaptor Configuration | |
public class URLSessionAdaptorConfiguration: HTTPAdaptorConfiguration { | |
public let adaptor: ManagedHTTPClientAdaptor.Type | |
public let urlSessionConfiguration: URLSessionConfiguration? | |
public init(adaptor: ManagedHTTPClientAdaptor.Type = URLSessionAdaptor.self, urlSessionConfiguration: URLSessionConfiguration? = nil) { | |
self.adaptor = adaptor | |
self.urlSessionConfiguration = urlSessionConfiguration | |
} | |
public static var `default`: HTTPAdaptorConfiguration { | |
return URLSessionAdaptorConfiguration() | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment