remm 02/01/09 15:29:29 Modified: http11/src/java/org/apache/coyote/http11 Constants.java Http11Connector.java http11/src/java/org/apache/coyote/http11/filters ChunkedOutputFilter.java Log: - Add support for output chunking (input chunking is much harder to do OTOH). - Improve response processing, so that the response to 2 pipelined GETs is now correct. - Content delimitation on input is untested at the moment, and pipelining still could have bugs with the buffer management (only two out of three buffers are in use in the simple test). Revision Changes Path 1.5 +7 -0 jakarta-tomcat-connectors/http11/src/java/org/apache/coyote/http11/Constants.java Index: Constants.java =================================================================== RCS file: /home/cvs/jakarta-tomcat-connectors/http11/src/java/org/apache/coyote/http11/Constants.java,v retrieving revision 1.4 retrieving revision 1.5 diff -u -r1.4 -r1.5 --- Constants.java 9 Jan 2002 12:57:49 -0000 1.4 +++ Constants.java 9 Jan 2002 23:29:29 -0000 1.5 @@ -78,6 +78,13 @@ /** + * Server string. + */ + public static final String SERVER = + "Apache Coyote HTTP/1.1 Connector [1.0]"; + + + /** * CR. */ public static final byte CR = (byte) '\r'; 1.8 +55 -15 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.7 retrieving revision 1.8 diff -u -r1.7 -r1.8 --- Http11Connector.java 9 Jan 2002 12:57:49 -0000 1.7 +++ Http11Connector.java 9 Jan 2002 23:29:29 -0000 1.8 @@ -67,6 +67,7 @@ import org.apache.tomcat.util.buf.ByteChunk; import org.apache.tomcat.util.buf.MessageBytes; +import org.apache.tomcat.util.http.FastHttpDateFormat; import org.apache.tomcat.util.http.MimeHeaders; import org.apache.coyote.ActionHook; @@ -265,7 +266,6 @@ inputBuffer.parseHeaders(); } catch (EOFException e) { - e.printStackTrace(); error = true; break; } catch (InterruptedIOException e) { @@ -350,6 +350,8 @@ // Send a 100 status back if it makes sense (response not committed // yet, and client specified an expectation for 100-continue) + // FIXME + } else if (actionCode == ActionCode.ACTION_CLOSE) { // Close @@ -414,10 +416,10 @@ boolean http11 = true; contentDelimitation = false; - MessageBytes protocol = request.protocol(); - if (protocol.equals(Constants.HTTP_11)) { + MessageBytes protocolMB = request.protocol(); + if (protocolMB.equals(Constants.HTTP_11)) { http11 = true; - } else if (protocol.equals(Constants.HTTP_10)) { + } else if (protocolMB.equals(Constants.HTTP_10)) { http11 = false; keepAlive = false; } else { @@ -427,6 +429,8 @@ response.setStatus(505); } + MessageBytes methodMB = request.method(); + // Check connection header MessageBytes connectionValueMB = request.getMimeHeaders().getValue("connection"); @@ -464,6 +468,15 @@ 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 @@ -484,7 +497,7 @@ // Unsupported transfer encoding error = true; // Send 501; Unimplemented - response.setStatus(502); + response.setStatus(501); } startPos = commaPos + 1; commaPos = transferEncodingValue.indexOf(',', startPos); @@ -495,7 +508,7 @@ // Unsupported transfer encoding error = true; // Send 501; Unimplemented - response.setStatus(502); + response.setStatus(501); } } @@ -518,16 +531,49 @@ */ protected void prepareResponse() { + boolean http11 = true; + boolean http09 = false; 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 + } - outputBuffer.addActiveFilter - (outputFilters[Constants.IDENTITY_FILTER]); + OutputFilter[] outputFilters = outputBuffer.getFilters(); int contentLength = request.getContentLength(); if (contentLength != -1) { + outputBuffer.addActiveFilter + (outputFilters[Constants.IDENTITY_FILTER]); contentDelimitation = true; + } else { + if (http11) { + outputBuffer.addActiveFilter + (outputFilters[Constants.CHUNKED_FILTER]); + contentDelimitation = true; + response.addHeader("Transfer-Encoding", "chunked"); + } + } + + // Add date header + response.addHeader("Date", FastHttpDateFormat.getCurrentDate()); + + // Add server header + response.addHeader("Server", Constants.SERVER); + + // Add transfer encoding header + // FIXME + + if (!contentDelimitation) { + // Mark as close the connection after the request, and add the + // connection: close header + keepAlive = false; + response.addHeader("Connection", "close"); } // Build the response header @@ -539,12 +585,6 @@ outputBuffer.sendHeader(headers.getName(i), headers.getValue(i)); } outputBuffer.endHeaders(); - - if (!contentDelimitation) { - // Mark as close the connection after the request, and add the - // connection: close header - keepAlive = false; - } } 1.2 +48 -4 jakarta-tomcat-connectors/http11/src/java/org/apache/coyote/http11/filters/ChunkedOutputFilter.java Index: ChunkedOutputFilter.java =================================================================== RCS file: /home/cvs/jakarta-tomcat-connectors/http11/src/java/org/apache/coyote/http11/filters/ChunkedOutputFilter.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- ChunkedOutputFilter.java 24 Dec 2001 20:44:40 -0000 1.1 +++ ChunkedOutputFilter.java 9 Jan 2002 23:29:29 -0000 1.2 @@ -62,6 +62,7 @@ import java.io.IOException; import org.apache.tomcat.util.buf.ByteChunk; +import org.apache.tomcat.util.buf.HexUtils; import org.apache.coyote.OutputBuffer; import org.apache.coyote.Response; @@ -82,11 +83,33 @@ protected static final ByteChunk ENCODING = new ByteChunk(); + /** + * End chunk. + */ + protected static final ByteChunk END_CHUNK = new ByteChunk(); + + // ----------------------------------------------------- Static Initializer static { ENCODING.setBytes(ENCODING_NAME.getBytes(), 0, ENCODING_NAME.length()); + String endChunkValue = "0\r\n\r\n"; + END_CHUNK.setBytes(endChunkValue.getBytes(), + 0, endChunkValue.length()); + } + + + // ------------------------------------------------------------ Constructor + + + /** + * Default constructor. + */ + public ChunkedOutputFilter() { + chunkLength = new byte[10]; + chunkLength[8] = (byte) '\r'; + chunkLength[9] = (byte) '\n'; } @@ -99,6 +122,18 @@ protected OutputBuffer buffer; + /** + * Buffer used for chunk length conversion. + */ + protected byte[] chunkLength = new byte[10]; + + + /** + * Chunk header. + */ + protected ByteChunk chunkHeader = new ByteChunk(); + + // ------------------------------------------------------------- Properties @@ -116,11 +151,19 @@ int result = chunk.getLength(); if (result <= 0) { - return -1; + return 0; } - // Write chunk header - // FIXME + // Calculate chunk header + int pos = 7; + int current = result; + while (current > 0) { + int digit = current % 16; + current = current / 16; + chunkLength[pos--] = HexUtils.HEX[digit]; + } + chunkHeader.setBytes(chunkLength, pos + 1, 9 - pos); + buffer.doWrite(chunkHeader); buffer.doWrite(chunk); @@ -157,7 +200,8 @@ throws IOException { // Write end chunk - // FIXME + buffer.doWrite(END_CHUNK); + return 0; }
-- To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]> For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>