Sorry for the spam if you are on both newsgroups. I have been asked to move
this to the user's group rather than the developers group. I still think it's
a developer issue, but I am more interested in actually finding answers than
arguing the point.
I am using a standard UrlHttpConnection to connect to Tomcat. When I use
setChunkedStreamingMode, no matter what the setting, I start getting bad method
names in my servlet.
HttpURLConnection conn = (HttpURLConnection)url.openConnection();
conn.setChunkedStreamingMode(1024);
I am seeing this in my override of the .service() method in the Servlet, which
is the earliest point available to me if I stay within the confines of the
spec. The method name comes in as '0\n\nPOST'. I've tracked this through a
bunch of Tomcat classes, working on the 5.5.27 code base.
I have intercepted the socket InputStream (in Http11BaseProtocol) and looked at
the data coming in. It is what I expect ('POST .'). Yes, let me repeat that,
the data coming in from the socket is good. I've visually inspected it, and it
matches the spec.
When I get into the InternalInputBuffer, I am seeing there is data left over at
the end of one stream ('0\n\n') which gets appended to the beginning of the
next request because of the code in .nextRequest(). It almost looks like
someone downstream is not consuming the very last byte in the buffer.
But then why the heck does .nextRequest copy it into the new buffer for the
next request? This makes no sense to me.
So I have verified that the data is coming in right. And at the very first
entry point into the servlet, the method name is messed up.
This appears to be happening in Tomcat, and has been replicated on a number of
machines.
So PLEASE, can ANYONE tell me what .nextRequest() is doing? It says that ***
All bytes of the current request should have been already consumed.*** That is
not what I am seeing. And this part of the code isn't dealing with corrupt data
very elegantly (it assumes that everything is perfect).
Is this a problem with downstream code, which has a responsibility to consume
every byte in the input stream? Or is it bad code in nextRequest(), which
really should not be taking the tail of one request and appending it to the
next? Or is it something else?
Thanks! See below for more info.
From: Jason Smith
Sent: Monday, April 06, 2009 11:08 AM
To: '[email protected]'
Subject: RE: Help with a Tomcat bug.
More info. In InternalInputBuffer.nextRequest(), I noticed there is code to
pull remaining bytes into the current buffer before switching.
/**
* 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.
*/
public void nextRequest()
throws IOException {
// Recycle Request object
request.recycle();
// Determine the header buffer used for next request
byte[] newHeaderBuf = null;
if (buf == headerBuffer1) {
newHeaderBuf = headerBuffer2;
} else {
newHeaderBuf = headerBuffer1;
}
// Copy leftover bytes from buf to newHeaderBuf
System.arraycopy(buf, pos, newHeaderBuf, 0, lastValid - pos);
if(lastValid-pos > 0)
{
System.out.println("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
System.out.println("'" + new String(Arrays.copyOf(newHeaderBuf,
lastValid - pos), "US-ASCII") + "'");
}
// Swap buffers
buf = newHeaderBuf;
// 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;
}
I am seeing something like this at one point:
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
'POST /dh/services/jmap/__exists__ HTTP/1.1
But I am also seeing this where this problem is cropping up:
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
'0
'
Anyone got any ideas on how to fix this? Data from one POST is being carried
over to the next POST!!!!!
From: Jason Smith
Sent: Monday, April 06, 2009 10:16 AM
To: '[email protected]'
Subject: Help with a Tomcat bug.
When using .setChunkedStreamingMode(.) from the client, I was getting back an
invalid method name in my servlet. Specifically, in the overridden service()
method, the request.getMethod() was returning '0\n\nPOST'.
I've tracked this all the way into
org.apache.coyote.http11.InternalInputBuffer.
In .parseRequestLine, the first thing it does is consume leading CRs and LFs.
Well, the first line I am getting is '0\n'. So it won't consume that line.
The next step parses to the next SPACE character. So it picks up the 0, the
CRs and LFs, all the way to the end of POST.
The bottom line is that at this point, in this method, the HTTP method name is
already messed up.
Should this be fixed in this method, or is there a better place?
One quick fix:
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) || (chr ==
'0'));
I simply check for the '0' character as well. This is a bit of a hack, but I
don't know the code well enough to know if the leading '0' (which I believe is
the last line from a previous chunked POST) is supposed to be there or not.
Any help would be appreciated.
Tomcat 5.5.27, Java 6u13.
Jason Smith
Software Engineer
InfoTrust Group, Inc.
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]