Skip to content

Instantly share code, notes, and snippets.

@gauthierm
Created July 22, 2021 23:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gauthierm/0451d58a61d9d1a1eb84d5162b68d8b6 to your computer and use it in GitHub Desktop.
Save gauthierm/0451d58a61d9d1a1eb84d5162b68d8b6 to your computer and use it in GitHub Desktop.
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