Changing Netty 4 HTTP File Server example to use ChunkedStream instead of ChunkedFile -
i'm trying wrap head around netty 4 way of implementing http server serve httpresponses bodies using chunked transfer-encoding when total data size unknown.
as starting point, changed httpstaticfileserverhandler (found in https://github.com/netty/netty/tree/netty-4.0.0.cr1/example/src/main/java/io/netty/example/http/file) use chunkedstream instead of chunkedfile (they both chunkedbyteinputs).
i understand not ideal in original example use case use fileinputstream think makes example reusing known code.
so, here diff against httpstaticfileserverhandler class io.netty.example.http.file package (vs. 4.0.0.cr1):
diff --git a/example/src/main/java/io/netty/example/http/file/httpstaticfileserverhandler.java b/example/src/main/java/io/netty/example/http/file/httpstaticfileserverhandler.java index 904579b..0d3592f 100644 --- a/example/src/main/java/io/netty/example/http/file/httpstaticfileserverhandler.java +++ b/example/src/main/java/io/netty/example/http/file/httpstaticfileserverhandler.java @@ -27,13 +27,14 @@ import io.netty.handler.codec.http.fullhttpresponse; import io.netty.handler.codec.http.httpheaders; import io.netty.handler.codec.http.httpresponse; import io.netty.handler.codec.http.httpresponsestatus; -import io.netty.handler.stream.chunkedfile; +import io.netty.handler.stream.chunkedstream; import io.netty.util.charsetutil; import javax.activation.mimetypesfiletypemap; import java.io.file; +import java.io.fileinputstream; import java.io.filenotfoundexception; -import java.io.randomaccessfile; +import java.io.inputstream; import java.io.unsupportedencodingexception; import java.net.urldecoder; import java.text.simpledateformat; @@ -159,17 +160,15 @@ public class httpstaticfileserverhandler extends channelinboundmessagehandlerada } } - randomaccessfile raf; + inputstream raf; // use inputstream instead of randomaccessfile try { - raf = new randomaccessfile(file, "r"); + raf = new fileinputstream(file); } catch (filenotfoundexception fnfe) { senderror(ctx, not_found); return; } - long filelength = raf.length(); httpresponse response = new defaulthttpresponse(http_1_1, ok); - setcontentlength(response, filelength); setcontenttypeheader(response, file); setdateandcacheheaders(response, file); if (iskeepalive(request)) { @@ -180,7 +179,7 @@ public class httpstaticfileserverhandler extends channelinboundmessagehandlerada ctx.write(response); // write content. - channelfuture writefuture = ctx.write(new chunkedfile(raf, 0, filelength, 8192)); + channelfuture writefuture = ctx.write(new chunkedstream(raf)); // use chunkedstream instead of chunkedfile // decide whether close connection or not. if (!iskeepalive(request)) {
and here complete changed file: https://gist.github.com/eskatos/5311587
changes minimal: use fileinputstream instead of randomaccessfile , chunkedstream instead of chunkedfile. pipeline untouched.
to reproduce, apply changes netty example, run , try download file.
after change, directory listing works because reponses not chunked file downloads don't. client download file never finish download, hold connection , wait forever. i've tried several browsers curl, wget etc.. i've tried add bytelogginghandler pipeline , can see empty trailing chunk don't understand why browser still wait data.
any clue?
in order terminate chunked transfer of unkown size (content-length not known , not specified) send empty chunk last chunk. permits keep connection open in order support keepalives:
ctx.write(new chunkedinputadapter(new chunkedstream(raf, 8192))); channelfuture writefuture = ctx.writeandflush(lasthttpcontent.empty_last_content);
here complete example: https://github.com/scireum/sirius/blob/develop/web/src/sirius/web/http/response.java#l649
Comments
Post a Comment