jetty-9 more progress with RFC2616 tests

This commit is contained in:
Greg Wilkins 2012-05-23 18:04:50 +02:00
parent 8b98e3918c
commit 4473572b6d
17 changed files with 548 additions and 247 deletions

View File

@ -36,8 +36,8 @@ public class HttpGenerator
// states
public enum Action { FLUSH, COMPLETE, PREPARE };
public enum State { START, COMMITTING, COMMITTING_COMPLETING, COMMITTED, COMPLETING, END };
public enum Result { NEED_CHUNK,NEED_COMMIT,NEED_BUFFER,FLUSH,FLUSH_CONTENT,OK,SHUTDOWN_OUT};
public enum State { START, COMMITTING, COMMITTING_COMPLETING, COMMITTED, COMPLETING, COMPLETING_1XX, END };
public enum Result { NEED_CHUNK,NEED_INFO,NEED_HEADER,NEED_BUFFER,FLUSH,FLUSH_CONTENT,OK,SHUTDOWN_OUT};
// other statics
public static final int CHUNK_SIZE = 12;
@ -279,12 +279,12 @@ public class HttpGenerator
case COMMITTING_COMPLETING:
{
if (info==null)
return Result.NEED_COMMIT;
return Result.NEED_INFO;
if (info instanceof RequestInfo)
{
if (header==null || header.capacity()<=CHUNK_SIZE)
return Result.NEED_COMMIT;
return Result.NEED_HEADER;
if(info.getHttpVersion()==HttpVersion.HTTP_0_9)
{
@ -313,7 +313,7 @@ public class HttpGenerator
// yes we need a response header
if (header==null || header.capacity()<=CHUNK_SIZE)
return Result.NEED_COMMIT;
return Result.NEED_HEADER;
// Are we persistent by default?
if (_persistent==null)
@ -330,8 +330,8 @@ public class HttpGenerator
if (status!=101 )
{
header.put(HttpTokens.CRLF);
_state = State.START;
return Result.OK;
_state=State.COMPLETING_1XX;
return Result.FLUSH;
}
}
else if (status==204 || status==304)
@ -419,6 +419,10 @@ public class HttpGenerator
return result;
case COMPLETING_1XX:
reset();
return Result.OK;
case END:
if (!_persistent)
result=Result.SHUTDOWN_OUT;
@ -964,7 +968,7 @@ public class HttpGenerator
_head = head;
}
boolean isInformational()
public boolean isInformational()
{
return _status>=100 && _status<200;
}

View File

@ -1112,8 +1112,8 @@ public class HttpParser
/* ------------------------------------------------------------------------------- */
public void close()
{
if (_state!=State.END)
throw new IllegalStateException(toString());
if (_state!=State.END && _state!=State.CLOSED)
LOG.warn("Closing {}",this);
_persistent=false;
reset();
}
@ -1134,6 +1134,8 @@ public class HttpParser
{
this._state=state;
_endOfContent=EndOfContent.UNKNOWN_CONTENT;
if (state==State.CLOSED)
_persistent=false;
}
/* ------------------------------------------------------------------------------- */

View File

@ -52,7 +52,7 @@ public class HttpGeneratorClientTest
HttpGenerator.Result
result=gen.generate(null,null,null,null,null,Action.COMPLETE);
assertEquals(HttpGenerator.State.COMMITTING_COMPLETING,gen.getState());
assertEquals(HttpGenerator.Result.NEED_COMMIT,result);
assertEquals(HttpGenerator.Result.NEED_INFO,result);
Info info = new Info("GET","/index.html");
info.getHttpFields().add("Host","something");
info.getHttpFields().add("User-Agent","test");
@ -105,7 +105,7 @@ public class HttpGeneratorClientTest
assertTrue(BufferUtil.isEmpty(content1));
result=gen.generate(null,null,null,buffer,null,Action.COMPLETE);
assertEquals(HttpGenerator.Result.NEED_COMMIT,result);
assertEquals(HttpGenerator.Result.NEED_INFO,result);
assertEquals(HttpGenerator.State.COMMITTING_COMPLETING,gen.getState());
Info info = new Info("POST","/index.html");
@ -158,7 +158,7 @@ public class HttpGeneratorClientTest
assertEquals(0,content0.remaining());
result=gen.generate(null,null,null,buffer,content1,null);
assertEquals(HttpGenerator.Result.NEED_COMMIT,result);
assertEquals(HttpGenerator.Result.NEED_INFO,result);
assertEquals(HttpGenerator.State.COMMITTING,gen.getState());
assertEquals("Hello World! The",BufferUtil.toString(buffer));
assertEquals(43,content1.remaining());
@ -257,7 +257,7 @@ public class HttpGeneratorClientTest
HttpGenerator.Result
result=gen.generate(null,null,null,null,content0,null);
assertEquals(HttpGenerator.Result.NEED_COMMIT,result);
assertEquals(HttpGenerator.Result.NEED_INFO,result);
assertEquals(HttpGenerator.State.COMMITTING,gen.getState());
Info info = new Info("POST","/index.html");
@ -338,7 +338,7 @@ public class HttpGeneratorClientTest
assertEquals(0,content0.remaining());
result=gen.generate(null,null,null,buffer,content1,null);
assertEquals(HttpGenerator.Result.NEED_COMMIT,result);
assertEquals(HttpGenerator.Result.NEED_INFO,result);
assertEquals(HttpGenerator.State.COMMITTING,gen.getState());
assertEquals("Hello World! The",BufferUtil.toString(buffer));
assertEquals(43,content1.remaining());
@ -419,7 +419,7 @@ public class HttpGeneratorClientTest
HttpGenerator.Result
result=gen.generate(null,null,null,null,content0,null);
assertEquals(HttpGenerator.Result.NEED_COMMIT,result);
assertEquals(HttpGenerator.Result.NEED_INFO,result);
assertEquals(HttpGenerator.State.COMMITTING,gen.getState());
Info info = new Info("POST","/index.html",59);

View File

@ -189,8 +189,11 @@ public class HttpGeneratorServerTest
switch(result)
{
case NEED_COMMIT:
case NEED_INFO:
info=new HttpGenerator.ResponseInfo(HttpVersion.fromVersion(version),_fields,_contentLength,_code,reason,_head);
break;
case NEED_HEADER:
header=BufferUtil.allocate(2048);
break;
@ -369,7 +372,7 @@ public class HttpGeneratorServerTest
HttpGenerator.Result
result=gen.generate(null,null,null,null,null,Action.COMPLETE);
assertEquals(HttpGenerator.State.COMMITTING_COMPLETING,gen.getState());
assertEquals(HttpGenerator.Result.NEED_COMMIT,result);
assertEquals(HttpGenerator.Result.NEED_INFO,result);
ResponseInfo info = new ResponseInfo(HttpVersion.HTTP_1_1,new HttpFields(),-1,200,null,false);
info.getHttpFields().add("Last-Modified",HttpFields.__01Jan1970);
@ -412,7 +415,7 @@ public class HttpGeneratorServerTest
assertEquals(0,content0.remaining());
result=gen.generate(null,null,null,buffer,content1,null);
assertEquals(HttpGenerator.Result.NEED_COMMIT,result);
assertEquals(HttpGenerator.Result.NEED_INFO,result);
assertEquals(HttpGenerator.State.COMMITTING,gen.getState());
assertEquals("Hello World! The",BufferUtil.toString(buffer));
assertEquals(43,content1.remaining());
@ -517,7 +520,7 @@ public class HttpGeneratorServerTest
assertEquals(0,content0.remaining());
result=gen.generate(null,null,null,buffer,content1,null);
assertEquals(HttpGenerator.Result.NEED_COMMIT,result);
assertEquals(HttpGenerator.Result.NEED_INFO,result);
assertEquals(HttpGenerator.State.COMMITTING,gen.getState());
assertEquals("Hello World! The",BufferUtil.toString(buffer));
assertEquals(43,content1.remaining());
@ -594,7 +597,7 @@ public class HttpGeneratorServerTest
HttpGenerator.Result
result=gen.generate(null,null,null,null,content0,null);
assertEquals(HttpGenerator.Result.NEED_COMMIT,result);
assertEquals(HttpGenerator.Result.NEED_INFO,result);
assertEquals(HttpGenerator.State.COMMITTING,gen.getState());
ResponseInfo info = new ResponseInfo(HttpVersion.HTTP_1_1,new HttpFields(),59,200,null,false);
@ -648,7 +651,7 @@ public class HttpGeneratorServerTest
HttpGenerator.Result
result=gen.generate(null,null,null,null,content0,null);
assertEquals(HttpGenerator.Result.NEED_COMMIT,result);
assertEquals(HttpGenerator.Result.NEED_INFO,result);
assertEquals(HttpGenerator.State.COMMITTING,gen.getState());
ResponseInfo info = new ResponseInfo(HttpVersion.HTTP_1_1,new HttpFields(),-1,200,null,false);
@ -730,7 +733,78 @@ public class HttpGeneratorServerTest
assertTrue(BufferUtil.isEmpty(content1));
result=gen.generate(null,null,null,buffer,null,Action.COMPLETE);
assertEquals(HttpGenerator.Result.NEED_COMMIT,result);
assertEquals(HttpGenerator.Result.NEED_INFO,result);
assertEquals(HttpGenerator.State.COMMITTING_COMPLETING,gen.getState());
ResponseInfo info = new ResponseInfo(HttpVersion.HTTP_1_1,new HttpFields(),-1,200,null,false);
info.getHttpFields().add("Last-Modified",HttpFields.__01Jan1970);
result=gen.generate(info,header,null,buffer,null,null);
assertEquals(HttpGenerator.Result.FLUSH,result);
assertEquals(HttpGenerator.State.COMPLETING,gen.getState());
String head = BufferUtil.toString(header);
BufferUtil.clear(header);
body+=BufferUtil.toString(buffer);
BufferUtil.clear(buffer);
result=gen.generate(info,null,null,buffer,null,null);
assertEquals(HttpGenerator.Result.OK,result);
assertEquals(HttpGenerator.State.END,gen.getState());
assertThat(head,containsString("HTTP/1.1 200 OK"));
assertThat(head,containsString("Last-Modified: Thu, 01 Jan 1970 00?00?00 GMT"));
assertThat(head,containsString("Content-Length: 58"));
assertTrue(head.endsWith("\r\n\r\n"));
assertEquals("Hello World. The quick brown fox jumped over the lazy dog.",body);
assertEquals(58,gen.getContentPrepared());
}
@Test
public void test100ThenResponseWithSmallContent() throws Exception
{
String body="";
ByteBuffer header=BufferUtil.allocate(4096);
ByteBuffer buffer=BufferUtil.allocate(8096);
ByteBuffer content=BufferUtil.toBuffer("Hello World");
ByteBuffer content1=BufferUtil.toBuffer(". The quick brown fox jumped over the lazy dog.");
HttpGenerator gen = new HttpGenerator();
HttpGenerator.Result
result=gen.generate(HttpGenerator.CONTINUE_100_INFO,null,null,null,null,Action.COMPLETE);
assertEquals(HttpGenerator.Result.NEED_HEADER,result);
assertEquals(HttpGenerator.State.COMMITTING_COMPLETING,gen.getState());
result=gen.generate(HttpGenerator.CONTINUE_100_INFO,header,null,null,null,Action.COMPLETE);
assertEquals(HttpGenerator.Result.FLUSH,result);
assertEquals(HttpGenerator.State.COMPLETING_1XX,gen.getState());
assertThat(BufferUtil.toString(header),Matchers.startsWith("HTTP/1.1 100 Continue"));
BufferUtil.clear(header);
result=gen.generate(null,null,null,null,null,null);
assertEquals(HttpGenerator.Result.OK,result);
assertEquals(HttpGenerator.State.START,gen.getState());
result=gen.generate(null,null,null,null,content,null);
assertEquals(HttpGenerator.Result.NEED_BUFFER,result);
assertEquals(HttpGenerator.State.START,gen.getState());
result=gen.generate(null,null,null,buffer,content,null);
assertEquals(HttpGenerator.Result.OK,result);
assertEquals(HttpGenerator.State.START,gen.getState());
assertEquals("Hello World",BufferUtil.toString(buffer));
assertTrue(BufferUtil.isEmpty(content));
result=gen.generate(null,null,null,buffer,content1,null);
assertEquals(HttpGenerator.Result.OK,result);
assertEquals(HttpGenerator.State.START,gen.getState());
assertEquals("Hello World. The quick brown fox jumped over the lazy dog.",BufferUtil.toString(buffer));
assertTrue(BufferUtil.isEmpty(content1));
result=gen.generate(null,null,null,buffer,null,Action.COMPLETE);
assertEquals(HttpGenerator.Result.NEED_INFO,result);
assertEquals(HttpGenerator.State.COMMITTING_COMPLETING,gen.getState());
ResponseInfo info = new ResponseInfo(HttpVersion.HTTP_1_1,new HttpFields(),-1,200,null,false);

View File

@ -32,7 +32,7 @@ public abstract class AbstractEndPoint implements EndPoint
}
@Override
public void setMaxIdleTime(int timeMs) throws IOException
public void setMaxIdleTime(int timeMs)
{
_maxIdleTime=timeMs;
}

View File

@ -121,9 +121,8 @@ public interface EndPoint
/* ------------------------------------------------------------ */
/** Set the max idle time.
* @param timeMs the max idle time in MS. Timeout <= 0 implies an infinite timeout
* @throws IOException if the timeout cannot be set.
*/
void setMaxIdleTime(int timeMs) throws IOException;
void setMaxIdleTime(int timeMs);

View File

@ -43,7 +43,6 @@ public abstract class ReadInterest
}
}
/* ------------------------------------------------------------ */
public void readable()
{

View File

@ -328,6 +328,7 @@ public abstract class HttpChannel
if (_state.isInitial())
{
_request.setDispatcherType(DispatcherType.REQUEST);
_request.setPathInfo(_uri.getPath());
getHttpConnector().customize(_request);
getServer().handle(this);
}

View File

@ -467,10 +467,15 @@ public class HttpConnection extends AbstractAsyncConnection
switch(result)
{
case NEED_COMMIT:
case NEED_INFO:
if (_info==null)
_info=_channel.getEventHandler().commit();
LOG.debug("{} Gcommit {}",this,_info);
if (_responseHeader==null)
_responseHeader=_bufferPool.acquire(_connector.getResponseHeaderSize(),false);
continue;
case NEED_HEADER:
_responseHeader=_bufferPool.acquire(_connector.getResponseHeaderSize(),false);
continue;
@ -541,7 +546,6 @@ public class HttpConnection extends AbstractAsyncConnection
LOG.debug("{} commit {}",this,_info);
// TODO review the locks with a mind that other threads may read and write
synchronized (_lock)
{
try
@ -558,16 +562,20 @@ public class HttpConnection extends AbstractAsyncConnection
LOG.debug("{} commit: {} ({},{},{})@{}",
this,
result,
BufferUtil.toSummaryString(_responseHeader),
BufferUtil.toDetailString(_responseHeader),
BufferUtil.toSummaryString(_responseBuffer),
BufferUtil.toSummaryString(content),
_generator.getState());
switch(result)
{
case NEED_COMMIT:
if (_info==null)
case NEED_INFO:
_info=_channel.getEventHandler().commit();
if (_responseHeader==null)
_responseHeader=_bufferPool.acquire(_connector.getResponseHeaderSize(),false);
break;
case NEED_HEADER:
_responseHeader=_bufferPool.acquire(_connector.getResponseHeaderSize(),false);
break;
@ -606,6 +614,8 @@ public class HttpConnection extends AbstractAsyncConnection
break loop;
case OK:
if (_info!=null && _info.isInformational())
_info=null;
break loop;
}
}
@ -731,8 +741,28 @@ public class HttpConnection extends AbstractAsyncConnection
}
}
@Override
public int available()
{
int available=super.available();
if (available==0 && _parser.isInContent() && BufferUtil.hasContent(_requestBuffer))
return 1;
return available;
}
@Override
public void consumeAll()
{
// Consume content only if the connection is persistent
if (!_generator.isPersistent())
{
_parser.setState(HttpParser.State.CLOSED);
synchronized (_inputQ.lock())
{
_inputQ.clear();
}
}
else
{
while (true)
{
@ -752,6 +782,7 @@ public class HttpConnection extends AbstractAsyncConnection
}
}
}
}
@Override

