Fields Summary |
---|
protected static org.apache.tomcat.util.res.StringManager | smThe string manager for this package. |
protected org.apache.coyote.Request | requestAssociated Coyote request. |
protected org.apache.tomcat.util.http.MimeHeaders | headersHeaders of the associated request. |
protected boolean | parsingHeaderState. |
protected boolean | swallowInputSwallow input ? (in the case of an expectation) |
protected byte[] | bufPointer to the current read buffer. |
protected int | lastValidLast valid byte. |
protected int | posPosition in the buffer. |
protected int | endPos of the end of the header in the buffer, which is also the
start of the body. |
protected InputStream | inputStreamUnderlying input stream. |
protected org.apache.coyote.InputBuffer | inputStreamInputBufferUnderlying input buffer. |
protected InputFilter[] | filterLibraryFilter library.
Note: Filter[0] is always the "chunked" filter. |
protected InputFilter[] | activeFiltersActive filters (in order). |
protected int | lastActiveFilterIndex of the last active filter. |
Methods Summary |
---|
public void | addActiveFilter(InputFilter filter)Add an input filter to the filter library.
if (lastActiveFilter == -1) {
filter.setBuffer(inputStreamInputBuffer);
} else {
for (int i = 0; i <= lastActiveFilter; i++) {
if (activeFilters[i] == filter)
return;
}
filter.setBuffer(activeFilters[lastActiveFilter]);
}
activeFilters[++lastActiveFilter] = filter;
filter.setRequest(request);
|
public void | addFilter(InputFilter filter)Add an input filter to the filter library.
// FIXME: Check for null ?
InputFilter[] newFilterLibrary =
new InputFilter[filterLibrary.length + 1];
for (int i = 0; i < filterLibrary.length; i++) {
newFilterLibrary[i] = filterLibrary[i];
}
newFilterLibrary[filterLibrary.length] = filter;
filterLibrary = newFilterLibrary;
activeFilters = new InputFilter[filterLibrary.length];
|
public void | clearFilters()Clear filters.
filterLibrary = new InputFilter[0];
lastActiveFilter = -1;
|
public int | doRead(org.apache.tomcat.util.buf.ByteChunk chunk, org.apache.coyote.Request req)Read some bytes.
if (lastActiveFilter == -1)
return inputStreamInputBuffer.doRead(chunk, req);
else
return activeFilters[lastActiveFilter].doRead(chunk,req);
|
public void | endRequest()End request (consumes leftover bytes).
if (swallowInput && (lastActiveFilter != -1)) {
int extraBytes = (int) activeFilters[lastActiveFilter].end();
pos = pos - extraBytes;
}
|
protected boolean | fill()Fill the internal buffer using data from the undelying input stream.
int nRead = 0;
if (parsingHeader) {
if (lastValid == buf.length) {
throw new IOException
(sm.getString("iib.requestheadertoolarge.error"));
}
nRead = inputStream.read(buf, pos, buf.length - lastValid);
if (nRead > 0) {
lastValid = pos + nRead;
}
} else {
if (buf.length - end < 4500) {
// In this case, the request header was really large, so we allocate a
// brand new one; the old one will get GCed when subsequent requests
// clear all references
buf = new byte[buf.length];
end = 0;
}
pos = end;
lastValid = pos;
nRead = inputStream.read(buf, pos, buf.length - lastValid);
if (nRead > 0) {
lastValid = pos + nRead;
}
}
return (nRead > 0);
|
public InputFilter[] | getFilters()Get filters.
return filterLibrary;
|
public java.io.InputStream | getInputStream()Get the underlying socket input stream.
return inputStream;
|
public void | nextRequest()End processing of current HTTP request.
Note: All bytes of the current request should have been already
consumed. This method only resets all the pointers so that we are ready
to parse the next HTTP request.
// Recycle Request object
request.recycle();
// Copy leftover bytes to the beginning of the buffer
if (lastValid - pos > 0) {
int npos = 0;
int opos = pos;
while (lastValid - opos > opos - npos) {
System.arraycopy(buf, opos, buf, npos, opos - npos);
npos += pos;
opos += pos;
}
System.arraycopy(buf, opos, buf, npos, lastValid - opos);
}
// Recycle filters
for (int i = 0; i <= lastActiveFilter; i++) {
activeFilters[i].recycle();
}
// Reset pointers
lastValid = lastValid - pos;
pos = 0;
lastActiveFilter = -1;
parsingHeader = true;
swallowInput = true;
|
public boolean | parseHeader()Parse an HTTP header.
//
// Check for blank line
//
byte chr = 0;
while (true) {
// Read new bytes if needed
if (pos >= lastValid) {
if (!fill())
throw new EOFException(sm.getString("iib.eof.error"));
}
chr = buf[pos];
if ((chr == Constants.CR) || (chr == Constants.LF)) {
if (chr == Constants.LF) {
pos++;
return false;
}
} else {
break;
}
pos++;
}
// Mark the current buffer position
int start = pos;
//
// Reading the header name
// Header name is always US-ASCII
//
boolean colon = false;
MessageBytes headerValue = null;
while (!colon) {
// Read new bytes if needed
if (pos >= lastValid) {
if (!fill())
throw new EOFException(sm.getString("iib.eof.error"));
}
if (buf[pos] == Constants.COLON) {
colon = true;
headerValue = headers.addValue(buf, start, pos - start);
}
chr = buf[pos];
if ((chr >= Constants.A) && (chr <= Constants.Z)) {
buf[pos] = (byte) (chr - Constants.LC_OFFSET);
}
pos++;
}
// Mark the current buffer position
start = pos;
int realPos = pos;
//
// Reading the header value (which can be spanned over multiple lines)
//
boolean eol = false;
boolean validLine = true;
while (validLine) {
boolean space = true;
// Skipping spaces
while (space) {
// Read new bytes if needed
if (pos >= lastValid) {
if (!fill())
throw new EOFException(sm.getString("iib.eof.error"));
}
if ((buf[pos] == Constants.SP) || (buf[pos] == Constants.HT)) {
pos++;
} else {
space = false;
}
}
int lastSignificantChar = realPos;
// Reading bytes until the end of the line
while (!eol) {
// Read new bytes if needed
if (pos >= lastValid) {
if (!fill())
throw new EOFException(sm.getString("iib.eof.error"));
}
if (buf[pos] == Constants.CR) {
} else if (buf[pos] == Constants.LF) {
eol = true;
} else if (buf[pos] == Constants.SP) {
buf[realPos] = buf[pos];
realPos++;
} else {
buf[realPos] = buf[pos];
realPos++;
lastSignificantChar = realPos;
}
pos++;
}
realPos = lastSignificantChar;
// Checking the first character of the new line. If the character
// is a LWS, then it's a multiline header
// Read new bytes if needed
if (pos >= lastValid) {
if (!fill())
throw new EOFException(sm.getString("iib.eof.error"));
}
chr = buf[pos];
if ((chr != Constants.SP) && (chr != Constants.HT)) {
validLine = false;
} else {
eol = false;
// Copying one extra space in the buffer (since there must
// be at least one space inserted between the lines)
buf[realPos] = chr;
realPos++;
}
}
// Set the header value
headerValue.setBytes(buf, start, realPos - start);
return true;
|
public void | parseHeaders()Parse the HTTP headers.
while (parseHeader()) {
}
parsingHeader = false;
end = pos;
|
public void | parseRequestLine()Read the request line. This function is meant to be used during the
HTTP request header parsing. Do NOT attempt to read the request body
using it.
int start = 0;
//
// Skipping blank lines
//
byte chr = 0;
do {
// Read new bytes if needed
if (pos >= lastValid) {
if (!fill())
throw new EOFException(sm.getString("iib.eof.error"));
}
chr = buf[pos++];
} while ((chr == Constants.CR) || (chr == Constants.LF));
pos--;
// Mark the current buffer position
start = pos;
//
// Reading the method name
// Method name is always US-ASCII
//
boolean space = false;
while (!space) {
// Read new bytes if needed
if (pos >= lastValid) {
if (!fill())
throw new EOFException(sm.getString("iib.eof.error"));
}
if (buf[pos] == Constants.SP) {
space = true;
request.method().setBytes(buf, start, pos - start);
}
pos++;
}
// Mark the current buffer position
start = pos;
int end = 0;
int questionPos = -1;
//
// Reading the URI
//
space = false;
boolean eol = false;
while (!space) {
// Read new bytes if needed
if (pos >= lastValid) {
if (!fill())
throw new EOFException(sm.getString("iib.eof.error"));
}
if (buf[pos] == Constants.SP) {
space = true;
end = pos;
} else if ((buf[pos] == Constants.CR)
|| (buf[pos] == Constants.LF)) {
// HTTP/0.9 style request
eol = true;
space = true;
end = pos;
} else if ((buf[pos] == Constants.QUESTION)
&& (questionPos == -1)) {
questionPos = pos;
}
pos++;
}
request.unparsedURI().setBytes(buf, start, end - start);
if (questionPos >= 0) {
request.queryString().setBytes(buf, questionPos + 1,
end - questionPos - 1);
request.requestURI().setBytes(buf, start, questionPos - start);
} else {
request.requestURI().setBytes(buf, start, end - start);
}
// Mark the current buffer position
start = pos;
end = 0;
//
// Reading the protocol
// Protocol is always US-ASCII
//
while (!eol) {
// Read new bytes if needed
if (pos >= lastValid) {
if (!fill())
throw new EOFException(sm.getString("iib.eof.error"));
}
if (buf[pos] == Constants.CR) {
end = pos;
} else if (buf[pos] == Constants.LF) {
if (end == 0)
end = pos;
eol = true;
}
pos++;
}
if ((end - start) > 0) {
request.protocol().setBytes(buf, start, end - start);
} else {
request.protocol().setString("");
}
|
public void | recycle()Recycle the input buffer. This should be called when closing the
connection.
// Recycle Request object
request.recycle();
inputStream = null;
lastValid = 0;
pos = 0;
lastActiveFilter = -1;
parsingHeader = true;
swallowInput = true;
|
public void | setInputStream(java.io.InputStream inputStream)Set the underlying socket input stream.
// ------------------------------------------------------------- Properties
// FIXME: Check for null ?
this.inputStream = inputStream;
|
public void | setSwallowInput(boolean swallowInput)Set the swallow input flag.
this.swallowInput = swallowInput;
|