@@ -339,7 +339,7 @@ final class HTTPProxySimulator: ChannelInboundHandler, RemovableChannelHandler {
339
339
}
340
340
341
341
internal struct HTTPResponseBuilder {
342
- let head : HTTPResponseHead
342
+ var head : HTTPResponseHead
343
343
var body : ByteBuffer ?
344
344
345
345
init ( _ version: HTTPVersion = HTTPVersion ( major: 1 , minor: 1 ) , status: HTTPResponseStatus , headers: HTTPHeaders = HTTPHeaders ( ) ) {
@@ -357,8 +357,13 @@ internal struct HTTPResponseBuilder {
357
357
}
358
358
}
359
359
360
+ let globalRequestCounter = NIOAtomic< Int> . makeAtomic( value: 0 )
361
+ let globalConnectionCounter = NIOAtomic< Int> . makeAtomic( value: 0 )
362
+
360
363
internal struct RequestInfo : Codable {
361
- let data : String
364
+ var data : String
365
+ var requestNumber : Int
366
+ var connectionNumber : Int
362
367
}
363
368
364
369
internal final class HttpBinHandler : ChannelInboundHandler {
@@ -367,16 +372,19 @@ internal final class HttpBinHandler: ChannelInboundHandler {
367
372
368
373
let channelPromise : EventLoopPromise < Channel > ?
369
374
var resps = CircularBuffer < HTTPResponseBuilder > ( )
370
- var closeAfterResponse = false
375
+ var responseHeaders = HTTPHeaders ( )
371
376
var delay : TimeAmount = . seconds( 0 )
372
377
let creationDate = Date ( )
373
378
let maxChannelAge : TimeAmount ?
374
379
var shouldClose = false
375
380
var isServingRequest = false
381
+ let myConnectionNumber : Int
382
+ var currentRequestNumber : Int = - 1
376
383
377
384
init ( channelPromise: EventLoopPromise < Channel > ? = nil , maxChannelAge: TimeAmount ? = nil ) {
378
385
self . channelPromise = channelPromise
379
386
self . maxChannelAge = maxChannelAge
387
+ self . myConnectionNumber = globalConnectionCounter. add ( 1 )
380
388
}
381
389
382
390
func handlerAdded( context: ChannelHandlerContext ) {
@@ -402,27 +410,31 @@ internal final class HttpBinHandler: ChannelInboundHandler {
402
410
self . delay = . nanoseconds( 0 )
403
411
}
404
412
405
- if let connection = head. headers [ " Connection " ] . first {
406
- self . closeAfterResponse = ( connection == " close " )
407
- } else {
408
- self . closeAfterResponse = false
413
+ for header in head. headers {
414
+ let needle = " x-send-back-header- "
415
+ if header. name. lowercased ( ) . starts ( with: needle) {
416
+ self . responseHeaders. add ( name: String ( header. name. dropFirst ( needle. count) ) ,
417
+ value: header. value)
418
+ }
409
419
}
410
420
}
411
421
412
422
func channelRead( context: ChannelHandlerContext , data: NIOAny ) {
413
423
self . isServingRequest = true
414
424
switch self . unwrapInboundIn ( data) {
415
425
case . head( let req) :
426
+ self . responseHeaders = HTTPHeaders ( )
427
+ self . currentRequestNumber = globalRequestCounter. add ( 1 )
416
428
self . parseAndSetOptions ( from: req)
417
429
let urlComponents = URLComponents ( string: req. uri) !
418
430
switch urlComponents. percentEncodedPath {
419
431
case " / " :
420
- var headers = HTTPHeaders ( )
432
+ var headers = self . responseHeaders
421
433
headers. add ( name: " X-Is-This-Slash " , value: " Yes " )
422
434
self . resps. append ( HTTPResponseBuilder ( status: . ok, headers: headers) )
423
435
return
424
436
case " /echo-uri " :
425
- var headers = HTTPHeaders ( )
437
+ var headers = self . responseHeaders
426
438
headers. add ( name: " X-Calling-URI " , value: req. uri)
427
439
self . resps. append ( HTTPResponseBuilder ( status: . ok, headers: headers) )
428
440
return
@@ -436,6 +448,13 @@ internal final class HttpBinHandler: ChannelInboundHandler {
436
448
}
437
449
self . resps. append ( HTTPResponseBuilder ( status: . ok) )
438
450
return
451
+ case " /stats " :
452
+ var body = context. channel. allocator. buffer ( capacity: 1 )
453
+ body. writeString ( " Just some stats mate. " )
454
+ var builder = HTTPResponseBuilder ( status: . ok)
455
+ builder. add ( body)
456
+
457
+ self . resps. append ( builder)
439
458
case " /post " :
440
459
if req. method != . POST {
441
460
self . resps. append ( HTTPResponseBuilder ( status: . methodNotAllowed) )
@@ -444,29 +463,29 @@ internal final class HttpBinHandler: ChannelInboundHandler {
444
463
self . resps. append ( HTTPResponseBuilder ( status: . ok) )
445
464
return
446
465
case " /redirect/302 " :
447
- var headers = HTTPHeaders ( )
466
+ var headers = self . responseHeaders
448
467
headers. add ( name: " location " , value: " /ok " )
449
468
self . resps. append ( HTTPResponseBuilder ( status: . found, headers: headers) )
450
469
return
451
470
case " /redirect/https " :
452
471
let port = self . value ( for: " port " , from: urlComponents. query!)
453
- var headers = HTTPHeaders ( )
472
+ var headers = self . responseHeaders
454
473
headers. add ( name: " Location " , value: " https://localhost: \( port) /ok " )
455
474
self . resps. append ( HTTPResponseBuilder ( status: . found, headers: headers) )
456
475
return
457
476
case " /redirect/loopback " :
458
477
let port = self . value ( for: " port " , from: urlComponents. query!)
459
- var headers = HTTPHeaders ( )
478
+ var headers = self . responseHeaders
460
479
headers. add ( name: " Location " , value: " http://127.0.0.1: \( port) /echohostheader " )
461
480
self . resps. append ( HTTPResponseBuilder ( status: . found, headers: headers) )
462
481
return
463
482
case " /redirect/infinite1 " :
464
- var headers = HTTPHeaders ( )
483
+ var headers = self . responseHeaders
465
484
headers. add ( name: " Location " , value: " /redirect/infinite2 " )
466
485
self . resps. append ( HTTPResponseBuilder ( status: . found, headers: headers) )
467
486
return
468
487
case " /redirect/infinite2 " :
469
- var headers = HTTPHeaders ( )
488
+ var headers = self . responseHeaders
470
489
headers. add ( name: " Location " , value: " /redirect/infinite1 " )
471
490
self . resps. append ( HTTPResponseBuilder ( status: . found, headers: headers) )
472
491
return
@@ -528,15 +547,15 @@ internal final class HttpBinHandler: ChannelInboundHandler {
528
547
if self . resps. isEmpty {
529
548
return
530
549
}
531
- let response = self . resps. removeFirst ( )
550
+ var response = self . resps. removeFirst ( )
551
+ response. head. headers. add ( contentsOf: self . responseHeaders)
532
552
context. write ( wrapOutboundOut ( . head( response. head) ) , promise: nil )
533
- if var body = response. body {
534
- let data = body. readData ( length: body. readableBytes) !
535
- let serialized = try ! JSONEncoder ( ) . encode ( RequestInfo ( data: String ( decoding: data,
536
- as: Unicode . UTF8. self) ) )
537
-
538
- var responseBody = context. channel. allocator. buffer ( capacity: serialized. count)
539
- responseBody. writeBytes ( serialized)
553
+ if let body = response. body {
554
+ let requestInfo = RequestInfo ( data: String ( buffer: body) ,
555
+ requestNumber: self . currentRequestNumber,
556
+ connectionNumber: self . myConnectionNumber)
557
+ let responseBody = try ! JSONEncoder ( ) . encodeAsByteBuffer ( requestInfo,
558
+ allocator: context. channel. allocator)
540
559
context. write ( wrapOutboundOut ( . body( . byteBuffer( responseBody) ) ) , promise: nil )
541
560
}
542
561
context. eventLoop. scheduleTask ( in: self . delay) {
@@ -549,7 +568,8 @@ internal final class HttpBinHandler: ChannelInboundHandler {
549
568
self . isServingRequest = false
550
569
switch result {
551
570
case . success:
552
- if self . closeAfterResponse || self . shouldClose {
571
+ if self . responseHeaders [ canonicalForm: " X-Close-Connection " ] . contains ( " true " ) ||
572
+ self . shouldClose {
553
573
context. close ( promise: nil )
554
574
}
555
575
case . failure( let error) :
0 commit comments