Skip to content

Instantly share code, notes, and snippets.

@adam-fowler
Created February 7, 2020 16:42
Show Gist options
  • Save adam-fowler/9efe36a8f3641f3a6e020ae1825c86ad to your computer and use it in GitHub Desktop.
Save adam-fowler/9efe36a8f3641f3a6e020ae1825c86ad to your computer and use it in GitHub Desktop.
NIO Transport services fail
import Network
import NIO
import NIOHTTP1
import NIOTransportServices
/// Channel Handler for serializing request header and data
class HTTPClientRequestSerializer : ChannelOutboundHandler {
typealias OutboundIn = Void
typealias OutboundOut = HTTPClientRequestPart
private let hostname: String
init(hostname: String) {
self.hostname = hostname
}
func write(context: ChannelHandlerContext, data: NIOAny, promise: EventLoopPromise<Void>?) {
//let request = unwrapOutboundIn(data)
var head = HTTPRequestHead(version: .init(major: 1, minor: 1), method: .GET, uri: "/bytes/24000")
head.headers.replaceOrAdd(name: "Host", value: hostname)
head.headers.replaceOrAdd(name: "Connection", value: "Close")
context.write(wrapOutboundOut(.head(head)), promise: nil)
context.write(self.wrapOutboundOut(.end(nil)), promise: promise)
}
}
/// Channel Handler for parsing response from server
class HTTPClientResponseHandler: ChannelInboundHandler {
typealias InboundIn = HTTPClientResponsePart
typealias OutboundOut = Void
let promise : EventLoopPromise<Void>
init(promise: EventLoopPromise<Void>) {
self.promise = promise
}
func errorCaught(context: ChannelHandlerContext, error: Error) {
context.fireErrorCaught(error)
}
func channelRead(context: ChannelHandlerContext, data: NIOAny) {
switch unwrapInboundIn(data) {
case .head(_):
print("Head")
case .body(_):
print("Body")
case .end(_):
print("End")
if context.channel.isActive {
context.fireChannelRead(wrapOutboundOut(()))
}
promise.succeed(())
}
}
}
@available (macOS 10.14, *)
func bootstrapTS(_ eventLoopGroup: EventLoopGroup) -> EventLoopFuture<Void> {
let hostname = "httpbin.org"
let response: EventLoopPromise<Void> = eventLoopGroup.next().makePromise()
_ = NIOTSConnectionBootstrap(group: eventLoopGroup)
.connectTimeout(TimeAmount.seconds(5))
.channelOption(ChannelOptions.socket(IPPROTO_TCP, TCP_NODELAY), value: 1)
.tlsOptions(NWProtocolTLS.Options())
.channelInitializer { channel in
return channel.pipeline.addHTTPClientHandlers()
.flatMap {
let handlers : [ChannelHandler] = [
HTTPClientRequestSerializer(hostname: hostname),
HTTPClientResponseHandler(promise: response)
]
return channel.pipeline.addHandlers(handlers)
}
}
.connect(host: hostname, port: 443)
.flatMap { channel -> EventLoopFuture<Void> in
return channel.writeAndFlush(Void())
}
.whenFailure { error in
response.fail(error)
}
return response.futureResult
}
@available (macOS 10.14, *)
func run() {
let eventLoopGroup = NIOTSEventLoopGroup()
do {
_ = try bootstrapTS(eventLoopGroup).wait()
} catch {
print("\(error)")
}
}
if #available(macOS 10.14, *) {
run()
}
print("Done")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment