JDK-6997628 : HttpURLConnection strips Content-Length header on Post
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.net
  • Affected Version: 6u22
  • Priority: P4
  • Status: Closed
  • Resolution: Won't Fix
  • OS: linux
  • CPU: x86
  • Submitted: 2010-11-04
  • Updated: 2022-07-04
  • Resolved: 2022-07-04
Description
FULL PRODUCT VERSION :
java version "1.6.0_22"


ADDITIONAL OS VERSION INFORMATION :
This appears on:
Ubuntu Linux
Windows 2003 32bit and 64bit
Windows 2008 64bit
Mac

EXTRA RELEVANT SYSTEM CONFIGURATION :
Configuration is not relavant it appears when upgrading any of OS to build 22

A DESCRIPTION OF THE PROBLEM :
When doing a HTTP Post via the HttpURLConnection

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
                    URL url = new URL("http://httpserver/uploadhandler");

                    HttpURLConnection urlConn = (HttpURLConnection)url.openConnection();

                    urlConn.setDoInput(true);

                    urlConn.setDoOutput(true);

                    urlConn.setUseCaches(false);

                    // Setup the Headers
                    urlConn.setRequestMethod("POST");
                    urlConn.setRequestProperty("Connection", "Keep-Alive");
                    urlConn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary + "; charset=UTF-8");
                    urlConn.setRequestProperty("Transfer-Encoding", "chunked" );
                    urlConn.setRequestProperty("User-Agent", "Test Agent" );
                    urlConn.setRequestProperty("Content-Length", Long.toString(contentLength));
                    urlConn.setChunkedStreamingMode(0);
                    urlConn.setReadTimeout(READ_TIMEOUT);
                    urlConn.setConnectTimeout(READ_TIMEOUT);

                    urlConn.connect();

                    DataOutputStream printout = new DataOutputStream (urlConn.getOutputStream());

                    // Write boundary and header
                    printout.writeBytes(contentBoundary);
                    printout.write(headerStr.getBytes("UTF-8"));

                    // write upload buffer
                    if (bytesRead != -1) {
                        printout.write(buffer, 0, bytesRead);
                    }

                    // Send the footer
                    printout.writeBytes(lineEnd);
                    printout.writeBytes(endingBoundary);

Using the above code in any version previous to build 22 the result shows a Content-Length header in the HTTP Request when inspected through wireshark.

Wireshark output with missing header:


POST /uploadhandler HTTP/1.1
Content-Type: multipart/form-data; boundary=***********vdvuiBIOG&#(RO#$Bkjdbvsdbebr
User-Agent: Test Agent
Cache-Control: no-cache
Pragma: no-cache
Host: httpserver
Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
Connection: keep-alive
Transfer-Encoding: chunked


EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The Content-Length as provided by the HttpURLConnection.setRequestProperty should be evident in the request to the HTTP server when doing a post.
ACTUAL -
All headers provided by the setRequestProperty are sent correctly except the Content-Length which appears to be stripped out.

ERROR MESSAGES/STACK TRACES THAT OCCUR :
No Error except from the server and wireshark capture not showing the content-length header.

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
                    URL url = new URL("http://httpserver/uploadhandler");

                    HttpURLConnection urlConn = (HttpURLConnection)url.openConnection();

                    urlConn.setDoInput(true);

                    urlConn.setDoOutput(true);

                    urlConn.setUseCaches(false);

                    // Setup the Headers
                    urlConn.setRequestMethod("POST");
                    urlConn.setRequestProperty("Connection", "Keep-Alive");
                    urlConn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary + "; charset=UTF-8");
                    urlConn.setRequestProperty("Transfer-Encoding", "chunked" );
                    urlConn.setRequestProperty("User-Agent", "Test Agent" );
                    urlConn.setRequestProperty("Content-Length", Long.toString(contentLength));
                    urlConn.setChunkedStreamingMode(0);
                    urlConn.setReadTimeout(READ_TIMEOUT);
                    urlConn.setConnectTimeout(READ_TIMEOUT);

                    urlConn.connect();

                    DataOutputStream printout = new DataOutputStream (urlConn.getOutputStream());

                    // Write boundary and header
                    printout.writeBytes(contentBoundary);
                    printout.write(headerStr.getBytes("UTF-8"));

                    // write upload buffer
                    if (bytesRead != -1) {
                        printout.write(buffer, 0, bytesRead);
                    }

                    // Send the footer
                    printout.writeBytes(lineEnd);
                    printout.writeBytes(endingBoundary);

---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
Unknown

Comments
As stated in the previous comment, if you need to set one of the restricted headers, define sun.net.http.allowRestrictedHeaders property. In most cases setting these headers explicitly is not correct. In particular, sending both Transfer-Encoding and Content-Length on the same request is prohibited by HTTP 1.1 spec.
04-07-2022

WORK AROUND Run with -Dsun.net.http.allowRestrictedHeaders=true
05-11-2010

EVALUATION The fix for CR 6961084 restricts the setting of some potentially security sensitive headers. Since these headers were allowed to be set in previous releases then of course compatibility is effected. A decision was made that compatibility was secondary to the security risk these headers posed. We understand that there may be valid apps out there that will be effected by this, so the sun.net.http.allowRestrictedHeaders property was added to revert to previous behavior. On another note, why is the Content-Length header being set when using chunked encoding? The Content-Length header seems unnecessary in this case.
05-11-2010