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.
I'd guess that the
HttpURLConnection
will simply override theContent-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
theContent-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 callingsetRequestProperty
.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
totrue
on JVM startup.This solved for me:
"connection.setFixedLengthStreamingMode(myString.getBytes().length);" before set the Content-Length header.