View File

@ -26,6 +26,7 @@ import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.omg.CORBA._PolicyStub;
public class LocalHttpConnector extends HttpConnector
{
@ -52,19 +53,24 @@ public class LocalHttpConnector extends HttpConnector
public ByteBuffer getResponses(ByteBuffer requestsBuffer) throws Exception
{
int phase=_executor._phaser.getPhase();
LOG.debug("getResponses");
Phaser phaser=_executor._phaser;
int phase = phaser.register(); // the corresponding arrival will be done by the acceptor thread when it takes
LocalEndPoint request = new LocalEndPoint();
request.setInput(requestsBuffer);
_connects.add(request);
_executor._phaser.awaitAdvance(phase);
phaser.awaitAdvance(phase);
return request.takeOutput();
}
public void executeRequest(String rawRequest)
public LocalEndPoint executeRequest(String rawRequest)
{
Phaser phaser=_executor._phaser;
int phase = phaser.register(); // the corresponding arrival will be done by the acceptor thread when it takes
LocalEndPoint endp = new LocalEndPoint();
endp.setInput(BufferUtil.toBuffer(rawRequest,StringUtil.__UTF8_CHARSET));
_connects.add(endp);
return endp;
}
@Override
@ -72,12 +78,10 @@ public class LocalHttpConnector extends HttpConnector
{
LOG.debug("accepting {}",acceptorID);
LocalEndPoint endp = _connects.take();
_executor._phaser.register();
HttpConnection connection=new HttpConnection(this,endp,getServer());
endp.setAsyncConnection(connection);
LOG.debug("accepted {} {}",endp,connection);
connection.onOpen();
_executor._phaser.arriveAndDeregister();
_executor._phaser.arriveAndDeregister(); // arrive for the register done in getResponses
}
@ -109,7 +113,7 @@ public class LocalHttpConnector extends HttpConnector
@Override
protected boolean onAdvance(int phase, int registeredParties)
{
return super.onAdvance(phase,registeredParties);
return false;
}
};
@ -123,6 +127,7 @@ public class LocalHttpConnector extends HttpConnector
public void execute(final Runnable task)
{
_phaser.register();
LOG.debug("{} execute {} {}",this,task,_phaser);
_executor.execute(new Runnable()
{
@Override
@ -141,17 +146,26 @@ public class LocalHttpConnector extends HttpConnector
}
}
private class LocalEndPoint extends AsyncByteArrayEndPoint
public class LocalEndPoint extends AsyncByteArrayEndPoint
{
LocalEndPoint()
{
setGrowOutput(true);
setMaxIdleTime(LocalHttpConnector.this.getMaxIdleTime());
}
LocalEndPoint(CountDownLatch onCloseLatch)
{
this();
}
public void addInput(String s)
{
// TODO this is a busy wait
while(getIn()==null || BufferUtil.hasContent(getIn()))
Thread.yield();
setInput(BufferUtil.toBuffer(s,StringUtil.__UTF8_CHARSET));
}
}
}

