2020import java .util .List ;
2121import java .util .Optional ;
2222
23+ import org .apache .http .impl .bootstrap .SSLServerSetupHandler ;
2324import org .jooby .test .MockUnit ;
2425import org .jooby .test .MockUnit .Block ;
2526import org .junit .Test ;
3839import io .netty .handler .codec .http .DefaultFullHttpResponse ;
3940import io .netty .handler .codec .http .DefaultHttpHeaders ;
4041import io .netty .handler .codec .http .DefaultHttpResponse ;
42+ import io .netty .handler .codec .http .HttpChunkedInput ;
4143import io .netty .handler .codec .http .HttpHeaderNames ;
4244import io .netty .handler .codec .http .HttpHeaderValues ;
4345import io .netty .handler .codec .http .HttpHeaders ;
4446import io .netty .handler .codec .http .HttpResponse ;
4547import io .netty .handler .codec .http .HttpResponseStatus ;
4648import io .netty .handler .codec .http .HttpVersion ;
4749import io .netty .handler .codec .http .LastHttpContent ;
50+ import io .netty .handler .ssl .SslHandler ;
51+ import io .netty .handler .stream .ChunkedInput ;
52+ import io .netty .handler .stream .ChunkedNioFile ;
4853import io .netty .handler .stream .ChunkedStream ;
4954import io .netty .handler .stream .ChunkedWriteHandler ;
5055import io .netty .util .Attribute ;
@@ -596,6 +601,17 @@ public void sendFileChannel() throws Exception {
596601 expect (chn .eventLoop ()).andReturn (loop );
597602
598603 })
604+ .expect (unit -> {
605+ ChannelPipeline pipeline = unit .mock (ChannelPipeline .class );
606+ expect (pipeline .get ("chunker" )).andReturn (null );
607+ expect (pipeline .get (SslHandler .class )).andReturn (null );
608+ expect (pipeline .addAfter (eq ("codec" ), eq ("chunker" ), isA (ChunkedWriteHandler .class )))
609+ .andReturn (pipeline );
610+
611+ ChannelHandlerContext ctx = unit .get (ChannelHandlerContext .class );
612+ expect (ctx .pipeline ()).andReturn (pipeline );
613+ expect (ctx .pipeline ()).andReturn (pipeline );
614+ })
599615 .expect (noKeepAliveNoLen )
600616 .run (unit -> {
601617 new NettyResponse (unit .get (ChannelHandlerContext .class ), bufferSize , keepAlive )
@@ -605,6 +621,84 @@ public void sendFileChannel() throws Exception {
605621 });
606622 }
607623
624+ @ Test
625+ public void sendFileChannelSSL () throws Exception {
626+ boolean keepAlive = false ;
627+ FileChannel fchannel = newFileChannel (8192 );
628+ new MockUnit (ChannelHandlerContext .class , ByteBuf .class , ChannelFuture .class )
629+ .expect (channel )
630+ .expect (headers )
631+ .expect (unit -> {
632+ DefaultHttpHeaders headers = unit .get (DefaultHttpHeaders .class );
633+ expect (headers .contains (HttpHeaderNames .CONTENT_LENGTH )).andReturn (false );
634+ expect (headers .remove (HttpHeaderNames .TRANSFER_ENCODING )).andReturn (headers );
635+ expect (headers .set (HttpHeaderNames .CONTENT_LENGTH , 8192L )).andReturn (headers );
636+ })
637+ .expect (unit -> {
638+ DefaultHttpResponse rsp = unit .mockConstructor (DefaultHttpResponse .class ,
639+ new Class []{HttpVersion .class ,
640+ HttpResponseStatus .class },
641+ HttpVersion .HTTP_1_1 , HttpResponseStatus .OK );
642+
643+ HttpHeaders headers = unit .mock (HttpHeaders .class );
644+ expect (headers .set (unit .get (DefaultHttpHeaders .class ))).andReturn (headers );
645+
646+ expect (rsp .headers ()).andReturn (headers );
647+
648+ unit .registerMock (HttpResponse .class , rsp );
649+ })
650+ .expect (unit -> {
651+ ChannelFuture future = unit .get (ChannelFuture .class );
652+
653+ ChannelHandlerContext ctx = unit .get (ChannelHandlerContext .class );
654+ expect (ctx .write (unit .get (HttpResponse .class ))).andReturn (future );
655+ })
656+ .expect (
657+ unit -> {
658+ ChunkedNioFile nioFile = unit .mockConstructor (ChunkedNioFile .class ,
659+ new Class []{FileChannel .class , long .class , long .class , int .class },
660+ fchannel , 0L , fchannel .size (), 8192 );
661+
662+ HttpChunkedInput chunked = unit .mockConstructor (HttpChunkedInput .class ,
663+ new Class []{ChunkedInput .class }, nioFile );
664+
665+ unit .registerMock (HttpChunkedInput .class , chunked );
666+ })
667+ .expect (unit -> {
668+ ChannelFuture future = unit .get (ChannelFuture .class );
669+
670+ ChannelHandlerContext ctx = unit .get (ChannelHandlerContext .class );
671+ expect (ctx .writeAndFlush (unit .get (HttpChunkedInput .class ))).andReturn (future );
672+ })
673+ .expect (setNeedFlush )
674+ .expect (unit -> {
675+ EventLoop loop = unit .mock (EventLoop .class );
676+ loop .execute (unit .capture (Runnable .class ));
677+
678+ Channel chn = unit .get (Channel .class );
679+ expect (chn .eventLoop ()).andReturn (loop );
680+
681+ })
682+ .expect (unit -> {
683+ ChannelPipeline pipeline = unit .mock (ChannelPipeline .class );
684+ expect (pipeline .get ("chunker" )).andReturn (null );
685+ expect (pipeline .get (SslHandler .class )).andReturn (unit .mock (SslHandler .class ));
686+ expect (pipeline .addAfter (eq ("codec" ), eq ("chunker" ), isA (ChunkedWriteHandler .class )))
687+ .andReturn (pipeline );
688+
689+ ChannelHandlerContext ctx = unit .get (ChannelHandlerContext .class );
690+ expect (ctx .pipeline ()).andReturn (pipeline );
691+ expect (ctx .pipeline ()).andReturn (pipeline );
692+ })
693+ .expect (noKeepAliveNoLen )
694+ .run (unit -> {
695+ new NettyResponse (unit .get (ChannelHandlerContext .class ), bufferSize , keepAlive )
696+ .send (fchannel );
697+ }, unit -> {
698+ unit .captured (Runnable .class ).iterator ().next ().run ();
699+ });
700+ }
701+
608702 @ Test
609703 public void sendFileChannelNoLen () throws Exception {
610704 boolean keepAlive = false ;
@@ -655,6 +749,17 @@ public void sendFileChannelNoLen() throws Exception {
655749 ChannelHandlerContext ctx = unit .get (ChannelHandlerContext .class );
656750 expect (ctx .writeAndFlush (LastHttpContent .EMPTY_LAST_CONTENT )).andReturn (future );
657751 })
752+ .expect (unit -> {
753+ ChannelPipeline pipeline = unit .mock (ChannelPipeline .class );
754+ expect (pipeline .get ("chunker" )).andReturn (null );
755+ expect (pipeline .get (SslHandler .class )).andReturn (null );
756+ expect (pipeline .addAfter (eq ("codec" ), eq ("chunker" ), isA (ChunkedWriteHandler .class )))
757+ .andReturn (pipeline );
758+
759+ ChannelHandlerContext ctx = unit .get (ChannelHandlerContext .class );
760+ expect (ctx .pipeline ()).andReturn (pipeline );
761+ expect (ctx .pipeline ()).andReturn (pipeline );
762+ })
658763 .expect (setNeedFlush )
659764 .expect (noKeepAliveNoLen )
660765 .expect (unit -> {
0 commit comments