mbecke 2004/05/11 20:07:03
Modified: httpclient/src/java/org/apache/commons/httpclient/methods
PostMethod.java EntityEnclosingMethod.java
RequestEntity.java InputStreamRequestEntity.java
ByteArrayRequestEntity.java
httpclient release_notes.txt
Added: httpclient/src/java/org/apache/commons/httpclient/methods
StringRequestEntity.java
Log:
Moved/added content type handling to RequestEntity.
PR: 28645
Submitted by: Michael Becke and Oleg Kalnichevski
Revision Changes Path
1.55 +13 -38
jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/methods/PostMethod.java
Index: PostMethod.java
===================================================================
RCS file:
/home/cvs/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/methods/PostMethod.java,v
retrieving revision 1.54
retrieving revision 1.55
diff -u -r1.54 -r1.55
--- PostMethod.java 28 Apr 2004 02:23:17 -0000 1.54
+++ PostMethod.java 12 May 2004 03:07:03 -0000 1.55
@@ -29,13 +29,9 @@
package org.apache.commons.httpclient.methods;
-import java.io.IOException;
import java.util.Iterator;
import java.util.Vector;
-import org.apache.commons.httpclient.HttpConnection;
-import org.apache.commons.httpclient.HttpException;
-import org.apache.commons.httpclient.HttpState;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.util.EncodingUtil;
import org.apache.commons.logging.Log;
@@ -162,9 +158,16 @@
*/
protected RequestEntity generateRequestEntity() {
if (!this.params.isEmpty()) {
+ // Use a ByteArrayRequestEntity instead of a StringRequestEntity.
+ // This is to avoid potential encoding issues. Form url encoded strings
+ // are ASCII by definition but the content type may not be. Treating
the content
+ // as bytes allows us to keep the current charset without worrying
about how
+ // this charset will effect the encoding of the form url encoded string.
String content = EncodingUtil.formUrlEncode(getParameters(),
getRequestCharSet());
- ByteArrayRequestEntity entity = new ByteArrayRequestEntity();
- entity.setContent(EncodingUtil.getAsciiBytes(content));
+ ByteArrayRequestEntity entity = new ByteArrayRequestEntity(
+ EncodingUtil.getAsciiBytes(content),
+ FORM_URL_ENCODED_CONTENT_TYPE
+ );
return entity;
} else {
return super.generateRequestEntity();
@@ -400,33 +403,5 @@
}
clearRequestBody();
addParameters(parametersBody);
- }
-
- /**
- * Adds <tt>Content Type: application/x-www-form-urlencoded</tt> header in
- * addition to the "standard" set of headers, if no <tt>Content Type</tt>
- * header has been set by the user
- *
- * @param state the [EMAIL PROTECTED] HttpState state} information associated
with this method
- * @param conn the [EMAIL PROTECTED] HttpConnection connection} used to execute
- * this HTTP method
- *
- * @throws IOException if an I/O (transport) error occurs. Some transport
exceptions
- * can be recovered from.
- * @throws HttpException if a protocol exception occurs. Usually protocol
exceptions
- * cannot be recovered from.
- *
- * @since 2.0
- */
- protected void addRequestHeaders(HttpState state, HttpConnection conn)
- throws IOException, HttpException {
- super.addRequestHeaders(state, conn);
-
- if (!this.params.isEmpty()) {
- //there are some parameters, so set the contentType header
- if (getRequestHeader("Content-Type") == null) {
- setRequestHeader("Content-Type", FORM_URL_ENCODED_CONTENT_TYPE);
- }
- }
}
}
1.34 +44 -15
jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/methods/EntityEnclosingMethod.java
Index: EntityEnclosingMethod.java
===================================================================
RCS file:
/home/cvs/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/methods/EntityEnclosingMethod.java,v
retrieving revision 1.33
retrieving revision 1.34
diff -u -r1.33 -r1.34
--- EntityEnclosingMethod.java 8 May 2004 10:12:07 -0000 1.33
+++ EntityEnclosingMethod.java 12 May 2004 03:07:03 -0000 1.34
@@ -34,12 +34,12 @@
import java.io.OutputStream;
import org.apache.commons.httpclient.ChunkedOutputStream;
+import org.apache.commons.httpclient.Header;
import org.apache.commons.httpclient.HttpConnection;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.HttpState;
import org.apache.commons.httpclient.HttpVersion;
import org.apache.commons.httpclient.ProtocolException;
-import org.apache.commons.httpclient.util.EncodingUtil;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -60,12 +60,14 @@
/**
* The content length will be calculated automatically. This implies
* buffering of the content.
+ * @deprecated Use [EMAIL PROTECTED]
InputStreamRequestEntity#CONTENT_LENGTH_AUTO}.
*/
public static final long CONTENT_LENGTH_AUTO = -2;
/**
* The request will use chunked transfer encoding. Content length is not
* calculated and the content is not buffered.<br>
+ * @deprecated Use [EMAIL PROTECTED] #setContentChunked(boolean)}.
*/
public static final long CONTENT_LENGTH_CHUNKED = -1;
@@ -167,19 +169,17 @@
if (requestBody != null) {
// use the request body, if it exists.
// this is just for backwards compatability
- ByteArrayRequestEntity entity = new ByteArrayRequestEntity();
- entity.setContent(requestBody);
- this.requestEntity = entity;
+ this.requestEntity = new ByteArrayRequestEntity(requestBody);
} else if (this.requestStream != null) {
- InputStreamRequestEntity entity = new InputStreamRequestEntity();
- entity.setContent(requestStream);
- entity.setContentLength(requestContentLength);
+ this.requestEntity = new InputStreamRequestEntity(
+ requestStream,
+ requestContentLength);
this.requestStream = null;
- this.requestEntity = entity;
} else if (this.requestString != null) {
- ByteArrayRequestEntity entity = new ByteArrayRequestEntity();
- entity.setContent(EncodingUtil.getBytes(this.requestString,
getRequestCharSet()));
- this.requestEntity = entity;
+ this.requestEntity = new StringRequestEntity(
+ requestString,
+ null,
+ getRequestCharSet());
}
return this.requestEntity;
@@ -238,6 +238,25 @@
this.requestContentLength = length;
}
+ /* (non-Javadoc)
+ * @see org.apache.commons.httpclient.HttpMethodBase#getRequestCharSet()
+ */
+ public String getRequestCharSet() {
+ if (getRequestHeader("Content-Type") == null) {
+ // check the content type from request entity
+ // We can't call getRequestEntity() since it will probably call
+ // this method.
+ if (this.requestEntity != null) {
+ return getContentCharSet(
+ new Header("Content-Type", requestEntity.getContentType()));
+ } else {
+ return super.getRequestCharSet();
+ }
+ } else {
+ return super.getRequestCharSet();
+ }
+ }
+
/**
* Sets length information about the request body.
*
@@ -330,7 +349,17 @@
super.addRequestHeaders(state, conn);
addContentLengthRequestHeader(state, conn);
+
+ // only use the content type of the request entity if it has not already
been
+ // set manually
+ if (getRequestHeader("Content-Type") == null) {
+ RequestEntity requestEntity = getRequestEntity();
+ if (requestEntity != null && requestEntity.getContentType() != null) {
+ setRequestHeader("Content-Type", requestEntity.getContentType());
+ }
+ }
}
+
/**
* Generates <tt>Content-Length</tt> or <tt>Transfer-Encoding: Chunked</tt>
* request header, as long as no <tt>Content-Length</tt> request header
1.2 +11 -3
jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/methods/RequestEntity.java
Index: RequestEntity.java
===================================================================
RCS file:
/home/cvs/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/methods/RequestEntity.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- RequestEntity.java 28 Apr 2004 02:23:17 -0000 1.1
+++ RequestEntity.java 12 May 2004 03:07:03 -0000 1.2
@@ -56,4 +56,12 @@
*/
long getContentLength();
+ /**
+ * Gets the entity's content type. This content type will be used as the value
for the
+ * "Content-Type" header.
+ * @return
+ * @see org.apache.commons.httpclient.HttpMethod#setRequestHeader(String,
String)
+ */
+ String getContentType();
+
}
1.2 +70 -28
jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/methods/InputStreamRequestEntity.java
Index: InputStreamRequestEntity.java
===================================================================
RCS file:
/home/cvs/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/methods/InputStreamRequestEntity.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- InputStreamRequestEntity.java 28 Apr 2004 02:23:17 -0000 1.1
+++ InputStreamRequestEntity.java 12 May 2004 03:07:03 -0000 1.2
@@ -43,21 +43,83 @@
*/
public class InputStreamRequestEntity implements RequestEntity {
+ /**
+ * The content length will be calculated automatically. This implies
+ * buffering of the content.
+ */
+ public static final int CONTENT_LENGTH_AUTO = -2;
+
private static final Log LOG =
LogFactory.getLog(InputStreamRequestEntity.class);
- private long contentLength = EntityEnclosingMethod.CONTENT_LENGTH_AUTO;
+ private long contentLength;
- private InputStream content = null;
+ private InputStream content;
/** The buffered request body, if any. */
private byte[] buffer = null;
+
+ /** The content type */
+ private String contentType;
/**
- * Creates a new InputStreamRequestEntity with no content.
+ * Creates a new InputStreamRequestEntity with the given content and a content
type of
+ * [EMAIL PROTECTED] RequestEntity#CONTENT_LENGTH_AUTO}.
+ * @param content The content to set.
*/
- public InputStreamRequestEntity() {
+ public InputStreamRequestEntity(InputStream content) {
+ this(content, null);
+ }
+
+ /**
+ * Creates a new InputStreamRequestEntity with the given content, content type,
and a
+ * content length of [EMAIL PROTECTED] RequestEntity#CONTENT_LENGTH_AUTO}.
+ * @param content The content to set.
+ * @param contentType The type of the content, or <code>null</code>.
+ */
+ public InputStreamRequestEntity(InputStream content, String contentType) {
+ this(content, CONTENT_LENGTH_AUTO, contentType);
+ }
+
+ /**
+ * Creates a new InputStreamRequestEntity with the given content and content
length.
+ * @param content The content to set.
+ * @param contentLength The content size in bytes or any of
+ * [EMAIL PROTECTED] EntityEnclosingMethod#CONTENT_LENGTH_AUTO
CONTENT_LENGTH_AUTO},
+ * [EMAIL PROTECTED] EntityEnclosingMethod#CONTENT_LENGTH_CHUNKED
CONTENT_LENGTH_CHUNKED}. If the number
+ * of bytes or <code>CONTENT_LENGTH_CHUNKED</code> is specified the content
will not be
+ * buffered when [EMAIL PROTECTED] #getContentLength()} is called.
+ */
+ public InputStreamRequestEntity(InputStream content, long contentLength) {
+ this(content, contentLength, null);
+ }
+
+ /**
+ * Creates a new InputStreamRequestEntity with the given content, content
length, and
+ * content type.
+ * @param content The content to set.
+ * @param contentLength The content size in bytes or any of
+ * [EMAIL PROTECTED] EntityEnclosingMethod#CONTENT_LENGTH_AUTO
CONTENT_LENGTH_AUTO},
+ * [EMAIL PROTECTED] EntityEnclosingMethod#CONTENT_LENGTH_CHUNKED
CONTENT_LENGTH_CHUNKED}. If the number
+ * of bytes or <code>CONTENT_LENGTH_CHUNKED</code> is specified the content
will not be
+ * buffered when [EMAIL PROTECTED] #getContentLength()} is called.
+ * @param contentType The type of the content, or <code>null</code>.
+ */
+ public InputStreamRequestEntity(InputStream content, long contentLength, String
contentType) {
+ if (content == null) {
+ throw new IllegalArgumentException("The content cannot be null");
+ }
+ this.content = content;
+ this.contentLength = contentLength;
+ this.contentType = contentType;
}
+ /* (non-Javadoc)
+ * @see org.apache.commons.httpclient.methods.RequestEntity#getContentType()
+ */
+ public String getContentType() {
+ return contentType;
+ }
+
/**
* Buffers request body input stream.
*/
@@ -125,37 +187,17 @@
* @see #setContentLength(long)
*/
public long getContentLength() {
- if (contentLength == EntityEnclosingMethod.CONTENT_LENGTH_AUTO && buffer ==
null) {
+ if (contentLength == CONTENT_LENGTH_AUTO && buffer == null) {
bufferContent();
}
return contentLength;
}
/**
- * Sets the content length.
- *
- * @param contentLength The content size in bytes or any of
- * [EMAIL PROTECTED] EntityEnclosingMethod#CONTENT_LENGTH_AUTO
CONTENT_LENGTH_AUTO},
- * [EMAIL PROTECTED] EntityEnclosingMethod#CONTENT_LENGTH_CHUNKED
CONTENT_LENGTH_CHUNKED}. If the number
- * of bytes or <code>CONTENT_LENGTH_CHUNKED</code> is specified the content
will not be
- * buffered when [EMAIL PROTECTED] #getContentLength()} is called.
- */
- public void setContentLength(long contentLength) {
- this.contentLength = contentLength;
- }
-
- /**
* @return Returns the content.
*/
public InputStream getContent() {
return content;
- }
-
- /**
- * @param inputStream The content to set.
- */
- public void setContent(InputStream inputStream) {
- this.content = inputStream;
}
}
1.2 +30 -19
jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/methods/ByteArrayRequestEntity.java
Index: ByteArrayRequestEntity.java
===================================================================
RCS file:
/home/cvs/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/methods/ByteArrayRequestEntity.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- ByteArrayRequestEntity.java 28 Apr 2004 02:23:17 -0000 1.1
+++ ByteArrayRequestEntity.java 12 May 2004 03:07:03 -0000 1.2
@@ -41,12 +41,29 @@
/** The content */
private byte[] content;
+ /** The content type */
+ private String contentType;
+
+ /**
+ * Creates a new entity with the given content.
+ * @param content The content to set.
+ */
+ public ByteArrayRequestEntity(byte[] content) {
+ this(content, null);
+ }
+
/**
- * Creates a new entity with no content. The content must be set before this
entity can be
- * used.
+ * Creates a new entity with the given content and content type.
+ * @param content The content to set.
+ * @param contentType The content type to set or <code>null</code>.
*/
- public ByteArrayRequestEntity() {
+ public ByteArrayRequestEntity(byte[] content, String contentType) {
super();
+ if (content == null) {
+ throw new IllegalArgumentException("The content cannot be null");
+ }
+ this.content = content;
+ this.contentType = contentType;
}
/**
@@ -57,12 +74,16 @@
}
/* (non-Javadoc)
+ * @see org.apache.commons.httpclient.methods.RequestEntity#getContentType()
+ */
+ public String getContentType() {
+ return contentType;
+ }
+
+ /* (non-Javadoc)
* @see
org.apache.commons.httpclient.RequestEntity#writeRequest(java.io.OutputStream)
*/
public void writeRequest(OutputStream out) throws IOException {
- if (content == null) {
- throw new IllegalStateException("Content must be set before entity is
written");
- }
out.write(content);
}
@@ -78,16 +99,6 @@
*/
public byte[] getContent() {
return content;
- }
-
- /**
- * @param content The content to set.
- */
- public void setContent(byte[] content) {
- if (content == null) {
- throw new IllegalArgumentException("The content cannot be null");
- }
- this.content = content;
}
}
1.1
jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/methods/StringRequestEntity.java
Index: StringRequestEntity.java
===================================================================
/*
* $Header:
/home/cvs/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/methods/StringRequestEntity.java,v
1.1 2004/05/12 03:07:03 mbecke Exp $
* $Revision: 1.1 $
* $Date: 2004/05/12 03:07:03 $
*
* ====================================================================
*
* Copyright 2004 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
* [Additional notices, if required by prior licensing conditions]
*
*/
package org.apache.commons.httpclient.methods;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import org.apache.commons.httpclient.HeaderElement;
import org.apache.commons.httpclient.NameValuePair;
/**
* A RequestEntity that contains a String.
*/
public class StringRequestEntity implements RequestEntity {
/** The content */
private String content;
/** The charset */
private String charset;
/** The content type (i.e. text/html; charset=EUC-JP). */
private String contentType;
/**
* Creates a new entity with the given content
*
* @param content The content to set.
*/
public StringRequestEntity(String content) {
this(content, null, null);
}
/**
* Creates a new entity with the given content, content type, and charset.
*
* @param content The content to set.
* @param contentType The type of the content, or <code>null</code>. The value
retured
* by [EMAIL PROTECTED] #getContentType()}. If this content type contains a
charset and the charset
* parameter is null, the content's type charset will be used.
* @param charset The charset of the content, or <code>null</code>. Used to
convert the
* content to bytes. If the content type does not contain a charset and
charset is not null,
* then the charset will be appended to the content type.
*/
public StringRequestEntity(String content, String contentType, String charset) {
super();
if (content == null) {
throw new IllegalArgumentException("The content cannot be null");
}
this.content = content;
this.contentType = contentType;
this.charset = charset;
// resolve the content type and the charset
if (contentType != null) {
HeaderElement[] values = HeaderElement.parseElements(contentType);
NameValuePair charsetPair = null;
for (int i = 0; i < values.length; i++) {
if ((charsetPair = values[i].getParameterByName("charset")) != null)
{
// charset found
break;
}
}
if (charset == null && charsetPair != null) {
// use the charset from the content type
this.charset = charsetPair.getValue();
} else if (charset != null && charsetPair == null) {
// append the charset to the content type
this.contentType = contentType + "; charset=" + charset;
}
}
}
/* (non-Javadoc)
* @see org.apache.commons.httpclient.methods.RequestEntity#getContentType()
*/
public String getContentType() {
return contentType;
}
/**
* @return <code>true</code>
*/
public boolean isRepeatable() {
return true;
}
/* (non-Javadoc)
* @see
org.apache.commons.httpclient.RequestEntity#writeRequest(java.io.OutputStream)
*/
public void writeRequest(OutputStream out) throws IOException {
Writer writer = null;
if (this.charset != null) {
writer = new OutputStreamWriter(out, this.charset);
} else {
writer = new OutputStreamWriter(out);
}
writer.write(content);
writer.flush();
}
/**
* @return The length of the content.
*/
public long getContentLength() {
return content.length();
}
/**
* @return Returns the content.
*/
public String getContent() {
return this.content;
}
/**
* @return Returns the charset used to convert the content to bytes.
<code>null</code> if
* no charset as been specified.
*/
public String getCharset() {
return charset;
}
}
1.24 +3 -0 jakarta-commons/httpclient/release_notes.txt
Index: release_notes.txt
===================================================================
RCS file: /home/cvs/jakarta-commons/httpclient/release_notes.txt,v
retrieving revision 1.23
retrieving revision 1.24
diff -u -r1.23 -r1.24
--- release_notes.txt 11 May 2004 20:48:12 -0000 1.23
+++ release_notes.txt 12 May 2004 03:07:03 -0000 1.24
@@ -50,6 +50,9 @@
Changes on the CVS trunk:
-------------------------
+ * 28645 - Moved/added content type handling to the RequestEntity.
+ Contributed by Michael Becke <mbecke at apache.org>, Oleg Kalnichevski
<olegk at apache.org>
+
* 20288 - Added ability to abort execution of HTTP methods
Contributed by Oleg Kalnichevski <olegk at apache.org>
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]