View File

@ -0,0 +1,75 @@
package org.eclipse.jetty.server;
import static org.hamcrest.Matchers.containsString;
import static org.junit.Assert.assertThat;
import org.eclipse.jetty.util.log.Log;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
public class LocalHttpConnectorTest
{
private Server _server;
private LocalHttpConnector _connector;
@Before
public void init() throws Exception
{
_server = new Server();
_connector = new LocalHttpConnector();
_server.addConnector(_connector);
_server.setHandler(new DumpHandler());
_server.start();
//_server.dumpStdErr();
}
@After
public void tini() throws Exception
{
_server.stop();
_server=null;
_connector=null;
}
@Test
public void testOneGET() throws Exception
{
String response=_connector.getResponses("GET /R1 HTTP/1.0\r\n\r\n");
assertThat(response,containsString("HTTP/1.1 200 OK"));
assertThat(response,containsString("pathInfo=/R1"));
}
@Test
public void testTwoGETs() throws Exception
{
String response=_connector.getResponses(
"GET /R1 HTTP/1.1\r\n"+
"Host: localhost\r\n"+
"\r\n"+
"GET /R2 HTTP/1.0\r\n\r\n");
assertThat(response,containsString("HTTP/1.1 200 OK"));
assertThat(response,containsString("pathInfo=/R1"));
response=response.substring(response.indexOf("</html>")+8);
assertThat(response,containsString("HTTP/1.1 200 OK"));
assertThat(response,containsString("pathInfo=/R2"));
}
@Test
public void testGETandGET() throws Exception
{
String response=_connector.getResponses("GET /R1 HTTP/1.0\r\n\r\n");
assertThat(response,containsString("HTTP/1.1 200 OK"));
assertThat(response,containsString("pathInfo=/R1"));
response=_connector.getResponses("GET /R2 HTTP/1.0\r\n\r\n");
assertThat(response,containsString("HTTP/1.1 200 OK"));
assertThat(response,containsString("pathInfo=/R2"));
}
}

