Index: test/org/apache/commons/httpclient/TestEntityEnclosingMethod.java
===================================================================
--- test/org/apache/commons/httpclient/TestEntityEnclosingMethod.java (revision 161419)
+++ test/org/apache/commons/httpclient/TestEntityEnclosingMethod.java (working copy)
@@ -153,7 +153,7 @@
this.server.setHttpService(new EchoService());
try {
this.client.executeMethod(method);
- fail("ProtocolException should habe been thrown");
+ fail("ProtocolException should have been thrown");
} catch (ProtocolException ex) {
// expected
} finally {
@@ -214,7 +214,7 @@
this.client.getState().setCredentials(AuthScope.ANY, creds);
try {
this.client.executeMethod(method);
- fail("ProtocolException should habe been thrown");
+ fail("ProtocolException should have been thrown");
} catch (ProtocolException ex) {
// expected
} finally {
@@ -222,31 +222,51 @@
}
}
+ public void testEnclosedEntityNegativeLength() throws Exception {
+
+ String inputstr = "This is a test message";
+ byte[] input = inputstr.getBytes("US-ASCII");
+ InputStream instream = new ByteArrayInputStream(input);
+
+ RequestEntity requestentity = new InputStreamRequestEntity(
+ instream, -14);
+ PostMethod method = new PostMethod("/");
+ method.setRequestEntity(requestentity);
+ method.setContentChunked(false);
+ this.server.setHttpService(new EchoService());
+ try {
+ this.client.executeMethod(method);
+ assertEquals(200, method.getStatusCode());
+ String body = method.getResponseBodyAsString();
+ assertEquals(inputstr, body);
+ assertNotNull(method.getRequestHeader("Transfer-Encoding"));
+ assertNull(method.getRequestHeader("Content-Length"));
+ } finally {
+ method.releaseConnection();
+ }
+ }
-// public void testEnclosedEntityNegativeExplicitLength() throws Exception {
-//
-// String inputstr = "This is a test message";
-// byte[] input = inputstr.getBytes("US-ASCII");
-// InputStream instream = new ByteArrayInputStream(input);
-//
-// RequestEntity requestentity = new InputStreamRequestEntity(
-// instream, -14);
-// PostMethod method = new PostMethod("/");
-// method.setRequestEntity(requestentity);
-// this.server.setHttpService(new EchoService());
-// try {
-// this.client.executeMethod(method);
-// assertEquals(200, method.getStatusCode());
-// String body = method.getResponseBodyAsString();
-// assertEquals(inputstr, body);
-// assertNull(method.getRequestHeader("Content-Transfer"));
-// assertNotNull(method.getRequestHeader("Content-Length"));
-// assertEquals(-14, Integer.parseInt(
-// method.getRequestHeader("Content-Length").getValue()));
-// } finally {
-// method.releaseConnection();
-// }
-// }
-
+ public void testEnclosedEntityNegativeLengthHTTP1_0() throws Exception {
+
+ String inputstr = "This is a test message";
+ byte[] input = inputstr.getBytes("US-ASCII");
+ InputStream instream = new ByteArrayInputStream(input);
+
+ RequestEntity requestentity = new InputStreamRequestEntity(
+ instream, -14);
+ PostMethod method = new PostMethod("/");
+ method.setRequestEntity(requestentity);
+ method.setContentChunked(false);
+ method.getParams().setVersion(HttpVersion.HTTP_1_0);
+ this.server.setHttpService(new EchoService());
+ try {
+ this.client.executeMethod(method);
+ fail("ProtocolException should have been thrown");
+ } catch (ProtocolException ex) {
+ // expected
+ } finally {
+ method.releaseConnection();
+ }
+ }
}
Index: java/org/apache/commons/httpclient/methods/EntityEnclosingMethod.java
===================================================================
--- java/org/apache/commons/httpclient/methods/EntityEnclosingMethod.java (revision 161419)
+++ java/org/apache/commons/httpclient/methods/EntityEnclosingMethod.java (working copy)
@@ -63,7 +63,7 @@
* buffering of the content.
* @deprecated Use {@link InputStreamRequestEntity#CONTENT_LENGTH_AUTO}.
*/
- public static final long CONTENT_LENGTH_AUTO = -2;
+ public static final long CONTENT_LENGTH_AUTO = InputStreamRequestEntity.CONTENT_LENGTH_AUTO;
/**
* The request will use chunked transfer encoding. Content length is not
@@ -88,8 +88,12 @@
/** The content length of the requestBodyStream or one of
* CONTENT_LENGTH_AUTO and CONTENT_LENGTH_CHUNKED.
+ *
+ * @deprecated
*/
- private long requestContentLength = CONTENT_LENGTH_AUTO;
+ private long requestContentLength = InputStreamRequestEntity.CONTENT_LENGTH_AUTO;
+
+ private boolean chunked = false;
// ----------------------------------------------------------- Constructors
@@ -305,7 +309,7 @@
* @since 3.0
*/
public void setContentChunked(boolean chunked) {
- this.requestContentLength = chunked ? CONTENT_LENGTH_CHUNKED : CONTENT_LENGTH_AUTO;
+ this.chunked = chunked;
}
/**
@@ -319,11 +323,9 @@
if (!hasRequestContent()) {
return 0;
}
- // TODO what to do about setting request content and content length
- if (this.requestContentLength != CONTENT_LENGTH_AUTO) {
- return this.requestContentLength;
+ if (this.chunked) {
+ return -1;
}
-
if (this.requestEntity == null) {
this.requestEntity = generateRequestEntity();
}
@@ -398,11 +400,15 @@
if ((getRequestHeader("content-length") == null)
&& (getRequestHeader("Transfer-Encoding") == null)) {
long len = getRequestContentLength();
- if (len >= 0) {
+ if (len < 0) {
+ if (getEffectiveVersion().greaterEquals(HttpVersion.HTTP_1_1)) {
+ addRequestHeader("Transfer-Encoding", "chunked");
+ } else {
+ throw new ProtocolException(getEffectiveVersion() +
+ " does not support chunk encoding");
+ }
+ } else {
addRequestHeader("Content-Length", String.valueOf(len));
- } else if ((len == CONTENT_LENGTH_CHUNKED)
- && (getEffectiveVersion().greaterEquals(HttpVersion.HTTP_1_1))) {
- addRequestHeader("Transfer-Encoding", "chunked");
}
}
}
@@ -463,22 +469,16 @@
LOG.debug("Request body has not been specified");
return true;
}
-
- long contentLength = getRequestContentLength();
-
- if ((contentLength == CONTENT_LENGTH_CHUNKED)
- && getEffectiveVersion().lessEquals(HttpVersion.HTTP_1_0)) {
- throw new ProtocolException(
- "Chunked transfer encoding not allowed for " +
- getEffectiveVersion().toString());
+ if (this.requestEntity == null) {
+ this.requestEntity = generateRequestEntity();
}
-
- this.requestEntity = generateRequestEntity();
if (requestEntity == null) {
LOG.debug("Request body is empty");
return true;
}
+ long contentLength = getRequestContentLength();
+
if ((this.repeatCount > 0) && !requestEntity.isRepeatable()) {
throw new ProtocolException(
"Unbuffered entity enclosing request can not be repeated.");
@@ -488,7 +488,7 @@
OutputStream outstream = conn.getRequestOutputStream();
- if (contentLength == CONTENT_LENGTH_CHUNKED) {
+ if (contentLength < 0) {
outstream = new ChunkedOutputStream(outstream);
}
@@ -519,8 +519,9 @@
public void recycle() {
LOG.trace("enter EntityEnclosingMethod.recycle()");
clearRequestBody();
- this.requestContentLength = CONTENT_LENGTH_AUTO;
+ this.requestContentLength = InputStreamRequestEntity.CONTENT_LENGTH_AUTO;
this.repeatCount = 0;
+ this.chunked = false;
super.recycle();
}
Index: java/org/apache/commons/httpclient/methods/RequestEntity.java
===================================================================
--- java/org/apache/commons/httpclient/methods/RequestEntity.java (revision 161419)
+++ java/org/apache/commons/httpclient/methods/RequestEntity.java (working copy)
@@ -53,9 +53,13 @@
void writeRequest(OutputStream out) throws IOException;
/**
- * Gets the request entity's length.
- * @return either a number >= 0 or
- * {@link org.apache.commons.httpclient.methods.EntityEnclosingMethod#CONTENT_LENGTH_CHUNKED}
+ * Gets the request entity's length. This method should return a non-negative value if the content
+ * length is known or a negative value if it is not. In the latter case the
+ * {@link org.apache.commons.httpclient.methods.EntityEnclosingMethod} will use chunk encoding to
+ * transmit the request entity.
+ *
+ * @return a non-negative value when content length is known or a negative value when content length
+ * is not known
*/
long getContentLength();