Why does Content-Length HTTP header field use a value other than the one given in Java code?
Asked Answered
S

2

6

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.

Sampling answered 19/5, 2011 at 8:58 Comment(0)
A
17

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.

Analysis answered 19/5, 2011 at 9:6 Comment(4)
The value of Content-Length was hardcoded by mistake. What's surprising me is that it works. I want to know why.Sampling
Your guess sounds reasonable. But where to find the documentation on it?Sampling
@joachim-sauer: Great answer! But I have tested with sun.net.http.allowRestrictedHeaders=true, and found the result is the same as before.Sampling
@wang: my long-ish analysis doesn't really apply here, since the Content-Length will be overwritten by the correct value anyway. I've updated my answer.Analysis
R
0

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.

Rhinitis answered 6/11, 2018 at 18:56 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.