-
Notifications
You must be signed in to change notification settings - Fork 1
Using Vapor HTTPClient as network transport for Swarm
Denys Telezhkin edited this page Feb 1, 2021
·
1 revision
Example of Vapor/HTTPClient implementation of networking transport for Swarm
:
import Foundation
import Vapor
import Swarm
import AsyncHTTPClient
#if canImport(FoundationNetworking)
import FoundationNetworking
#endif
class HTTPClientSpider : Spider {
let client : HTTPClient
private var future : EventLoopFuture<HTTPClient.Response>?
var httpHeaders : [String: String] = [:]
init(eventLoopGroupProvider: AsyncHTTPClient.HTTPClient.EventLoopGroupProvider,
configuration: AsyncHTTPClient.HTTPClient.Configuration = .init()) {
client = HTTPClient(eventLoopGroupProvider: eventLoopGroupProvider, configuration: configuration)
}
deinit {
client.shutdown { error in
if let error = error {
print("❗️ Failed to shut down HTTPClient on HTTPClientSpider instance with error: \(error)")
}
}
}
func request(url: ScrappableURL, completion: @escaping (Data?, URLResponse?, Error?) -> Void) {
do {
let request = try HTTPClient.Request(url: url.url, method: .GET, headers: .init(httpHeaders.map { ($0.key, $0.value)}), body: nil)
future = client.execute(request: request)
.always { result in
switch result {
case .success(let response):
let data = response.body?.getData(at: 0, length: response.body?.readableBytes ?? 0) ?? .init()
let httpResponse = HTTPURLResponse(url: url.url, statusCode: Int(response.status.code), httpVersion: response.version.description, headerFields: response.headers.reduce(into: [:], { result, current in
result[current.name] = current.value
}))
completion(data, httpResponse, nil)
case .failure(let error): completion(nil,nil,error)
}
}
} catch {
completion(nil,nil,error)
}
}
}
Usage for shared event loop:
func spider(for url: ScrappableURL) -> Spider {
return HTTPClientSpider(eventLoopProvider: .shared(eventLoop))
}