4646import io .jooby .value .Value ;
4747import io .netty .buffer .ByteBuf ;
4848import io .netty .buffer .Unpooled ;
49- import io .netty .channel .ChannelFuture ;
50- import io .netty .channel .ChannelFutureListener ;
51- import io .netty .channel .ChannelHandlerContext ;
52- import io .netty .channel .ChannelPipeline ;
53- import io .netty .channel .ChannelPromise ;
54- import io .netty .channel .DefaultFileRegion ;
49+ import io .netty .channel .*;
5550import io .netty .handler .codec .http .*;
5651import io .netty .handler .codec .http .cookie .ServerCookieDecoder ;
5752import io .netty .handler .codec .http .multipart .*;
@@ -320,7 +315,7 @@ public String getProtocol() {
320315
321316 @ NonNull @ Override
322317 public List <Certificate > getClientCertificates () {
323- SslHandler sslHandler = ( SslHandler ) ctx . channel (). pipeline (). get ( " ssl" );
318+ var sslHandler = ssl ( );
324319 if (sslHandler != null ) {
325320 try {
326321 return List .of (sslHandler .engine ().getSession ().getPeerCertificates ());
@@ -334,11 +329,22 @@ public List<Certificate> getClientCertificates() {
334329 @ NonNull @ Override
335330 public String getScheme () {
336331 if (scheme == null ) {
337- scheme = ctx . pipeline (). get ( " ssl" ) == null ? "http" : "https" ;
332+ scheme = ssl ( ) == null ? "http" : "https" ;
338333 }
339334 return scheme ;
340335 }
341336
337+ private SslHandler ssl () {
338+ return (SslHandler )
339+ Stream .of (ctx .channel (), ctx .channel ().parent ())
340+ .filter (Objects ::nonNull )
341+ .map (Channel ::pipeline )
342+ .map (it -> it .get ("ssl" ))
343+ .filter (Objects ::nonNull )
344+ .findFirst ()
345+ .orElse (null );
346+ }
347+
342348 @ NonNull @ Override
343349 public Context setScheme (@ NonNull String scheme ) {
344350 this .scheme = scheme ;
@@ -416,7 +422,7 @@ public Context upgrade(WebSocket.Initializer handler) {
416422 ? conf .getBytes ("websocket.maxSize" ).intValue ()
417423 : WebSocket .MAX_BUFFER_SIZE ;
418424 String webSocketURL = getProtocol () + "://" + req .headers ().get (HttpHeaderNames .HOST ) + path ;
419- WebSocketDecoderConfig config =
425+ var config =
420426 WebSocketDecoderConfig .newBuilder ()
421427 .allowExtensions (true )
422428 .allowMaskMismatch (false )
@@ -425,14 +431,16 @@ public Context upgrade(WebSocket.Initializer handler) {
425431 .build ();
426432 webSocket = new NettyWebSocket (this );
427433 handler .init (Context .readOnly (this ), webSocket );
428- FullHttpRequest webSocketRequest =
434+ var webSocketRequest =
429435 new DefaultFullHttpRequest (
430436 HTTP_1_1 ,
431437 req .method (),
432438 req .uri (),
433439 Unpooled .EMPTY_BUFFER ,
434440 req .headers (),
435441 EmptyHttpHeaders .INSTANCE );
442+ var codec = ctx .pipeline ().get (NettyServerCodec .class );
443+ codec .webSocketHandshake (ctx );
436444 WebSocketServerHandshakerFactory factory =
437445 new WebSocketServerHandshakerFactory (webSocketURL , null , config );
438446 WebSocketServerHandshaker handshaker = factory .newHandshaker (webSocketRequest );
@@ -856,15 +864,9 @@ private long responseLength() {
856864 private void prepareChunked () {
857865 responseStarted = true ;
858866 // remove flusher, doesn't play well with streaming/chunked responses
859- ChannelPipeline pipeline = ctx .pipeline ();
867+ var pipeline = ctx .pipeline ();
860868 if (pipeline .get ("chunker" ) == null ) {
861- String base =
862- Stream .of ("compressor" , "encoder" , "codec" , "http2" )
863- .filter (name -> pipeline .get (name ) != null )
864- .findFirst ()
865- .orElseThrow (
866- () -> new IllegalStateException ("No available handler for chunk writer" ));
867- pipeline .addAfter (base , "chunker" , new ChunkedWriteHandler ());
869+ pipeline .addBefore ("handler" , "chunker" , new ChunkedWriteHandler ());
868870 }
869871 if (!setHeaders .contains (CONTENT_LENGTH )) {
870872 setHeaders .set (TRANSFER_ENCODING , CHUNKED );
0 commit comments