HttpParser cleanup #2232

Signed-off-by: Greg Wilkins <gregw@webtide.com>
This commit is contained in:
Greg Wilkins 2018-03-13 13:22:01 +11:00
parent 0361cf6cd3
commit 915af401e1
2 changed files with 119 additions and 105 deletions

View File

@ -36,6 +36,7 @@ import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.util.log.Logger;
import static org.eclipse.jetty.http.HttpTokens.CARRIAGE_RETURN; import static org.eclipse.jetty.http.HttpTokens.CARRIAGE_RETURN;
import static org.eclipse.jetty.http.HttpTokens.COLON;
import static org.eclipse.jetty.http.HttpTokens.LINE_FEED; import static org.eclipse.jetty.http.HttpTokens.LINE_FEED;
import static org.eclipse.jetty.http.HttpTokens.SPACE; import static org.eclipse.jetty.http.HttpTokens.SPACE;
import static org.eclipse.jetty.http.HttpTokens.TAB; import static org.eclipse.jetty.http.HttpTokens.TAB;
@ -1074,7 +1075,7 @@ public class HttpParser
throw new BadMessageException(HttpStatus.BAD_REQUEST_400,"Header Folding"); throw new BadMessageException(HttpStatus.BAD_REQUEST_400,"Header Folding");
// header value without name - continuation? // header value without name - continuation?
if (_valueString==null) if (_valueString==null || _valueString.isEmpty())
{ {
_string.setLength(0); _string.setLength(0);
_length=0; _length=0;
@ -1166,10 +1167,6 @@ public class HttpParser
default: default:
{ {
// now handle the ch
if (b<HttpTokens.SPACE)
throw new BadMessageException();
// process previous header // process previous header
if (_state==State.HEADER) if (_state==State.HEADER)
parsedHeader(); parsedHeader();
@ -1266,114 +1263,124 @@ public class HttpParser
break; break;
case IN_NAME: case IN_NAME:
if (b>HttpTokens.SPACE && b!=HttpTokens.COLON) switch(b)
{ {
if (_header!=null) case SPACE:
{ case TAB:
setString(_header.asString()); //Ignore trailing whitespaces ?
_header=null; if (!complianceViolation(HttpComplianceSection.NO_WS_AFTER_FIELD_NAME,null))
_headerString=null; {
} _headerString=takeString();
_header=HttpHeader.CACHE.get(_headerString);
_string.append((char)b); _length=-1;
_length=_string.length(); setState(FieldState.WS_AFTER_NAME);
break; break;
} }
throw new IllegalCharacterException(_state,b,buffer);
// Fallthrough
case COLON:
case WS_AFTER_NAME:
if (b==HttpTokens.COLON)
{
if (_headerString==null)
{
_headerString=takeString(); _headerString=takeString();
_header=HttpHeader.CACHE.get(_headerString); _header=HttpHeader.CACHE.get(_headerString);
} _length=-1;
_length=-1; setState(FieldState.VALUE);
setState(FieldState.VALUE);
break;
}
if (b==HttpTokens.LINE_FEED)
{
if (_headerString==null)
{
_headerString=takeString();
_header=HttpHeader.CACHE.get(_headerString);
}
_string.setLength(0);
_valueString="";
_length=-1;
if (!complianceViolation(HttpComplianceSection.FIELD_COLON,_headerString))
{
setState(FieldState.FIELD);
break; break;
}
} case LINE_FEED:
_headerString=takeString();
_header=HttpHeader.CACHE.get(_headerString);
_string.setLength(0);
_valueString="";
_length=-1;
//Ignore trailing whitespaces if (!complianceViolation(HttpComplianceSection.FIELD_COLON,_headerString))
if (b==HttpTokens.SPACE && !complianceViolation(HttpComplianceSection.NO_WS_AFTER_FIELD_NAME,null)) {
setState(FieldState.FIELD);
break;
}
throw new IllegalCharacterException(_state,b,buffer);
default:
if (b<0)
throw new IllegalCharacterException(_state,b,buffer);
_string.append((char)b);
_length=_string.length();
break;
}
break;
case WS_AFTER_NAME:
switch(b)
{ {
setState(FieldState.WS_AFTER_NAME); case SPACE:
break; case TAB:
} break;
throw new IllegalCharacterException(_state,b,buffer); case COLON:
setState(FieldState.VALUE);
break;
case LINE_FEED:
if (!complianceViolation(HttpComplianceSection.FIELD_COLON,_headerString))
{
setState(FieldState.FIELD);
break;
}
throw new IllegalCharacterException(_state,b,buffer);
default:
throw new IllegalCharacterException(_state,b,buffer);
}
break;
case VALUE: case VALUE:
if (b>HttpTokens.SPACE || b<0) switch(b)
{ {
_string.append((char)(0xff&b)); case LINE_FEED:
_length=_string.length(); _string.setLength(0);
setState(FieldState.IN_VALUE); _valueString="";
break;
}
if (b==HttpTokens.SPACE || b==HttpTokens.TAB)
break;
if (b==HttpTokens.LINE_FEED)
{
_string.setLength(0);
_valueString="";
_length=-1;
setState(FieldState.FIELD);
break;
}
throw new IllegalCharacterException(_state,b,buffer);
case IN_VALUE:
if (b>=HttpTokens.SPACE || b<0 || b==HttpTokens.TAB)
{
if (_valueString!=null)
{
setString(_valueString);
_valueString=null;
_field=null;
}
_string.append((char)(0xff&b));
if (b>HttpTokens.SPACE || b<0)
_length=_string.length();
break;
}
if (b==HttpTokens.LINE_FEED)
{
if (_length > 0)
{
_valueString=takeString();
_length=-1; _length=-1;
}
setState(FieldState.FIELD); setState(FieldState.FIELD);
break;
case SPACE:
case TAB:
break;
default:
_string.append((char)(0xff&b));
_length=_string.length();
setState(FieldState.IN_VALUE);
break; break;
} }
break;
throw new IllegalCharacterException(_state,b,buffer);
case IN_VALUE:
switch(b)
{
case LINE_FEED:
if (_length > 0)
{
_valueString=takeString();
_length=-1;
}
setState(FieldState.FIELD);
break;
case SPACE:
case TAB:
_string.append((char)(0xff&b));
break;
default:
_string.append((char)(0xff&b));
_length=_string.length();
break;
}
break;
default: default:
throw new IllegalStateException(_state.toString()); throw new IllegalStateException(_state.toString());

View File

@ -18,6 +18,7 @@
package org.eclipse.jetty.http; package org.eclipse.jetty.http;
import static org.eclipse.jetty.http.HttpComplianceSection.NO_FIELD_FOLDING;
import static org.hamcrest.Matchers.contains; import static org.hamcrest.Matchers.contains;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
@ -261,6 +262,8 @@ public class HttpParserTest
"Host: localhost\r\n" + "Host: localhost\r\n" +
"Name: value\r\n" + "Name: value\r\n" +
" extra\r\n" + " extra\r\n" +
"Name2: \r\n" +
"\tvalue2\r\n" +
"\r\n"); "\r\n");
HttpParser.RequestHandler handler = new Handler(); HttpParser.RequestHandler handler = new Handler();
@ -270,10 +273,12 @@ public class HttpParserTest
Assert.assertThat(_bad, Matchers.nullValue()); Assert.assertThat(_bad, Matchers.nullValue());
Assert.assertEquals("Host", _hdr[0]); Assert.assertEquals("Host", _hdr[0]);
Assert.assertEquals("localhost", _val[0]); Assert.assertEquals("localhost", _val[0]);
Assert.assertEquals(2, _headers);
Assert.assertEquals("Name", _hdr[1]); Assert.assertEquals("Name", _hdr[1]);
Assert.assertEquals("value extra", _val[1]); Assert.assertEquals("value extra", _val[1]);
Assert.assertEquals(1, _headers); Assert.assertEquals("Name2", _hdr[2]);
Assert.assertThat(_complianceViolation, contains(HttpComplianceSection.NO_FIELD_FOLDING)); Assert.assertEquals("value2", _val[2]);
Assert.assertThat(_complianceViolation, contains(NO_FIELD_FOLDING,NO_FIELD_FOLDING));
} }
@Test @Test
@ -399,7 +404,7 @@ public class HttpParserTest
ByteBuffer buffer = BufferUtil.toBuffer( ByteBuffer buffer = BufferUtil.toBuffer(
"HTTP/1.1 204 No Content\r\n" + "HTTP/1.1 204 No Content\r\n" +
"Access-Control-Allow-Headers : Origin\r\n" + "Access-Control-Allow-Headers : Origin\r\n" +
"Other: value\r\n" + "Other\t : value\r\n" +
"\r\n"); "\r\n");
HttpParser.ResponseHandler handler = new Handler(); HttpParser.ResponseHandler handler = new Handler();
@ -422,7 +427,7 @@ public class HttpParserTest
Assert.assertEquals("Other", _hdr[1]); Assert.assertEquals("Other", _hdr[1]);
Assert.assertEquals("value", _val[1]); Assert.assertEquals("value", _val[1]);
Assert.assertThat(_complianceViolation, contains(HttpComplianceSection.NO_WS_AFTER_FIELD_NAME)); Assert.assertThat(_complianceViolation, contains(HttpComplianceSection.NO_WS_AFTER_FIELD_NAME,HttpComplianceSection.NO_WS_AFTER_FIELD_NAME));
} }
@Test @Test
@ -709,7 +714,9 @@ public class HttpParserTest
public void testBadHeaderEncoding() throws Exception public void testBadHeaderEncoding() throws Exception
{ {
ByteBuffer buffer = BufferUtil.toBuffer( ByteBuffer buffer = BufferUtil.toBuffer(
"GET / HTTP/1.0\r\nH\u00e6der0: value0\r\n\n\n"); "GET / HTTP/1.0\r\n"
+ "H\u00e6der0: value0\r\n"
+ "\n\n");
HttpParser.RequestHandler handler = new Handler(); HttpParser.RequestHandler handler = new Handler();
HttpParser parser = new HttpParser(handler); HttpParser parser = new HttpParser(handler);