View File

@ -1,19 +0,0 @@
package org.eclipse.jetty.server;
public class LocalServer
{
public static void main(String[] s) throws Exception
{
Server server = new Server();
LocalHttpConnector connector = new LocalHttpConnector();
server.addConnector(connector);
server.setHandler(new DumpHandler());
server.start();
server.dumpStdErr();
System.err.println(connector.getResponses("GET / HTTP/1.0\r\n\r\n"));
server.stop();
}
}

View File

@ -19,6 +19,8 @@
*/
package org.eclipse.jetty.server;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.not;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
@ -29,7 +31,10 @@ import java.util.List;
import org.eclipse.jetty.http.HttpFields;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.server.handler.HandlerCollection;
import org.eclipse.jetty.util.log.Log;
import org.hamcrest.Matchers;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
@ -46,6 +51,7 @@ public class RFC2616Test
{
server = new Server();
connector = new LocalHttpConnector();
connector.setMaxIdleTime(10000);
server.addConnector(connector);
ContextHandler vcontext=new ContextHandler();
@ -102,42 +108,99 @@ public class RFC2616Test
}
@Test
public void test3_6()
public void test3_6_a() throws Exception
{
String response=null;
try
{
int offset=0;
// Chunk last
response=connector.getResponses("GET /R1 HTTP/1.1\n"+"Host: localhost\n"+"Transfer-Encoding: chunked,identity\n"+"Content-Type: text/plain\n"
+"\015\012"+"5;\015\012"+"123\015\012\015\012"+"0;\015\012\015\012");
response=connector.getResponses(
"GET /R1 HTTP/1.1\n"+
"Host: localhost\n"+
"Transfer-Encoding: chunked,identity\n"+
"Content-Type: text/plain\n"+
"\015\012"+
"5;\015\012"+
"123\015\012\015\012"+
"0;\015\012\015\012");
checkContains(response,offset,"HTTP/1.1 400 Bad","Chunked last");
}
@Test
public void test3_6_b() throws Exception
{
String response=null;
int offset=0;
// Chunked
offset=0;
response=connector.getResponses("GET /R1 HTTP/1.1\n"+"Host: localhost\n"+"Transfer-Encoding: chunked\n"+"Content-Type: text/plain\n"+"\n"+"2;\n"
+"12\n"+"3;\n"+"345\n"+"0;\n\n"+
response=connector.getResponses(
"GET /R1 HTTP/1.1\n"+
"Host: localhost\n"+
"Transfer-Encoding: chunked\n"+
"Content-Type: text/plain\n"+
"\n"+
"2;\n"+
"12\n"+
"3;\n"+
"345\n"+
"0;\n\n"+
"GET /R2 HTTP/1.1\n"+"Host: localhost\n"+"Transfer-Encoding: chunked\n"+"Content-Type: text/plain\n"+"\n"+"4;\n"+"6789\n"+"5;\n"+"abcde\n"
+"0;\n\n"+
"GET /R2 HTTP/1.1\n"+
"Host: localhost\n"+
"Transfer-Encoding: chunked\n"+
"Content-Type: text/plain\n"+
"\n"+
"4;\n"+
"6789\n"+
"5;\n"+
"abcde\n"+
"0;\n\n"+
"GET /R3 HTTP/1.1\n"+"Host: localhost\n"+"Connection: close\n"+"\n");
"GET /R3 HTTP/1.1\n"+
"Host: localhost\n"+
"Connection: close\n"+
"\n");
offset=checkContains(response,offset,"HTTP/1.1 200","3.6.1 Chunking");
offset=checkContains(response,offset,"12345","3.6.1 Chunking");
offset=checkContains(response,offset,"HTTP/1.1 200","3.6.1 Chunking");
offset=checkContains(response,offset,"6789abcde","3.6.1 Chunking");
offset=checkContains(response,offset,"/R3","3.6.1 Chunking");
// Chunked
offset=0;
response=connector.getResponses("POST /R1 HTTP/1.1\n"+"Host: localhost\n"+"Transfer-Encoding: chunked\n"+"Content-Type: text/plain\n"+"\n"+"3;\n"
+"fgh\n"+"3;\n"+"Ijk\n"+"0;\n\n"+
}
"POST /R2 HTTP/1.1\n"+"Host: localhost\n"+"Transfer-Encoding: chunked\n"+"Content-Type: text/plain\n"+"\n"+"4;\n"+"lmno\n"+"5;\n"+"Pqrst\n"
+"0;\n\n"+
@Test
public void test3_6_c() throws Exception
{
String response=null;
int offset=0;
"GET /R3 HTTP/1.1\n"+"Host: localhost\n"+"Connection: close\n"+"\n");
response=connector.getResponses(
"POST /R1 HTTP/1.1\n"+
"Host: localhost\n"+
"Transfer-Encoding: chunked\n"+
"Content-Type: text/plain\n"+
"\n"+
"3;\n"+
"fgh\n"+
"3;\n"+
"Ijk\n"+
"0;\n\n"+
"POST /R2 HTTP/1.1\n"+
"Host: localhost\n"+
"Transfer-Encoding: chunked\n"+
"Content-Type: text/plain\n"+
"\n"+
"4;\n"+
"lmno\n"+
"5;\n"+
"Pqrst\n"+
"0;\n\n"+
"GET /R3 HTTP/1.1\n"+
"Host: localhost\n"+
"Connection: close\n"+
"\n");
checkNotContained(response,"HTTP/1.1 100","3.6.1 Chunking");
offset=checkContains(response,offset,"HTTP/1.1 200","3.6.1 Chunking");
offset=checkContains(response,offset,"fghIjk","3.6.1 Chunking");
@ -145,23 +208,36 @@ public class RFC2616Test
offset=checkContains(response,offset,"lmnoPqrst","3.6.1 Chunking");
offset=checkContains(response,offset,"/R3","3.6.1 Chunking");
// Chunked and keep alive
offset=0;
response=connector.getResponses("GET /R1 HTTP/1.1\n"+"Host: localhost\n"+"Transfer-Encoding: chunked\n"+"Content-Type: text/plain\n"
+"Connection: keep-alive\n"+"\n"+"3;\n"+"123\n"+"3;\n"+"456\n"+"0;\n\n"+
}
"GET /R2 HTTP/1.1\n"+"Host: localhost\n"+"Connection: close\n"+"\n");
@Test
public void test3_6_d() throws Exception
{
String response=null;
int offset=0;
// Chunked and keep alive
response=connector.getResponses(
"GET /R1 HTTP/1.1\n"+
"Host: localhost\n"+
"Transfer-Encoding: chunked\n"+
"Content-Type: text/plain\n"+
"Connection: keep-alive\n"+
"\n"+
"3;\n"+
"123\n"+
"3;\n"+
"456\n"+
"0;\n\n"+
"GET /R2 HTTP/1.1\n"+
"Host: localhost\n"+
"Connection: close\n"+
"\n");
offset=checkContains(response,offset,"HTTP/1.1 200","3.6.1 Chunking")+10;
offset=checkContains(response,offset,"123456","3.6.1 Chunking");
offset=checkContains(response,offset,"/R2","3.6.1 Chunking")+10;
}
catch (Exception e)
{
e.printStackTrace();
assertTrue(false);
if (response!=null)
System.err.println(response);
}
}
@Test
@ -189,40 +265,74 @@ public class RFC2616Test
}
@Test
public void test4_4()
{
try
public void test4_4_2() throws Exception
{
String response;
int offset=0;
// 2
// If _content length not used, second request will not be read.
offset=0;
response=connector.getResponses("GET /R1 HTTP/1.1\n"+"Host: localhost\n"+"Transfer-Encoding: identity\n"+"Content-Type: text/plain\n"
+"Content-Length: 5\n"+"\n"+"123\015\012"+
response=connector.getResponses(
"GET /R1 HTTP/1.1\n"+
"Host: localhost\n"+
"Transfer-Encoding: identity\n"+
"Content-Type: text/plain\n"+
"Content-Length: 5\n"+
"\n"+
"123\015\012"+
"GET /R2 HTTP/1.1\n"+"Host: localhost\n"+"Connection: close\n"+"\n");
"GET /R2 HTTP/1.1\n"+
"Host: localhost\n"+
"Transfer-Encoding: other\n"+
"Connection: close\n"+
"\n");
offset=checkContains(response,offset,"HTTP/1.1 200 OK","2. identity")+10;
offset=checkContains(response,offset,"/R1","2. identity")+3;
offset=checkContains(response,offset,"HTTP/1.1 200 OK","2. identity")+10;
offset=checkContains(response,offset,"/R2","2. identity")+3;
}
@Test
public void test4_4_3() throws Exception
{
String response;
int offset=0;
// 3
// _content length is ignored, as chunking is used. If it is
// not ignored, the second request wont be seen.
offset=0;
response=connector.getResponses("GET /R1 HTTP/1.1\n"+"Host: localhost\n"+"Transfer-Encoding: chunked\n"+"Content-Type: text/plain\n"
+"Content-Length: 100\n"+"\n"+"3;\n"+"123\n"+"3;\n"+"456\n"+"0;\n"+"\n"+
response=connector.getResponses(
"GET /R1 HTTP/1.1\n"+
"Host: localhost\n"+
"Transfer-Encoding: chunked\n"+
"Content-Type: text/plain\n"+
"Content-Length: 100\n"+
"\n"+
"3;\n"+
"123\n"+
"3;\n"+
"456\n"+
"0;\n"+
"\n"+
"GET /R2 HTTP/1.1\n"+"Host: localhost\n"+"Connection: close\n"+"Content-Type: text/plain\n"+"Content-Length: 6\n"+"\n"+"123456");
"GET /R2 HTTP/1.1\n"+
"Host: localhost\n"+
"Connection: close\n"+
"Content-Type: text/plain\n"+
"Content-Length: 6\n"+
"\n"+
"abcdef");
offset=checkContains(response,offset,"HTTP/1.1 200 OK","3. ignore c-l")+1;
offset=checkContains(response,offset,"/R1","3. ignore c-l")+1;
offset=checkContains(response,offset,"123456","3. ignore c-l")+1;
offset=checkContains(response,offset,"HTTP/1.1 200 OK","3. ignore c-l")+1;
offset=checkContains(response,offset,"/R2","3. _content-length")+1;
offset=checkContains(response,offset,"123456","3. _content-length")+1;
offset=checkContains(response,offset,"abcdef","3. _content-length")+1;
}
@Test
public void test4_4_4() throws Exception
{
// No _content length
assertTrue("Skip 411 checks as IE breaks this rule",true);
// offset=0; connector.reopen();
@ -243,15 +353,23 @@ public class RFC2616Test
// "HTTP/1.0 411 ","411 length required")+10;
}
catch (Exception e)
@Test
public void test5_2_1() throws Exception
{
e.printStackTrace();
assertTrue(false);
}
String response;
int offset=0;
// Default Host
offset=0;
response=connector.getResponses("GET http://VirtualHost:8888/path/R1 HTTP/1.1\n"+"Host: wronghost\n"+"\n");
offset=checkContains(response,offset,"HTTP/1.1 200","Default host")+1;
offset=checkContains(response,offset,"Virtual Dump","virtual host")+1;
offset=checkContains(response,offset,"pathInfo=/path/R1","Default host")+1;
}
@Test
public void test5_2() throws Exception
public void test5_2_2() throws Exception
{
String response;
int offset=0;
@ -259,11 +377,24 @@ public class RFC2616Test
// Default Host
offset=0;
response=connector.getResponses("GET /path/R1 HTTP/1.1\n"+"Host: localhost\n"+"\n");
offset=checkContains(response,offset,"HTTP/1.1 200","Default host")+1;
offset=checkContains(response,offset,"Dump HttpHandler","Default host")+1;
offset=checkContains(response,offset,"pathInfo=/path/R1","Default host")+1;
// Virtual Host
offset=0;
response=connector.getResponses("GET /path/R2 HTTP/1.1\n"+"Host: VirtualHost\n"+"\n");
offset=checkContains(response,offset,"HTTP/1.1 200","Default host")+1;
offset=checkContains(response,offset,"Virtual Dump","virtual host")+1;
offset=checkContains(response,offset,"pathInfo=/path/R2","Default host")+1;
}
@Test
public void test5_2() throws Exception
{
String response;
int offset=0;
// Virtual Host
offset=0;
response=connector.getResponses("GET /path/R1 HTTP/1.1\n"+"Host: VirtualHost\n"+"\n");
@ -319,38 +450,39 @@ public class RFC2616Test
}
@Test
public void test8_2() throws Exception
public void test10_4_18() throws Exception
{
String response;
int offset=0;
// No Expect 100
offset=0;
response=connector.getResponses("GET /R1 HTTP/1.1\n"+
"Host: localhost\n"+
"Content-Type: text/plain\n"+
"Content-Length: 8\n"+
"\n",true);
assertTrue("8.2.3 no expect 100",response==null || response.length()==0);
response=connector.getResponses("GET /R1 HTTP/1.1\n"+
"Host: localhost\n"+
"Content-Type: text/plain\n"+
"Content-Length: 8\n"+
"\n"+
"AbCdEf\015\012",true);
offset=checkContains(response,offset,"HTTP/1.1 200","8.2.3 no expect 100")+1;
offset=checkContains(response,offset,"AbCdEf","8.2.3 no expect 100")+1;
// Expect Failure
offset=0;
response=connector.getResponses("GET /R1 HTTP/1.1\n"+"Host: localhost\n"+"Expect: unknown\n"+"Content-Type: text/plain\n"+"Content-Length: 8\n"
+"\n");
response=connector.getResponses(
"GET /R1 HTTP/1.1\n"+
"Host: localhost\n"+
"Expect: unknown\n"+
"Content-Type: text/plain\n"+
"Content-Length: 8\n"+
"\n");
offset=checkContains(response,offset,"HTTP/1.1 417","8.2.3 expect failure")+1;
}
@Test
public void test8_2_3_dash5() throws Exception
{
String response;
int offset=0;
// Expect with body
offset=0;
response=connector.getResponses("GET /R1 HTTP/1.1\n"+"Host: localhost\n"+"Expect: 100-continue\n"+"Content-Type: text/plain\n"
+"Content-Length: 8\n"+"Connection: close\n"+"\n"+"123456\015\012");
response=connector.getResponses(
"GET /R1 HTTP/1.1\n"+
"Host: localhost\n"+
"Expect: 100-continue\n"+
"Content-Type: text/plain\n"+
"Content-Length: 8\n"+
"Connection: close\n"+
"\n"+
"123456\015\012");
checkNotContained(response,offset,"HTTP/1.1 100 ","8.2.3 expect 100");
offset=checkContains(response,offset,"HTTP/1.1 200 OK","8.2.3 expect with body")+1;
}
@ -358,23 +490,27 @@ public class RFC2616Test
@Test
public void test8_2_3() throws Exception
{
String response;
int offset=0;
// Expect 100
response=connector.getResponses("GET /R1 HTTP/1.1\n"+
LocalHttpConnector.LocalEndPoint endp =connector.executeRequest("GET /R1 HTTP/1.1\n"+
"Host: localhost\n"+
"Connection: close\n"+
"Expect: 100-continue\n"+
"Content-Type: text/plain\n"+
"Content-Length: 8\n"+
"\n",true);
offset=checkContains(response,offset,"HTTP/1.1 100 ","8.2.3 expect 100")+1;
checkNotContained(response,offset,"HTTP/1.1 200","8.2.3 expect 100");
/* can't test this with localconnector.
response=connector.getResponses("654321\015\012");
"\n");
Thread.sleep(200);
String infomational= endp.takeOutputString();
offset=checkContains(infomational,offset,"HTTP/1.1 100 ","8.2.3 expect 100")+1;
checkNotContained(infomational,offset,"HTTP/1.1 200","8.2.3 expect 100");
endp.addInput("654321\015\012");
Thread.sleep(200);
String response= endp.takeOutputString();
offset=0;
offset=checkContains(response,offset,"HTTP/1.1 200","8.2.3 expect 100")+1;
offset=checkContains(response,offset,"654321","8.2.3 expect 100")+1;
*/
}
@Test
@ -390,7 +526,7 @@ public class RFC2616Test
"Expect: 100-continue\n"+
"Content-Type: text/plain\n"+
"Content-Length: 8\n"+
"\n",true);
"\n");
checkNotContained(response,offset,"HTTP/1.1 100","8.2.3 expect 100");
offset=checkContains(response,offset,"HTTP/1.1 401 ","8.2.3 expect 100")+1;
offset=checkContains(response,offset,"Connection: close","8.2.3 expect 100")+1;
@ -819,24 +955,16 @@ public class RFC2616Test
private int checkContains(String s, int offset, String c, String test)
{
int o=s.indexOf(c,offset);
if (o<offset)
{
System.err.println("FAILED: "+test);
System.err.println("'"+c+"' not in:");
System.err.println(s.substring(offset));
System.err.flush();
System.out.println("--\n"+s);
System.out.flush();
assertTrue(test,false);
}
return o;
// System.err.println("===");
// System.err.println(s);
// System.err.println("---");
Assert.assertThat(test,s.substring(offset),containsString(c));
return s.indexOf(c,offset);
}
private void checkNotContained(String s, int offset, String c, String test)
{
int o=s.indexOf(c,offset);
assertTrue(test,o<offset);
Assert.assertThat(test,s.substring(offset),not(containsString(c)));
}
private void checkNotContained(String s, String c, String test)

