HttpParser cleanup #2232
Signed-off-by: Greg Wilkins <gregw@webtide.com>
This commit is contained in:
parent
0361cf6cd3
commit
915af401e1
|
@ -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());
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue