remm 02/01/13 16:17:59 Modified: http11/src/java/org/apache/coyote/http11 Http11Connector.java http11/src/java/org/apache/coyote/http11/filters ChunkedInputFilter.java Log: - Add input chunking support (last big piece of code for the HTTP connector). - Add support for the "no content" status codes: 204, 205 and 304. - Add support for HEAD. - Add HTTP/0.9 support (untested). Revision Changes Path 1.12 +43 -14 jakarta-tomcat-connectors/http11/src/java/org/apache/coyote/http11/Http11Connector.java Index: Http11Connector.java =================================================================== RCS file: /home/cvs/jakarta-tomcat-connectors/http11/src/java/org/apache/coyote/http11/Http11Connector.java,v retrieving revision 1.11 retrieving revision 1.12 diff -u -r1.11 -r1.12 --- Http11Connector.java 10 Jan 2002 16:58:17 -0000 1.11 +++ Http11Connector.java 14 Jan 2002 00:17:58 -0000 1.12 @@ -446,6 +446,10 @@ } else if (protocolMB.equals(Constants.HTTP_10)) { http11 = false; keepAlive = false; + } else if (protocolMB.equals("")) { + // HTTP/0.9 + http11 = false; + keepAlive = false; } else { // Unsupported protocol http11 = false; @@ -493,15 +497,6 @@ inputBuffer.addActiveFilter (inputFilters[Constants.IDENTITY_FILTER]); contentDelimitation = true; - } else { - // If method is GET or HEAD, prevent from reading any content - if ((methodMB.equals("GET")) - || (methodMB.equals("HEAD")) - || (methodMB.equals("TRACE"))) { - inputBuffer.addActiveFilter - (inputFilters[Constants.VOID_FILTER]); - contentDelimitation = true; - } } // Parse transfer-encoding header @@ -544,6 +539,17 @@ response.setStatus(400); } + if (!contentDelimitation) { + // If method is GET or HEAD, prevent from reading any content + if ((methodMB.equals("GET")) + || (methodMB.equals("HEAD")) + || (methodMB.equals("TRACE"))) { + inputBuffer.addActiveFilter + (inputFilters[Constants.VOID_FILTER]); + contentDelimitation = true; + } + } + if (!contentDelimitation) keepAlive = false; @@ -557,18 +563,38 @@ protected void prepareResponse() { boolean http09 = false; + boolean entityBody = true; contentDelimitation = false; + OutputFilter[] outputFilters = outputBuffer.getFilters(); + MessageBytes protocolMB = request.protocol(); if (protocolMB.equals(Constants.HTTP_11)) { http11 = true; } else if (protocolMB.equals(Constants.HTTP_10)) { http11 = false; - } else { - // FIXME: Check for HTTP/0.9 + } else if (protocolMB.equals("")) { + // HTTP/0.9 + outputBuffer.addActiveFilter + (outputFilters[Constants.IDENTITY_FILTER]); + return; } - OutputFilter[] outputFilters = outputBuffer.getFilters(); + int statusCode = response.getStatus(); + if ((statusCode == 204) || (statusCode == 205) + || (statusCode == 304)) { + // No entity body + outputBuffer.addActiveFilter + (outputFilters[Constants.VOID_FILTER]); + entityBody = false; + } + + MessageBytes methodMB = request.method(); + if (methodMB.equals("HEAD")) { + // No entity body + outputBuffer.addActiveFilter + (outputFilters[Constants.VOID_FILTER]); + } int contentLength = response.getContentLength(); if (contentLength != -1) { @@ -576,7 +602,7 @@ (outputFilters[Constants.IDENTITY_FILTER]); contentDelimitation = true; } else { - if (http11) { + if (entityBody && http11) { outputBuffer.addActiveFilter (outputFilters[Constants.CHUNKED_FILTER]); contentDelimitation = true; @@ -593,10 +619,13 @@ // Add transfer encoding header // FIXME - if (!contentDelimitation) { + if ((entityBody) && (!contentDelimitation)) { // Mark as close the connection after the request, and add the // connection: close header keepAlive = false; + } + + if (!keepAlive) { response.addHeader("Connection", "close"); } 1.2 +192 -11 jakarta-tomcat-connectors/http11/src/java/org/apache/coyote/http11/filters/ChunkedInputFilter.java Index: ChunkedInputFilter.java =================================================================== RCS file: /home/cvs/jakarta-tomcat-connectors/http11/src/java/org/apache/coyote/http11/filters/ChunkedInputFilter.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- ChunkedInputFilter.java 24 Dec 2001 20:44:40 -0000 1.1 +++ ChunkedInputFilter.java 14 Jan 2002 00:17:58 -0000 1.2 @@ -62,9 +62,11 @@ import java.io.IOException; import org.apache.tomcat.util.buf.ByteChunk; +import org.apache.tomcat.util.buf.HexUtils; import org.apache.coyote.InputBuffer; import org.apache.coyote.Request; +import org.apache.coyote.http11.Constants; import org.apache.coyote.http11.InputFilter; /** @@ -94,15 +96,45 @@ /** - * Remaining bytes in the current chunk. + * Next buffer in the pipeline. */ - protected long remaining = -1; + protected InputBuffer buffer; /** - * Next buffer in the pipeline. + * Number of bytes remaining in the current chunk. */ - protected InputBuffer buffer; + protected int remaining = 0; + + + /** + * Position in the buffer. + */ + protected int pos = 0; + + + /** + * Last valid byte in the buffer. + */ + protected int lastValid = 0; + + + /** + * Read bytes buffer. + */ + protected byte[] buf = null; + + + /** + * Byte chunk used to read bytes. + */ + protected ByteChunk readChunk = new ByteChunk(); + + + /** + * Flag set to true when the end chunk has been read. + */ + protected boolean endChunk = false; // ------------------------------------------------------------- Properties @@ -123,12 +155,35 @@ public int doRead(ByteChunk chunk) throws IOException { - buffer.doRead(chunk); + if (endChunk) + return -1; + + if (remaining <= 0) { + if (!parseChunkHeader()) { + throw new IOException("Invalid chunk"); + } + if (endChunk) { + parseEndChunk(); + return -1; + } + } - int result = chunk.getLength(); + int result = 0; - if (result <= 0) { - return -1; + if (pos >= lastValid) { + readBytes(); + } + + if (remaining > (lastValid - pos)) { + result = lastValid - pos; + remaining = remaining - result; + chunk.setBytes(buf, pos, result); + } else { + result = remaining; + chunk.setBytes(buf, pos, remaining); + pos = pos + remaining; + remaining = 0; + parseCRLF(); } return result; @@ -152,9 +207,12 @@ public long end() throws IOException { - // FIXME: Consume extra bytes. - // FIXME: If too many bytes were read, return the amount. - return remaining; + // Consume extra bytes : parse the stream until the end chunk is found + while (doRead(readChunk) >= 0) { + } + + // Return the number of extra bytes which were consumed + return (lastValid - pos); } @@ -172,6 +230,9 @@ */ public void recycle() { remaining = 0; + pos = 0; + lastValid = 0; + endChunk = false; } @@ -181,6 +242,126 @@ */ public ByteChunk getEncodingName() { return ENCODING; + } + + + // ------------------------------------------------------ Protected Methods + + + /** + * Read bytes from the previous buffer. + */ + protected int readBytes() + throws IOException { + + int nRead = buffer.doRead(readChunk); + pos = readChunk.getStart(); + lastValid = readChunk.getEnd(); + buf = readChunk.getBytes(); + + return nRead; + + } + + + /** + * Parse the header of a chunk. + */ + protected boolean parseChunkHeader() + throws IOException { + + int result = 0; + boolean eol = false; + int begin = pos; + int end = begin; + boolean readDigit = false; + + while (!eol) { + + if (pos >= lastValid) { + if (readBytes() <= 0) + return false; + } + + if (buf[pos] == Constants.CR) { + } else if (buf[pos] == Constants.LF) { + eol = true; + } else { + if (HexUtils.DEC[buf[pos]] != -1) { + if (!readDigit) { + readDigit = true; + begin = pos; + } + end = pos; + } + } + + pos++; + + } + + if (!readDigit) + return false; + + int offset = 1; + for (int i = end; i >= begin; i--) { + int val = HexUtils.DEC[buf[i]]; + if (val == -1) + return false; + result = result + val * offset; + offset = offset * 16; + } + + if (result == 0) + endChunk = true; + + remaining = result; + + return true; + + } + + + /** + * Parse CRLF at end of chunk. + */ + protected boolean parseCRLF() + throws IOException { + + boolean eol = false; + + while (!eol) { + + if (pos >= lastValid) { + if (readBytes() <= 0) + return false; + } + + if (buf[pos] == Constants.CR) { + } else if (buf[pos] == Constants.LF) { + eol = true; + } else { + return false; + } + + pos++; + + } + + return true; + + } + + + /** + * Parse end chunk data. + * FIXME: Handle trailers + */ + protected boolean parseEndChunk() + throws IOException { + + return parseCRLF(); // FIXME + }
-- To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]> For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>