Index: org/apache/commons/httpclient/ConnectMethod.java
===================================================================
RCS file: /home/cvspublic/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/ConnectMethod.java,v
retrieving revision 1.22
diff -u -r1.22 ConnectMethod.java
--- org/apache/commons/httpclient/ConnectMethod.java 10 Nov 2003 23:19:49 -0000 1.22
+++ org/apache/commons/httpclient/ConnectMethod.java 12 Nov 2003 10:21:34 -0000
@@ -238,7 +238,7 @@
*
* @return true if the connection should be closed
*/
- protected boolean shouldCloseConnection(HttpConnection conn) {
+ protected boolean shouldCloseConnection(HttpConnection conn) throws ProtocolException {
if (getStatusCode() == HttpStatus.SC_OK) {
Header connectionHeader = null;
if (!conn.isTransparent()) {
Index: org/apache/commons/httpclient/HttpMethodBase.java
===================================================================
RCS file: /home/cvspublic/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/HttpMethodBase.java,v
retrieving revision 1.189
diff -u -r1.189 HttpMethodBase.java
--- org/apache/commons/httpclient/HttpMethodBase.java 5 Nov 2003 20:45:34 -0000 1.189
+++ org/apache/commons/httpclient/HttpMethodBase.java 12 Nov 2003 10:21:34 -0000
@@ -123,6 +123,7 @@
* @author Oleg Kalnichevski
* @author Mike Bowler
* @author Gary Gregory
+ * @author Christian Kohlschuetter
*
* @version $Revision: 1.189 $ $Date: 2003/11/05 20:45:34 $
*/
@@ -697,6 +698,9 @@
setResponseStream(null);
this.responseBody = outstream.toByteArray();
}
+ } catch (ProtocolException e) {
+ LOG.error("Protocol violation detected while reading response body", e);
+ this.responseBody = null;
} catch (IOException e) {
LOG.error("I/O failure reading response body", e);
this.responseBody = null;
@@ -879,14 +883,43 @@
* @param conn the connection in question
*
* @return boolean true if we should close the connection.
+ * @throws ProtocolException if we detect an intolerable protocol violation
*/
- protected boolean shouldCloseConnection(HttpConnection conn) {
+ protected boolean shouldCloseConnection(HttpConnection conn) throws ProtocolException {
// Connection must be closed due to an abnormal circumstance
if (isConnectionCloseForced()) {
LOG.debug("Should force-close connection.");
return true;
}
+
+ // At this point, no response data should be available.
+ // If there is data available, assume a protocol violation and
+ // close the connection
+ int detectSurplusData =
+ getParams().getIntParameter(
+ HttpMethodParams.DETECT_SURPLUS_RESPONSE_DATA,
+ 1);
+ if (detectSurplusData > 0) {
+ try {
+ if (conn.isResponseAvailable()) {
+ if (detectSurplusData == 2) {
+ throw new ProtocolException("Unexpected surplus response data available");
+ } else {
+ LOG.debug("Unexpected surplus response data available");
+ return true;
+ }
+ }
+
+ } catch (ProtocolException e) {
+ throw e;
+ } catch (IOException e) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Unexpected IOException; closing connection", e);
+ }
+ return true;
+ }
+ }
Header connectionHeader = null;
// In case being connected via a proxy server
@@ -1754,7 +1787,7 @@
result = new AutoCloseInputStream(
result,
new ResponseConsumedWatcher() {
- public void responseConsumed() {
+ public void responseConsumed() throws ProtocolException {
responseBodyConsumed();
}
}
@@ -1831,14 +1864,26 @@
throws IOException, HttpRecoverableException, HttpException {
LOG.trace("enter HttpMethodBase.readStatusLine(HttpState, HttpConnection)");
+ final int maxGarbageLines = getParams().getIntParameter(HttpMethodParams.STATUS_LINE_GARBAGE_LIMIT, Integer.MAX_VALUE);
+
//read out the HTTP status string
- String s = conn.readLine();
- while ((s != null) && !StatusLine.startsWithHTTP(s)) {
- if (Wire.enabled()) {
- Wire.input(s + "\r\n");
- }
+ int attempts = 0;
+ String s;
+ do {
s = conn.readLine();
- }
+ if(s != null) {
+ if (Wire.enabled()) {
+ Wire.input(s + "\r\n");
+ }
+
+ if(StatusLine.startsWithHTTP(s)) {
+ break;
+ } else {
+ s = null;
+ }
+ }
+ } while(attempts++ < maxGarbageLines);
+
if (s == null) {
// A null statusString means the connection was lost before we got a
// response. Try again.
@@ -1846,9 +1891,7 @@
+ " line from the response: unable to find line starting with"
+ " \"HTTP\"");
}
- if (Wire.enabled()) {
- Wire.input(s + "\r\n");
- }
+
//create the status line from the status string
statusLine = new StatusLine(s);
@@ -2236,7 +2279,7 @@
* inside the execute call.
+ * Such surplus data makes the HTTP connection unreliable for keep-alive + * requests, as malicious response data (faked headers etc.) can lead to undesired + * results on the next request using that connection. + *
+ *+ * The following values are permitted: + *
0 - No action (detection disabled)1 - If surplus data has been detected, simply close the connection2 - If surplus data has been detected, throw a {@link ProtocolException}+ * This parameter expects a value of type {@link Integer}. + *
+ */ + public static final String DETECT_SURPLUS_RESPONSE_DATA = "http.protocol.detect-surplus-response-data"; + + /** + * Defines the maximum number of ignorable lines before we expect + * a HTTP response's status code. + *
+ * With HTTP/1.1 persistent connections, the problem arises that
+ * broken scripts could return a wrong Content-Length
+ * (there are more bytes sent than specified).
+ * Unfortunately, in some cases, this is not possible after the bad response,
+ * but only before the next one.
+ * So, HttpClient must be able to skip those surplus lines this way.
+ *
+ * Set this to 0 to disallow any garbage lines before the status line.
+ * To specify no limit, use {@link Integer.MAX_VALUE}.
+ *