Я пытаюсь понять, как Netty 4 реализует HTTP-сервер, который обслуживает тела HttpResponses, используя кодирование передачи по частям, когда общий размер данных неизвестен.
В качестве отправной точки я просто изменил HttpStaticFileServerHandler (находится в https://github.com/netty/netty/tree/netty-4.0.0.CR1/example/src/main/java/io/netty/example/http/file), чтобы использовать ChunkedStream вместо ChunkedFile (они оба являются ChunkedByteInputs).
Я понимаю, что в исходном примере использовать FileInputStream не идеально, но я думаю, что это хороший пример повторного использования уже известного кода.
Итак, вот сравнение с классом HttpStaticFileServerHandler из пакета io.netty.example.http.file (по сравнению с 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 an InputStream instead of a 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 the content.
- ChannelFuture writeFuture = ctx.write(new ChunkedFile(raf, 0, fileLength, 8192));
+ ChannelFuture writeFuture = ctx.write(new ChunkedStream(raf)); // Use a ChunkedStream instead of a ChunkedFile
// Decide whether to close the connection or not.
if (!isKeepAlive(request)) {
А вот и полностью измененный файл: https://gist.github.com/eskatos/5311587
Изменения минимальны: используйте FileInputStream вместо RandomAccessFile и ChunkedStream вместо ChunkedFile. Трубопровод не тронут.
Чтобы воспроизвести, просто примените изменения к примеру Netty, запустите его и попробуйте загрузить любой файл.
После этого изменения список каталогов, очевидно, работает, потому что ответы не разбиваются на части, а загрузки файлов - нет. Клиент загружает файл, но никогда не заканчивает загрузку, удерживает соединение и ждет вечно. Я пробовал несколько браузеров для curl, wget и т. Д. Я также пытался добавить ByteLoggingHandler в конвейер, и я вижу пустой завершающий фрагмент, поэтому я не понимаю, почему браузер все еще ждет данных.
Любая подсказка?