我最初的目的是验证 HTTP 分块传输。但是无意中发现了这个不一致。
API 旨在将文件返回给客户端。我对它使用 HEAD
和 GET
方法。 返回不同的 header 。
对于 GET
,我得到了这些 header :(这是我所期望的。)
对于 HEAD
,我得到这些 header :
根据 this thread 、HEAD
和 GET
应该 返回相同的 header ,但不一定。
我的问题是:
如果使用Transfer-Encoding: chunked
,因为文件是动态提供给客户端的,而 Tomcat 服务器无法预先知道它的大小,当使用HEAD
方法时,Tomcat 如何知道Content-Length
? Tomcat 是否只是试运行 处理程序并计算所有文件字节数?为什么它不简单地返回相同的 Transfer-Encoding: chunked
header ?
下面是我使用 Spring Web MVC 实现的 RESTful API:
@RestController
public class ChunkedTransferAPI {
@Autowired
ServletContext servletContext;
@RequestMapping(value = "bootfile.efi", method = { RequestMethod.GET, RequestMethod.HEAD })
public void doHttpBoot(HttpServletResponse response) {
String filename = "/bootfile.efi";
try {
ServletOutputStream output = response.getOutputStream();
InputStream input = servletContext.getResourceAsStream(filename);
BufferedInputStream bufferedInput = new BufferedInputStream(input);
int datum = bufferedInput.read();
while (datum != -1) {
output.write(datum);
datum = bufferedInput.read();
}
output.flush();
output.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
添加 1
在我的代码中,我没有明确添加任何 header ,那么一定是 Tomcat 添加了它认为合适的 Content-Length
和 Transfer-Encoding
header .
那么,Tomcat 决定发送哪些 header 的规则是什么?
添加 2
可能与Tomcat的工作方式有关。我希望有人能在这里阐明一些问题。否则,我将调试到 Tomcat 8 的源代码并分享结果。但这可能需要一段时间。
相关:
最佳答案
Does Tomcat just dry-run the handler and count all the file bytes?
是的,javax.servlet.http.HttpServlet.doHead() 的默认实现就是这样做的。
您可以查看 HttpServlet.java 中的帮助类 NoBodyResponse、NoBodyOutputStream
DefaultServlet 类(用于提供静态文件的 Tomcat servlet)更为明智。它能够发送正确的 Content-Length 值,以及为文件的一个子集(Range
header )提供 GET 请求。您可以将您的请求转发给该 servlet,使用
ServletContext.getNamedDispatcher("default").forward(request, response);
关于http - 为什么 Tomcat 会为我的 RESTful API 返回不同的 HEAD 和 GET 请求 header ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34290203/