You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by re...@apache.org on 2002/01/14 01:17:59 UTC
cvs commit: jakarta-tomcat-connectors/http11/src/java/org/apache/coyote/http11/filters ChunkedInputFilter.java
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: <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>