jetty-9: HTTP client: fixed problem when idle connections were closed remotely: the local connection was not closed.

This commit is contained in:
Simone Bordet 2012-10-12 11:38:14 +02:00
parent 707acbeed7
commit 6159d6f268
3 changed files with 71 additions and 3 deletions

View File

@ -286,8 +286,15 @@ public class HttpConnection extends AbstractConnection implements Connection
{
HttpExchange exchange = getExchange();
if (exchange != null)
{
exchange.receive();
// If there is no exchange, we just ignore because the selector may be woken up by a remote close
}
else
{
// If there is no exchange, then could be either a remote close,
// or garbage bytes; in both cases we close the connection
close();
}
}
protected void receive()
@ -314,7 +321,6 @@ public class HttpConnection extends AbstractConnection implements Connection
{
if ("close".equalsIgnoreCase(values.nextElement()))
{
destination.remove(this);
close();
return;
}
@ -324,7 +330,6 @@ public class HttpConnection extends AbstractConnection implements Connection
}
else
{
destination.remove(this);
close();
}
}
@ -356,6 +361,7 @@ public class HttpConnection extends AbstractConnection implements Connection
@Override
public void close()
{
destination.remove(this);
getEndPoint().shutdownOutput();
LOG.debug("{} oshut", this);
getEndPoint().close();

View File

@ -25,6 +25,7 @@ import org.eclipse.jetty.client.api.ContentResponse;
import org.eclipse.jetty.client.api.Destination;
import org.eclipse.jetty.client.api.Request;
import org.eclipse.jetty.client.util.BlockingResponseListener;
import org.eclipse.jetty.toolchain.test.annotation.Slow;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.junit.Assert;
import org.junit.Test;
@ -57,4 +58,32 @@ public class HttpClientExplicitConnectionTest extends AbstractHttpClientServerTe
Assert.assertTrue(httpDestination.getIdleConnections().isEmpty());
}
}
@Slow
@Test
public void testExplicitConnectionIsClosedOnRemoteClose() throws Exception
{
start(new EmptyServerHandler());
Destination destination = client.getDestination(scheme, "localhost", connector.getLocalPort());
Connection connection = destination.newConnection().get(5, TimeUnit.SECONDS);
Request request = client.newRequest(destination.host(), destination.port()).scheme(scheme);
BlockingResponseListener listener = new BlockingResponseListener();
connection.send(request, listener);
ContentResponse response = listener.get(5, TimeUnit.SECONDS);
Assert.assertEquals(200, response.status());
connector.stop();
// Give the connection some time to process the remote close
TimeUnit.SECONDS.sleep(1);
HttpConnection httpConnection = (HttpConnection)connection;
Assert.assertFalse(httpConnection.getEndPoint().isOpen());
HttpDestination httpDestination = (HttpDestination)destination;
Assert.assertTrue(httpDestination.getActiveConnections().isEmpty());
Assert.assertTrue(httpDestination.getIdleConnections().isEmpty());
}
}

View File

@ -28,6 +28,7 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.client.api.Connection;
import org.eclipse.jetty.client.api.ContentResponse;
import org.eclipse.jetty.client.api.Request;
import org.eclipse.jetty.client.api.Response;
import org.eclipse.jetty.client.api.Result;
@ -427,4 +428,36 @@ public class HttpConnectionLifecycleTest extends AbstractHttpClientServerTest
logger.setHideStacks(false);
}
}
@Slow
@Test
public void test_IdleConnection_IsClosed_OnRemoteClose() throws Exception
{
start(new EmptyServerHandler());
String host = "localhost";
int port = connector.getLocalPort();
HttpDestination destination = (HttpDestination)client.getDestination(scheme, host, port);
final BlockingQueue<Connection> idleConnections = destination.getIdleConnections();
Assert.assertEquals(0, idleConnections.size());
final BlockingQueue<Connection> activeConnections = destination.getActiveConnections();
Assert.assertEquals(0, activeConnections.size());
ContentResponse response = client.newRequest(host, port)
.scheme(scheme)
.send()
.get(5, TimeUnit.SECONDS);
Assert.assertEquals(200, response.status());
connector.stop();
// Give the connection some time to process the remote close
TimeUnit.SECONDS.sleep(1);
Assert.assertEquals(0, idleConnections.size());
Assert.assertEquals(0, activeConnections.size());
}
}