jetty-9 improved contract between HttpConnection and HttpChannel
This commit is contained in:
parent
40ed3a013a
commit
b8517abb14
|
@ -167,6 +167,14 @@ public class HttpGenerator
|
|||
return _contentPrepared;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public void abort()
|
||||
{
|
||||
_persistent=false;
|
||||
_state=State.END;
|
||||
_content=null;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public Result generate(Info info, ByteBuffer header, ByteBuffer chunk, ByteBuffer buffer, ByteBuffer content, Action action)
|
||||
{
|
||||
|
|
|
@ -52,7 +52,7 @@ public class HttpParser
|
|||
CHUNK_SIZE,
|
||||
CHUNK_PARAMS,
|
||||
CHUNK,
|
||||
SEEKING_EOF
|
||||
CLOSED
|
||||
};
|
||||
|
||||
private final HttpHandler _handler;
|
||||
|
@ -158,11 +158,17 @@ public class HttpParser
|
|||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public boolean isIdle()
|
||||
public boolean isStart()
|
||||
{
|
||||
return isState(State.START);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public boolean isClosed()
|
||||
{
|
||||
return isState(State.CLOSED);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public boolean isComplete()
|
||||
{
|
||||
|
@ -181,37 +187,6 @@ public class HttpParser
|
|||
return _persistent;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------------- */
|
||||
public void setPersistent(boolean persistent)
|
||||
{
|
||||
_persistent = persistent;
|
||||
if (!_persistent &&(_state==State.END || _state==State.START))
|
||||
_state=State.SEEKING_EOF;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------------- */
|
||||
/**
|
||||
* Parse until {@link #END END} state.
|
||||
* If the parser is already in the END state, then it is {@link #reset reset} and re-parsed.
|
||||
* @throws IllegalStateException If the buffers have already been partially parsed.
|
||||
*/
|
||||
public void parseAll(ByteBuffer buffer) throws IOException
|
||||
{
|
||||
if (_state==State.END)
|
||||
reset();
|
||||
if (_state!=State.START)
|
||||
throw new IllegalStateException("!START");
|
||||
|
||||
// continue parsing
|
||||
while (_state != State.END && buffer.hasRemaining())
|
||||
{
|
||||
int remaining=buffer.remaining();
|
||||
parseNext(buffer);
|
||||
if (remaining==buffer.remaining())
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------------- */
|
||||
/* Quick lookahead for the start state looking for a request method or a HTTP version,
|
||||
* otherwise skip white space until something else to parse.
|
||||
|
@ -238,6 +213,7 @@ public class HttpParser
|
|||
if (_version!=null)
|
||||
{
|
||||
buffer.position(buffer.position()+_version.asString().length()+1);
|
||||
_persistent=_version.getVerion()>=HttpVersion.HTTP_1_1.getVerion();
|
||||
_state=State.SPACE1;
|
||||
return;
|
||||
}
|
||||
|
@ -328,7 +304,7 @@ public class HttpParser
|
|||
badMessage(buffer, "Unknown Version");
|
||||
return true;
|
||||
}
|
||||
_persistent=HttpVersion.HTTP_1_1==_version;
|
||||
_persistent=_version.getVerion()>=HttpVersion.HTTP_1_1.getVerion();
|
||||
_state=State.SPACE1;
|
||||
}
|
||||
else if (ch < HttpTokens.SPACE && ch>=0)
|
||||
|
@ -397,8 +373,8 @@ public class HttpParser
|
|||
_utf8.reset();
|
||||
return_from_parse|=_requestHandler.startRequest(_method,_methodString,_uri,null);
|
||||
_persistent=false;
|
||||
_state=State.SEEKING_EOF;
|
||||
return_from_parse|=_handler.headerComplete(false,false);
|
||||
_state=State.END;
|
||||
return_from_parse|=_handler.headerComplete(false,_persistent);
|
||||
return_from_parse|=_handler.messageComplete(_contentPosition);
|
||||
}
|
||||
else
|
||||
|
@ -428,7 +404,7 @@ public class HttpParser
|
|||
_string.setLength(0);
|
||||
buffer.position(buffer.position()+_version.asString().length()-1);
|
||||
_eol=buffer.get();
|
||||
_persistent=HttpVersion.HTTP_1_1==_version;
|
||||
_persistent=_version.getVerion()>=HttpVersion.HTTP_1_1.getVerion();
|
||||
_state=State.HEADER;
|
||||
return_from_parse|=_requestHandler.startRequest(_method,_methodString, _uri, _version);
|
||||
}
|
||||
|
@ -448,8 +424,8 @@ public class HttpParser
|
|||
// HTTP/0.9
|
||||
return_from_parse|=_requestHandler.startRequest(_method,_methodString, _uri, null);
|
||||
_persistent=false;
|
||||
_state=State.SEEKING_EOF;
|
||||
return_from_parse|=_handler.headerComplete(false,false);
|
||||
_state=State.END;
|
||||
return_from_parse|=_handler.headerComplete(false,_persistent);
|
||||
return_from_parse|=_handler.messageComplete(_contentPosition);
|
||||
}
|
||||
}
|
||||
|
@ -467,7 +443,7 @@ public class HttpParser
|
|||
}
|
||||
|
||||
_eol=ch;
|
||||
_persistent=HttpVersion.HTTP_1_1==_version;
|
||||
_persistent=_version.getVerion()>=HttpVersion.HTTP_1_1.getVerion();
|
||||
_state=State.HEADER;
|
||||
return_from_parse|=_requestHandler.startRequest(_method,_methodString, _uri, _version);
|
||||
continue;
|
||||
|
@ -649,7 +625,8 @@ public class HttpParser
|
|||
{
|
||||
case EOF_CONTENT:
|
||||
_state=State.EOF_CONTENT;
|
||||
return_from_parse|=_handler.headerComplete(true,false);
|
||||
_persistent=false;
|
||||
return_from_parse|=_handler.headerComplete(true,_persistent);
|
||||
break;
|
||||
|
||||
case CHUNKED_CONTENT:
|
||||
|
@ -659,7 +636,7 @@ public class HttpParser
|
|||
|
||||
case NO_CONTENT:
|
||||
return_from_parse|=_handler.headerComplete(false,_persistent);
|
||||
_state=_persistent||(_responseStatus>=100&&_responseStatus<200)?State.END:State.SEEKING_EOF;
|
||||
_state=State.END;
|
||||
return_from_parse|=_handler.messageComplete(_contentPosition);
|
||||
break;
|
||||
|
||||
|
@ -863,34 +840,41 @@ public class HttpParser
|
|||
* Parse until next Event.
|
||||
* @return True if an {@link RequestHandler} method was called and it returned true;
|
||||
*/
|
||||
public boolean parseNext(ByteBuffer buffer) throws IOException
|
||||
public boolean parseNext(ByteBuffer buffer)
|
||||
{
|
||||
try
|
||||
{
|
||||
// process end states
|
||||
if (_state == State.END)
|
||||
// TODO should we consume white space here?
|
||||
return false;
|
||||
// handle initial state
|
||||
switch(_state)
|
||||
{
|
||||
case START:
|
||||
_version=null;
|
||||
_method=null;
|
||||
_methodString=null;
|
||||
_uri=null;
|
||||
_endOfContent=EndOfContent.UNKNOWN_CONTENT;
|
||||
_header=null;
|
||||
quickStart(buffer);
|
||||
break;
|
||||
|
||||
case CONTENT:
|
||||
if (_contentPosition==_contentLength)
|
||||
{
|
||||
_state=State.END;
|
||||
if(_handler.messageComplete(_contentPosition))
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
|
||||
case END:
|
||||
return false;
|
||||
|
||||
case CLOSED:
|
||||
BufferUtil.clear(buffer);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_state == State.CONTENT && _contentPosition == _contentLength)
|
||||
{
|
||||
// TODO why is this not _state=_persistent?State.END:State.SEEKING_EOF;
|
||||
_state=State.END;
|
||||
if(_handler.messageComplete(_contentPosition))
|
||||
return true;
|
||||
}
|
||||
|
||||
// Handle start
|
||||
if (_state==State.START)
|
||||
{
|
||||
_version=null;
|
||||
_method=null;
|
||||
_methodString=null;
|
||||
_uri=null;
|
||||
_endOfContent=EndOfContent.UNKNOWN_CONTENT;
|
||||
_header=null;
|
||||
quickStart(buffer);
|
||||
}
|
||||
|
||||
// Request/response line
|
||||
if (_state.ordinal()<State.HEADER.ordinal())
|
||||
|
@ -904,7 +888,7 @@ public class HttpParser
|
|||
// Handle HEAD response
|
||||
if (_responseStatus>0 && _headResponse)
|
||||
{
|
||||
_state=_persistent||(_responseStatus>=100&&_responseStatus<200)?State.END:State.SEEKING_EOF;
|
||||
_state=State.END;
|
||||
if (_handler.messageComplete(_contentLength))
|
||||
return true;
|
||||
}
|
||||
|
@ -936,7 +920,7 @@ public class HttpParser
|
|||
long remaining=_contentLength - _contentPosition;
|
||||
if (remaining == 0)
|
||||
{
|
||||
_state=_persistent?State.END:State.SEEKING_EOF;
|
||||
_state=State.END;
|
||||
if (_handler.messageComplete(_contentPosition))
|
||||
return true;
|
||||
}
|
||||
|
@ -960,7 +944,7 @@ public class HttpParser
|
|||
|
||||
if(_contentPosition == _contentLength)
|
||||
{
|
||||
_state=_persistent?State.END:State.SEEKING_EOF;
|
||||
_state=State.END;
|
||||
if (_handler.messageComplete(_contentPosition))
|
||||
return true;
|
||||
}
|
||||
|
@ -995,7 +979,7 @@ public class HttpParser
|
|||
{
|
||||
if (_eol==HttpTokens.CARRIAGE_RETURN && buffer.hasRemaining() && buffer.get(buffer.position())==HttpTokens.LINE_FEED)
|
||||
_eol=buffer.get();
|
||||
_state=_persistent?State.END:State.SEEKING_EOF;
|
||||
_state=State.END;
|
||||
if (_handler.messageComplete(_contentPosition))
|
||||
return true;
|
||||
}
|
||||
|
@ -1025,7 +1009,7 @@ public class HttpParser
|
|||
{
|
||||
if (_eol==HttpTokens.CARRIAGE_RETURN && buffer.hasRemaining() && buffer.get(buffer.position())==HttpTokens.LINE_FEED)
|
||||
_eol=buffer.get();
|
||||
_state=_persistent?State.END:State.SEEKING_EOF;
|
||||
_state=State.END;
|
||||
if (_handler.messageComplete(_contentPosition))
|
||||
return true;
|
||||
}
|
||||
|
@ -1058,12 +1042,6 @@ public class HttpParser
|
|||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case SEEKING_EOF:
|
||||
{
|
||||
buffer.clear().limit(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1082,7 +1060,7 @@ public class HttpParser
|
|||
{
|
||||
BufferUtil.clear(buffer);
|
||||
_persistent=false;
|
||||
_state=State.SEEKING_EOF;
|
||||
_state=State.END;
|
||||
_handler.badMessage(reason);
|
||||
}
|
||||
|
||||
|
@ -1095,8 +1073,6 @@ public class HttpParser
|
|||
switch(_state)
|
||||
{
|
||||
case END:
|
||||
case SEEKING_EOF:
|
||||
_state=State.END;
|
||||
break;
|
||||
|
||||
case EOF_CONTENT:
|
||||
|
@ -1111,18 +1087,26 @@ public class HttpParser
|
|||
_handler.messageComplete(_contentPosition);
|
||||
}
|
||||
|
||||
if (!isComplete() && !isIdle())
|
||||
if (!isComplete() && !isStart())
|
||||
throw new EofException();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------------- */
|
||||
public void close()
|
||||
{
|
||||
if (_state!=State.END)
|
||||
throw new IllegalStateException(toString());
|
||||
_persistent=false;
|
||||
reset();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------------- */
|
||||
public void reset()
|
||||
{
|
||||
// reset state
|
||||
// TODO why is this not _state=_persistent?State.START:(_state=State.SEEKING_EOF);
|
||||
_state=_persistent?State.START:(_state==State.END?State.END:State.SEEKING_EOF);
|
||||
_state=_persistent?State.START:State.CLOSED;
|
||||
_endOfContent=EndOfContent.UNKNOWN_CONTENT;
|
||||
_contentPosition=0;
|
||||
_responseStatus=0;
|
||||
|
@ -1140,10 +1124,11 @@ public class HttpParser
|
|||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return String.format("%s{s=%s,c=%d}",
|
||||
return String.format("%s{s=%s,c=%d,p=%b}",
|
||||
getClass().getSimpleName(),
|
||||
_state,
|
||||
_contentLength);
|
||||
_contentLength,
|
||||
_persistent);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
|
|
@ -336,16 +336,7 @@ public class HttpGeneratorServerTest
|
|||
parser=new HttpParser(handler);
|
||||
parser.setHeadResponse(tr[r]._head);
|
||||
|
||||
try
|
||||
{
|
||||
parser.parseNext(BufferUtil.toBuffer(response));
|
||||
}
|
||||
catch(IOException e)
|
||||
{
|
||||
if (tr[r]._body!=null)
|
||||
throw new Exception(t,e);
|
||||
continue;
|
||||
}
|
||||
parser.parseNext(BufferUtil.toBuffer(response));
|
||||
|
||||
if (tr[r]._body!=null)
|
||||
assertEquals(t,tr[r]._body, this._content);
|
||||
|
|
|
@ -19,6 +19,7 @@ import static org.junit.Assert.assertTrue;
|
|||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.eclipse.jetty.http.HttpParser.State;
|
||||
import org.eclipse.jetty.util.BufferUtil;
|
||||
import org.eclipse.jetty.util.StringUtil;
|
||||
import org.junit.Assert;
|
||||
|
@ -30,6 +31,31 @@ import org.junit.Test;
|
|||
*/
|
||||
public class HttpParserTest
|
||||
{
|
||||
|
||||
/* ------------------------------------------------------------------------------- */
|
||||
/**
|
||||
* Parse until {@link #END END} state.
|
||||
* If the parser is already in the END state, then it is {@link #reset reset} and re-parsed.
|
||||
* @param parser TODO
|
||||
* @throws IllegalStateException If the buffers have already been partially parsed.
|
||||
*/
|
||||
public static void parseAll(HttpParser parser, ByteBuffer buffer)
|
||||
{
|
||||
if (parser.isState(State.END))
|
||||
parser.reset();
|
||||
if (!parser.isState(State.START))
|
||||
throw new IllegalStateException("!START");
|
||||
|
||||
// continue parsing
|
||||
while (!parser.isState(State.END) && buffer.hasRemaining())
|
||||
{
|
||||
int remaining=buffer.remaining();
|
||||
parser.parseNext(buffer);
|
||||
if (remaining==buffer.remaining())
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLineParse0() throws Exception
|
||||
{
|
||||
|
@ -37,11 +63,11 @@ public class HttpParserTest
|
|||
|
||||
Handler handler = new Handler();
|
||||
HttpParser parser= new HttpParser((HttpParser.RequestHandler)handler);
|
||||
parser.parseAll(buffer);
|
||||
assertEquals("POST", f0);
|
||||
assertEquals("/foo", f1);
|
||||
assertEquals("HTTP/1.0", f2);
|
||||
assertEquals(-1, h);
|
||||
parseAll(parser,buffer);
|
||||
assertEquals("POST", _methodOrVersion);
|
||||
assertEquals("/foo", _uriOrStatus);
|
||||
assertEquals("HTTP/1.0", _versionOrReason);
|
||||
assertEquals(-1, _h);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -49,14 +75,14 @@ public class HttpParserTest
|
|||
{
|
||||
ByteBuffer buffer= BufferUtil.toBuffer("GET /999\015\012");
|
||||
|
||||
f2= null;
|
||||
_versionOrReason= null;
|
||||
Handler handler = new Handler();
|
||||
HttpParser parser= new HttpParser((HttpParser.RequestHandler)handler);
|
||||
parser.parseAll(buffer);
|
||||
assertEquals("GET", f0);
|
||||
assertEquals("/999", f1);
|
||||
assertEquals(null, f2);
|
||||
assertEquals(-1, h);
|
||||
parseAll(parser,buffer);
|
||||
assertEquals("GET", _methodOrVersion);
|
||||
assertEquals("/999", _uriOrStatus);
|
||||
assertEquals(null, _versionOrReason);
|
||||
assertEquals(-1, _h);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -64,14 +90,14 @@ public class HttpParserTest
|
|||
{
|
||||
ByteBuffer buffer= BufferUtil.toBuffer("POST /222 \015\012");
|
||||
|
||||
f2= null;
|
||||
_versionOrReason= null;
|
||||
Handler handler = new Handler();
|
||||
HttpParser parser= new HttpParser((HttpParser.RequestHandler)handler);
|
||||
parser.parseAll(buffer);
|
||||
assertEquals("POST", f0);
|
||||
assertEquals("/222", f1);
|
||||
assertEquals(null, f2);
|
||||
assertEquals(-1, h);
|
||||
parseAll(parser,buffer);
|
||||
assertEquals("POST", _methodOrVersion);
|
||||
assertEquals("/222", _uriOrStatus);
|
||||
assertEquals(null, _versionOrReason);
|
||||
assertEquals(-1, _h);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -81,11 +107,11 @@ public class HttpParserTest
|
|||
|
||||
Handler handler = new Handler();
|
||||
HttpParser parser= new HttpParser((HttpParser.RequestHandler)handler);
|
||||
parser.parseAll(buffer);
|
||||
assertEquals("POST", f0);
|
||||
assertEquals("/fo\u0690", f1);
|
||||
assertEquals("HTTP/1.0", f2);
|
||||
assertEquals(-1, h);
|
||||
parseAll(parser,buffer);
|
||||
assertEquals("POST", _methodOrVersion);
|
||||
assertEquals("/fo\u0690", _uriOrStatus);
|
||||
assertEquals("HTTP/1.0", _versionOrReason);
|
||||
assertEquals(-1, _h);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -95,11 +121,11 @@ public class HttpParserTest
|
|||
|
||||
Handler handler = new Handler();
|
||||
HttpParser parser= new HttpParser((HttpParser.RequestHandler)handler);
|
||||
parser.parseAll(buffer);
|
||||
assertEquals("POST", f0);
|
||||
assertEquals("/foo?param=\u0690", f1);
|
||||
assertEquals("HTTP/1.0", f2);
|
||||
assertEquals(-1, h);
|
||||
parseAll(parser,buffer);
|
||||
assertEquals("POST", _methodOrVersion);
|
||||
assertEquals("/foo?param=\u0690", _uriOrStatus);
|
||||
assertEquals("HTTP/1.0", _versionOrReason);
|
||||
assertEquals(-1, _h);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -108,12 +134,12 @@ public class HttpParserTest
|
|||
ByteBuffer buffer= BufferUtil.toBuffer("CONNECT 192.168.1.2:80 HTTP/1.1\015\012" + "\015\012");
|
||||
Handler handler = new Handler();
|
||||
HttpParser parser= new HttpParser((HttpParser.RequestHandler)handler);
|
||||
parser.parseAll(buffer);
|
||||
parseAll(parser,buffer);
|
||||
assertTrue(handler.request);
|
||||
assertEquals("CONNECT", f0);
|
||||
assertEquals("192.168.1.2:80", f1);
|
||||
assertEquals("HTTP/1.1", f2);
|
||||
assertEquals(-1, h);
|
||||
assertEquals("CONNECT", _methodOrVersion);
|
||||
assertEquals("192.168.1.2:80", _uriOrStatus);
|
||||
assertEquals("HTTP/1.1", _versionOrReason);
|
||||
assertEquals(-1, _h);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -133,26 +159,26 @@ public class HttpParserTest
|
|||
"\015\012");
|
||||
Handler handler = new Handler();
|
||||
HttpParser parser= new HttpParser((HttpParser.RequestHandler)handler);
|
||||
parser.parseAll(buffer);
|
||||
parseAll(parser,buffer);
|
||||
|
||||
assertEquals("GET", f0);
|
||||
assertEquals("/", f1);
|
||||
assertEquals("HTTP/1.0", f2);
|
||||
assertEquals("Host", hdr[0]);
|
||||
assertEquals("localhost", val[0]);
|
||||
assertEquals("Header1", hdr[1]);
|
||||
assertEquals("value1", val[1]);
|
||||
assertEquals("Header 2", hdr[2]);
|
||||
assertEquals("value 2a value 2b", val[2]);
|
||||
assertEquals("Header3", hdr[3]);
|
||||
assertEquals(null, val[3]);
|
||||
assertEquals("Header4", hdr[4]);
|
||||
assertEquals("value4", val[4]);
|
||||
assertEquals("Server5", hdr[5]);
|
||||
assertEquals("notServer", val[5]);
|
||||
assertEquals("Host Header", hdr[6]);
|
||||
assertEquals("notHost", val[6]);
|
||||
assertEquals(6, h);
|
||||
assertEquals("GET", _methodOrVersion);
|
||||
assertEquals("/", _uriOrStatus);
|
||||
assertEquals("HTTP/1.0", _versionOrReason);
|
||||
assertEquals("Host", _hdr[0]);
|
||||
assertEquals("localhost", _val[0]);
|
||||
assertEquals("Header1", _hdr[1]);
|
||||
assertEquals("value1", _val[1]);
|
||||
assertEquals("Header 2", _hdr[2]);
|
||||
assertEquals("value 2a value 2b", _val[2]);
|
||||
assertEquals("Header3", _hdr[3]);
|
||||
assertEquals(null, _val[3]);
|
||||
assertEquals("Header4", _hdr[4]);
|
||||
assertEquals("value4", _val[4]);
|
||||
assertEquals("Server5", _hdr[5]);
|
||||
assertEquals("notServer", _val[5]);
|
||||
assertEquals("Host Header", _hdr[6]);
|
||||
assertEquals("notHost", _val[6]);
|
||||
assertEquals(6, _h);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -191,22 +217,22 @@ public class HttpParserTest
|
|||
parser.parseNext(buffer);
|
||||
}
|
||||
|
||||
assertEquals("SPLIT", f0);
|
||||
assertEquals("/", f1);
|
||||
assertEquals("HTTP/1.0", f2);
|
||||
assertEquals("Host", hdr[0]);
|
||||
assertEquals("localhost", val[0]);
|
||||
assertEquals("Header1", hdr[1]);
|
||||
assertEquals("value1", val[1]);
|
||||
assertEquals("Header2", hdr[2]);
|
||||
assertEquals("value 2a value 2b", val[2]);
|
||||
assertEquals("Header3", hdr[3]);
|
||||
assertEquals(null, val[3]);
|
||||
assertEquals("Header4", hdr[4]);
|
||||
assertEquals("value4", val[4]);
|
||||
assertEquals("Server5", hdr[5]);
|
||||
assertEquals("notServer", val[5]);
|
||||
assertEquals(5, h);
|
||||
assertEquals("SPLIT", _methodOrVersion);
|
||||
assertEquals("/", _uriOrStatus);
|
||||
assertEquals("HTTP/1.0", _versionOrReason);
|
||||
assertEquals("Host", _hdr[0]);
|
||||
assertEquals("localhost", _val[0]);
|
||||
assertEquals("Header1", _hdr[1]);
|
||||
assertEquals("value1", _val[1]);
|
||||
assertEquals("Header2", _hdr[2]);
|
||||
assertEquals("value 2a value 2b", _val[2]);
|
||||
assertEquals("Header3", _hdr[3]);
|
||||
assertEquals(null, _val[3]);
|
||||
assertEquals("Header4", _hdr[4]);
|
||||
assertEquals("value4", _val[4]);
|
||||
assertEquals("Server5", _hdr[5]);
|
||||
assertEquals("notServer", _val[5]);
|
||||
assertEquals(5, _h);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -226,14 +252,14 @@ public class HttpParserTest
|
|||
+ "0\015\012");
|
||||
Handler handler = new Handler();
|
||||
HttpParser parser= new HttpParser((HttpParser.RequestHandler)handler);
|
||||
parser.parseAll(buffer);
|
||||
parseAll(parser,buffer);
|
||||
|
||||
assertEquals("GET", f0);
|
||||
assertEquals("/chunk", f1);
|
||||
assertEquals("HTTP/1.0", f2);
|
||||
assertEquals(1, h);
|
||||
assertEquals("Header1", hdr[0]);
|
||||
assertEquals("value1", val[0]);
|
||||
assertEquals("GET", _methodOrVersion);
|
||||
assertEquals("/chunk", _uriOrStatus);
|
||||
assertEquals("HTTP/1.0", _versionOrReason);
|
||||
assertEquals(1, _h);
|
||||
assertEquals("Header1", _hdr[0]);
|
||||
assertEquals("value1", _val[0]);
|
||||
assertEquals("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ", _content);
|
||||
}
|
||||
|
||||
|
@ -241,7 +267,7 @@ public class HttpParserTest
|
|||
public void testMultiParse() throws Exception
|
||||
{
|
||||
ByteBuffer buffer= BufferUtil.toBuffer(
|
||||
"GET /mp HTTP/1.0\015\012"
|
||||
"GET /mp HTTP/1.0\015\012"
|
||||
+ "Connection: Keep-Alive\015\012"
|
||||
+ "Header1: value1\015\012"
|
||||
+ "Transfer-Encoding: chunked\015\012"
|
||||
|
@ -251,11 +277,15 @@ public class HttpParserTest
|
|||
+ "1a\015\012"
|
||||
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ\015\012"
|
||||
+ "0\015\012"
|
||||
|
||||
+ "\015\012"
|
||||
|
||||
+ "POST /foo HTTP/1.0\015\012"
|
||||
+ "Connection: Keep-Alive\015\012"
|
||||
+ "Header2: value2\015\012"
|
||||
+ "Content-Length: 0\015\012"
|
||||
+ "\015\012"
|
||||
|
||||
+ "PUT /doodle HTTP/1.0\015\012"
|
||||
+ "Connection: close\015\012"
|
||||
+ "Header3: value3\015\012"
|
||||
|
@ -267,33 +297,35 @@ public class HttpParserTest
|
|||
Handler handler = new Handler();
|
||||
HttpParser parser= new HttpParser((HttpParser.RequestHandler)handler);
|
||||
parser.parseNext(buffer);
|
||||
assertEquals("GET", f0);
|
||||
assertEquals("/mp", f1);
|
||||
assertEquals("HTTP/1.0", f2);
|
||||
assertEquals(2, h);
|
||||
assertEquals("Header1", hdr[1]);
|
||||
assertEquals("value1", val[1]);
|
||||
assertEquals("GET", _methodOrVersion);
|
||||
assertEquals("/mp", _uriOrStatus);
|
||||
assertEquals("HTTP/1.0", _versionOrReason);
|
||||
assertEquals(2, _h);
|
||||
assertEquals("Header1", _hdr[1]);
|
||||
assertEquals("value1", _val[1]);
|
||||
assertEquals("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ", _content);
|
||||
|
||||
parser.reset();
|
||||
init();
|
||||
parser.parseNext(buffer);
|
||||
assertEquals("POST", f0);
|
||||
assertEquals("/foo", f1);
|
||||
assertEquals("HTTP/1.0", f2);
|
||||
assertEquals(2, h);
|
||||
assertEquals("Header2", hdr[1]);
|
||||
assertEquals("value2", val[1]);
|
||||
assertEquals("POST", _methodOrVersion);
|
||||
assertEquals("/foo", _uriOrStatus);
|
||||
assertEquals("HTTP/1.0", _versionOrReason);
|
||||
assertEquals(2, _h);
|
||||
assertEquals("Header2", _hdr[1]);
|
||||
assertEquals("value2", _val[1]);
|
||||
assertEquals(null, _content);
|
||||
|
||||
parser.reset();
|
||||
init();
|
||||
parser.parseNext(buffer);
|
||||
parser.inputShutdown();
|
||||
assertEquals("PUT", f0);
|
||||
assertEquals("/doodle", f1);
|
||||
assertEquals("HTTP/1.0", f2);
|
||||
assertEquals(2, h);
|
||||
assertEquals("Header3", hdr[1]);
|
||||
assertEquals("value3", val[1]);
|
||||
assertEquals("PUT", _methodOrVersion);
|
||||
assertEquals("/doodle", _uriOrStatus);
|
||||
assertEquals("HTTP/1.0", _versionOrReason);
|
||||
assertEquals(2, _h);
|
||||
assertEquals("Header3", _hdr[1]);
|
||||
assertEquals("value3", _val[1]);
|
||||
assertEquals("0123456789", _content);
|
||||
}
|
||||
|
||||
|
@ -310,12 +342,12 @@ public class HttpParserTest
|
|||
Handler handler = new Handler();
|
||||
HttpParser parser= new HttpParser((HttpParser.ResponseHandler)handler);
|
||||
parser.parseNext(buffer);
|
||||
assertEquals("HTTP/1.1", f0);
|
||||
assertEquals("200", f1);
|
||||
assertEquals("Correct", f2);
|
||||
assertEquals("HTTP/1.1", _methodOrVersion);
|
||||
assertEquals("200", _uriOrStatus);
|
||||
assertEquals("Correct", _versionOrReason);
|
||||
assertEquals(10,_content.length());
|
||||
assertTrue(headerCompleted);
|
||||
assertTrue(messageCompleted);
|
||||
assertTrue(_headerCompleted);
|
||||
assertTrue(_messageCompleted);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -329,20 +361,21 @@ public class HttpParserTest
|
|||
Handler handler = new Handler();
|
||||
HttpParser parser= new HttpParser((HttpParser.ResponseHandler)handler);
|
||||
parser.parseNext(buffer);
|
||||
assertEquals("HTTP/1.1", f0);
|
||||
assertEquals("304", f1);
|
||||
assertEquals("Not-Modified", f2);
|
||||
assertTrue(headerCompleted);
|
||||
assertTrue(messageCompleted);
|
||||
assertEquals("HTTP/1.1", _methodOrVersion);
|
||||
assertEquals("304", _uriOrStatus);
|
||||
assertEquals("Not-Modified", _versionOrReason);
|
||||
assertTrue(_headerCompleted);
|
||||
assertTrue(_messageCompleted);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResponseParse2() throws Exception
|
||||
{
|
||||
ByteBuffer buffer= BufferUtil.toBuffer(
|
||||
"HTTP/1.1 204 No-Content\015\012"
|
||||
"HTTP/1.1 204 No-Content\015\012"
|
||||
+ "Header: value\015\012"
|
||||
+ "\015\012"
|
||||
|
||||
+ "HTTP/1.1 200 Correct\015\012"
|
||||
+ "Content-Length: 10\015\012"
|
||||
+ "Content-Type: text/plain\015\012"
|
||||
|
@ -352,23 +385,23 @@ public class HttpParserTest
|
|||
Handler handler = new Handler();
|
||||
HttpParser parser= new HttpParser((HttpParser.ResponseHandler)handler);
|
||||
parser.parseNext(buffer);
|
||||
assertEquals("HTTP/1.1", f0);
|
||||
assertEquals("204", f1);
|
||||
assertEquals("No-Content", f2);
|
||||
assertTrue(headerCompleted);
|
||||
assertTrue(messageCompleted);
|
||||
assertEquals("HTTP/1.1", _methodOrVersion);
|
||||
assertEquals("204", _uriOrStatus);
|
||||
assertEquals("No-Content", _versionOrReason);
|
||||
assertTrue(_headerCompleted);
|
||||
assertTrue(_messageCompleted);
|
||||
|
||||
|
||||
parser.setPersistent(true);
|
||||
parser.reset();
|
||||
init();
|
||||
|
||||
parser.parseNext(buffer);
|
||||
parser.inputShutdown();
|
||||
assertEquals("HTTP/1.1", f0);
|
||||
assertEquals("200", f1);
|
||||
assertEquals("Correct", f2);
|
||||
assertEquals("HTTP/1.1", _methodOrVersion);
|
||||
assertEquals("200", _uriOrStatus);
|
||||
assertEquals("Correct", _versionOrReason);
|
||||
assertEquals(_content.length(), 10);
|
||||
assertTrue(headerCompleted);
|
||||
assertTrue(messageCompleted);
|
||||
assertTrue(_headerCompleted);
|
||||
assertTrue(_messageCompleted);
|
||||
}
|
||||
|
||||
|
||||
|
@ -385,12 +418,12 @@ public class HttpParserTest
|
|||
Handler handler = new Handler();
|
||||
HttpParser parser= new HttpParser((HttpParser.ResponseHandler)handler);
|
||||
parser.parseNext(buffer);
|
||||
assertEquals("HTTP/1.1", f0);
|
||||
assertEquals("200", f1);
|
||||
assertEquals(null, f2);
|
||||
assertEquals("HTTP/1.1", _methodOrVersion);
|
||||
assertEquals("200", _uriOrStatus);
|
||||
assertEquals(null, _versionOrReason);
|
||||
assertEquals(_content.length(), 10);
|
||||
assertTrue(headerCompleted);
|
||||
assertTrue(messageCompleted);
|
||||
assertTrue(_headerCompleted);
|
||||
assertTrue(_messageCompleted);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -406,12 +439,12 @@ public class HttpParserTest
|
|||
Handler handler = new Handler();
|
||||
HttpParser parser= new HttpParser((HttpParser.ResponseHandler)handler);
|
||||
parser.parseNext(buffer);
|
||||
assertEquals("HTTP/1.1", f0);
|
||||
assertEquals("200", f1);
|
||||
assertEquals(null, f2);
|
||||
assertEquals("HTTP/1.1", _methodOrVersion);
|
||||
assertEquals("200", _uriOrStatus);
|
||||
assertEquals(null, _versionOrReason);
|
||||
assertEquals(_content.length(), 10);
|
||||
assertTrue(headerCompleted);
|
||||
assertTrue(messageCompleted);
|
||||
assertTrue(_headerCompleted);
|
||||
assertTrue(_messageCompleted);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -425,12 +458,12 @@ public class HttpParserTest
|
|||
Handler handler = new Handler();
|
||||
HttpParser parser= new HttpParser((HttpParser.ResponseHandler)handler);
|
||||
parser.parseNext(buffer);
|
||||
assertEquals("HTTP/1.1", f0);
|
||||
assertEquals("304", f1);
|
||||
assertEquals("found", f2);
|
||||
assertEquals("HTTP/1.1", _methodOrVersion);
|
||||
assertEquals("304", _uriOrStatus);
|
||||
assertEquals("found", _versionOrReason);
|
||||
assertEquals(null,_content);
|
||||
assertTrue(headerCompleted);
|
||||
assertTrue(messageCompleted);
|
||||
assertTrue(_headerCompleted);
|
||||
assertTrue(_messageCompleted);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -449,12 +482,12 @@ public class HttpParserTest
|
|||
HttpParser parser= new HttpParser((HttpParser.ResponseHandler)handler);
|
||||
|
||||
parser.parseNext(buffer);
|
||||
assertEquals("HTTP/1.1", f0);
|
||||
assertEquals("200", f1);
|
||||
assertEquals("OK", f2);
|
||||
assertEquals("HTTP/1.1", _methodOrVersion);
|
||||
assertEquals("200", _uriOrStatus);
|
||||
assertEquals("OK", _versionOrReason);
|
||||
assertEquals(null,_content);
|
||||
assertTrue(headerCompleted);
|
||||
assertTrue(messageCompleted);
|
||||
assertTrue(_headerCompleted);
|
||||
assertTrue(_messageCompleted);
|
||||
|
||||
|
||||
}
|
||||
|
@ -472,10 +505,10 @@ public class HttpParserTest
|
|||
HttpParser parser= new HttpParser((HttpParser.RequestHandler)handler);
|
||||
|
||||
parser.parseNext(buffer);
|
||||
assertEquals(null,f0);
|
||||
assertEquals(null,_methodOrVersion);
|
||||
assertEquals("No URI",_bad);
|
||||
assertFalse(buffer.hasRemaining());
|
||||
assertEquals(HttpParser.State.SEEKING_EOF,parser.getState());
|
||||
assertEquals(HttpParser.State.END,parser.getState());
|
||||
}
|
||||
|
||||
|
||||
|
@ -492,10 +525,10 @@ public class HttpParserTest
|
|||
HttpParser parser= new HttpParser((HttpParser.RequestHandler)handler);
|
||||
|
||||
parser.parseNext(buffer);
|
||||
assertEquals(null,f0);
|
||||
assertEquals(null,_methodOrVersion);
|
||||
assertEquals("No URI",_bad);
|
||||
assertFalse(buffer.hasRemaining());
|
||||
assertEquals(HttpParser.State.SEEKING_EOF,parser.getState());
|
||||
assertEquals(HttpParser.State.END,parser.getState());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -511,10 +544,10 @@ public class HttpParserTest
|
|||
HttpParser parser= new HttpParser((HttpParser.ResponseHandler)handler);
|
||||
|
||||
parser.parseNext(buffer);
|
||||
assertEquals(null,f0);
|
||||
assertEquals(null,_methodOrVersion);
|
||||
assertEquals("Unknown Version",_bad);
|
||||
assertFalse(buffer.hasRemaining());
|
||||
assertEquals(HttpParser.State.SEEKING_EOF,parser.getState());
|
||||
assertEquals(HttpParser.State.END,parser.getState());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -530,10 +563,10 @@ public class HttpParserTest
|
|||
HttpParser parser= new HttpParser((HttpParser.ResponseHandler)handler);
|
||||
|
||||
parser.parseNext(buffer);
|
||||
assertEquals(null,f0);
|
||||
assertEquals(null,_methodOrVersion);
|
||||
assertEquals("No Status",_bad);
|
||||
assertFalse(buffer.hasRemaining());
|
||||
assertEquals(HttpParser.State.SEEKING_EOF,parser.getState());
|
||||
assertEquals(HttpParser.State.END,parser.getState());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -549,10 +582,10 @@ public class HttpParserTest
|
|||
HttpParser parser= new HttpParser((HttpParser.ResponseHandler)handler);
|
||||
|
||||
parser.parseNext(buffer);
|
||||
assertEquals(null,f0);
|
||||
assertEquals(null,_methodOrVersion);
|
||||
assertEquals("No Status",_bad);
|
||||
assertFalse(buffer.hasRemaining());
|
||||
assertEquals(HttpParser.State.SEEKING_EOF,parser.getState());
|
||||
assertEquals(HttpParser.State.END,parser.getState());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -568,10 +601,10 @@ public class HttpParserTest
|
|||
HttpParser parser= new HttpParser((HttpParser.ResponseHandler)handler);
|
||||
|
||||
parser.parseNext(buffer);
|
||||
assertEquals(null,f0);
|
||||
assertEquals(null,_methodOrVersion);
|
||||
assertEquals("Unknown Version",_bad);
|
||||
assertFalse(buffer.hasRemaining());
|
||||
assertEquals(HttpParser.State.SEEKING_EOF,parser.getState());
|
||||
assertEquals(HttpParser.State.END,parser.getState());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -587,10 +620,10 @@ public class HttpParserTest
|
|||
HttpParser parser= new HttpParser((HttpParser.RequestHandler)handler);
|
||||
|
||||
parser.parseNext(buffer);
|
||||
assertEquals("GET",f0);
|
||||
assertEquals("GET",_methodOrVersion);
|
||||
assertEquals("Bad Content-Length",_bad);
|
||||
assertFalse(buffer.hasRemaining());
|
||||
assertEquals(HttpParser.State.SEEKING_EOF,parser.getState());
|
||||
assertEquals(HttpParser.State.END,parser.getState());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -606,10 +639,10 @@ public class HttpParserTest
|
|||
HttpParser parser= new HttpParser((HttpParser.RequestHandler)handler);
|
||||
|
||||
parser.parseNext(buffer);
|
||||
assertEquals("GET",f0);
|
||||
assertEquals("GET",_methodOrVersion);
|
||||
assertEquals("Bad Content-Length",_bad);
|
||||
assertFalse(buffer.hasRemaining());
|
||||
assertEquals(HttpParser.State.SEEKING_EOF,parser.getState());
|
||||
assertEquals(HttpParser.State.END,parser.getState());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -625,10 +658,10 @@ public class HttpParserTest
|
|||
HttpParser parser= new HttpParser((HttpParser.RequestHandler)handler);
|
||||
|
||||
parser.parseNext(buffer);
|
||||
assertEquals("GET",f0);
|
||||
assertEquals("GET",_methodOrVersion);
|
||||
assertEquals("Bad Content-Length",_bad);
|
||||
assertFalse(buffer.hasRemaining());
|
||||
assertEquals(HttpParser.State.SEEKING_EOF,parser.getState());
|
||||
assertEquals(HttpParser.State.END,parser.getState());
|
||||
}
|
||||
|
||||
|
||||
|
@ -637,25 +670,27 @@ public class HttpParserTest
|
|||
{
|
||||
_bad=null;
|
||||
_content=null;
|
||||
f0=null;
|
||||
f1=null;
|
||||
f2=null;
|
||||
hdr=null;
|
||||
val=null;
|
||||
h=0;
|
||||
_methodOrVersion=null;
|
||||
_uriOrStatus=null;
|
||||
_versionOrReason=null;
|
||||
_hdr=null;
|
||||
_val=null;
|
||||
_h=0;
|
||||
_headerCompleted=false;
|
||||
_messageCompleted=false;
|
||||
}
|
||||
|
||||
private String _bad;
|
||||
private String _content;
|
||||
private String f0;
|
||||
private String f1;
|
||||
private String f2;
|
||||
private String[] hdr;
|
||||
private String[] val;
|
||||
private int h;
|
||||
private String _methodOrVersion;
|
||||
private String _uriOrStatus;
|
||||
private String _versionOrReason;
|
||||
private String[] _hdr;
|
||||
private String[] _val;
|
||||
private int _h;
|
||||
|
||||
private boolean headerCompleted;
|
||||
private boolean messageCompleted;
|
||||
private boolean _headerCompleted;
|
||||
private boolean _messageCompleted;
|
||||
|
||||
private class Handler implements HttpParser.RequestHandler, HttpParser.ResponseHandler
|
||||
{
|
||||
|
@ -678,16 +713,16 @@ public class HttpParserTest
|
|||
public boolean startRequest(HttpMethod httpMethod, String method, String uri, HttpVersion version)
|
||||
{
|
||||
request=true;
|
||||
h= -1;
|
||||
hdr= new String[9];
|
||||
val= new String[9];
|
||||
f0= method;
|
||||
f1= uri;
|
||||
f2= version==null?null:version.asString();
|
||||
_h= -1;
|
||||
_hdr= new String[9];
|
||||
_val= new String[9];
|
||||
_methodOrVersion= method;
|
||||
_uriOrStatus= uri;
|
||||
_versionOrReason= version==null?null:version.asString();
|
||||
|
||||
fields=new HttpFields();
|
||||
messageCompleted = false;
|
||||
headerCompleted = false;
|
||||
_messageCompleted = false;
|
||||
_headerCompleted = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -695,8 +730,8 @@ public class HttpParserTest
|
|||
public boolean parsedHeader(HttpHeader header, String name, String value)
|
||||
{
|
||||
//System.err.println("header "+name+": "+value);
|
||||
hdr[++h]= name;
|
||||
val[h]= value;
|
||||
_hdr[++_h]= name;
|
||||
_val[_h]= value;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -714,7 +749,7 @@ public class HttpParserTest
|
|||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
headerCompleted = true;
|
||||
_headerCompleted = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -722,7 +757,7 @@ public class HttpParserTest
|
|||
public boolean messageComplete(long contentLength)
|
||||
{
|
||||
//System.err.println("messageComplete");
|
||||
messageCompleted = true;
|
||||
_messageCompleted = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -736,16 +771,16 @@ public class HttpParserTest
|
|||
public boolean startResponse(HttpVersion version, int status, String reason)
|
||||
{
|
||||
request=false;
|
||||
f0 = version.asString();
|
||||
f1 = Integer.toString(status);
|
||||
f2 = reason==null?null:reason.toString();
|
||||
_methodOrVersion = version.asString();
|
||||
_uriOrStatus = Integer.toString(status);
|
||||
_versionOrReason = reason==null?null:reason.toString();
|
||||
|
||||
fields=new HttpFields();
|
||||
hdr= new String[9];
|
||||
val= new String[9];
|
||||
_hdr= new String[9];
|
||||
_val= new String[9];
|
||||
|
||||
messageCompleted = false;
|
||||
headerCompleted = false;
|
||||
_messageCompleted = false;
|
||||
_headerCompleted = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -90,7 +90,7 @@ public abstract class HttpChannel
|
|||
|
||||
private int _requests;
|
||||
private int _include;
|
||||
|
||||
|
||||
private HttpVersion _version = HttpVersion.HTTP_1_1;
|
||||
|
||||
private boolean _expect = false;
|
||||
|
@ -285,6 +285,9 @@ public abstract class HttpChannel
|
|||
/* ------------------------------------------------------------ */
|
||||
public void reset()
|
||||
{
|
||||
_expect=false;
|
||||
_expect100Continue=false;
|
||||
_expect102Processing=false;
|
||||
_requestFields.clear();
|
||||
_request.recycle();
|
||||
_responseFields.clear();
|
||||
|
@ -295,9 +298,9 @@ public abstract class HttpChannel
|
|||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
protected void handleRequest()
|
||||
protected void process()
|
||||
{
|
||||
LOG.debug("{} handleRequest",this);
|
||||
LOG.debug("{} process",this);
|
||||
|
||||
String threadName=null;
|
||||
if (LOG.isDebugEnabled())
|
||||
|
@ -306,8 +309,6 @@ public abstract class HttpChannel
|
|||
Thread.currentThread().setName(threadName+" - "+_uri);
|
||||
}
|
||||
|
||||
Throwable async_exception=null;
|
||||
|
||||
__currentChannel.set(this);
|
||||
try
|
||||
{
|
||||
|
@ -324,7 +325,6 @@ public abstract class HttpChannel
|
|||
_request.setHandled(false);
|
||||
_out.reopen();
|
||||
|
||||
|
||||
if (_state.isInitial())
|
||||
{
|
||||
_request.setDispatcherType(DispatcherType.REQUEST);
|
||||
|
@ -345,21 +345,21 @@ public abstract class HttpChannel
|
|||
catch (EofException e)
|
||||
{
|
||||
LOG.debug(e);
|
||||
async_exception=e;
|
||||
_state.error(e);
|
||||
_request.setHandled(true);
|
||||
}
|
||||
catch (ServletException e)
|
||||
{
|
||||
LOG.warn(String.valueOf(_uri),e.toString());
|
||||
LOG.debug(String.valueOf(_uri),e);
|
||||
async_exception=e;
|
||||
_state.error(e);
|
||||
_request.setHandled(true);
|
||||
commitError(500, null, e.toString());
|
||||
}
|
||||
catch (Throwable e)
|
||||
{
|
||||
LOG.warn(String.valueOf(_uri),e);
|
||||
async_exception=e;
|
||||
_state.error(e);
|
||||
_request.setHandled(true);
|
||||
commitError(500, null, e.toString());
|
||||
}
|
||||
|
@ -377,22 +377,20 @@ public abstract class HttpChannel
|
|||
|
||||
if (_state.isUncompleted())
|
||||
{
|
||||
_state.doComplete(async_exception);
|
||||
|
||||
if (_expect100Continue)
|
||||
{
|
||||
LOG.debug("100 continues not sent");
|
||||
// We didn't send 100 continues, but the latest interpretation
|
||||
// of the spec (see httpbis) is that the client will either
|
||||
// send the body anyway, or close. So we no longer need to
|
||||
// do anything special here other than make the connection not persistent
|
||||
_expect100Continue = false;
|
||||
if (!_response.isCommitted())
|
||||
_response.addHeader(HttpHeader.CONNECTION,HttpHeaderValue.CLOSE.toString());
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (_expect100Continue)
|
||||
{
|
||||
LOG.debug("100 continues not sent");
|
||||
// We didn't send 100 continues, but the latest interpretation
|
||||
// of the spec (see httpbis) is that the client will either
|
||||
// send the body anyway, or close. So we no longer need to
|
||||
// do anything special here other than make the connection not persistent
|
||||
_expect100Continue = false;
|
||||
if (!_response.isCommitted())
|
||||
_response.addHeader(HttpHeader.CONNECTION,HttpHeaderValue.CLOSE.toString());
|
||||
}
|
||||
|
||||
if (!_response.isCommitted() && !_request.isHandled())
|
||||
_response.sendError(404);
|
||||
_response.complete();
|
||||
|
@ -401,8 +399,12 @@ public abstract class HttpChannel
|
|||
{
|
||||
LOG.warn(e);
|
||||
}
|
||||
_request.setHandled(true);
|
||||
completed();
|
||||
finally
|
||||
{
|
||||
_state.doComplete();
|
||||
_request.setHandled(true);
|
||||
completed();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -633,7 +635,7 @@ public abstract class HttpChannel
|
|||
default:
|
||||
}
|
||||
|
||||
// Either handle now or wait for first content
|
||||
// Either handle now or wait for first content/message complete
|
||||
if (_expect100Continue)
|
||||
return true;
|
||||
|
||||
|
|
|
@ -59,7 +59,7 @@ public class HttpChannelState implements AsyncContext, Continuation
|
|||
// REDISPATCH REDISPATCHED
|
||||
// REDISPATCHED ASYNCSTARTED UNCOMPLETED
|
||||
// COMPLETING UNCOMPLETED UNCOMPLETED
|
||||
// UNCOMPLETED COMPLETED
|
||||
// UNCOMPLETED UNCOMPLETED COMPLETED
|
||||
// COMPLETED
|
||||
|
||||
public enum State
|
||||
|
@ -287,7 +287,7 @@ public class HttpChannelState implements AsyncContext, Continuation
|
|||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @return false if the handling of the request should not proceed
|
||||
* @return true if the handling of the request should proceed
|
||||
*/
|
||||
protected boolean handling()
|
||||
{
|
||||
|
@ -316,6 +316,7 @@ public class HttpChannelState implements AsyncContext, Continuation
|
|||
_state=State.UNCOMPLETED;
|
||||
return false;
|
||||
|
||||
case UNCOMPLETED:
|
||||
case ASYNCWAIT:
|
||||
return false;
|
||||
|
||||
|
@ -355,9 +356,9 @@ public class HttpChannelState implements AsyncContext, Continuation
|
|||
}
|
||||
|
||||
_state=State.ASYNCSTARTED;
|
||||
List<AsyncListener> recycle=_lastAsyncListeners;
|
||||
List<AsyncListener> listeners=_lastAsyncListeners;
|
||||
_lastAsyncListeners=_asyncListeners;
|
||||
_asyncListeners=recycle;
|
||||
_asyncListeners=listeners;
|
||||
if (_asyncListeners!=null)
|
||||
_asyncListeners.clear();
|
||||
break;
|
||||
|
@ -383,6 +384,18 @@ public class HttpChannelState implements AsyncContext, Continuation
|
|||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
protected void error(Throwable th)
|
||||
{
|
||||
synchronized (this)
|
||||
{
|
||||
// TODO should we change state here?
|
||||
|
||||
if (_event!=null)
|
||||
_event._cause=th;
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Signal that the HttpConnection has finished handling the request.
|
||||
|
@ -600,7 +613,7 @@ public class HttpChannelState implements AsyncContext, Continuation
|
|||
/* (non-Javadoc)
|
||||
* @see javax.servlet.ServletRequest#complete()
|
||||
*/
|
||||
protected void doComplete(Throwable ex)
|
||||
protected void doComplete()
|
||||
{
|
||||
final List<ContinuationListener> cListeners;
|
||||
final List<AsyncListener> aListeners;
|
||||
|
@ -627,10 +640,10 @@ public class HttpChannelState implements AsyncContext, Continuation
|
|||
{
|
||||
try
|
||||
{
|
||||
if (ex!=null)
|
||||
if (_event!=null && _event._cause!=null)
|
||||
{
|
||||
_event.getSuppliedRequest().setAttribute(RequestDispatcher.ERROR_EXCEPTION,ex);
|
||||
_event.getSuppliedRequest().setAttribute(RequestDispatcher.ERROR_MESSAGE,ex.getMessage());
|
||||
_event.getSuppliedRequest().setAttribute(RequestDispatcher.ERROR_EXCEPTION,_event._cause);
|
||||
_event.getSuppliedRequest().setAttribute(RequestDispatcher.ERROR_MESSAGE,_event._cause.getMessage());
|
||||
listener.onError(_event);
|
||||
}
|
||||
else
|
||||
|
@ -678,6 +691,8 @@ public class HttpChannelState implements AsyncContext, Continuation
|
|||
cancelTimeout();
|
||||
_timeoutMs=DEFAULT_TIMEOUT;
|
||||
_continuationListeners=null;
|
||||
if (_event!=null)
|
||||
_event._cause=null;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1004,6 +1019,7 @@ public class HttpChannelState implements AsyncContext, Continuation
|
|||
private final ServletContext _suspendedContext;
|
||||
private ServletContext _dispatchContext;
|
||||
private String _path;
|
||||
private Throwable _cause;
|
||||
|
||||
public AsyncEventState(ServletContext context, ServletRequest request, ServletResponse response)
|
||||
{
|
||||
|
@ -1037,7 +1053,7 @@ public class HttpChannelState implements AsyncContext, Continuation
|
|||
@Override
|
||||
public void run()
|
||||
{
|
||||
_channel.handleRequest();
|
||||
_channel.process();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -46,7 +46,7 @@ public class HttpConnection extends AbstractAsyncConnection
|
|||
private final HttpGenerator _generator;
|
||||
private final HttpChannel _channel;
|
||||
private final ByteBufferPool _bufferPool;
|
||||
private final HttpInput _httpInput;
|
||||
private final HttpHttpInput _httpInput;
|
||||
|
||||
private ResponseInfo _info;
|
||||
ByteBuffer _requestBuffer=null;
|
||||
|
@ -129,7 +129,11 @@ public class HttpConnection extends AbstractAsyncConnection
|
|||
/* ------------------------------------------------------------ */
|
||||
public void reset()
|
||||
{
|
||||
_parser.reset();
|
||||
if (_generator.isPersistent())
|
||||
_parser.reset();
|
||||
else
|
||||
_parser.close();
|
||||
|
||||
_generator.reset();
|
||||
_channel.reset();
|
||||
_httpInput.recycle();
|
||||
|
@ -247,10 +251,10 @@ public class HttpConnection extends AbstractAsyncConnection
|
|||
// to handle a request. Call the channel and this will either handle the
|
||||
// request/response to completion OR if the request suspends, the channel
|
||||
// will be left in !idle state so our outer loop will exit.
|
||||
_channel.handleRequest();
|
||||
_channel.process();
|
||||
|
||||
// Return if the channel is still processing the request
|
||||
if (!_channel.isIdle())
|
||||
if (_channel.isSuspended())
|
||||
{
|
||||
// release buffer if all input has been consumed
|
||||
if (_httpInput.available()==0)
|
||||
|
@ -265,11 +269,6 @@ public class HttpConnection extends AbstractAsyncConnection
|
|||
return;
|
||||
}
|
||||
}
|
||||
else if (BufferUtil.hasContent(_requestBuffer))
|
||||
{
|
||||
LOG.warn("STATE MACHINE FAILURE??? {} {}",_parser,BufferUtil.toDetailString(_requestBuffer));
|
||||
BufferUtil.clear(_requestBuffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(Exception e)
|
||||
|
@ -367,7 +366,15 @@ public class HttpConnection extends AbstractAsyncConnection
|
|||
{
|
||||
// We could not send the error, so a sudden close of the connection will at least tell
|
||||
// the client something is wrong
|
||||
|
||||
getEndPoint().close();
|
||||
|
||||
if (BufferUtil.hasContent(_responseBuffer))
|
||||
{
|
||||
BufferUtil.clear(_responseBuffer);
|
||||
releaseRequestBuffer();
|
||||
}
|
||||
_generator.abort();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
@ -376,7 +383,15 @@ public class HttpConnection extends AbstractAsyncConnection
|
|||
@Override
|
||||
protected void completed()
|
||||
{
|
||||
LOG.debug(BufferUtil.toDetailString(_requestBuffer));
|
||||
LOG.debug("{} completed");
|
||||
|
||||
// parser should be either complete or can be completed with single call
|
||||
if (!_parser.isComplete())
|
||||
{
|
||||
// TODO make this much more efficient
|
||||
_httpInput.consumeAll();
|
||||
}
|
||||
|
||||
HttpConnection.this.reset();
|
||||
|
||||
// if the onReadable method is not executing
|
||||
|
@ -384,7 +399,7 @@ public class HttpConnection extends AbstractAsyncConnection
|
|||
{
|
||||
// TODO is there a race here?
|
||||
|
||||
if (_parser.isIdle())
|
||||
if (_parser.isStart())
|
||||
{
|
||||
// it wants to eat more
|
||||
if (_requestBuffer==null)
|
||||
|
@ -398,7 +413,7 @@ public class HttpConnection extends AbstractAsyncConnection
|
|||
});
|
||||
}
|
||||
}
|
||||
else if (!getEndPoint().isOutputShutdown() && _parser.getState()==HttpParser.State.SEEKING_EOF)
|
||||
else if (!getEndPoint().isOutputShutdown() && _parser.isState(HttpParser.State.CLOSED))
|
||||
{
|
||||
// TODO This is a catch all indicating some protocol handling failure
|
||||
// Currently needed for requests saying they are HTTP/2.0.
|
||||
|
@ -704,6 +719,27 @@ public class HttpConnection extends AbstractAsyncConnection
|
|||
}
|
||||
}
|
||||
|
||||
protected void consumeAll()
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
synchronized (_inputQ)
|
||||
{
|
||||
_inputQ.clear();
|
||||
}
|
||||
if (_parser.isComplete())
|
||||
return;
|
||||
try
|
||||
{
|
||||
blockForContent();
|
||||
}
|
||||
catch(IOException e)
|
||||
{
|
||||
LOG.warn(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void onContentQueued(ByteBuffer ref)
|
||||
|
|
|
@ -38,8 +38,7 @@ import org.eclipse.jetty.util.BufferUtil;
|
|||
public abstract class HttpInput extends ServletInputStream
|
||||
{
|
||||
protected final byte[] _oneByte=new byte[1];
|
||||
|
||||
private final ArrayQueue<ByteBuffer> _inputQ=new ArrayQueue<>();
|
||||
protected final ArrayQueue<ByteBuffer> _inputQ=new ArrayQueue<>();
|
||||
private ByteBuffer _content;
|
||||
private boolean _inputEOF;
|
||||
|
||||
|
|
|
@ -1247,7 +1247,9 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
|
|||
public void testUnreadInput () throws Exception
|
||||
{
|
||||
configureServer(new NoopHandler());
|
||||
final int REQS=5;
|
||||
final int REQS=2;
|
||||
char[] fill = new char[65*1024];
|
||||
Arrays.fill(fill,'.');
|
||||
String content="This is a loooooooooooooooooooooooooooooooooo"+
|
||||
"ooooooooooooooooooooooooooooooooooooooooooooo"+
|
||||
"ooooooooooooooooooooooooooooooooooooooooooooo"+
|
||||
|
@ -1258,7 +1260,7 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
|
|||
"ooooooooooooooooooooooooooooooooooooooooooooo"+
|
||||
"ooooooooooooooooooooooooooooooooooooooooooooo"+
|
||||
"oooooooooooonnnnnnnnnnnnnnnnggggggggg content"+
|
||||
new String(new char[65*1024]);
|
||||
new String(fill);
|
||||
final byte[] bytes = content.getBytes();
|
||||
|
||||
Socket client=newSocket(HOST,_connector.getLocalPort());
|
||||
|
@ -1276,7 +1278,7 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
|
|||
out.write(("Content-Length: "+bytes.length+"\r\n" + "\r\n").getBytes(StringUtil.__ISO_8859_1));
|
||||
out.write(bytes,0,bytes.length);
|
||||
}
|
||||
out.write("GET / HTTP/1.1\r\nHost: localhost\r\nConnection: close\r\n\r\n".getBytes(StringUtil.__ISO_8859_1));
|
||||
out.write("GET / HTTP/1.1\r\nHost: last\r\nConnection: close\r\n\r\n".getBytes(StringUtil.__ISO_8859_1));
|
||||
out.flush();
|
||||
}
|
||||
catch(Exception e)
|
||||
|
|
|
@ -12,14 +12,8 @@
|
|||
// ========================================================================
|
||||
|
||||
package org.eclipse.jetty.server;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.io.OutputStream;
|
||||
import java.net.Socket;
|
||||
|
||||
import org.eclipse.jetty.server.HttpServerTestFixture.EchoHandler;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* HttpServer Tester.
|
||||
|
@ -33,17 +27,16 @@ public class SelectChannelServerTest extends HttpServerTestBase
|
|||
}
|
||||
|
||||
@Override
|
||||
public void testCommittedError() throws Exception
|
||||
public void testRequest1() throws Exception
|
||||
{
|
||||
super.testCommittedError();
|
||||
super.testRequest1();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void testFragmentedChunk() throws Exception
|
||||
public void testUnreadInput() throws Exception
|
||||
{
|
||||
super.testFragmentedChunk();
|
||||
super.testUnreadInput();
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue