Index: java/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.121 diff -u -r1.121 HttpMethodBase.java --- java/org/apache/commons/httpclient/HttpMethodBase.java 7 Mar 2003 13:50:52 -0000 1.121 +++ java/org/apache/commons/httpclient/HttpMethodBase.java 11 Mar 2003 10:25:37 -0000 @@ -649,6 +649,67 @@ } } + + /** + * Return the length (in bytes) of my response body, as specified in a + * Content-Length header. + * + *

+ * Return -1 when the content-length is unknown. + *

+ * + * @return content length, if Content-Length header is available. + * 0 indicates that the request has no body. + * If Content-Length header is not present, the method + * returns -1. + */ + protected int getResponseContentLength() { + Header[] headers = getResponseHeaderGroup().getHeaders("Content-Length"); + if (headers.length == 0) { + return -1; + } + if (headers.length > 1) { + LOG.warn("Multiple content-length headers detected"); + } + for (int i = headers.length - 1; i >= 0; i++) { + Header header = headers[i]; + String lengthValue = null; + // we're using this just in case the content length is duplicated + // i.e. '57, 57' + try { + HeaderElement[] lengthElements = header.getValues(); + + if (lengthElements.length > 1) { + // looks like the content length header was duplicated. if so + // they won't be key=value pairs so we just want to get + // the name not the value (which should be null) + // take the first value and ignore any others + lengthValue = lengthElements[0].getName(); + } else { + lengthValue = header.getValue(); + } + } + catch(HttpException e) { + if (LOG.isWarnEnabled()) { + LOG.warn("Invalid content-length value: " + e.getMessage()); + } + lengthValue = null; + } + if (lengthValue != null) { + try { + return Integer.parseInt(lengthValue); + } catch(NumberFormatException e) { + if (LOG.isWarnEnabled()) { + LOG.warn("Invalid content-length value: " + e.getMessage()); + } + } + } + // See if we can have better luck with another header, if present + } + return -1; + } + + /** * Return my response body, if any, as a byte array. Otherwise return * null. @@ -1798,7 +1859,6 @@ LOG.trace("enter HttpMethodBase.readResponseBody(HttpState, HttpConnection)"); responseBody = null; // is this desired? - Header lengthHeader = getResponseHeader("Content-Length"); Header transferEncodingHeader = getResponseHeader("Transfer-Encoding"); InputStream is = conn.getResponseInputStream(); if (Wire.enabled()) { @@ -1807,45 +1867,21 @@ InputStream result = null; // We use Transfer-Encoding if present and ignore Content-Length. // RFC2616, 4.4 item number 3 - if (null != transferEncodingHeader) { + if (transferEncodingHeader != null) { if ("chunked".equalsIgnoreCase(transferEncodingHeader.getValue())) { result = new ChunkedInputStream(is, this); } - } else if (null != lengthHeader) { - - // we're using this just in case the content length is duplicated - // i.e. '57, 57' - HeaderElement[] lengthElements = lengthHeader.getValues(); - String lengthValue = null; - - if (lengthElements.length > 1) { - // looks like the content length header was duplicated. if so - // they won't be key=value pairs so we just want to get - // the name not the value (which should be null) - // take the first value and ignore any others - lengthValue = lengthElements[0].getName(); + } else { + int expectedLength = getResponseContentLength(); + if (expectedLength == -1) { + if (canResponseHaveBody(statusLine.getStatusCode()) && + !getName().equalsIgnoreCase("connect")) { + result = is; + } } else { - lengthValue = lengthHeader.getValue(); - } - - try { - int expectedLength = Integer.parseInt(lengthValue); - // FIXME: what if the content length is 0, perhaps we should - // just return an empty stream in that case result = new ContentLengthInputStream(is, expectedLength); - } catch (NumberFormatException e) { - throw new HttpException( - "Unable to parse server response content length: '" - + lengthValue + "'" - ); - } - - } else if (canResponseHaveBody(statusLine.getStatusCode()) - && !getName().equals(ConnectMethod.NAME)) { - result = is; - } - + } // if there is a result - ALWAYS wrap it in an observer which will // close the underlying stream as soon as it is consumed, and notify // the watcher that the stream has been consumed.