Merged branch 'jetty-9.3.x' into 'master'.

This commit is contained in:
Simone Bordet 2016-04-11 19:39:04 +02:00
commit e2f252f817
6 changed files with 152 additions and 21 deletions

View File

@ -146,17 +146,16 @@ public class HttpConnectionOverHTTP extends AbstractConnection implements Connec
{
if (closed.compareAndSet(false, true))
{
// First close then abort, to be sure that the connection cannot be reused
// from an onFailure() handler or by blocking code waiting for completion.
getHttpDestination().close(this);
abort(failure);
getEndPoint().shutdownOutput();
if (LOG.isDebugEnabled())
LOG.debug("Shutdown {}", this);
getEndPoint().close();
if (LOG.isDebugEnabled())
LOG.debug("Closed {}", this);
abort(failure);
}
}

View File

@ -32,9 +32,11 @@ import org.junit.After;
import org.junit.Assert;
import org.junit.Assume;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
@Ignore
public class ExternalSiteTest
{
@Rule

View File

@ -223,17 +223,16 @@ public class HttpConnectionOverFCGI extends AbstractConnection implements Connec
{
if (closed.compareAndSet(false, true))
{
// First close then abort, to be sure that the connection cannot be reused
// from an onFailure() handler or by blocking code waiting for completion.
getHttpDestination().close(this);
abort(failure);
getEndPoint().shutdownOutput();
if (LOG.isDebugEnabled())
LOG.debug("Shutdown {}", this);
getEndPoint().close();
if (LOG.isDebugEnabled())
LOG.debug("Closed {}", this);
abort(failure);
}
}

View File

@ -20,6 +20,7 @@ package org.eclipse.jetty.http2.client.http;
import java.nio.channels.AsynchronousCloseException;
import java.util.Set;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
@ -77,6 +78,15 @@ public class HttpConnectionOverHTTP2 extends HttpConnection implements Sweeper.S
getHttpDestination().release(this);
}
@Override
public boolean onIdleTimeout(long idleTimeout)
{
boolean close = super.onIdleTimeout(idleTimeout);
if (close)
close(new TimeoutException("idle_timeout"));
return false;
}
public boolean isClosed()
{
return closed.get();
@ -92,11 +102,11 @@ public class HttpConnectionOverHTTP2 extends HttpConnection implements Sweeper.S
{
if (closed.compareAndSet(false, true))
{
// First close then abort, to be sure that the connection cannot be reused
// from an onFailure() handler or by blocking code waiting for completion.
getHttpDestination().close(this);
session.close(ErrorCode.NO_ERROR.code, failure.getMessage(), Callback.NOOP);
abort(failure);
session.close(ErrorCode.NO_ERROR.code, failure.getMessage(), Callback.NOOP);
}
}

View File

@ -313,6 +313,83 @@ public class HttpClientTransportOverHTTP2Test extends AbstractTest
Assert.assertEquals(HttpStatus.OK_200, response.getStatus());
}
@Test
public void testConnectionIdleTimeoutSendsResetFrame() throws Exception
{
long idleTimeout = 1000;
CountDownLatch resetLatch = new CountDownLatch(1);
start(new ServerSessionListener.Adapter()
{
@Override
public Stream.Listener onNewStream(Stream stream, HeadersFrame frame)
{
return new Stream.Listener.Adapter()
{
@Override
public void onReset(Stream stream, ResetFrame frame)
{
resetLatch.countDown();
}
};
}
});
client.stop();
client.setIdleTimeout(idleTimeout);
client.start();
try
{
client.newRequest("localhost", connector.getLocalPort())
// Make sure the connection idle times out, not the stream.
.idleTimeout(2 * idleTimeout, TimeUnit.MILLISECONDS)
.send();
Assert.fail();
}
catch (ExecutionException e)
{
// Expected.
}
Assert.assertTrue(resetLatch.await(5, TimeUnit.SECONDS));
}
@Test
public void testRequestIdleTimeoutSendsResetFrame() throws Exception
{
CountDownLatch resetLatch = new CountDownLatch(1);
start(new ServerSessionListener.Adapter()
{
@Override
public Stream.Listener onNewStream(Stream stream, HeadersFrame frame)
{
return new Stream.Listener.Adapter()
{
@Override
public void onReset(Stream stream, ResetFrame frame)
{
resetLatch.countDown();
}
};
}
});
try
{
long idleTimeout = 1000;
client.newRequest("localhost", connector.getLocalPort())
.idleTimeout(idleTimeout, TimeUnit.MILLISECONDS)
.send();
Assert.fail();
}
catch (ExecutionException e)
{
// Expected.
}
Assert.assertTrue(resetLatch.await(5, TimeUnit.SECONDS));
}
@Ignore
@Test
public void testExternalServer() throws Exception

View File

@ -52,8 +52,11 @@ public class HttpClientIdleTimeoutTest extends AbstractTest
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
{
baseRequest.setHandled(true);
AsyncContext asyncContext = request.startAsync();
asyncContext.setTimeout(0);
if (target.equals("/timeout"))
{
AsyncContext asyncContext = request.startAsync();
asyncContext.setTimeout(0);
}
}
});
client.stop();
@ -61,13 +64,19 @@ public class HttpClientIdleTimeoutTest extends AbstractTest
client.start();
final CountDownLatch latch = new CountDownLatch(1);
client.newRequest(newURI()).send(result ->
{
if (result.isFailed())
latch.countDown();
});
client.newRequest(newURI())
.path("/timeout")
.send(result ->
{
if (result.isFailed())
latch.countDown();
});
Assert.assertTrue(latch.await(2 * idleTimeout, TimeUnit.MILLISECONDS));
// Verify that after the timeout we can make another request.
ContentResponse response = client.newRequest(newURI()).send();
Assert.assertEquals(HttpStatus.OK_200, response.getStatus());
}
@Test
@ -79,13 +88,17 @@ public class HttpClientIdleTimeoutTest extends AbstractTest
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
{
baseRequest.setHandled(true);
AsyncContext asyncContext = request.startAsync();
asyncContext.setTimeout(0);
if (target.equals("/timeout"))
{
AsyncContext asyncContext = request.startAsync();
asyncContext.setTimeout(0);
}
}
});
final CountDownLatch latch = new CountDownLatch(1);
client.newRequest(newURI())
.path("/timeout")
.idleTimeout(idleTimeout, TimeUnit.MILLISECONDS)
.send(result ->
{
@ -94,10 +107,41 @@ public class HttpClientIdleTimeoutTest extends AbstractTest
});
Assert.assertTrue(latch.await(2 * idleTimeout, TimeUnit.MILLISECONDS));
// Verify that after the timeout we can make another request.
ContentResponse response = client.newRequest(newURI()).send();
Assert.assertEquals(HttpStatus.OK_200, response.getStatus());
}
@Test
public void testServerIdleTimeout() throws Exception
public void testIdleClientIdleTimeout() throws Exception
{
start(new AbstractHandler()
{
@Override
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
{
baseRequest.setHandled(true);
}
});
client.stop();
client.setIdleTimeout(idleTimeout);
client.start();
// Make a first request to open a connection.
ContentResponse response = client.newRequest(newURI()).send();
Assert.assertEquals(HttpStatus.OK_200, response.getStatus());
// Let the connection idle timeout.
Thread.sleep(2 * idleTimeout);
// Verify that after the timeout we can make another request.
response = client.newRequest(newURI()).send();
Assert.assertEquals(HttpStatus.OK_200, response.getStatus());
}
@Test
public void testIdleServerIdleTimeout() throws Exception
{
start(new AbstractHandler()
{