View File

@ -804,7 +804,7 @@ public class RequestTest
String request="POST / HTTP/1.1\r\n"+
"Host: whatever\r\n"+
"Content-Type: "+MimeTypes.FORM_ENCODED+"\r\n"+
"Content-Type: "+MimeTypes.Type.FORM_ENCODED.asString()+"\r\n"+
"Content-Length: "+buf.length()+"\r\n"+
"Connection: close\r\n"+
"\r\n"+
@ -832,7 +832,7 @@ public class RequestTest
{
((Request)request).setHandled(true);
if (request.getContentLength()>0 && !MimeTypes.FORM_ENCODED.equals(request.getContentType()))
if (request.getContentLength()>0 && !MimeTypes.Type.FORM_ENCODED.asString().equals(request.getContentType()))
_content=IO.toString(request.getInputStream());
if (_checker!=null && _checker.check(request,response))

View File

@ -33,7 +33,6 @@ import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSessionContext;
import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.http.HttpURI;
@ -78,7 +77,7 @@ public class ResponseTest
@Test
public void testContentType() throws Exception
{
AbstractHttpConnection connection = new TestHttpConnection(connector,new ByteArrayEndPoint(), connector.getServer());
TestHttpChannel connection = new TestHttpChannel(connector,new ByteArrayEndPoint(), connector.getServer());
Response response = connection.getResponse();
assertEquals(null,response.getContentType());
@ -133,7 +132,7 @@ public class ResponseTest
public void testLocale() throws Exception
{
AbstractHttpConnection connection = new TestHttpConnection(connector,new ByteArrayEndPoint(), connector.getServer());
TestHttpChannel connection = new TestHttpChannel(connector,new ByteArrayEndPoint(), connector.getServer());
Request request = connection.getRequest();
Response response = connection.getResponse();
ContextHandler context = new ContextHandler();
@ -157,7 +156,7 @@ public class ResponseTest
@Test
public void testContentTypeCharacterEncoding() throws Exception
{
AbstractHttpConnection connection = new TestHttpConnection(connector,new ByteArrayEndPoint(), connector.getServer());
TestHttpChannel connection = new TestHttpChannel(connector,new ByteArrayEndPoint(), connector.getServer());
Response response = connection.getResponse();
@ -189,7 +188,7 @@ public class ResponseTest
@Test
public void testCharacterEncodingContentType() throws Exception
{
Response response = new Response(new TestHttpConnection(connector,new ByteArrayEndPoint(), connector.getServer()));
Response response = new Response(new TestHttpChannel(connector,new ByteArrayEndPoint(), connector.getServer()));
response.setCharacterEncoding("utf-8");
response.setContentType("foo/bar");
@ -218,7 +217,7 @@ public class ResponseTest
@Test
public void testContentTypeWithCharacterEncoding() throws Exception
{
Response response = new Response(new TestHttpConnection(connector,new ByteArrayEndPoint(), connector.getServer()));
Response response = new Response(new TestHttpChannel(connector,new ByteArrayEndPoint(), connector.getServer()));
response.setCharacterEncoding("utf16");
response.setContentType("foo/bar; charset=utf-8");
@ -247,7 +246,7 @@ public class ResponseTest
@Test
public void testContentTypeWithOther() throws Exception
{
Response response = new Response(new TestHttpConnection(connector,new ByteArrayEndPoint(), connector.getServer()));
Response response = new Response(new TestHttpChannel(connector,new ByteArrayEndPoint(), connector.getServer()));
response.setContentType("foo/bar; other=xyz");
assertEquals("foo/bar; other=xyz",response.getContentType());
@ -270,7 +269,7 @@ public class ResponseTest
@Test
public void testContentTypeWithCharacterEncodingAndOther() throws Exception
{
Response response = new Response(new TestHttpConnection(connector,new ByteArrayEndPoint(), connector.getServer()));
Response response = new Response(new TestHttpChannel(connector,new ByteArrayEndPoint(), connector.getServer()));
response.setCharacterEncoding("utf16");
response.setContentType("foo/bar; charset=utf-8 other=xyz");
@ -310,7 +309,7 @@ public class ResponseTest
response.sendError(500, "Database Error");
assertEquals(500, response.getStatus());
assertEquals("Database Error", response.getReason());
assertEquals("must-revalidate,no-cache,no-store", response.getHeader(HttpHeader.CACHE_CONTROL));
assertEquals("must-revalidate,no-cache,no-store", response.getHeader(HttpHeader.CACHE_CONTROL.asString()));
response=newResponse();
@ -323,14 +322,14 @@ public class ResponseTest
response.sendError(406, "Super Nanny");
assertEquals(406, response.getStatus());
assertEquals("Super Nanny", response.getReason());
assertEquals("must-revalidate,no-cache,no-store", response.getHeader(HttpHeader.CACHE_CONTROL));
assertEquals("must-revalidate,no-cache,no-store", response.getHeader(HttpHeader.CACHE_CONTROL.asString()));
}
@Test
public void testEncodeRedirect()
throws Exception
{
AbstractHttpConnection connection=new TestHttpConnection(connector,new ByteArrayEndPoint(), connector.getServer());
TestHttpChannel connection=new TestHttpChannel(connector,new ByteArrayEndPoint(), connector.getServer());
Response response = new Response(connection);
Request request = connection.getRequest();
request.setServerName("myhost");
@ -395,7 +394,7 @@ public class ResponseTest
for (int i=1;i<tests.length;i++)
{
ByteArrayEndPoint out=new ByteArrayEndPoint(new byte[]{},4096);
AbstractHttpConnection connection=new TestHttpConnection(connector,out, connector.getServer());
TestHttpChannel connection=new TestHttpChannel(connector,out, connector.getServer());
Response response = new Response(connection);
Request request = connection.getRequest();
request.setServerName("myhost");
@ -423,7 +422,7 @@ public class ResponseTest
@Test
public void testSetBufferSize () throws Exception
{
Response response = new Response(new TestHttpConnection(connector,new ByteArrayEndPoint(), connector.getServer()));
Response response = new Response(new TestHttpChannel(connector,new ByteArrayEndPoint(), connector.getServer()));
response.setBufferSize(20*1024);
response.getWriter().print("hello");
try
@ -487,7 +486,7 @@ public class ResponseTest
@Test
public void testAddCookie() throws Exception
{
Response response = new Response(new TestHttpConnection(connector,new ByteArrayEndPoint(), connector.getServer()));
Response response = new Response(new TestHttpChannel(connector,new ByteArrayEndPoint(), connector.getServer()));
Cookie cookie=new Cookie("name","value");
cookie.setDomain("domain");
@ -507,9 +506,9 @@ public class ResponseTest
ByteArrayEndPoint endPoint = new ByteArrayEndPoint();
endPoint.setOutput(new ByteArrayBuffer(1024));
endPoint.setGrowOutput(true);
AbstractHttpConnection connection=new TestHttpConnection(connector, endPoint, connector.getServer());
TestHttpChannel connection=new TestHttpChannel(connector, endPoint, connector.getServer());
connection.getGenerator().reset();
AbstractHttpConnection.setCurrentHttpChannel(connection);
TestHttpChannel.setCurrentHttpChannel(connection);
Response response = connection.getResponse();
connection.getRequest().setRequestURI("/test");
return response;
@ -609,24 +608,20 @@ public class ResponseTest
}
}
static class TestHttpConnection extends AbstractHttpConnection
static class TestHttpChannel extends HttpChannel
{
public TestHttpConnection(Connector connector, EndPoint endpoint, Server server)
public TestHttpChannel(Connector connector, EndPoint endpoint, Server server)
{
super(server,null,null);
super(connector,endpoint,server);
}
public TestHttpConnection(Connector connector, EndPoint endpoint, Server server, Parser parser, Generator generator, Request request)
public TestHttpChannel(Connector connector, EndPoint endpoint, Server server, Parser parser, Generator generator, Request request)
{
super(connector,endpoint,server,parser,generator,request);
}
@Override
public AsyncConnection handle() throws IOException
{
return this;
}
}
}

View File

@ -371,7 +371,7 @@ public class QueuedThreadPool extends AbstractLifeCycle implements SizedThreadPo
public void execute(Runnable job)
{
if (!dispatch(job))
throw new RejectedExecutionException();
throw new RejectedExecutionException(toString());
}
/* ------------------------------------------------------------ */
@ -500,15 +500,13 @@ public class QueuedThreadPool extends AbstractLifeCycle implements SizedThreadPo
AggregateLifeCycle.dumpObject(out,this);
AggregateLifeCycle.dump(out,indent,dump);
}
/* ------------------------------------------------------------ */
@Override
public String toString()
{
return _name+"{"+getMinThreads()+"<="+getIdleThreads()+"<="+getThreads()+"/"+getMaxThreads()+","+(_jobs==null?-1:_jobs.size())+"}";
return String.format("%s{%b,%d<=%d<=%d/%d,%d}",_name,isRunning(),getMinThreads(),getIdleThreads(),getThreads(),getMaxThreads(),(_jobs==null?-1:_jobs.size()));
}
/* ------------------------------------------------------------ */