views:

82

answers:

1

I am using the Apache HttpClient (4.1) included in Android to execute a HttpPut. I have verified that I only have 1 content-length header. However, every time I send the request, I get a protocol exception about the Content-Length header already specified.

HttpClient client = new DefaultHttpClient();
putMethod = new HttpPut(url + encodedFileName);
putMethod.addHeader(..)  //<-once for each header
putMethod.setEntity(new ByteArrayEntity(data));
client.execute(putMethod);  //throws Exception

Caused by: org.apache.http.ProtocolException: Content-Length header already present at org.apache.http.protocol.RequestContent.process(RequestContent.java:70) at org.apache.http.protocol.BasicHttpProcessor.process(BasicHttpProcessor.java:290)

Any ideas?

+4  A: 

I've not used HttpClient myself, but I suspect that the problem is that putMethod.setEntity(...) is implicitly supplying a content length and you are also setting it explicitly via one of the putMethod.addHeader(...) calls.

Stephen C
Exactly. You never have to set Content-Length yourself in Java unless you are using a plain Socket.
EJP
@EJP - or the java.net URLConnection classes.
Stephen C
No, they do it for you. You only have to set it if you *aren't* using those.
EJP
@EJP - incorrect. With an HttpURLConnection, the **only** way to create an HTTP request with a body is for the application to call `getOutput()` and write to the resulting `OutputStream`. The implementation only knows how many bytes of content it is sending when the application closes the stream. By then it is to late to go back and write a "content-length" in the request header.
Stephen C
Obviously you've never tried it. HttpURLConnection provides a ByteArrayOutputStream as he output stream, so it can do exactly that. Except in the case when you are in chunked transfer mode when it doesn't need to.
EJP
@EJP - I use HttpURLConnection all the time. But I've always gone on what I've understood the javadoc to mean.
Stephen C
Fair enough, but the Javadoc doesn't say it can't build its own Content-Length header, and it also says 'In the common case, all of the pre-connection parameters and general request properties can be ignored: the pre-connection parameters and request properties default to sensible values. For most clients of this interface, there are only two interesting methods ...'
EJP
Thanks for the help guys. I found the source for 4.1 and of course you are right. However, it seems you either could or should in 3.x. Not sure which...
AdamC
Btw - I was able to verify this by setting a request interceptor (at the end) and looking at the modified request. It shows the Content-Length already set.
AdamC