为什么 Content-Length HTTP 标头字段使用的值与 Java 代码中给出的值不同?

我有一段 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.

相关文章