Issue #612
Added support to parse and ignore HTTP/1.1 chunking trailers. Handle an early EOF within the trailer gracefully rather than with earlyEOF.
This commit is contained in:
parent
058e4658e4
commit
d2b8980243
|
@ -28,8 +28,6 @@ import org.eclipse.jetty.http.HttpTokens.EndOfContent;
|
|||
import org.eclipse.jetty.util.ArrayTernaryTrie;
|
||||
import org.eclipse.jetty.util.ArrayTrie;
|
||||
import org.eclipse.jetty.util.BufferUtil;
|
||||
import org.eclipse.jetty.util.HostPort;
|
||||
import org.eclipse.jetty.util.StringUtil;
|
||||
import org.eclipse.jetty.util.Trie;
|
||||
import org.eclipse.jetty.util.TypeUtil;
|
||||
import org.eclipse.jetty.util.Utf8StringBuilder;
|
||||
|
@ -133,6 +131,7 @@ public class HttpParser
|
|||
CHUNK_SIZE,
|
||||
CHUNK_PARAMS,
|
||||
CHUNK,
|
||||
CHUNK_TRAILER,
|
||||
CHUNK_END,
|
||||
END,
|
||||
CLOSE, // The associated stream/endpoint should be closed
|
||||
|
@ -682,7 +681,7 @@ public class HttpParser
|
|||
if (_maxHeaderBytes>0 && ++_headerBytes>_maxHeaderBytes)
|
||||
{
|
||||
LOG.warn("URI is too large >"+_maxHeaderBytes);
|
||||
throw new BadMessageException(HttpStatus.REQUEST_URI_TOO_LONG_414);
|
||||
throw new BadMessageException(HttpStatus.URI_TOO_LONG_414);
|
||||
}
|
||||
_uri.append(array,p-1,len+1);
|
||||
buffer.position(i-buffer.arrayOffset());
|
||||
|
@ -1383,14 +1382,16 @@ public class HttpParser
|
|||
break;
|
||||
|
||||
case EOF_CONTENT:
|
||||
case CHUNK_END:
|
||||
setState(State.CLOSED);
|
||||
return _handler.messageComplete();
|
||||
|
||||
case CONTENT:
|
||||
case CHUNKED_CONTENT:
|
||||
case CHUNK_SIZE:
|
||||
case CHUNK_PARAMS:
|
||||
case CHUNK:
|
||||
case CONTENT:
|
||||
case CHUNKED_CONTENT:
|
||||
case CHUNK_SIZE:
|
||||
case CHUNK_PARAMS:
|
||||
case CHUNK:
|
||||
case CHUNK_TRAILER:
|
||||
setState(State.CLOSED);
|
||||
_handler.earlyEOF();
|
||||
break;
|
||||
|
@ -1592,7 +1593,6 @@ public class HttpParser
|
|||
|
||||
case CHUNK_END:
|
||||
{
|
||||
// TODO handle chunk trailer
|
||||
ch=next(buffer);
|
||||
if (ch==0)
|
||||
break;
|
||||
|
@ -1601,7 +1601,19 @@ public class HttpParser
|
|||
setState(State.END);
|
||||
return _handler.messageComplete();
|
||||
}
|
||||
throw new IllegalCharacterException(_state,ch,buffer);
|
||||
setState(State.CHUNK_TRAILER);
|
||||
break;
|
||||
}
|
||||
|
||||
case CHUNK_TRAILER:
|
||||
{
|
||||
// TODO handle chunk trailer values
|
||||
ch=next(buffer);
|
||||
if (ch==0)
|
||||
break;
|
||||
if (ch == HttpTokens.LINE_FEED)
|
||||
setState(State.CHUNK_END);
|
||||
break;
|
||||
}
|
||||
|
||||
case CLOSED:
|
||||
|
|
|
@ -779,6 +779,101 @@ public class HttpParserTest
|
|||
Assert.assertTrue(_messageCompleted);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testChunkParseTrailer() throws Exception
|
||||
{
|
||||
ByteBuffer buffer = BufferUtil.toBuffer(
|
||||
"GET /chunk HTTP/1.0\r\n"
|
||||
+ "Header1: value1\r\n"
|
||||
+ "Transfer-Encoding: chunked\r\n"
|
||||
+ "\r\n"
|
||||
+ "a;\r\n"
|
||||
+ "0123456789\r\n"
|
||||
+ "1a\r\n"
|
||||
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ\r\n"
|
||||
+ "0\r\n"
|
||||
+ "Trailer: value\r\n"
|
||||
+ "\r\n");
|
||||
HttpParser.RequestHandler handler = new Handler();
|
||||
HttpParser parser = new HttpParser(handler);
|
||||
parseAll(parser, buffer);
|
||||
|
||||
Assert.assertEquals("GET", _methodOrVersion);
|
||||
Assert.assertEquals("/chunk", _uriOrStatus);
|
||||
Assert.assertEquals("HTTP/1.0", _versionOrReason);
|
||||
Assert.assertEquals(1, _headers);
|
||||
Assert.assertEquals("Header1", _hdr[0]);
|
||||
Assert.assertEquals("value1", _val[0]);
|
||||
Assert.assertEquals("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ", _content);
|
||||
|
||||
Assert.assertTrue(_headerCompleted);
|
||||
Assert.assertTrue(_messageCompleted);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testChunkParseBadTrailer() throws Exception
|
||||
{
|
||||
ByteBuffer buffer = BufferUtil.toBuffer(
|
||||
"GET /chunk HTTP/1.0\r\n"
|
||||
+ "Header1: value1\r\n"
|
||||
+ "Transfer-Encoding: chunked\r\n"
|
||||
+ "\r\n"
|
||||
+ "a;\r\n"
|
||||
+ "0123456789\r\n"
|
||||
+ "1a\r\n"
|
||||
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ\r\n"
|
||||
+ "0\r\n"
|
||||
+ "Trailer: value");
|
||||
HttpParser.RequestHandler handler = new Handler();
|
||||
HttpParser parser = new HttpParser(handler);
|
||||
parseAll(parser, buffer);
|
||||
parser.atEOF();
|
||||
parser.parseNext(BufferUtil.EMPTY_BUFFER);
|
||||
|
||||
Assert.assertEquals("GET", _methodOrVersion);
|
||||
Assert.assertEquals("/chunk", _uriOrStatus);
|
||||
Assert.assertEquals("HTTP/1.0", _versionOrReason);
|
||||
Assert.assertEquals(1, _headers);
|
||||
Assert.assertEquals("Header1", _hdr[0]);
|
||||
Assert.assertEquals("value1", _val[0]);
|
||||
Assert.assertEquals("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ", _content);
|
||||
|
||||
Assert.assertTrue(_headerCompleted);
|
||||
Assert.assertTrue(_early);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testChunkParseNoTrailer() throws Exception
|
||||
{
|
||||
ByteBuffer buffer = BufferUtil.toBuffer(
|
||||
"GET /chunk HTTP/1.0\r\n"
|
||||
+ "Header1: value1\r\n"
|
||||
+ "Transfer-Encoding: chunked\r\n"
|
||||
+ "\r\n"
|
||||
+ "a;\r\n"
|
||||
+ "0123456789\r\n"
|
||||
+ "1a\r\n"
|
||||
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ\r\n"
|
||||
+ "0\r\n");
|
||||
HttpParser.RequestHandler handler = new Handler();
|
||||
HttpParser parser = new HttpParser(handler);
|
||||
parseAll(parser, buffer);
|
||||
parser.atEOF();
|
||||
parser.parseNext(BufferUtil.EMPTY_BUFFER);
|
||||
|
||||
Assert.assertEquals("GET", _methodOrVersion);
|
||||
Assert.assertEquals("/chunk", _uriOrStatus);
|
||||
Assert.assertEquals("HTTP/1.0", _versionOrReason);
|
||||
Assert.assertEquals(1, _headers);
|
||||
Assert.assertEquals("Header1", _hdr[0]);
|
||||
Assert.assertEquals("value1", _val[0]);
|
||||
Assert.assertEquals("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ", _content);
|
||||
|
||||
Assert.assertTrue(_headerCompleted);
|
||||
Assert.assertTrue(_messageCompleted);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStartEOF() throws Exception
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue