问题
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);
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?
I searched in HTTP spec but found no hint. I did not use any Transfer-Encoding or Transfer-coding.
回答1:
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 ;-)
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.
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).
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).
The restriction can manually be disabled by setting the System property sun.net.http.allowRestrictedHeaders
to true
on JVM startup.
回答2:
This solved for me:
connection.setFixedLengthStreamingMode(myString.getBytes().length);
conn.setRequestProperty("Content-length", String.valueOf(myString.getBytes().length));
"connection.setFixedLengthStreamingMode(myString.getBytes().length);" before set the Content-Length header.
来源:https://stackoverflow.com/questions/6056125/why-does-content-length-http-header-field-use-a-value-other-than-the-one-given-i