Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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.

like image 580
chance Avatar asked May 19 '11 08:05

chance


People also ask

What is the purpose of Content Length in HTTP header?

The Content-Length header indicates the size of the message body, in bytes, sent to the recipient.

How do I change the Content Length of an HTTP header?

In PHP you would use something like this. header("Content-Length: ". filesize($filename)); In case of "Content-Type: application/x-www-form-urlencoded" the encoded data is sent to the processing agent designated so you can set the length or size of the data you are going to post.

Is Content Length header necessary in HTTP?

Description. The Content-Length is optional in an HTTP request. For a GET or DELETE the length must be zero. For POST, if Content-Length is specified and it does not match the length of the message-line, the message is either truncated, or padded with nulls to the specified length.

How is HTTP Content Length calculated?

As bytes are represented with two hexadecimal digits, one can divide the number of digits by two to obtain the content length (There are 12 hexadecimal digits in "48656c6c6f21" which equates to six bytes, as indicated in the header "Content-Length: 6" sent from the server).


1 Answers

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.

like image 92
Joachim Sauer Avatar answered Sep 21 '22 02:09

Joachim Sauer