15
15
import AsyncHTTPClient
16
16
import Foundation
17
17
import NIO
18
+ import NIOConcurrencyHelpers
18
19
import NIOHTTP1
19
20
import NIOSSL
20
21
@@ -90,9 +91,10 @@ internal final class RecordingHandler<Input, Output>: ChannelDuplexHandler {
90
91
}
91
92
}
92
93
93
- internal class HttpBin {
94
+ internal final class HTTPBin {
94
95
let group = MultiThreadedEventLoopGroup ( numberOfThreads: 1 )
95
96
let serverChannel : Channel
97
+ let isShutdown : Atomic < Bool > = . init( value: false )
96
98
97
99
var port : Int {
98
100
return Int ( self . serverChannel. localAddress!. port!)
@@ -125,7 +127,7 @@ internal class HttpBin {
125
127
}
126
128
} . flatMap {
127
129
if ssl {
128
- return HttpBin . configureTLS ( channel: channel) . flatMap {
130
+ return HTTPBin . configureTLS ( channel: channel) . flatMap {
129
131
channel. pipeline. addHandler ( HttpBinHandler ( channelPromise: channelPromise) )
130
132
}
131
133
} else {
@@ -135,8 +137,13 @@ internal class HttpBin {
135
137
} . bind ( host: " 127.0.0.1 " , port: 0 ) . wait ( )
136
138
}
137
139
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 " )
140
147
}
141
148
}
142
149
@@ -186,7 +193,7 @@ final class HTTPProxySimulator: ChannelInboundHandler, RemovableChannelHandler {
186
193
187
194
switch self . option {
188
195
case . tls:
189
- _ = HttpBin . configureTLS ( channel: context. channel)
196
+ _ = HTTPBin . configureTLS ( channel: context. channel)
190
197
case . plaintext: break
191
198
}
192
199
}
@@ -311,20 +318,16 @@ internal final class HttpBinHandler: ChannelInboundHandler {
311
318
response. add ( body)
312
319
self . resps. prepend ( response)
313
320
case . end:
314
- if let promise = self . channelPromise {
315
- promise. succeed ( context. channel)
316
- }
321
+ self . channelPromise? . succeed ( context. channel)
317
322
if self . resps. isEmpty {
318
323
return
319
324
}
320
325
let response = self . resps. removeFirst ( )
321
326
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) ) )
328
331
329
332
var responseBody = context. channel. allocator. buffer ( capacity: serialized. count)
330
333
responseBody. writeBytes ( serialized)
@@ -395,9 +398,7 @@ internal final class HttpBinForSSLUncleanShutdownHandler: ChannelInboundHandler
395
398
func channelRead( context: ChannelHandlerContext , data: NIOAny ) {
396
399
switch self . unwrapInboundIn ( data) {
397
400
case . head( let req) :
398
- if let promise = self . channelPromise {
399
- promise. succeed ( context. channel)
400
- }
401
+ self . channelPromise? . succeed ( context. channel)
401
402
402
403
let response : String ?
403
404
switch req. uri {
@@ -440,7 +441,7 @@ internal final class HttpBinForSSLUncleanShutdownHandler: ChannelInboundHandler
440
441
context. writeAndFlush ( self . wrapOutboundOut ( buffer) , promise: nil )
441
442
}
442
443
443
- _ = context. channel. pipeline. removeHandler ( name: " NIOSSLServerHandler " ) . map { _ in
444
+ context. channel. pipeline. removeHandler ( name: " NIOSSLServerHandler " ) . whenSuccess {
444
445
context. close ( promise: nil )
445
446
}
446
447
case . body:
0 commit comments