如何使用JDK自带com.sun.net.httpserver发送带Trailers的HTTP响应?
如何用JDK自带的com.sun.net.httpserver发送响应体后的Trailers?
先看我们要实现的目标HTTP响应格式:
HTTP/1.1 200 OK Content-Type: text/plain Transfer-Encoding: chunked Trailer: Expires 7\r\n Mozilla\r\n 9\r\n Developer\r\n 7\r\n Network\r\n 0\r\n Expires: Wed, 21 Oct 2015 07:28:00 GMT\r\n \r\n
首先要明确:调用HttpExchange.sendResponseHeaders()传入responseLength=0确实能启用分块传输编码,但JDK自带的sun.net.httpserver.ChunkedOutputStream并没有实现Trailers的支持,没法直接用它来添加响应体后的Trailers。
要实现这个需求,你需要绕过默认的分块输出流,手动处理分块编码和Trailers的写入,步骤如下:
- 先在响应头里声明分块编码和要发送的Trailer字段:
httpExchange.getResponseHeaders().set("Transfer-Encoding", "chunked"); httpExchange.getResponseHeaders().set("Trailer", "Expires");
- 调用
sendResponseHeaders时传入-1(表示响应长度未知,这是启用分块的标准写法,比传0更规范):
httpExchange.sendResponseHeaders(200, -1);
- 获取原始输出流,严格按照HTTP分块格式写入内容、结束块和Trailers:
OutputStream os = httpExchange.getResponseBody(); // 写入第一个数据块 String chunk1 = "Mozilla"; byte[] chunk1Bytes = chunk1.getBytes(StandardCharsets.UTF_8); os.write(Integer.toHexString(chunk1Bytes.length).getBytes()); os.write("\r\n".getBytes()); os.write(chunk1Bytes); os.write("\r\n".getBytes()); // 写入第二个数据块 String chunk2 = "Developer"; byte[] chunk2Bytes = chunk2.getBytes(StandardCharsets.UTF_8); os.write(Integer.toHexString(chunk2Bytes.length).getBytes()); os.write("\r\n".getBytes()); os.write(chunk2Bytes); os.write("\r\n".getBytes()); // 写入第三个数据块 String chunk3 = "Network"; byte[] chunk3Bytes = chunk3.getBytes(StandardCharsets.UTF_8); os.write(Integer.toHexString(chunk3Bytes.length).getBytes()); os.write("\r\n".getBytes()); os.write(chunk3Bytes); os.write("\r\n".getBytes()); // 写入结束块(0长度) os.write("0\r\n".getBytes()); // 写入Trailer字段 os.write("Expires: Wed, 21 Oct 2015 07:28:00 GMT\r\n".getBytes()); // 结束整个响应 os.write("\r\n".getBytes()); os.flush(); os.close();
注意事项
- 手动处理分块时必须严格遵循HTTP规范:每个块的长度是十六进制字符串,后跟
\r\n,再是块内容,最后用\r\n收尾 - 结束块固定是
0\r\n,之后写入所有Trailer字段(格式和普通HTTP响应头一致),最后再写一个\r\n完成整个响应
内容的提问来源于stack exchange,提问作者Андрей Щеглов
相关产品推荐
相关产品推荐

