jetty-9 passing timeout tests
This commit is contained in:
parent
b8517abb14
commit
294150f485
|
@ -18,6 +18,7 @@ import java.nio.ByteBuffer;
|
|||
|
||||
import org.eclipse.jetty.http.HttpTokens.EndOfContent;
|
||||
import org.eclipse.jetty.io.EofException;
|
||||
import org.eclipse.jetty.io.RuntimeIOException;
|
||||
import org.eclipse.jetty.util.BufferUtil;
|
||||
import org.eclipse.jetty.util.StringUtil;
|
||||
import org.eclipse.jetty.util.Utf8StringBuilder;
|
||||
|
@ -870,7 +871,16 @@ public class HttpParser
|
|||
return false;
|
||||
|
||||
case CLOSED:
|
||||
int count=0;
|
||||
while (BufferUtil.hasContent(buffer))
|
||||
{
|
||||
byte b=buffer.get();
|
||||
if (!Character.isWhitespace((char)b) || count++>4)
|
||||
{
|
||||
BufferUtil.clear(buffer);
|
||||
throw new IOException("Illegal characters");
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1049,6 +1059,12 @@ public class HttpParser
|
|||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
if (isClosed())
|
||||
{
|
||||
LOG.debug(e);
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
|
||||
LOG.warn(e);
|
||||
_handler.badMessage(e.toString());
|
||||
return true;
|
||||
|
|
|
@ -393,7 +393,13 @@ public abstract class HttpChannel
|
|||
|
||||
if (!_response.isCommitted() && !_request.isHandled())
|
||||
_response.sendError(404);
|
||||
|
||||
// Complete reading the request
|
||||
_in.consumeAll();
|
||||
|
||||
// Complete generating the response
|
||||
_response.complete();
|
||||
|
||||
}
|
||||
catch(IOException e)
|
||||
{
|
||||
|
@ -497,8 +503,9 @@ public abstract class HttpChannel
|
|||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return String.format("%s{r=%d,a=%s}",
|
||||
super.toString(),
|
||||
return String.format("%s@%x{r=%d,a=%s}",
|
||||
getClass().getSimpleName(),
|
||||
hashCode(),
|
||||
_requests,
|
||||
_state.getState());
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@ import org.eclipse.jetty.util.log.Logger;
|
|||
*/
|
||||
public class HttpConnection extends AbstractAsyncConnection
|
||||
{
|
||||
private static final Logger LOG = Log.getLogger(HttpConnection.class);
|
||||
public static final Logger LOG = Log.getLogger(HttpConnection.class);
|
||||
|
||||
private static final ThreadLocal<HttpConnection> __currentConnection = new ThreadLocal<HttpConnection>();
|
||||
|
||||
|
@ -273,6 +273,9 @@ public class HttpConnection extends AbstractAsyncConnection
|
|||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
if (_parser.isClosed())
|
||||
LOG.debug(e);
|
||||
else
|
||||
LOG.warn(e);
|
||||
getEndPoint().close();
|
||||
}
|
||||
|
@ -282,6 +285,14 @@ public class HttpConnection extends AbstractAsyncConnection
|
|||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
@Override
|
||||
public void onReadFail(Throwable cause)
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
super.onReadFail(cause);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
@Override
|
||||
public void onClose()
|
||||
|
@ -383,15 +394,16 @@ public class HttpConnection extends AbstractAsyncConnection
|
|||
@Override
|
||||
protected void completed()
|
||||
{
|
||||
// This is called by HttpChannel#process when it knows that it's handling of the request/response cycle
|
||||
// is complete. This may be in the original thread dispatched to the connection that has called process from
|
||||
// the connection#onReadable method, or it may be from a thread dispatched to call process as the result
|
||||
// of a resumed suspended request.
|
||||
// At this point the HttpChannel will have completed the generation of any response (although it might remain to
|
||||
// be asynchronously flushed TBD), but it may not have consumed the entire
|
||||
|
||||
LOG.debug("{} completed");
|
||||
|
||||
// parser should be either complete or can be completed with single call
|
||||
if (!_parser.isComplete())
|
||||
{
|
||||
// TODO make this much more efficient
|
||||
_httpInput.consumeAll();
|
||||
}
|
||||
|
||||
// Reset everything for the next cycle.
|
||||
HttpConnection.this.reset();
|
||||
|
||||
// if the onReadable method is not executing
|
||||
|
@ -719,15 +731,16 @@ public class HttpConnection extends AbstractAsyncConnection
|
|||
}
|
||||
}
|
||||
|
||||
protected void consumeAll()
|
||||
@Override
|
||||
public void consumeAll()
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
synchronized (_inputQ)
|
||||
synchronized (_inputQ.lock())
|
||||
{
|
||||
_inputQ.clear();
|
||||
}
|
||||
if (_parser.isComplete())
|
||||
if (_parser.isComplete() || _parser.isClosed())
|
||||
return;
|
||||
try
|
||||
{
|
||||
|
|
|
@ -21,6 +21,8 @@ import javax.servlet.ServletInputStream;
|
|||
|
||||
import org.eclipse.jetty.util.ArrayQueue;
|
||||
import org.eclipse.jetty.util.BufferUtil;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
|
||||
|
||||
|
||||
|
@ -37,6 +39,8 @@ import org.eclipse.jetty.util.BufferUtil;
|
|||
*/
|
||||
public abstract class HttpInput extends ServletInputStream
|
||||
{
|
||||
private static final Logger LOG = Log.getLogger(HttpInput.class);
|
||||
|
||||
protected final byte[] _oneByte=new byte[1];
|
||||
protected final ArrayQueue<ByteBuffer> _inputQ=new ArrayQueue<>();
|
||||
private ByteBuffer _content;
|
||||
|
@ -50,7 +54,7 @@ public abstract class HttpInput extends ServletInputStream
|
|||
/* ------------------------------------------------------------ */
|
||||
public void recycle()
|
||||
{
|
||||
synchronized (_inputQ)
|
||||
synchronized (_inputQ.lock())
|
||||
{
|
||||
_inputEOF=false;
|
||||
|
||||
|
@ -179,4 +183,25 @@ public abstract class HttpInput extends ServletInputStream
|
|||
_inputEOF=true;
|
||||
}
|
||||
}
|
||||
|
||||
public void consumeAll()
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
synchronized (_inputQ.lock())
|
||||
{
|
||||
_inputQ.clear();
|
||||
}
|
||||
if (_inputEOF)
|
||||
return;
|
||||
try
|
||||
{
|
||||
blockForContent();
|
||||
}
|
||||
catch(IOException e)
|
||||
{
|
||||
LOG.warn(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,12 +34,13 @@ import org.eclipse.jetty.io.EndPoint;
|
|||
import org.eclipse.jetty.io.ssl.SslConnection;
|
||||
import org.eclipse.jetty.server.handler.AbstractHandler;
|
||||
import org.eclipse.jetty.util.IO;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
public abstract class ConnectorTimeoutTest extends HttpServerTestFixture
|
||||
{
|
||||
protected static final int MAX_IDLE_TIME=250;
|
||||
protected static final int MAX_IDLE_TIME=500;
|
||||
private int sleepTime = MAX_IDLE_TIME + MAX_IDLE_TIME/5;
|
||||
private int minimumTestRuntime = MAX_IDLE_TIME-MAX_IDLE_TIME/5;
|
||||
private int maximumTestRuntime = MAX_IDLE_TIME*10;
|
||||
|
@ -150,7 +151,7 @@ public abstract class ConnectorTimeoutTest extends HttpServerTestFixture
|
|||
// Get the server side endpoint
|
||||
EndPoint endp = endpoint.exchange(null,10,TimeUnit.SECONDS);
|
||||
if (endp instanceof SslConnection.ApplicationEndPoint)
|
||||
endp=((SslConnection.ApplicationEndPoint)endp).getEndpoint();
|
||||
endp=((SslConnection.ApplicationEndPoint)endp).getAsyncConnection().getEndPoint();
|
||||
|
||||
// read the response
|
||||
String result=IO.toString(is);
|
||||
|
@ -160,7 +161,7 @@ public abstract class ConnectorTimeoutTest extends HttpServerTestFixture
|
|||
assertEquals(-1, is.read());
|
||||
|
||||
// wait for idle timeout
|
||||
TimeUnit.MILLISECONDS.sleep(MAX_IDLE_TIME+MAX_IDLE_TIME/2);
|
||||
TimeUnit.MILLISECONDS.sleep(3*MAX_IDLE_TIME);
|
||||
|
||||
|
||||
// further writes will get broken pipe or similar
|
||||
|
@ -185,6 +186,75 @@ public abstract class ConnectorTimeoutTest extends HttpServerTestFixture
|
|||
Assert.assertFalse(endp.isOpen());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMaxIdleWithRequest10ClientIgnoresClose() throws Exception
|
||||
{
|
||||
final Exchanger<EndPoint> endpoint = new Exchanger<EndPoint>();
|
||||
configureServer(new HelloWorldHandler()
|
||||
{
|
||||
@Override
|
||||
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException,
|
||||
ServletException
|
||||
{
|
||||
try
|
||||
{
|
||||
endpoint.exchange(baseRequest.getHttpChannel().getConnection().getEndPoint());
|
||||
}
|
||||
catch(Exception e)
|
||||
{}
|
||||
super.handle(target,baseRequest,request,response);
|
||||
}
|
||||
|
||||
});
|
||||
Socket client=newSocket(HOST,_connector.getLocalPort());
|
||||
client.setSoTimeout(10000);
|
||||
|
||||
assertFalse(client.isClosed());
|
||||
|
||||
OutputStream os=client.getOutputStream();
|
||||
InputStream is=client.getInputStream();
|
||||
|
||||
os.write((
|
||||
"GET / HTTP/1.0\r\n"+
|
||||
"host: "+HOST+":"+_connector.getLocalPort()+"\r\n"+
|
||||
"connection: close\r\n"+
|
||||
"\r\n").getBytes("utf-8"));
|
||||
os.flush();
|
||||
|
||||
// Get the server side endpoint
|
||||
EndPoint endp = endpoint.exchange(null,10,TimeUnit.SECONDS);
|
||||
if (endp instanceof SslConnection.ApplicationEndPoint)
|
||||
endp=((SslConnection.ApplicationEndPoint)endp).getAsyncConnection().getEndPoint();
|
||||
|
||||
// read the response
|
||||
String result=IO.toString(is);
|
||||
Assert.assertThat("OK",result,containsString("200 OK"));
|
||||
|
||||
// check client reads EOF
|
||||
assertEquals(-1, is.read());
|
||||
|
||||
// further writes will get broken pipe or similar
|
||||
try
|
||||
{
|
||||
for (int i=0;i<1000;i++)
|
||||
{
|
||||
os.write((
|
||||
"GET / HTTP/1.0\r\n"+
|
||||
"host: "+HOST+":"+_connector.getLocalPort()+"\r\n"+
|
||||
"connection: keep-alive\r\n"+
|
||||
"\r\n").getBytes("utf-8"));
|
||||
os.flush();
|
||||
}
|
||||
Assert.fail("half close should have timed out");
|
||||
}
|
||||
catch(SocketException e)
|
||||
{
|
||||
// expected
|
||||
}
|
||||
// check the server side is closed
|
||||
Assert.assertFalse(endp.isOpen());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMaxIdleWithRequest11NoClientClose() throws Exception
|
||||
{
|
||||
|
@ -234,7 +304,7 @@ public abstract class ConnectorTimeoutTest extends HttpServerTestFixture
|
|||
// check client reads EOF
|
||||
assertEquals(-1, is.read());
|
||||
|
||||
TimeUnit.MILLISECONDS.sleep(MAX_IDLE_TIME+MAX_IDLE_TIME/2);
|
||||
TimeUnit.MILLISECONDS.sleep(3*MAX_IDLE_TIME);
|
||||
|
||||
|
||||
// further writes will get broken pipe or similar
|
||||
|
|
|
@ -1014,6 +1014,7 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
|
|||
{
|
||||
public EndPoint _endp;
|
||||
|
||||
@Override
|
||||
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
|
||||
{
|
||||
_endp=baseRequest.getHttpChannel().getConnection().getEndPoint();
|
||||
|
@ -1032,6 +1033,7 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
|
|||
{
|
||||
public Exchanger<Object> _ex = new Exchanger<Object>();
|
||||
|
||||
@Override
|
||||
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
|
||||
{
|
||||
baseRequest.setHandled(true);
|
||||
|
|
|
@ -332,7 +332,7 @@ public class StdErrLog extends AbstractLogger
|
|||
|
||||
for (Logger log : Log.getLoggers().values())
|
||||
{
|
||||
if (log instanceof StdErrLog)
|
||||
if (log.getName().startsWith(getName()) && log instanceof StdErrLog)
|
||||
((StdErrLog)log).setLevel(LEVEL_DEBUG);
|
||||
}
|
||||
}
|
||||
|
@ -342,7 +342,7 @@ public class StdErrLog extends AbstractLogger
|
|||
|
||||
for (Logger log : Log.getLoggers().values())
|
||||
{
|
||||
if (log instanceof StdErrLog)
|
||||
if (log.getName().startsWith(getName()) && log instanceof StdErrLog)
|
||||
((StdErrLog)log).setLevel(((StdErrLog)log)._configuredLevel);
|
||||
}
|
||||
}
|
||||
|
@ -574,6 +574,10 @@ public class StdErrLog extends AbstractLogger
|
|||
logger.setSource(_source);
|
||||
logger._stderr = this._stderr;
|
||||
|
||||
// Force the child to have any programmatic configuration
|
||||
if (_level!=_configuredLevel)
|
||||
logger._level=_level;
|
||||
|
||||
return logger;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue