jetty-9 simplified error handling
This commit is contained in:
parent
cd719bf979
commit
d59a47d376
|
@ -168,7 +168,7 @@ public class HttpGenerator
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
/* ------------------------------------------------------------ */
|
||||||
public Result generateRequest(RequestInfo info, ByteBuffer headerOrChunk, ByteBuffer content, boolean last)
|
public Result generateRequest(RequestInfo info, ByteBuffer header, ByteBuffer chunk, ByteBuffer content, boolean last)
|
||||||
{
|
{
|
||||||
switch(_state)
|
switch(_state)
|
||||||
{
|
{
|
||||||
|
@ -178,7 +178,7 @@ public class HttpGenerator
|
||||||
return Result.NEED_INFO;
|
return Result.NEED_INFO;
|
||||||
|
|
||||||
// Do we need a request header
|
// Do we need a request header
|
||||||
if (headerOrChunk==null || headerOrChunk.capacity()<=CHUNK_SIZE)
|
if (header==null)
|
||||||
return Result.NEED_HEADER;
|
return Result.NEED_HEADER;
|
||||||
|
|
||||||
// If we have not been told our persistence, set the default
|
// If we have not been told our persistence, set the default
|
||||||
|
@ -186,7 +186,6 @@ public class HttpGenerator
|
||||||
_persistent=(info.getHttpVersion().ordinal() > HttpVersion.HTTP_1_0.ordinal());
|
_persistent=(info.getHttpVersion().ordinal() > HttpVersion.HTTP_1_0.ordinal());
|
||||||
|
|
||||||
// prepare the header
|
// prepare the header
|
||||||
ByteBuffer header = headerOrChunk;
|
|
||||||
int pos=BufferUtil.flipToFill(header);
|
int pos=BufferUtil.flipToFill(header);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -232,9 +231,8 @@ public class HttpGenerator
|
||||||
if (isChunking())
|
if (isChunking())
|
||||||
{
|
{
|
||||||
// Do we need a chunk buffer?
|
// Do we need a chunk buffer?
|
||||||
if (headerOrChunk==null || headerOrChunk.capacity()>CHUNK_SIZE)
|
if (chunk==null)
|
||||||
return Result.NEED_CHUNK;
|
return Result.NEED_CHUNK;
|
||||||
ByteBuffer chunk = headerOrChunk;
|
|
||||||
BufferUtil.clearToFill(chunk);
|
BufferUtil.clearToFill(chunk);
|
||||||
prepareChunk(chunk,len);
|
prepareChunk(chunk,len);
|
||||||
BufferUtil.flipToFlush(chunk,0);
|
BufferUtil.flipToFlush(chunk,0);
|
||||||
|
@ -259,9 +257,8 @@ public class HttpGenerator
|
||||||
if (isChunking())
|
if (isChunking())
|
||||||
{
|
{
|
||||||
// Do we need a chunk buffer?
|
// Do we need a chunk buffer?
|
||||||
if (headerOrChunk==null || headerOrChunk.capacity()>CHUNK_SIZE)
|
if (chunk==null)
|
||||||
return Result.NEED_CHUNK;
|
return Result.NEED_CHUNK;
|
||||||
ByteBuffer chunk=headerOrChunk;
|
|
||||||
BufferUtil.clearToFill(chunk);
|
BufferUtil.clearToFill(chunk);
|
||||||
prepareChunk(chunk,0);
|
prepareChunk(chunk,0);
|
||||||
BufferUtil.flipToFlush(chunk,0);
|
BufferUtil.flipToFlush(chunk,0);
|
||||||
|
@ -284,7 +281,7 @@ public class HttpGenerator
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
/* ------------------------------------------------------------ */
|
||||||
public Result generateResponse(ResponseInfo info, ByteBuffer headerOrChunk, ByteBuffer content, boolean last)
|
public Result generateResponse(ResponseInfo info, ByteBuffer header, ByteBuffer chunk, ByteBuffer content, boolean last)
|
||||||
{
|
{
|
||||||
switch(_state)
|
switch(_state)
|
||||||
{
|
{
|
||||||
|
@ -306,7 +303,7 @@ public class HttpGenerator
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do we need a response header
|
// Do we need a response header
|
||||||
if (headerOrChunk==null || headerOrChunk.capacity()<=CHUNK_SIZE)
|
if (header==null)
|
||||||
return Result.NEED_HEADER;
|
return Result.NEED_HEADER;
|
||||||
|
|
||||||
// If we have not been told our persistence, set the default
|
// If we have not been told our persistence, set the default
|
||||||
|
@ -314,7 +311,6 @@ public class HttpGenerator
|
||||||
_persistent=(info.getHttpVersion().ordinal() > HttpVersion.HTTP_1_0.ordinal());
|
_persistent=(info.getHttpVersion().ordinal() > HttpVersion.HTTP_1_0.ordinal());
|
||||||
|
|
||||||
// prepare the header
|
// prepare the header
|
||||||
ByteBuffer header = headerOrChunk;
|
|
||||||
int pos=BufferUtil.flipToFill(header);
|
int pos=BufferUtil.flipToFill(header);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -383,18 +379,15 @@ public class HttpGenerator
|
||||||
// handle the content.
|
// handle the content.
|
||||||
if (len>0)
|
if (len>0)
|
||||||
{
|
{
|
||||||
// Do we need a chunk buffer?
|
|
||||||
if (isChunking() && BufferUtil.space(headerOrChunk) < CHUNK_SIZE)
|
|
||||||
return Result.NEED_CHUNK;
|
|
||||||
|
|
||||||
ByteBuffer chunk = headerOrChunk;
|
|
||||||
_contentPrepared+=len;
|
|
||||||
if (isChunking())
|
if (isChunking())
|
||||||
{
|
{
|
||||||
|
if (chunk==null)
|
||||||
|
return Result.NEED_CHUNK;
|
||||||
BufferUtil.clearToFill(chunk);
|
BufferUtil.clearToFill(chunk);
|
||||||
prepareChunk(chunk,len);
|
prepareChunk(chunk,len);
|
||||||
BufferUtil.flipToFlush(chunk,0);
|
BufferUtil.flipToFlush(chunk,0);
|
||||||
}
|
}
|
||||||
|
_contentPrepared+=len;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (last)
|
if (last)
|
||||||
|
@ -420,11 +413,10 @@ public class HttpGenerator
|
||||||
if (isChunking())
|
if (isChunking())
|
||||||
{
|
{
|
||||||
// Do we need a chunk buffer?
|
// Do we need a chunk buffer?
|
||||||
if (BufferUtil.space(headerOrChunk) < CHUNK_SIZE)
|
if (chunk==null)
|
||||||
return Result.NEED_CHUNK;
|
return Result.NEED_CHUNK;
|
||||||
|
|
||||||
// Write the last chunk
|
// Write the last chunk
|
||||||
ByteBuffer chunk=headerOrChunk;
|
|
||||||
BufferUtil.clearToFill(chunk);
|
BufferUtil.clearToFill(chunk);
|
||||||
prepareChunk(chunk,0);
|
prepareChunk(chunk,0);
|
||||||
BufferUtil.flipToFlush(chunk,0);
|
BufferUtil.flipToFlush(chunk,0);
|
||||||
|
|
|
@ -1114,7 +1114,7 @@ public class HttpParser
|
||||||
|
|
||||||
LOG.warn("badMessage: "+e.toString()+" for "+_handler);
|
LOG.warn("badMessage: "+e.toString()+" for "+_handler);
|
||||||
LOG.debug(e);
|
LOG.debug(e);
|
||||||
badMessage(buffer,HttpStatus.BAD_REQUEST_400,e.toString());
|
badMessage(buffer,HttpStatus.BAD_REQUEST_400,null);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -175,14 +175,15 @@ public class HttpTester
|
||||||
|
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
ByteBuffer header=null;
|
ByteBuffer header=null;
|
||||||
|
ByteBuffer chunk=null;
|
||||||
ByteBuffer content=_content==null?null:ByteBuffer.wrap(_content.toByteArray());
|
ByteBuffer content=_content==null?null:ByteBuffer.wrap(_content.toByteArray());
|
||||||
|
|
||||||
|
|
||||||
loop: while(!generator.isEnd())
|
loop: while(!generator.isEnd())
|
||||||
{
|
{
|
||||||
HttpGenerator.Result result = info instanceof RequestInfo
|
HttpGenerator.Result result = info instanceof RequestInfo
|
||||||
?generator.generateRequest((RequestInfo)info,header,content,true)
|
?generator.generateRequest((RequestInfo)info,header,chunk,content,true)
|
||||||
:generator.generateResponse((ResponseInfo)info,header,content,true);
|
:generator.generateResponse((ResponseInfo)info,header,chunk,content,true);
|
||||||
switch(result)
|
switch(result)
|
||||||
{
|
{
|
||||||
case NEED_HEADER:
|
case NEED_HEADER:
|
||||||
|
@ -190,7 +191,7 @@ public class HttpTester
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
case NEED_CHUNK:
|
case NEED_CHUNK:
|
||||||
header=BufferUtil.allocate(HttpGenerator.CHUNK_SIZE);
|
chunk=BufferUtil.allocate(HttpGenerator.CHUNK_SIZE);
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
case NEED_INFO:
|
case NEED_INFO:
|
||||||
|
@ -202,6 +203,11 @@ public class HttpTester
|
||||||
out.write(BufferUtil.toArray(header));
|
out.write(BufferUtil.toArray(header));
|
||||||
BufferUtil.clear(header);
|
BufferUtil.clear(header);
|
||||||
}
|
}
|
||||||
|
if (BufferUtil.hasContent(chunk))
|
||||||
|
{
|
||||||
|
out.write(BufferUtil.toArray(chunk));
|
||||||
|
BufferUtil.clear(chunk);
|
||||||
|
}
|
||||||
if (BufferUtil.hasContent(content))
|
if (BufferUtil.hasContent(content))
|
||||||
{
|
{
|
||||||
out.write(BufferUtil.toArray(content));
|
out.write(BufferUtil.toArray(content));
|
||||||
|
|
|
@ -54,7 +54,7 @@ public class HttpGeneratorClientTest
|
||||||
HttpGenerator gen = new HttpGenerator();
|
HttpGenerator gen = new HttpGenerator();
|
||||||
|
|
||||||
HttpGenerator.Result
|
HttpGenerator.Result
|
||||||
result=gen.generateRequest(null,null,null,true);
|
result=gen.generateRequest(null,null,null,null, true);
|
||||||
assertEquals(HttpGenerator.Result.NEED_INFO,result);
|
assertEquals(HttpGenerator.Result.NEED_INFO,result);
|
||||||
assertEquals(HttpGenerator.State.START,gen.getState());
|
assertEquals(HttpGenerator.State.START,gen.getState());
|
||||||
|
|
||||||
|
@ -63,18 +63,18 @@ public class HttpGeneratorClientTest
|
||||||
info.getHttpFields().add("User-Agent","test");
|
info.getHttpFields().add("User-Agent","test");
|
||||||
assertTrue(!gen.isChunking());
|
assertTrue(!gen.isChunking());
|
||||||
|
|
||||||
result=gen.generateRequest(info,null,null,true);
|
result=gen.generateRequest(info,null,null,null, true);
|
||||||
assertEquals(HttpGenerator.Result.NEED_HEADER,result);
|
assertEquals(HttpGenerator.Result.NEED_HEADER,result);
|
||||||
assertEquals(HttpGenerator.State.START,gen.getState());
|
assertEquals(HttpGenerator.State.START,gen.getState());
|
||||||
|
|
||||||
result=gen.generateRequest(info,header,null,true);
|
result=gen.generateRequest(info,header,null,null, true);
|
||||||
assertEquals(HttpGenerator.Result.FLUSH,result);
|
assertEquals(HttpGenerator.Result.FLUSH,result);
|
||||||
assertEquals(HttpGenerator.State.COMPLETING,gen.getState());
|
assertEquals(HttpGenerator.State.COMPLETING,gen.getState());
|
||||||
assertTrue(!gen.isChunking());
|
assertTrue(!gen.isChunking());
|
||||||
String out = BufferUtil.toString(header);
|
String out = BufferUtil.toString(header);
|
||||||
BufferUtil.clear(header);
|
BufferUtil.clear(header);
|
||||||
|
|
||||||
result=gen.generateResponse(null,null,null,false);
|
result=gen.generateResponse(null,null,null,null, false);
|
||||||
assertEquals(HttpGenerator.Result.DONE,result);
|
assertEquals(HttpGenerator.Result.DONE,result);
|
||||||
assertEquals(HttpGenerator.State.END,gen.getState());
|
assertEquals(HttpGenerator.State.END,gen.getState());
|
||||||
assertTrue(!gen.isChunking());
|
assertTrue(!gen.isChunking());
|
||||||
|
@ -94,7 +94,7 @@ public class HttpGeneratorClientTest
|
||||||
HttpGenerator gen = new HttpGenerator();
|
HttpGenerator gen = new HttpGenerator();
|
||||||
|
|
||||||
HttpGenerator.Result
|
HttpGenerator.Result
|
||||||
result=gen.generateRequest(null,null,content0,true);
|
result=gen.generateRequest(null,null,null,content0, true);
|
||||||
assertEquals(HttpGenerator.Result.NEED_INFO,result);
|
assertEquals(HttpGenerator.Result.NEED_INFO,result);
|
||||||
assertEquals(HttpGenerator.State.START,gen.getState());
|
assertEquals(HttpGenerator.State.START,gen.getState());
|
||||||
|
|
||||||
|
@ -102,11 +102,11 @@ public class HttpGeneratorClientTest
|
||||||
info.getHttpFields().add("Host","something");
|
info.getHttpFields().add("Host","something");
|
||||||
info.getHttpFields().add("User-Agent","test");
|
info.getHttpFields().add("User-Agent","test");
|
||||||
|
|
||||||
result=gen.generateRequest(info,null,content0,true);
|
result=gen.generateRequest(info,null,null,content0, true);
|
||||||
assertEquals(HttpGenerator.Result.NEED_HEADER,result);
|
assertEquals(HttpGenerator.Result.NEED_HEADER,result);
|
||||||
assertEquals(HttpGenerator.State.START,gen.getState());
|
assertEquals(HttpGenerator.State.START,gen.getState());
|
||||||
|
|
||||||
result=gen.generateRequest(info,header,content0,true);
|
result=gen.generateRequest(info,header,null,content0, true);
|
||||||
assertEquals(HttpGenerator.Result.FLUSH,result);
|
assertEquals(HttpGenerator.Result.FLUSH,result);
|
||||||
assertEquals(HttpGenerator.State.COMPLETING,gen.getState());
|
assertEquals(HttpGenerator.State.COMPLETING,gen.getState());
|
||||||
assertTrue(!gen.isChunking());
|
assertTrue(!gen.isChunking());
|
||||||
|
@ -115,7 +115,7 @@ public class HttpGeneratorClientTest
|
||||||
out+=BufferUtil.toString(content0);
|
out+=BufferUtil.toString(content0);
|
||||||
BufferUtil.clear(content0);
|
BufferUtil.clear(content0);
|
||||||
|
|
||||||
result=gen.generateResponse(null,null,null,false);
|
result=gen.generateResponse(null,null,null,null, false);
|
||||||
assertEquals(HttpGenerator.Result.DONE,result);
|
assertEquals(HttpGenerator.Result.DONE,result);
|
||||||
assertEquals(HttpGenerator.State.END,gen.getState());
|
assertEquals(HttpGenerator.State.END,gen.getState());
|
||||||
assertTrue(!gen.isChunking());
|
assertTrue(!gen.isChunking());
|
||||||
|
@ -140,7 +140,7 @@ public class HttpGeneratorClientTest
|
||||||
HttpGenerator gen = new HttpGenerator();
|
HttpGenerator gen = new HttpGenerator();
|
||||||
|
|
||||||
HttpGenerator.Result
|
HttpGenerator.Result
|
||||||
result=gen.generateRequest(null,null,content0,false);
|
result=gen.generateRequest(null,null,null,content0, false);
|
||||||
assertEquals(HttpGenerator.Result.NEED_INFO,result);
|
assertEquals(HttpGenerator.Result.NEED_INFO,result);
|
||||||
assertEquals(HttpGenerator.State.START,gen.getState());
|
assertEquals(HttpGenerator.State.START,gen.getState());
|
||||||
|
|
||||||
|
@ -148,11 +148,11 @@ public class HttpGeneratorClientTest
|
||||||
info.getHttpFields().add("Host","something");
|
info.getHttpFields().add("Host","something");
|
||||||
info.getHttpFields().add("User-Agent","test");
|
info.getHttpFields().add("User-Agent","test");
|
||||||
|
|
||||||
result=gen.generateRequest(info,null,content0,false);
|
result=gen.generateRequest(info,null,null,content0, false);
|
||||||
assertEquals(HttpGenerator.Result.NEED_HEADER,result);
|
assertEquals(HttpGenerator.Result.NEED_HEADER,result);
|
||||||
assertEquals(HttpGenerator.State.START,gen.getState());
|
assertEquals(HttpGenerator.State.START,gen.getState());
|
||||||
|
|
||||||
result=gen.generateRequest(info,header,content0,false);
|
result=gen.generateRequest(info,header,null,content0, false);
|
||||||
assertEquals(HttpGenerator.Result.FLUSH,result);
|
assertEquals(HttpGenerator.Result.FLUSH,result);
|
||||||
assertEquals(HttpGenerator.State.COMMITTED,gen.getState());
|
assertEquals(HttpGenerator.State.COMMITTED,gen.getState());
|
||||||
assertTrue(gen.isChunking());
|
assertTrue(gen.isChunking());
|
||||||
|
@ -161,11 +161,11 @@ public class HttpGeneratorClientTest
|
||||||
out+=BufferUtil.toString(content0);
|
out+=BufferUtil.toString(content0);
|
||||||
BufferUtil.clear(content0);
|
BufferUtil.clear(content0);
|
||||||
|
|
||||||
result=gen.generateRequest(null,header,content1,false);
|
result=gen.generateRequest(null,header,null,content1, false);
|
||||||
assertEquals(HttpGenerator.Result.NEED_CHUNK,result);
|
assertEquals(HttpGenerator.Result.NEED_CHUNK,result);
|
||||||
assertEquals(HttpGenerator.State.COMMITTED,gen.getState());
|
assertEquals(HttpGenerator.State.COMMITTED,gen.getState());
|
||||||
|
|
||||||
result=gen.generateRequest(null,chunk,content1,false);
|
result=gen.generateRequest(null,null,chunk,content1, false);
|
||||||
assertEquals(HttpGenerator.Result.FLUSH,result);
|
assertEquals(HttpGenerator.Result.FLUSH,result);
|
||||||
assertEquals(HttpGenerator.State.COMMITTED,gen.getState());
|
assertEquals(HttpGenerator.State.COMMITTED,gen.getState());
|
||||||
assertTrue(gen.isChunking());
|
assertTrue(gen.isChunking());
|
||||||
|
@ -174,19 +174,19 @@ public class HttpGeneratorClientTest
|
||||||
out+=BufferUtil.toString(content1);
|
out+=BufferUtil.toString(content1);
|
||||||
BufferUtil.clear(content1);
|
BufferUtil.clear(content1);
|
||||||
|
|
||||||
result=gen.generateResponse(null,chunk,null,true);
|
result=gen.generateResponse(null,null,chunk,null, true);
|
||||||
assertEquals(HttpGenerator.Result.CONTINUE,result);
|
assertEquals(HttpGenerator.Result.CONTINUE,result);
|
||||||
assertEquals(HttpGenerator.State.COMPLETING,gen.getState());
|
assertEquals(HttpGenerator.State.COMPLETING,gen.getState());
|
||||||
assertTrue(gen.isChunking());
|
assertTrue(gen.isChunking());
|
||||||
|
|
||||||
result=gen.generateResponse(null,chunk,null,true);
|
result=gen.generateResponse(null,null,chunk,null, true);
|
||||||
assertEquals(HttpGenerator.Result.FLUSH,result);
|
assertEquals(HttpGenerator.Result.FLUSH,result);
|
||||||
assertEquals(HttpGenerator.State.COMPLETING,gen.getState());
|
assertEquals(HttpGenerator.State.COMPLETING,gen.getState());
|
||||||
out+=BufferUtil.toString(chunk);
|
out+=BufferUtil.toString(chunk);
|
||||||
BufferUtil.clear(chunk);
|
BufferUtil.clear(chunk);
|
||||||
assertTrue(!gen.isChunking());
|
assertTrue(!gen.isChunking());
|
||||||
|
|
||||||
result=gen.generateResponse(null,chunk,null,true);
|
result=gen.generateResponse(null,null,chunk,null, true);
|
||||||
assertEquals(HttpGenerator.Result.DONE,result);
|
assertEquals(HttpGenerator.Result.DONE,result);
|
||||||
assertEquals(HttpGenerator.State.END,gen.getState());
|
assertEquals(HttpGenerator.State.END,gen.getState());
|
||||||
|
|
||||||
|
@ -212,7 +212,7 @@ public class HttpGeneratorClientTest
|
||||||
HttpGenerator gen = new HttpGenerator();
|
HttpGenerator gen = new HttpGenerator();
|
||||||
|
|
||||||
HttpGenerator.Result
|
HttpGenerator.Result
|
||||||
result=gen.generateRequest(null,null,content0,false);
|
result=gen.generateRequest(null,null,null,content0, false);
|
||||||
assertEquals(HttpGenerator.Result.NEED_INFO,result);
|
assertEquals(HttpGenerator.Result.NEED_INFO,result);
|
||||||
assertEquals(HttpGenerator.State.START,gen.getState());
|
assertEquals(HttpGenerator.State.START,gen.getState());
|
||||||
|
|
||||||
|
@ -220,11 +220,11 @@ public class HttpGeneratorClientTest
|
||||||
info.getHttpFields().add("Host","something");
|
info.getHttpFields().add("Host","something");
|
||||||
info.getHttpFields().add("User-Agent","test");
|
info.getHttpFields().add("User-Agent","test");
|
||||||
|
|
||||||
result=gen.generateRequest(info,null,content0,false);
|
result=gen.generateRequest(info,null,null,content0, false);
|
||||||
assertEquals(HttpGenerator.Result.NEED_HEADER,result);
|
assertEquals(HttpGenerator.Result.NEED_HEADER,result);
|
||||||
assertEquals(HttpGenerator.State.START,gen.getState());
|
assertEquals(HttpGenerator.State.START,gen.getState());
|
||||||
|
|
||||||
result=gen.generateRequest(info,header,content0,false);
|
result=gen.generateRequest(info,header,null,content0, false);
|
||||||
assertEquals(HttpGenerator.Result.FLUSH,result);
|
assertEquals(HttpGenerator.Result.FLUSH,result);
|
||||||
assertEquals(HttpGenerator.State.COMMITTED,gen.getState());
|
assertEquals(HttpGenerator.State.COMMITTED,gen.getState());
|
||||||
assertTrue(!gen.isChunking());
|
assertTrue(!gen.isChunking());
|
||||||
|
@ -233,19 +233,19 @@ public class HttpGeneratorClientTest
|
||||||
out+=BufferUtil.toString(content0);
|
out+=BufferUtil.toString(content0);
|
||||||
BufferUtil.clear(content0);
|
BufferUtil.clear(content0);
|
||||||
|
|
||||||
result=gen.generateRequest(null,null,content1,false);
|
result=gen.generateRequest(null,null,null,content1, false);
|
||||||
assertEquals(HttpGenerator.Result.FLUSH,result);
|
assertEquals(HttpGenerator.Result.FLUSH,result);
|
||||||
assertEquals(HttpGenerator.State.COMMITTED,gen.getState());
|
assertEquals(HttpGenerator.State.COMMITTED,gen.getState());
|
||||||
assertTrue(!gen.isChunking());
|
assertTrue(!gen.isChunking());
|
||||||
out+=BufferUtil.toString(content1);
|
out+=BufferUtil.toString(content1);
|
||||||
BufferUtil.clear(content1);
|
BufferUtil.clear(content1);
|
||||||
|
|
||||||
result=gen.generateResponse(null,null,null,true);
|
result=gen.generateResponse(null,null,null,null, true);
|
||||||
assertEquals(HttpGenerator.Result.CONTINUE,result);
|
assertEquals(HttpGenerator.Result.CONTINUE,result);
|
||||||
assertEquals(HttpGenerator.State.COMPLETING,gen.getState());
|
assertEquals(HttpGenerator.State.COMPLETING,gen.getState());
|
||||||
assertTrue(!gen.isChunking());
|
assertTrue(!gen.isChunking());
|
||||||
|
|
||||||
result=gen.generateResponse(null,null,null,true);
|
result=gen.generateResponse(null,null,null,null, true);
|
||||||
assertEquals(HttpGenerator.Result.DONE,result);
|
assertEquals(HttpGenerator.Result.DONE,result);
|
||||||
assertEquals(HttpGenerator.State.END,gen.getState());
|
assertEquals(HttpGenerator.State.END,gen.getState());
|
||||||
out+=BufferUtil.toString(chunk);
|
out+=BufferUtil.toString(chunk);
|
||||||
|
|
|
@ -149,6 +149,7 @@ public class HttpGeneratorServerTest
|
||||||
// System.err.printf("content %d %s%n",c,BufferUtil.toDetailString(content));
|
// System.err.printf("content %d %s%n",c,BufferUtil.toDetailString(content));
|
||||||
}
|
}
|
||||||
ByteBuffer header = null;
|
ByteBuffer header = null;
|
||||||
|
ByteBuffer chunk = null;
|
||||||
HttpGenerator.ResponseInfo info = null;
|
HttpGenerator.ResponseInfo info = null;
|
||||||
|
|
||||||
loop:
|
loop:
|
||||||
|
@ -164,22 +165,7 @@ public class HttpGeneratorServerTest
|
||||||
// Generate
|
// Generate
|
||||||
boolean last = !BufferUtil.hasContent(content);
|
boolean last = !BufferUtil.hasContent(content);
|
||||||
|
|
||||||
/*
|
HttpGenerator.Result result = gen.generateResponse(info, header, chunk, content, last);
|
||||||
System.err.printf("generate(%s,%s,%s,%s,%s)@%s%n",
|
|
||||||
BufferUtil.toSummaryString(header),
|
|
||||||
BufferUtil.toSummaryString(chunk),
|
|
||||||
BufferUtil.toSummaryString(buffer),
|
|
||||||
BufferUtil.toSummaryString(content),
|
|
||||||
action,gen.getState());
|
|
||||||
*/
|
|
||||||
HttpGenerator.Result result = gen.generateResponse(info, header, content, last);
|
|
||||||
/*System.err.printf("%s (%s,%s,%s,%s,%s)@%s%n",
|
|
||||||
result,
|
|
||||||
BufferUtil.toSummaryString(header),
|
|
||||||
BufferUtil.toSummaryString(chunk),
|
|
||||||
BufferUtil.toSummaryString(buffer),
|
|
||||||
BufferUtil.toSummaryString(content),
|
|
||||||
action,gen.getState());*/
|
|
||||||
|
|
||||||
switch (result)
|
switch (result)
|
||||||
{
|
{
|
||||||
|
@ -192,7 +178,7 @@ public class HttpGeneratorServerTest
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
case NEED_CHUNK:
|
case NEED_CHUNK:
|
||||||
header = BufferUtil.allocate(HttpGenerator.CHUNK_SIZE);
|
chunk = BufferUtil.allocate(HttpGenerator.CHUNK_SIZE);
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
case FLUSH:
|
case FLUSH:
|
||||||
|
@ -201,6 +187,11 @@ public class HttpGeneratorServerTest
|
||||||
response += BufferUtil.toString(header);
|
response += BufferUtil.toString(header);
|
||||||
header.position(header.limit());
|
header.position(header.limit());
|
||||||
}
|
}
|
||||||
|
if (BufferUtil.hasContent(chunk))
|
||||||
|
{
|
||||||
|
response += BufferUtil.toString(chunk);
|
||||||
|
chunk.position(chunk.limit());
|
||||||
|
}
|
||||||
if (BufferUtil.hasContent(content))
|
if (BufferUtil.hasContent(content))
|
||||||
{
|
{
|
||||||
response += BufferUtil.toString(content);
|
response += BufferUtil.toString(content);
|
||||||
|
@ -322,23 +313,23 @@ public class HttpGeneratorServerTest
|
||||||
HttpGenerator gen = new HttpGenerator();
|
HttpGenerator gen = new HttpGenerator();
|
||||||
|
|
||||||
HttpGenerator.Result
|
HttpGenerator.Result
|
||||||
result = gen.generateResponse(null, null, null, true);
|
result = gen.generateResponse(null, null, null, null, true);
|
||||||
assertEquals(HttpGenerator.Result.NEED_INFO, result);
|
assertEquals(HttpGenerator.Result.NEED_INFO, result);
|
||||||
assertEquals(HttpGenerator.State.START, gen.getState());
|
assertEquals(HttpGenerator.State.START, gen.getState());
|
||||||
|
|
||||||
ResponseInfo info = new ResponseInfo(HttpVersion.HTTP_1_1, new HttpFields(), -1, 200, null, false);
|
ResponseInfo info = new ResponseInfo(HttpVersion.HTTP_1_1, new HttpFields(), -1, 200, null, false);
|
||||||
info.getHttpFields().add("Last-Modified", HttpFields.__01Jan1970);
|
info.getHttpFields().add("Last-Modified", HttpFields.__01Jan1970);
|
||||||
|
|
||||||
result = gen.generateResponse(info, null, null, true);
|
result = gen.generateResponse(info, null, null, null, true);
|
||||||
assertEquals(HttpGenerator.Result.NEED_HEADER, result);
|
assertEquals(HttpGenerator.Result.NEED_HEADER, result);
|
||||||
|
|
||||||
result = gen.generateResponse(info, header, null, true);
|
result = gen.generateResponse(info, header, null, null, true);
|
||||||
assertEquals(HttpGenerator.Result.FLUSH, result);
|
assertEquals(HttpGenerator.Result.FLUSH, result);
|
||||||
assertEquals(HttpGenerator.State.COMPLETING, gen.getState());
|
assertEquals(HttpGenerator.State.COMPLETING, gen.getState());
|
||||||
String head = BufferUtil.toString(header);
|
String head = BufferUtil.toString(header);
|
||||||
BufferUtil.clear(header);
|
BufferUtil.clear(header);
|
||||||
|
|
||||||
result = gen.generateResponse(null, null, null, false);
|
result = gen.generateResponse(null, null, null, null, false);
|
||||||
assertEquals(HttpGenerator.Result.DONE, result);
|
assertEquals(HttpGenerator.Result.DONE, result);
|
||||||
assertEquals(HttpGenerator.State.END, gen.getState());
|
assertEquals(HttpGenerator.State.END, gen.getState());
|
||||||
|
|
||||||
|
@ -356,7 +347,7 @@ public class HttpGeneratorServerTest
|
||||||
HttpGenerator gen = new HttpGenerator();
|
HttpGenerator gen = new HttpGenerator();
|
||||||
|
|
||||||
HttpGenerator.Result
|
HttpGenerator.Result
|
||||||
result = gen.generateResponse(null, null, null, true);
|
result = gen.generateResponse(null, null, null, null, true);
|
||||||
assertEquals(HttpGenerator.Result.NEED_INFO, result);
|
assertEquals(HttpGenerator.Result.NEED_INFO, result);
|
||||||
assertEquals(HttpGenerator.State.START, gen.getState());
|
assertEquals(HttpGenerator.State.START, gen.getState());
|
||||||
|
|
||||||
|
@ -365,13 +356,13 @@ public class HttpGeneratorServerTest
|
||||||
info.getHttpFields().add("Connection", "Upgrade");
|
info.getHttpFields().add("Connection", "Upgrade");
|
||||||
info.getHttpFields().add("Sec-WebSocket-Accept", "123456789==");
|
info.getHttpFields().add("Sec-WebSocket-Accept", "123456789==");
|
||||||
|
|
||||||
result = gen.generateResponse(info, header, null, true);
|
result = gen.generateResponse(info, header, null, null, true);
|
||||||
assertEquals(HttpGenerator.Result.FLUSH, result);
|
assertEquals(HttpGenerator.Result.FLUSH, result);
|
||||||
assertEquals(HttpGenerator.State.COMPLETING, gen.getState());
|
assertEquals(HttpGenerator.State.COMPLETING, gen.getState());
|
||||||
String head = BufferUtil.toString(header);
|
String head = BufferUtil.toString(header);
|
||||||
BufferUtil.clear(header);
|
BufferUtil.clear(header);
|
||||||
|
|
||||||
result = gen.generateResponse(info, null, null, false);
|
result = gen.generateResponse(info, null, null, null, false);
|
||||||
assertEquals(HttpGenerator.Result.DONE, result);
|
assertEquals(HttpGenerator.Result.DONE, result);
|
||||||
assertEquals(HttpGenerator.State.END, gen.getState());
|
assertEquals(HttpGenerator.State.END, gen.getState());
|
||||||
|
|
||||||
|
@ -391,17 +382,17 @@ public class HttpGeneratorServerTest
|
||||||
ByteBuffer content1 = BufferUtil.toBuffer("The quick brown fox jumped over the lazy dog. ");
|
ByteBuffer content1 = BufferUtil.toBuffer("The quick brown fox jumped over the lazy dog. ");
|
||||||
HttpGenerator gen = new HttpGenerator();
|
HttpGenerator gen = new HttpGenerator();
|
||||||
|
|
||||||
HttpGenerator.Result result = gen.generateResponse(null, null, content0, false);
|
HttpGenerator.Result result = gen.generateResponse(null, null, null, content0, false);
|
||||||
assertEquals(HttpGenerator.Result.NEED_INFO, result);
|
assertEquals(HttpGenerator.Result.NEED_INFO, result);
|
||||||
assertEquals(HttpGenerator.State.START, gen.getState());
|
assertEquals(HttpGenerator.State.START, gen.getState());
|
||||||
|
|
||||||
ResponseInfo info = new ResponseInfo(HttpVersion.HTTP_1_1, new HttpFields(), -1, 200, null, false);
|
ResponseInfo info = new ResponseInfo(HttpVersion.HTTP_1_1, new HttpFields(), -1, 200, null, false);
|
||||||
info.getHttpFields().add("Last-Modified", HttpFields.__01Jan1970);
|
info.getHttpFields().add("Last-Modified", HttpFields.__01Jan1970);
|
||||||
result = gen.generateResponse(info, null, content0, false);
|
result = gen.generateResponse(info, null, null, content0, false);
|
||||||
assertEquals(HttpGenerator.Result.NEED_HEADER, result);
|
assertEquals(HttpGenerator.Result.NEED_HEADER, result);
|
||||||
assertEquals(HttpGenerator.State.START, gen.getState());
|
assertEquals(HttpGenerator.State.START, gen.getState());
|
||||||
|
|
||||||
result = gen.generateResponse(info, header, content0, false);
|
result = gen.generateResponse(info, header, null, content0, false);
|
||||||
assertEquals(HttpGenerator.Result.FLUSH, result);
|
assertEquals(HttpGenerator.Result.FLUSH, result);
|
||||||
assertEquals(HttpGenerator.State.COMMITTED, gen.getState());
|
assertEquals(HttpGenerator.State.COMMITTED, gen.getState());
|
||||||
|
|
||||||
|
@ -410,7 +401,7 @@ public class HttpGeneratorServerTest
|
||||||
out += BufferUtil.toString(content0);
|
out += BufferUtil.toString(content0);
|
||||||
BufferUtil.clear(content0);
|
BufferUtil.clear(content0);
|
||||||
|
|
||||||
result = gen.generateResponse(null, chunk, content1, false);
|
result = gen.generateResponse(null,null,chunk, content1, false);
|
||||||
assertEquals(HttpGenerator.Result.FLUSH, result);
|
assertEquals(HttpGenerator.Result.FLUSH, result);
|
||||||
assertEquals(HttpGenerator.State.COMMITTED, gen.getState());
|
assertEquals(HttpGenerator.State.COMMITTED, gen.getState());
|
||||||
out += BufferUtil.toString(chunk);
|
out += BufferUtil.toString(chunk);
|
||||||
|
@ -418,17 +409,17 @@ public class HttpGeneratorServerTest
|
||||||
out += BufferUtil.toString(content1);
|
out += BufferUtil.toString(content1);
|
||||||
BufferUtil.clear(content1);
|
BufferUtil.clear(content1);
|
||||||
|
|
||||||
result = gen.generateResponse(null, chunk, null, true);
|
result = gen.generateResponse(null,null,chunk, null, true);
|
||||||
assertEquals(HttpGenerator.Result.CONTINUE, result);
|
assertEquals(HttpGenerator.Result.CONTINUE, result);
|
||||||
assertEquals(HttpGenerator.State.COMPLETING, gen.getState());
|
assertEquals(HttpGenerator.State.COMPLETING, gen.getState());
|
||||||
|
|
||||||
result = gen.generateResponse(null, chunk, null, true);
|
result = gen.generateResponse(null,null,chunk, null, true);
|
||||||
assertEquals(HttpGenerator.Result.FLUSH, result);
|
assertEquals(HttpGenerator.Result.FLUSH, result);
|
||||||
assertEquals(HttpGenerator.State.COMPLETING, gen.getState());
|
assertEquals(HttpGenerator.State.COMPLETING, gen.getState());
|
||||||
out += BufferUtil.toString(chunk);
|
out += BufferUtil.toString(chunk);
|
||||||
BufferUtil.clear(chunk);
|
BufferUtil.clear(chunk);
|
||||||
|
|
||||||
result = gen.generateResponse(null, chunk, null, true);
|
result = gen.generateResponse(null,null,chunk, null, true);
|
||||||
assertEquals(HttpGenerator.Result.DONE, result);
|
assertEquals(HttpGenerator.Result.DONE, result);
|
||||||
assertEquals(HttpGenerator.State.END, gen.getState());
|
assertEquals(HttpGenerator.State.END, gen.getState());
|
||||||
|
|
||||||
|
@ -453,17 +444,17 @@ public class HttpGeneratorServerTest
|
||||||
|
|
||||||
HttpGenerator.Result
|
HttpGenerator.Result
|
||||||
|
|
||||||
result = gen.generateResponse(null, null, content0, false);
|
result = gen.generateResponse(null, null, null, content0, false);
|
||||||
assertEquals(HttpGenerator.Result.NEED_INFO, result);
|
assertEquals(HttpGenerator.Result.NEED_INFO, result);
|
||||||
assertEquals(HttpGenerator.State.START, gen.getState());
|
assertEquals(HttpGenerator.State.START, gen.getState());
|
||||||
|
|
||||||
ResponseInfo info = new ResponseInfo(HttpVersion.HTTP_1_1, new HttpFields(), 59, 200, null, false);
|
ResponseInfo info = new ResponseInfo(HttpVersion.HTTP_1_1, new HttpFields(), 59, 200, null, false);
|
||||||
info.getHttpFields().add("Last-Modified", HttpFields.__01Jan1970);
|
info.getHttpFields().add("Last-Modified", HttpFields.__01Jan1970);
|
||||||
result = gen.generateResponse(info, null, content0, false);
|
result = gen.generateResponse(info, null, null, content0, false);
|
||||||
assertEquals(HttpGenerator.Result.NEED_HEADER, result);
|
assertEquals(HttpGenerator.Result.NEED_HEADER, result);
|
||||||
assertEquals(HttpGenerator.State.START, gen.getState());
|
assertEquals(HttpGenerator.State.START, gen.getState());
|
||||||
|
|
||||||
result = gen.generateResponse(info, header, content0, false);
|
result = gen.generateResponse(info, header, null, content0, false);
|
||||||
assertEquals(HttpGenerator.Result.FLUSH, result);
|
assertEquals(HttpGenerator.Result.FLUSH, result);
|
||||||
assertEquals(HttpGenerator.State.COMMITTED, gen.getState());
|
assertEquals(HttpGenerator.State.COMMITTED, gen.getState());
|
||||||
|
|
||||||
|
@ -472,17 +463,17 @@ public class HttpGeneratorServerTest
|
||||||
out += BufferUtil.toString(content0);
|
out += BufferUtil.toString(content0);
|
||||||
BufferUtil.clear(content0);
|
BufferUtil.clear(content0);
|
||||||
|
|
||||||
result = gen.generateResponse(null, null, content1, false);
|
result = gen.generateResponse(null, null, null, content1, false);
|
||||||
assertEquals(HttpGenerator.Result.FLUSH, result);
|
assertEquals(HttpGenerator.Result.FLUSH, result);
|
||||||
assertEquals(HttpGenerator.State.COMMITTED, gen.getState());
|
assertEquals(HttpGenerator.State.COMMITTED, gen.getState());
|
||||||
out += BufferUtil.toString(content1);
|
out += BufferUtil.toString(content1);
|
||||||
BufferUtil.clear(content1);
|
BufferUtil.clear(content1);
|
||||||
|
|
||||||
result = gen.generateResponse(null, null, null, true);
|
result = gen.generateResponse(null, null, null, null, true);
|
||||||
assertEquals(HttpGenerator.Result.CONTINUE, result);
|
assertEquals(HttpGenerator.Result.CONTINUE, result);
|
||||||
assertEquals(HttpGenerator.State.COMPLETING, gen.getState());
|
assertEquals(HttpGenerator.State.COMPLETING, gen.getState());
|
||||||
|
|
||||||
result = gen.generateResponse(null, null, null, true);
|
result = gen.generateResponse(null, null, null, null, true);
|
||||||
assertEquals(HttpGenerator.Result.DONE, result);
|
assertEquals(HttpGenerator.Result.DONE, result);
|
||||||
assertEquals(HttpGenerator.State.END, gen.getState());
|
assertEquals(HttpGenerator.State.END, gen.getState());
|
||||||
|
|
||||||
|
@ -504,33 +495,33 @@ public class HttpGeneratorServerTest
|
||||||
|
|
||||||
HttpGenerator.Result
|
HttpGenerator.Result
|
||||||
|
|
||||||
result = gen.generateResponse(HttpGenerator.CONTINUE_100_INFO, null, null, false);
|
result = gen.generateResponse(HttpGenerator.CONTINUE_100_INFO, null, null, null, false);
|
||||||
assertEquals(HttpGenerator.Result.NEED_HEADER, result);
|
assertEquals(HttpGenerator.Result.NEED_HEADER, result);
|
||||||
assertEquals(HttpGenerator.State.START, gen.getState());
|
assertEquals(HttpGenerator.State.START, gen.getState());
|
||||||
|
|
||||||
result = gen.generateResponse(HttpGenerator.CONTINUE_100_INFO, header, null, false);
|
result = gen.generateResponse(HttpGenerator.CONTINUE_100_INFO, header, null, null, false);
|
||||||
assertEquals(HttpGenerator.Result.FLUSH, result);
|
assertEquals(HttpGenerator.Result.FLUSH, result);
|
||||||
assertEquals(HttpGenerator.State.COMPLETING_1XX, gen.getState());
|
assertEquals(HttpGenerator.State.COMPLETING_1XX, gen.getState());
|
||||||
String out = BufferUtil.toString(header);
|
String out = BufferUtil.toString(header);
|
||||||
|
|
||||||
result = gen.generateResponse(null, null, null, false);
|
result = gen.generateResponse(null, null, null, null, false);
|
||||||
assertEquals(HttpGenerator.Result.DONE, result);
|
assertEquals(HttpGenerator.Result.DONE, result);
|
||||||
assertEquals(HttpGenerator.State.START, gen.getState());
|
assertEquals(HttpGenerator.State.START, gen.getState());
|
||||||
|
|
||||||
assertThat(out, containsString("HTTP/1.1 100 Continue"));
|
assertThat(out, containsString("HTTP/1.1 100 Continue"));
|
||||||
|
|
||||||
|
|
||||||
result = gen.generateResponse(null, null, content0, false);
|
result = gen.generateResponse(null, null, null, content0, false);
|
||||||
assertEquals(HttpGenerator.Result.NEED_INFO, result);
|
assertEquals(HttpGenerator.Result.NEED_INFO, result);
|
||||||
assertEquals(HttpGenerator.State.START, gen.getState());
|
assertEquals(HttpGenerator.State.START, gen.getState());
|
||||||
|
|
||||||
ResponseInfo info = new ResponseInfo(HttpVersion.HTTP_1_1, new HttpFields(), 59, 200, null, false);
|
ResponseInfo info = new ResponseInfo(HttpVersion.HTTP_1_1, new HttpFields(), 59, 200, null, false);
|
||||||
info.getHttpFields().add("Last-Modified", HttpFields.__01Jan1970);
|
info.getHttpFields().add("Last-Modified", HttpFields.__01Jan1970);
|
||||||
result = gen.generateResponse(info, null, content0, false);
|
result = gen.generateResponse(info, null, null, content0, false);
|
||||||
assertEquals(HttpGenerator.Result.NEED_HEADER, result);
|
assertEquals(HttpGenerator.Result.NEED_HEADER, result);
|
||||||
assertEquals(HttpGenerator.State.START, gen.getState());
|
assertEquals(HttpGenerator.State.START, gen.getState());
|
||||||
|
|
||||||
result = gen.generateResponse(info, header, content0, false);
|
result = gen.generateResponse(info, header, null, content0, false);
|
||||||
assertEquals(HttpGenerator.Result.FLUSH, result);
|
assertEquals(HttpGenerator.Result.FLUSH, result);
|
||||||
assertEquals(HttpGenerator.State.COMMITTED, gen.getState());
|
assertEquals(HttpGenerator.State.COMMITTED, gen.getState());
|
||||||
|
|
||||||
|
@ -539,17 +530,17 @@ public class HttpGeneratorServerTest
|
||||||
out += BufferUtil.toString(content0);
|
out += BufferUtil.toString(content0);
|
||||||
BufferUtil.clear(content0);
|
BufferUtil.clear(content0);
|
||||||
|
|
||||||
result = gen.generateResponse(null, null, content1, false);
|
result = gen.generateResponse(null, null, null, content1, false);
|
||||||
assertEquals(HttpGenerator.Result.FLUSH, result);
|
assertEquals(HttpGenerator.Result.FLUSH, result);
|
||||||
assertEquals(HttpGenerator.State.COMMITTED, gen.getState());
|
assertEquals(HttpGenerator.State.COMMITTED, gen.getState());
|
||||||
out += BufferUtil.toString(content1);
|
out += BufferUtil.toString(content1);
|
||||||
BufferUtil.clear(content1);
|
BufferUtil.clear(content1);
|
||||||
|
|
||||||
result = gen.generateResponse(null, null, null, true);
|
result = gen.generateResponse(null, null, null, null, true);
|
||||||
assertEquals(HttpGenerator.Result.CONTINUE, result);
|
assertEquals(HttpGenerator.Result.CONTINUE, result);
|
||||||
assertEquals(HttpGenerator.State.COMPLETING, gen.getState());
|
assertEquals(HttpGenerator.State.COMPLETING, gen.getState());
|
||||||
|
|
||||||
result = gen.generateResponse(null, null, null, true);
|
result = gen.generateResponse(null, null, null, null, true);
|
||||||
assertEquals(HttpGenerator.Result.DONE, result);
|
assertEquals(HttpGenerator.Result.DONE, result);
|
||||||
assertEquals(HttpGenerator.State.END, gen.getState());
|
assertEquals(HttpGenerator.State.END, gen.getState());
|
||||||
|
|
||||||
|
|
|
@ -253,7 +253,7 @@ public class HttpChannel implements HttpParser.RequestHandler, Runnable
|
||||||
LOG.warn(String.valueOf(_uri), e);
|
LOG.warn(String.valueOf(_uri), e);
|
||||||
_state.error(e);
|
_state.error(e);
|
||||||
_request.setHandled(true);
|
_request.setHandled(true);
|
||||||
handleError(e);
|
handleException(e);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
|
@ -312,45 +312,6 @@ public class HttpChannel implements HttpParser.RequestHandler, Runnable
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean complete()
|
|
||||||
{
|
|
||||||
LOG.debug("{} complete", this);
|
|
||||||
if (_state.isCompleting())
|
|
||||||
{
|
|
||||||
_state.completed();
|
|
||||||
if (isExpecting100Continue())
|
|
||||||
{
|
|
||||||
LOG.debug("100-Continue response 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 (!isCommitted())
|
|
||||||
_response.addHeader(HttpHeader.CONNECTION.toString(), HttpHeaderValue.CLOSE.toString());
|
|
||||||
else
|
|
||||||
LOG.warn("Cannot send 'Connection: close' for 100-Continue, response is already committed");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!_response.isCommitted() && !_request.isHandled())
|
|
||||||
_response.sendError(Response.SC_NOT_FOUND, null, null);
|
|
||||||
|
|
||||||
_request.setHandled(true);
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
_response.getHttpOutput().close();
|
|
||||||
}
|
|
||||||
catch (IOException x)
|
|
||||||
{
|
|
||||||
// We cannot write the response, so there is no point in calling
|
|
||||||
// response.sendError() since that writes, and we already know we cannot write.
|
|
||||||
LOG.debug("Could not write response", x);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return _request.getHttpInput().isShutdown();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>Sends an error 500, performing a special logic to detect whether the request is suspended,
|
* <p>Sends an error 500, performing a special logic to detect whether the request is suspended,
|
||||||
* to avoid concurrent writes from the application.</p>
|
* to avoid concurrent writes from the application.</p>
|
||||||
|
@ -360,11 +321,11 @@ public class HttpChannel implements HttpParser.RequestHandler, Runnable
|
||||||
*
|
*
|
||||||
* @param x the Throwable that caused the problem
|
* @param x the Throwable that caused the problem
|
||||||
*/
|
*/
|
||||||
private void handleError(Throwable x)
|
protected void handleException(Throwable x)
|
||||||
{
|
{
|
||||||
if (_state.isSuspended())
|
try
|
||||||
{
|
{
|
||||||
try
|
if (_state.isSuspended())
|
||||||
{
|
{
|
||||||
HttpFields fields = new HttpFields();
|
HttpFields fields = new HttpFields();
|
||||||
ResponseInfo info = new ResponseInfo(_request.getHttpVersion(), fields, 0, Response.SC_INTERNAL_SERVER_ERROR, null, _request.isHead());
|
ResponseInfo info = new ResponseInfo(_request.getHttpVersion(), fields, 0, Response.SC_INTERNAL_SERVER_ERROR, null, _request.isHead());
|
||||||
|
@ -372,112 +333,20 @@ public class HttpChannel implements HttpParser.RequestHandler, Runnable
|
||||||
if (!committed)
|
if (!committed)
|
||||||
LOG.warn("Could not send response error 500, response is already committed");
|
LOG.warn("Could not send response error 500, response is already committed");
|
||||||
}
|
}
|
||||||
catch (IOException e)
|
else
|
||||||
{
|
{
|
||||||
// We tried our best, just log
|
_request.setAttribute(RequestDispatcher.ERROR_EXCEPTION,x);
|
||||||
LOG.debug("Could not commit response error 500", e);
|
_request.setAttribute(RequestDispatcher.ERROR_EXCEPTION_TYPE,x.getClass());
|
||||||
}
|
_response.sendError(500, x.getMessage());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
catch (IOException e)
|
||||||
{
|
{
|
||||||
_response.sendError(500, null, x.getMessage());
|
// We tried our best, just log
|
||||||
|
LOG.debug("Could not commit response error 500", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void sendError(ResponseInfo info, String extraContent)
|
|
||||||
{
|
|
||||||
int status = info.getStatus();
|
|
||||||
try
|
|
||||||
{
|
|
||||||
String reason = info.getReason();
|
|
||||||
if (reason == null)
|
|
||||||
reason = HttpStatus.getMessage(status);
|
|
||||||
|
|
||||||
// If we are allowed to have a body
|
|
||||||
if (status != Response.SC_NO_CONTENT &&
|
|
||||||
status != Response.SC_NOT_MODIFIED &&
|
|
||||||
status != Response.SC_PARTIAL_CONTENT &&
|
|
||||||
status >= Response.SC_OK)
|
|
||||||
{
|
|
||||||
ErrorHandler errorHandler = null;
|
|
||||||
ContextHandler.Context context = _request.getContext();
|
|
||||||
if (context != null)
|
|
||||||
errorHandler = context.getContextHandler().getErrorHandler();
|
|
||||||
if (errorHandler == null)
|
|
||||||
errorHandler = getServer().getBean(ErrorHandler.class);
|
|
||||||
if (errorHandler != null)
|
|
||||||
{
|
|
||||||
_request.setAttribute(RequestDispatcher.ERROR_STATUS_CODE, new Integer(status));
|
|
||||||
_request.setAttribute(RequestDispatcher.ERROR_MESSAGE, reason);
|
|
||||||
_request.setAttribute(RequestDispatcher.ERROR_REQUEST_URI, _request.getRequestURI());
|
|
||||||
_request.setAttribute(RequestDispatcher.ERROR_SERVLET_NAME, _request.getServletName());
|
|
||||||
errorHandler.handle(null, _request, _request, _response);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
HttpFields fields = info.getHttpFields();
|
|
||||||
fields.put(HttpHeader.CACHE_CONTROL, "must-revalidate,no-cache,no-store");
|
|
||||||
fields.put(HttpHeader.CONTENT_TYPE, MimeTypes.Type.TEXT_HTML_8859_1.toString());
|
|
||||||
|
|
||||||
reason = escape(reason);
|
|
||||||
String uri = escape(_request.getRequestURI());
|
|
||||||
extraContent = escape(extraContent);
|
|
||||||
|
|
||||||
StringBuilder writer = new StringBuilder(2048);
|
|
||||||
writer.append("<html>\n");
|
|
||||||
writer.append("<head>\n");
|
|
||||||
writer.append("<meta http-equiv=\"Content-Type\" content=\"text/html;charset=ISO-8859-1\"/>\n");
|
|
||||||
writer.append("<title>Error ").append(Integer.toString(status)).append(' ').append(reason).append("</title>\n");
|
|
||||||
writer.append("</head>\n");
|
|
||||||
writer.append("<body>\n");
|
|
||||||
writer.append("<h2>HTTP ERROR: ").append(Integer.toString(status)).append("</h2>\n");
|
|
||||||
writer.append("<p>Problem accessing ").append(uri).append(". Reason:\n");
|
|
||||||
writer.append("<pre>").append(reason).append("</pre></p>");
|
|
||||||
if (extraContent != null)
|
|
||||||
writer.append("<p>").append(extraContent).append("</p>");
|
|
||||||
writer.append("<hr /><i><small>Powered by Jetty://</small></i>\n");
|
|
||||||
writer.append("</body>\n");
|
|
||||||
writer.append("</html>");
|
|
||||||
byte[] bytes = writer.toString().getBytes(StringUtil.__ISO_8859_1);
|
|
||||||
fields.put(HttpHeader.CONTENT_LENGTH, String.valueOf(bytes.length));
|
|
||||||
_response.getOutputStream().write(bytes);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (status != Response.SC_PARTIAL_CONTENT)
|
|
||||||
{
|
|
||||||
// TODO: not sure why we need to modify the request when writing an error ?
|
|
||||||
// TODO: or modify the response if the error code cannot have a body ?
|
|
||||||
// _channel.getRequest().getHttpFields().remove(HttpHeader.CONTENT_TYPE);
|
|
||||||
// _channel.getRequest().getHttpFields().remove(HttpHeader.CONTENT_LENGTH);
|
|
||||||
// _characterEncoding = null;
|
|
||||||
// _mimeType = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
complete();
|
|
||||||
|
|
||||||
// TODO: is this needed ?
|
|
||||||
if (_state.isIdle())
|
|
||||||
_state.complete();
|
|
||||||
_request.getHttpInput().shutdown();
|
|
||||||
}
|
|
||||||
catch (IOException x)
|
|
||||||
{
|
|
||||||
// We failed to write the error, bail out
|
|
||||||
LOG.debug("Could not write error response " + status, x);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private String escape(String reason)
|
|
||||||
{
|
|
||||||
if (reason != null)
|
|
||||||
{
|
|
||||||
reason = reason.replaceAll("&", "&");
|
|
||||||
reason = reason.replaceAll("<", "<");
|
|
||||||
reason = reason.replaceAll(">", ">");
|
|
||||||
}
|
|
||||||
return reason;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isExpecting100Continue()
|
public boolean isExpecting100Continue()
|
||||||
{
|
{
|
||||||
return _expect100Continue;
|
return _expect100Continue;
|
||||||
|
@ -634,7 +503,7 @@ public class HttpChannel implements HttpParser.RequestHandler, Runnable
|
||||||
|
|
||||||
if (_expect)
|
if (_expect)
|
||||||
{
|
{
|
||||||
_response.sendError(Response.SC_EXPECTATION_FAILED, null, null);
|
badMessage(HttpStatus.EXPECTATION_FAILED_417,null);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -653,9 +522,7 @@ public class HttpChannel implements HttpParser.RequestHandler, Runnable
|
||||||
public boolean content(ByteBuffer ref)
|
public boolean content(ByteBuffer ref)
|
||||||
{
|
{
|
||||||
if (LOG.isDebugEnabled())
|
if (LOG.isDebugEnabled())
|
||||||
{
|
|
||||||
LOG.debug("{} content {}", this, BufferUtil.toDetailString(ref));
|
LOG.debug("{} content {}", this, BufferUtil.toDetailString(ref));
|
||||||
}
|
|
||||||
_request.getHttpInput().content(ref);
|
_request.getHttpInput().content(ref);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -125,46 +125,6 @@ public class HttpConnection extends AbstractConnection implements Runnable, Http
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean readAndParse() throws IOException
|
|
||||||
{
|
|
||||||
// If there is a request buffer, we are re-entering here
|
|
||||||
if (_requestBuffer == null)
|
|
||||||
{
|
|
||||||
_requestBuffer = _bufferPool.acquire(_configuration.getRequestHeaderSize(), false);
|
|
||||||
|
|
||||||
int filled = getEndPoint().fill(_requestBuffer);
|
|
||||||
|
|
||||||
LOG.debug("{} filled {}", this, filled);
|
|
||||||
|
|
||||||
// If we failed to fill
|
|
||||||
if (filled == 0)
|
|
||||||
{
|
|
||||||
// Somebody wanted to read, we didn't so schedule another attempt
|
|
||||||
releaseRequestBuffer();
|
|
||||||
fillInterested();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else if (filled < 0)
|
|
||||||
{
|
|
||||||
_parser.inputShutdown();
|
|
||||||
// We were only filling if fully consumed, so if we have
|
|
||||||
// read -1 then we have nothing to parse and thus nothing that
|
|
||||||
// will generate a response. If we had a suspended request pending
|
|
||||||
// a response or a request waiting in the buffer, we would not be here.
|
|
||||||
if (getEndPoint().isOutputShutdown())
|
|
||||||
getEndPoint().close();
|
|
||||||
else
|
|
||||||
getEndPoint().shutdownOutput();
|
|
||||||
// buffer must be empty and the channel must be idle, so we can release.
|
|
||||||
releaseRequestBuffer();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse the buffer
|
|
||||||
return _parser.parseNext(_requestBuffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>Parses and handles HTTP messages.</p>
|
* <p>Parses and handles HTTP messages.</p>
|
||||||
* <p>This method is called when this {@link Connection} is ready to read bytes from the {@link EndPoint}.
|
* <p>This method is called when this {@link Connection} is ready to read bytes from the {@link EndPoint}.
|
||||||
|
@ -183,7 +143,43 @@ public class HttpConnection extends AbstractConnection implements Runnable, Http
|
||||||
{
|
{
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
if (readAndParse())
|
// If there is a request buffer, we are re-entering here
|
||||||
|
if (BufferUtil.isEmpty(_requestBuffer))
|
||||||
|
{
|
||||||
|
if (_requestBuffer == null)
|
||||||
|
_requestBuffer = _bufferPool.acquire(_configuration.getRequestHeaderSize(), false);
|
||||||
|
|
||||||
|
int filled = getEndPoint().fill(_requestBuffer);
|
||||||
|
|
||||||
|
LOG.debug("{} filled {}", this, filled);
|
||||||
|
|
||||||
|
// If we failed to fill
|
||||||
|
if (filled == 0)
|
||||||
|
{
|
||||||
|
// Somebody wanted to read, we didn't so schedule another attempt
|
||||||
|
releaseRequestBuffer();
|
||||||
|
fillInterested();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (filled < 0)
|
||||||
|
{
|
||||||
|
_parser.inputShutdown();
|
||||||
|
// We were only filling if fully consumed, so if we have
|
||||||
|
// read -1 then we have nothing to parse and thus nothing that
|
||||||
|
// will generate a response. If we had a suspended request pending
|
||||||
|
// a response or a request waiting in the buffer, we would not be here.
|
||||||
|
if (getEndPoint().isOutputShutdown())
|
||||||
|
getEndPoint().close();
|
||||||
|
else
|
||||||
|
getEndPoint().shutdownOutput();
|
||||||
|
// buffer must be empty and the channel must be idle, so we can release.
|
||||||
|
releaseRequestBuffer();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse the buffer
|
||||||
|
if (_parser.parseNext(_requestBuffer))
|
||||||
{
|
{
|
||||||
// The parser returned true, which indicates the channel is ready to handle a request.
|
// The parser returned true, which indicates the channel is ready to handle a request.
|
||||||
// Call the channel and this will either handle the request/response to completion OR,
|
// Call the channel and this will either handle the request/response to completion OR,
|
||||||
|
@ -250,9 +246,10 @@ public class HttpConnection extends AbstractConnection implements Runnable, Http
|
||||||
// TODO This is always blocking! One of the important use-cases is to be able to write large static content without a thread
|
// TODO This is always blocking! One of the important use-cases is to be able to write large static content without a thread
|
||||||
|
|
||||||
ByteBuffer header = null;
|
ByteBuffer header = null;
|
||||||
|
ByteBuffer chunk = null;
|
||||||
out: while (true)
|
out: while (true)
|
||||||
{
|
{
|
||||||
HttpGenerator.Result result = _generator.generateResponse(info, header, content, lastContent);
|
HttpGenerator.Result result = _generator.generateResponse(info, header, chunk, content, lastContent);
|
||||||
if (LOG.isDebugEnabled())
|
if (LOG.isDebugEnabled())
|
||||||
LOG.debug("{} generate: {} ({},{},{})@{}",
|
LOG.debug("{} generate: {} ({},{},{})@{}",
|
||||||
this,
|
this,
|
||||||
|
@ -266,34 +263,40 @@ public class HttpConnection extends AbstractConnection implements Runnable, Http
|
||||||
{
|
{
|
||||||
case NEED_HEADER:
|
case NEED_HEADER:
|
||||||
{
|
{
|
||||||
if (header != null)
|
|
||||||
_bufferPool.release(header);
|
|
||||||
header = _bufferPool.acquire(_configuration.getResponseHeaderSize(), false);
|
header = _bufferPool.acquire(_configuration.getResponseHeaderSize(), false);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
case NEED_CHUNK:
|
case NEED_CHUNK:
|
||||||
{
|
{
|
||||||
if (header != null)
|
chunk = _bufferPool.acquire(HttpGenerator.CHUNK_SIZE, false);
|
||||||
_bufferPool.release(header);
|
|
||||||
header = _bufferPool.acquire(HttpGenerator.CHUNK_SIZE, false);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
case FLUSH:
|
case FLUSH:
|
||||||
{
|
{
|
||||||
|
// Don't write the chunk or the content if this is a HEAD response
|
||||||
if (_channel.getRequest().isHead())
|
if (_channel.getRequest().isHead())
|
||||||
{
|
{
|
||||||
|
BufferUtil.clear(chunk);
|
||||||
BufferUtil.clear(content);
|
BufferUtil.clear(content);
|
||||||
if (BufferUtil.hasContent(header))
|
|
||||||
blockingWrite(header);
|
|
||||||
}
|
}
|
||||||
else if (BufferUtil.hasContent(header))
|
|
||||||
|
// If we have a header
|
||||||
|
if (BufferUtil.hasContent(header))
|
||||||
{
|
{
|
||||||
|
// we know there will not be a chunk, so write either header+content or just the header
|
||||||
if (BufferUtil.hasContent(content))
|
if (BufferUtil.hasContent(content))
|
||||||
blockingWrite(header, content);
|
blockingWrite(header, content);
|
||||||
else
|
else
|
||||||
blockingWrite(header);
|
blockingWrite(header);
|
||||||
}
|
}
|
||||||
else if (BufferUtil.hasContent(content))
|
else if (BufferUtil.hasContent(chunk))
|
||||||
|
{
|
||||||
|
if (BufferUtil.hasContent(content))
|
||||||
|
blockingWrite(chunk,content);
|
||||||
|
else
|
||||||
|
blockingWrite(chunk);
|
||||||
|
}
|
||||||
|
else if (BufferUtil.hasContent(content))
|
||||||
{
|
{
|
||||||
blockingWrite(content);
|
blockingWrite(content);
|
||||||
}
|
}
|
||||||
|
@ -306,6 +309,10 @@ public class HttpConnection extends AbstractConnection implements Runnable, Http
|
||||||
}
|
}
|
||||||
case DONE:
|
case DONE:
|
||||||
{
|
{
|
||||||
|
if (header!=null)
|
||||||
|
_bufferPool.release(header);
|
||||||
|
if (chunk!=null)
|
||||||
|
_bufferPool.release(chunk);
|
||||||
break out;
|
break out;
|
||||||
}
|
}
|
||||||
case CONTINUE:
|
case CONTINUE:
|
||||||
|
@ -433,17 +440,49 @@ public class HttpConnection extends AbstractConnection implements Runnable, Http
|
||||||
@Override
|
@Override
|
||||||
protected void blockForContent() throws IOException
|
protected void blockForContent() throws IOException
|
||||||
{
|
{
|
||||||
|
/* We extend the blockForContent method to replace the
|
||||||
|
default implementation of a blocking queue with an implementation
|
||||||
|
that uses the calling thread to block on a readable callback and
|
||||||
|
then to do the parsing before before attempting the read.
|
||||||
|
*/
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
FutureCallback<Void> callback = new FutureCallback<>();
|
// Can the parser progress (even with an empty buffer)
|
||||||
getEndPoint().fillInterested(null, callback);
|
boolean event=_parser.parseNext(_requestBuffer==null?BufferUtil.EMPTY_BUFFER:_requestBuffer);
|
||||||
callback.get();
|
|
||||||
if (readAndParse())
|
// If there is more content to parse, leep so we can queue all content from this buffer now without the
|
||||||
break;
|
// need to call blockForContent again
|
||||||
else
|
while (BufferUtil.hasContent(_requestBuffer) && _parser.inContentState())
|
||||||
releaseRequestBuffer();
|
event|=_parser.parseNext(_requestBuffer);
|
||||||
|
|
||||||
|
// If we have an event, return
|
||||||
|
if (event)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Do we have content ready to parse?
|
||||||
|
if (BufferUtil.isEmpty(_requestBuffer))
|
||||||
|
{
|
||||||
|
// Wait until we can read
|
||||||
|
FutureCallback<Void> block=new FutureCallback<>();
|
||||||
|
getEndPoint().fillInterested(null,block);
|
||||||
|
LOG.debug("{} block readable on {}",this,block);
|
||||||
|
block.get();
|
||||||
|
|
||||||
|
// We will need a buffer to read into
|
||||||
|
if (_requestBuffer==null)
|
||||||
|
_requestBuffer=_bufferPool.acquire(_configuration.getRequestBufferSize(),false);
|
||||||
|
|
||||||
|
// read some data
|
||||||
|
int filled=getEndPoint().fill(_requestBuffer);
|
||||||
|
LOG.debug("{} block filled {}",this,filled);
|
||||||
|
if (filled<0)
|
||||||
|
{
|
||||||
|
_parser.inputShutdown();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (InterruptedException x)
|
catch (InterruptedException x)
|
||||||
|
@ -510,6 +549,13 @@ public class HttpConnection extends AbstractConnection implements Runnable, Http
|
||||||
_generator.setPersistent(false);
|
_generator.setPersistent(false);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void handleException(Throwable x)
|
||||||
|
{
|
||||||
|
_generator.setPersistent(false);
|
||||||
|
super.handleException(x);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -238,7 +238,10 @@ public class LocalConnector extends AbstractConnector
|
||||||
if (!_closed.await(idleFor,units))
|
if (!_closed.await(idleFor,units))
|
||||||
{
|
{
|
||||||
if (size==getOutput().remaining())
|
if (size==getOutput().remaining())
|
||||||
|
{
|
||||||
|
LOG.debug("idle for {} {}",idleFor,units);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
size=getOutput().remaining();
|
size=getOutput().remaining();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,8 @@ import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
|
import javax.servlet.RequestDispatcher;
|
||||||
import javax.servlet.ServletOutputStream;
|
import javax.servlet.ServletOutputStream;
|
||||||
import javax.servlet.http.Cookie;
|
import javax.servlet.http.Cookie;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
@ -41,6 +43,9 @@ import org.eclipse.jetty.http.HttpStatus;
|
||||||
import org.eclipse.jetty.http.HttpURI;
|
import org.eclipse.jetty.http.HttpURI;
|
||||||
import org.eclipse.jetty.http.HttpVersion;
|
import org.eclipse.jetty.http.HttpVersion;
|
||||||
import org.eclipse.jetty.http.MimeTypes;
|
import org.eclipse.jetty.http.MimeTypes;
|
||||||
|
import org.eclipse.jetty.server.handler.ContextHandler;
|
||||||
|
import org.eclipse.jetty.server.handler.ErrorHandler;
|
||||||
|
import org.eclipse.jetty.util.ByteArrayISO8859Writer;
|
||||||
import org.eclipse.jetty.util.StringUtil;
|
import org.eclipse.jetty.util.StringUtil;
|
||||||
import org.eclipse.jetty.util.URIUtil;
|
import org.eclipse.jetty.util.URIUtil;
|
||||||
import org.eclipse.jetty.util.log.Log;
|
import org.eclipse.jetty.util.log.Log;
|
||||||
|
@ -297,36 +302,102 @@ public class Response implements HttpServletResponse
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void sendError(int code, String message) throws IOException
|
public void sendError(int code, String message) throws IOException
|
||||||
{
|
|
||||||
sendError(code, message, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void sendError(int code, String message, String content)
|
|
||||||
{
|
{
|
||||||
if (isIncluding())
|
if (isIncluding())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (isCommitted())
|
if (isCommitted())
|
||||||
{
|
LOG.warn("Committed before "+code+" "+message);
|
||||||
LOG.warn("Could not commit error {} {}, response already committed", code, message);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
resetBuffer();
|
resetBuffer();
|
||||||
_characterEncoding = null;
|
_characterEncoding=null;
|
||||||
setHeader(HttpHeader.EXPIRES, null);
|
setHeader(HttpHeader.EXPIRES,null);
|
||||||
setHeader(HttpHeader.LAST_MODIFIED, null);
|
setHeader(HttpHeader.LAST_MODIFIED,null);
|
||||||
setHeader(HttpHeader.CACHE_CONTROL, null);
|
setHeader(HttpHeader.CACHE_CONTROL,null);
|
||||||
setHeader(HttpHeader.CONTENT_TYPE, null);
|
setHeader(HttpHeader.CONTENT_TYPE,null);
|
||||||
setHeader(HttpHeader.CONTENT_LENGTH, null);
|
setHeader(HttpHeader.CONTENT_LENGTH,null);
|
||||||
|
|
||||||
if (message == null)
|
|
||||||
message = HttpStatus.getMessage(code);
|
|
||||||
setStatus(code, message);
|
|
||||||
|
|
||||||
_outputType = OutputType.NONE;
|
_outputType = OutputType.NONE;
|
||||||
|
setStatus(code);
|
||||||
|
_reason=message;
|
||||||
|
|
||||||
_channel.sendError(newResponseInfo(), content);
|
if (message==null)
|
||||||
|
message=HttpStatus.getMessage(code);
|
||||||
|
|
||||||
|
// If we are allowed to have a body
|
||||||
|
if (code!=SC_NO_CONTENT &&
|
||||||
|
code!=SC_NOT_MODIFIED &&
|
||||||
|
code!=SC_PARTIAL_CONTENT &&
|
||||||
|
code>=SC_OK)
|
||||||
|
{
|
||||||
|
Request request = _channel.getRequest();
|
||||||
|
|
||||||
|
ErrorHandler error_handler = null;
|
||||||
|
ContextHandler.Context context = request.getContext();
|
||||||
|
if (context!=null)
|
||||||
|
error_handler=context.getContextHandler().getErrorHandler();
|
||||||
|
if (error_handler==null)
|
||||||
|
error_handler = _channel.getServer().getBean(ErrorHandler.class);
|
||||||
|
if (error_handler!=null)
|
||||||
|
{
|
||||||
|
request.setAttribute(RequestDispatcher.ERROR_STATUS_CODE,new Integer(code));
|
||||||
|
request.setAttribute(RequestDispatcher.ERROR_MESSAGE, message);
|
||||||
|
request.setAttribute(RequestDispatcher.ERROR_REQUEST_URI, request.getRequestURI());
|
||||||
|
request.setAttribute(RequestDispatcher.ERROR_SERVLET_NAME,request.getServletName());
|
||||||
|
error_handler.handle(null,_channel.getRequest(),_channel.getRequest(),this );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
setHeader(HttpHeader.CACHE_CONTROL, "must-revalidate,no-cache,no-store");
|
||||||
|
setContentType(MimeTypes.Type.TEXT_HTML_8859_1.toString());
|
||||||
|
ByteArrayISO8859Writer writer= new ByteArrayISO8859Writer(2048);
|
||||||
|
if (message != null)
|
||||||
|
{
|
||||||
|
message= StringUtil.replace(message, "&", "&");
|
||||||
|
message= StringUtil.replace(message, "<", "<");
|
||||||
|
message= StringUtil.replace(message, ">", ">");
|
||||||
|
}
|
||||||
|
String uri= request.getRequestURI();
|
||||||
|
if (uri!=null)
|
||||||
|
{
|
||||||
|
uri= StringUtil.replace(uri, "&", "&");
|
||||||
|
uri= StringUtil.replace(uri, "<", "<");
|
||||||
|
uri= StringUtil.replace(uri, ">", ">");
|
||||||
|
}
|
||||||
|
|
||||||
|
writer.write("<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html;charset=ISO-8859-1\"/>\n");
|
||||||
|
writer.write("<title>Error ");
|
||||||
|
writer.write(Integer.toString(code));
|
||||||
|
writer.write(' ');
|
||||||
|
if (message==null)
|
||||||
|
message=HttpStatus.getMessage(code);
|
||||||
|
writer.write(message);
|
||||||
|
writer.write("</title>\n</head>\n<body>\n<h2>HTTP ERROR: ");
|
||||||
|
writer.write(Integer.toString(code));
|
||||||
|
writer.write("</h2>\n<p>Problem accessing ");
|
||||||
|
writer.write(uri);
|
||||||
|
writer.write(". Reason:\n<pre> ");
|
||||||
|
writer.write(message);
|
||||||
|
writer.write("</pre>");
|
||||||
|
writer.write("</p>\n<hr /><i><small>Powered by Jetty://</small></i>");
|
||||||
|
writer.write("\n</body>\n</html>\n");
|
||||||
|
|
||||||
|
writer.flush();
|
||||||
|
setContentLength(writer.size());
|
||||||
|
writer.writeTo(getOutputStream());
|
||||||
|
writer.destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (code!=SC_PARTIAL_CONTENT)
|
||||||
|
{
|
||||||
|
// TODO work out why this is required?
|
||||||
|
_channel.getRequest().getHttpFields().remove(HttpHeader.CONTENT_TYPE);
|
||||||
|
_channel.getRequest().getHttpFields().remove(HttpHeader.CONTENT_LENGTH);
|
||||||
|
_characterEncoding=null;
|
||||||
|
_mimeType=null;
|
||||||
|
}
|
||||||
|
|
||||||
|
complete();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -530,7 +601,10 @@ public class Response implements HttpServletResponse
|
||||||
@Override
|
@Override
|
||||||
public void setStatus(int sc)
|
public void setStatus(int sc)
|
||||||
{
|
{
|
||||||
setStatus(sc, null);
|
if (sc <= 0)
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
if (!isIncluding())
|
||||||
|
_status = sc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -351,10 +351,13 @@ public class Server extends HandlerWrapper implements Attributes
|
||||||
|
|
||||||
for (Connector connector : _connectors)
|
for (Connector connector : _connectors)
|
||||||
{
|
{
|
||||||
while (connector.getStatistics().isRunning() && connector.getStatistics().getConnectionsOpen()>0 && System.currentTimeMillis()<stop_by)
|
if (connector.getStatistics().isRunning() && connector.getStatistics().getConnectionsOpen()>0 && System.currentTimeMillis()<stop_by)
|
||||||
{
|
{
|
||||||
System.err.println(((Dumpable)connector).dump());
|
if (LOG.isDebugEnabled())
|
||||||
Thread.sleep(100);
|
System.err.println(((Dumpable)connector).dump());
|
||||||
|
LOG.info("Waiting for connections to close on {}...",connector);
|
||||||
|
while (connector.getStatistics().isRunning() && connector.getStatistics().getConnectionsOpen()>0 && System.currentTimeMillis()<stop_by)
|
||||||
|
Thread.sleep(100);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -321,7 +321,8 @@ public class HttpConnectionTest
|
||||||
int offset=0;
|
int offset=0;
|
||||||
|
|
||||||
offset=0;
|
offset=0;
|
||||||
requests="GET /R1?read=1&error=500 HTTP/1.1\n"+
|
requests=
|
||||||
|
"GET /R1?read=1&error=500 HTTP/1.1\n"+
|
||||||
"Host: localhost\n"+
|
"Host: localhost\n"+
|
||||||
"Transfer-Encoding: chunked\n"+
|
"Transfer-Encoding: chunked\n"+
|
||||||
"Content-Type: text/plain; charset=utf-8\n"+
|
"Content-Type: text/plain; charset=utf-8\n"+
|
||||||
|
@ -340,12 +341,12 @@ public class HttpConnectionTest
|
||||||
"abcdefghij\n";
|
"abcdefghij\n";
|
||||||
|
|
||||||
response=connector.getResponses(requests);
|
response=connector.getResponses(requests);
|
||||||
|
|
||||||
offset = checkContains(response,offset,"HTTP/1.1 500");
|
offset = checkContains(response,offset,"HTTP/1.1 500");
|
||||||
offset = checkContains(response,offset,"HTTP/1.1 200");
|
offset = checkContains(response,offset,"HTTP/1.1 200");
|
||||||
offset = checkContains(response,offset,"/R2");
|
offset = checkContains(response,offset,"/R2");
|
||||||
offset = checkContains(response,offset,"encoding=UTF-8");
|
offset = checkContains(response,offset,"encoding=UTF-8");
|
||||||
offset = checkContains(response,offset,"abcdefghij");
|
offset = checkContains(response,offset,"abcdefghij");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -376,7 +377,7 @@ public class HttpConnectionTest
|
||||||
Logger logger = Log.getLogger(HttpChannel.class);
|
Logger logger = Log.getLogger(HttpChannel.class);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
logger.info("EXPECTING: java.lang.IllegalStateException...");
|
logger.info("EXPECTING: java.lang.IllegalStateException...");
|
||||||
((StdErrLog)logger).setHideStacks(true);
|
((StdErrLog)logger).setHideStacks(true);
|
||||||
response=connector.getResponses(requests);
|
response=connector.getResponses(requests);
|
||||||
offset = checkContains(response,offset,"HTTP/1.1 500");
|
offset = checkContains(response,offset,"HTTP/1.1 500");
|
||||||
|
|
|
@ -379,6 +379,7 @@ public class RequestTest
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
String content="";
|
String content="";
|
||||||
|
|
||||||
for (int l=0;l<1025;l++)
|
for (int l=0;l<1025;l++)
|
||||||
|
@ -390,7 +391,9 @@ public class RequestTest
|
||||||
"Connection: close\r\n"+
|
"Connection: close\r\n"+
|
||||||
"\r\n"+
|
"\r\n"+
|
||||||
content;
|
content;
|
||||||
|
Log.getRootLogger().debug("test l={}",l);
|
||||||
String response = _connector.getResponses(request);
|
String response = _connector.getResponses(request);
|
||||||
|
Log.getRootLogger().debug(response);
|
||||||
assertEquals(l,length[0]);
|
assertEquals(l,length[0]);
|
||||||
if (l>0)
|
if (l>0)
|
||||||
assertEquals(l,_handler._content.length());
|
assertEquals(l,_handler._content.length());
|
||||||
|
|
|
@ -47,6 +47,7 @@ import org.eclipse.jetty.server.session.HashSessionIdManager;
|
||||||
import org.eclipse.jetty.server.session.HashSessionManager;
|
import org.eclipse.jetty.server.session.HashSessionManager;
|
||||||
import org.eclipse.jetty.server.session.HashedSession;
|
import org.eclipse.jetty.server.session.HashedSession;
|
||||||
import org.eclipse.jetty.util.FutureCallback;
|
import org.eclipse.jetty.util.FutureCallback;
|
||||||
|
import org.eclipse.jetty.util.IO;
|
||||||
import org.hamcrest.Matchers;
|
import org.hamcrest.Matchers;
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
|
@ -103,35 +104,14 @@ public class ResponseTest
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
_channel = new HttpChannel(_connector,null,endp,null,null)
|
_channel = new HttpChannel(_connector,new HttpConfiguration(null,false),endp,null,null)
|
||||||
{
|
{
|
||||||
// @Override
|
|
||||||
protected void flush(ByteBuffer content, boolean last) throws IOException
|
|
||||||
{
|
|
||||||
content.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Override
|
|
||||||
protected FutureCallback<Void> write(ResponseInfo info, ByteBuffer content) throws IOException
|
|
||||||
{
|
|
||||||
content.clear();
|
|
||||||
FutureCallback<Void> fcb = new FutureCallback<>();
|
|
||||||
fcb.completed(null);
|
|
||||||
return fcb;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ScheduledExecutorService getScheduler()
|
public ScheduledExecutorService getScheduler()
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public HttpConfiguration getHttpConfiguration()
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void execute(Runnable task)
|
protected void execute(Runnable task)
|
||||||
{
|
{
|
||||||
|
|
|
@ -104,8 +104,11 @@ public class BufferUtil
|
||||||
*/
|
*/
|
||||||
public static void clear(ByteBuffer buffer)
|
public static void clear(ByteBuffer buffer)
|
||||||
{
|
{
|
||||||
buffer.position(0);
|
if (buffer!=null)
|
||||||
buffer.limit(0);
|
{
|
||||||
|
buffer.position(0);
|
||||||
|
buffer.limit(0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
/* ------------------------------------------------------------ */
|
||||||
|
|
Loading…
Reference in New Issue