@@ -23,6 +23,7 @@ public final class HTTPServer {
2323 /// - reuseAddress: When `true`, can prevent errors re-binding to a socket after successive server restarts.
2424 /// - tcpNoDelay: When `true`, OS will attempt to minimize TCP packet delay.
2525 /// - supportCompression: When `true`, HTTP server will support gzip and deflate compression.
26+ /// - supportPipelining: When `true`, HTTP server will support pipelined HTTP requests.
2627 /// - serverName: If set, this name will be serialized as the `Server` header in outgoing responses.
2728 /// - upgraders: An array of `HTTPProtocolUpgrader` to check for with each request.
2829 /// - worker: `Worker` to perform async work on.
@@ -36,6 +37,7 @@ public final class HTTPServer {
3637 reuseAddress: Bool = true ,
3738 tcpNoDelay: Bool = true ,
3839 supportCompression: Bool = false ,
40+ supportPipelining: Bool = false ,
3941 serverName: String ? = nil ,
4042 upgraders: [ HTTPProtocolUpgrader ] = [ ] ,
4143 on worker: Worker ,
@@ -59,7 +61,7 @@ public final class HTTPServer {
5961
6062 // configure the pipeline
6163 return channel. pipeline. configureHTTPServerPipeline (
62- withPipeliningAssistance: false ,
64+ withPipeliningAssistance: supportPipelining ,
6365 withServerUpgrade: upgrade,
6466 withErrorHandling: false
6567 ) . then {
@@ -126,6 +128,9 @@ private final class HTTPServerHandler<R>: ChannelInboundHandler where R: HTTPSer
126128
127129 /// Optional server header.
128130 private let serverHeader : String ?
131+
132+ /// If true, we are waiting for a response to be sent.
133+ var awaitingReponse : Bool
129134
130135 /// Current HTTP state.
131136 var state : HTTPServerState
@@ -137,10 +142,12 @@ private final class HTTPServerHandler<R>: ChannelInboundHandler where R: HTTPSer
137142 self . errorHandler = onError
138143 self . serverHeader = serverHeader
139144 self . state = . ready
145+ self . awaitingReponse = false
140146 }
141147
142148 /// See `ChannelInboundHandler`.
143149 func channelRead( ctx: ChannelHandlerContext , data: NIOAny ) {
150+ debugOnly { assert ( !self . awaitingReponse, " Pipelined HTTP request detected. Enable pipelining to prevent this error. " ) }
144151 debugOnly { assert ( ctx. channel. eventLoop. inEventLoop) }
145152 switch unwrapInboundIn ( data) {
146153 case . head( let head) :
@@ -197,6 +204,7 @@ private final class HTTPServerHandler<R>: ChannelInboundHandler where R: HTTPSer
197204 case . streamingBody( let stream) : _ = stream. write ( . end)
198205 }
199206 state = . ready
207+ self . awaitingReponse = true
200208 }
201209 }
202210
@@ -246,6 +254,7 @@ private final class HTTPServerHandler<R>: ChannelInboundHandler where R: HTTPSer
246254 }
247255
248256 // begin serializing
257+ self . awaitingReponse = false
249258 ctx. write ( wrapOutboundOut ( . head( reshead) ) , promise: nil )
250259 if reqhead. method == . HEAD || res. status == . noContent {
251260 // skip sending the body for HEAD requests
0 commit comments