1515import AsyncHTTPClient
1616import Foundation
1717import NIO
18+ import NIOConcurrencyHelpers
1819import NIOHTTP1
1920import NIOSSL
2021
@@ -90,9 +91,10 @@ internal final class RecordingHandler<Input, Output>: ChannelDuplexHandler {
9091 }
9192}
9293
93- internal class HttpBin {
94+ internal final class HTTPBin {
9495 let group = MultiThreadedEventLoopGroup ( numberOfThreads: 1 )
9596 let serverChannel : Channel
97+ let isShutdown : Atomic < Bool > = . init( value: false )
9698
9799 var port : Int {
98100 return Int ( self . serverChannel. localAddress!. port!)
@@ -125,7 +127,7 @@ internal class HttpBin {
125127 }
126128 } . flatMap {
127129 if ssl {
128- return HttpBin . configureTLS ( channel: channel) . flatMap {
130+ return HTTPBin . configureTLS ( channel: channel) . flatMap {
129131 channel. pipeline. addHandler ( HttpBinHandler ( channelPromise: channelPromise) )
130132 }
131133 } else {
@@ -135,8 +137,13 @@ internal class HttpBin {
135137 } . bind ( host: " 127.0.0.1 " , port: 0 ) . wait ( )
136138 }
137139
138- func shutdown( ) {
139- try ! self . group. syncShutdownGracefully ( )
140+ func shutdown( ) throws {
141+ self . isShutdown. store ( true )
142+ try self . group. syncShutdownGracefully ( )
143+ }
144+
145+ deinit {
146+ assert ( self . isShutdown. load ( ) , " HTTPBin not shutdown before deinit " )
140147 }
141148}
142149
@@ -186,7 +193,7 @@ final class HTTPProxySimulator: ChannelInboundHandler, RemovableChannelHandler {
186193
187194 switch self . option {
188195 case . tls:
189- _ = HttpBin . configureTLS ( channel: context. channel)
196+ _ = HTTPBin . configureTLS ( channel: context. channel)
190197 case . plaintext: break
191198 }
192199 }
@@ -311,20 +318,16 @@ internal final class HttpBinHandler: ChannelInboundHandler {
311318 response. add ( body)
312319 self . resps. prepend ( response)
313320 case . end:
314- if let promise = self . channelPromise {
315- promise. succeed ( context. channel)
316- }
321+ self . channelPromise? . succeed ( context. channel)
317322 if self . resps. isEmpty {
318323 return
319324 }
320325 let response = self . resps. removeFirst ( )
321326 context. write ( wrapOutboundOut ( . head( response. head) ) , promise: nil )
322- if let body = response. body {
323- let data = body. withUnsafeReadableBytes {
324- Data ( bytes: $0. baseAddress!, count: $0. count)
325- }
326-
327- let serialized = try ! JSONEncoder ( ) . encode ( RequestInfo ( data: String ( data: data, encoding: . utf8) !) )
327+ if var body = response. body {
328+ let data = body. readData ( length: body. readableBytes) !
329+ let serialized = try ! JSONEncoder ( ) . encode ( RequestInfo ( data: String ( decoding: data,
330+ as: Unicode . UTF8. self) ) )
328331
329332 var responseBody = context. channel. allocator. buffer ( capacity: serialized. count)
330333 responseBody. writeBytes ( serialized)
@@ -395,9 +398,7 @@ internal final class HttpBinForSSLUncleanShutdownHandler: ChannelInboundHandler
395398 func channelRead( context: ChannelHandlerContext , data: NIOAny ) {
396399 switch self . unwrapInboundIn ( data) {
397400 case . head( let req) :
398- if let promise = self . channelPromise {
399- promise. succeed ( context. channel)
400- }
401+ self . channelPromise? . succeed ( context. channel)
401402
402403 let response : String ?
403404 switch req. uri {
@@ -440,7 +441,7 @@ internal final class HttpBinForSSLUncleanShutdownHandler: ChannelInboundHandler
440441 context. writeAndFlush ( self . wrapOutboundOut ( buffer) , promise: nil )
441442 }
442443
443- _ = context. channel. pipeline. removeHandler ( name: " NIOSSLServerHandler " ) . map { _ in
444+ context. channel. pipeline. removeHandler ( name: " NIOSSLServerHandler " ) . whenSuccess {
444445 context. close ( promise: nil )
445446 }
446447 case . body:
0 commit comments