问题描述
我有一段 Java 代码将字节数组传输到 HTTP 服务器:
I have a piece of Java code to transfer a byte array to HTTP server:
HttpURLConnection connection = (HttpURLConnection) url.openConnection(); connection.setDoInput(true); connection.setDoOutput(true); connection.setUseCaches(false); connection.setRequestMethod("POST"); connection.setRequestProperty("Connection", "Keep-Alive"); connection.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + myBoundary); connection.setRequestProperty("Content-Length", 1024);
我使用此代码传输大小大于 1024 的字节数组.它运行良好.但是实际的 HTTP 消息(由 Wireshark 捕获)显示 Content-Length 的值是实际大小而不是1024. 为什么?
I used this code to transfer a byte array whose size is greater than 1024. It worked well. But the actual HTTP message (captured by Wireshark) shows that the value of Content-Length is the actual size instead of 1024. Why?
我在 HTTP 规范 中进行了搜索,但没有找到任何提示.我没有使用任何传输编码或传输编码.
I searched in HTTP spec but found no hint. I did not use any Transfer-Encoding or Transfer-coding.
推荐答案
我猜 HttpURLConnection 将简单地用正确的值覆盖 Content-Length 标头,因为它知道撒谎是不好的 ;-)
I'd guess that the HttpURLConnection will simply override the Content-Length header with the correct value, since it knows that lying about it is no good ;-)
事实上:在 sun.net.www.protocol.HttpURLConnection 如果合适,Content-Length 会被设置.这发生在 用户指定的标头设置之后,因此该值将被覆盖.
And indeed: at the lines 535-550 of sun.net.www.protocol.HttpURLConnection the Content-Length is set if appropriate. This happens after the user-specified headers are set, so that value will be overwritten.
这是正确的:如果您传输的数据量与声称的数量不匹配,那么您只会混淆另一端.
And it's right about that: if the amount of data you transfer does not match the claimed amount, then you'll only confuse the other end.
检查 sun.net.www.protocol.http.HttpURLConnection的来源好像有一个headers列表是限制的,调用setRequestProperty.Content-Length 在该列表中.不幸的是,这似乎没有记录(至少我找不到任何关于此的文档,只有 此处讨论相关问题).
Checking the source of sun.net.www.protocol.http.HttpURLConnection it seems that there is a list of headers that are restricted and will silently be ignored when calling setRequestProperty. Content-Length is among that list. Unfortunately this seems to be undocumented (at least I couldn't find any documentation on this, only a discussion of a related problem here).
搜索 引入此功能"的 ChangeSet 似乎引入此更改是对安全漏洞 CVE-2010-3541 和 CVE-2010-3573 (有关此主题的 Redhat 错误).
Googling for the Bug IDs (?) mentioned in the ChangeSet that introduced this "functionality" it seems that this change was introduces as a reaction to the security vulnerabilities CVE-2010-3541 and CVE-2010-3573 (Redhat bug on this topic).
可以通过在 JVM 启动时将系统属性 sun.net.http.allowRestrictedHeaders 设置为 true 手动禁用限制.
The restriction can manually be disabled by setting the System property sun.net.http.allowRestrictedHeaders to true on JVM startup.