use of io.undertow.client.ClientConnection in project undertow by undertow-io.
the class ProxyConnectionPool method returnConnection.
/**
* Called when the IO thread has completed a successful request
*
* @param connectionHolder The client connection holder
*/
private void returnConnection(final ConnectionHolder connectionHolder) {
ClientStatistics stats = connectionHolder.clientConnection.getStatistics();
this.requestCount.incrementAndGet();
if (stats != null) {
// we update the stats when the connection is closed
this.read.addAndGet(stats.getRead());
this.written.addAndGet(stats.getWritten());
stats.reset();
}
HostThreadData hostData = getData();
if (closed) {
// the host has been closed
IoUtils.safeClose(connectionHolder.clientConnection);
ConnectionHolder con = hostData.availableConnections.poll();
while (con != null) {
IoUtils.safeClose(con.clientConnection);
con = hostData.availableConnections.poll();
}
redistributeQueued(hostData);
return;
}
// only do something if the connection is open. If it is closed then
// the close setter will handle creating a new connection and decrementing
// the connection count
final ClientConnection connection = connectionHolder.clientConnection;
if (connection.isOpen() && !connection.isUpgraded()) {
CallbackHolder callback = hostData.awaitingConnections.poll();
while (callback != null && callback.isCancelled()) {
callback = hostData.awaitingConnections.poll();
}
if (callback != null) {
if (callback.getTimeoutKey() != null) {
callback.getTimeoutKey().remove();
}
// Anything waiting for a connection is not expecting exclusivity.
connectionReady(connectionHolder, callback.getCallback(), callback.getExchange(), false);
} else {
final int cachedConnectionCount = hostData.availableConnections.size();
if (cachedConnectionCount >= maxCachedConnections) {
// Close the longest idle connection instead of the current one
final ConnectionHolder holder = hostData.availableConnections.poll();
if (holder != null) {
IoUtils.safeClose(holder.clientConnection);
}
}
hostData.availableConnections.add(connectionHolder);
// If the soft max and ttl are configured
if (timeToLive > 0) {
// we only start the timeout process once we have hit the core pool size
// otherwise connections could start timing out immediately once the core pool size is hit
// and if we never hit the core pool size then it does not make sense to start timers which are never
// used (as timers are expensive)
final long currentTime = System.currentTimeMillis();
connectionHolder.timeout = currentTime + timeToLive;
if (hostData.availableConnections.size() > coreCachedConnections) {
if (hostData.nextTimeout <= 0) {
hostData.timeoutKey = WorkerUtils.executeAfter(connection.getIoThread(), hostData.timeoutTask, timeToLive, TimeUnit.MILLISECONDS);
hostData.nextTimeout = connectionHolder.timeout;
}
}
}
}
} else if (connection.isOpen() && connection.isUpgraded()) {
// we treat upgraded connections as closed
// as we do not want the connection pool filled with upgraded connections
// if the connection is actually closed the close setter will handle it
connection.getCloseSetter().set(null);
handleClosedConnection(hostData, connectionHolder);
}
}
use of io.undertow.client.ClientConnection in project undertow by undertow-io.
the class SimpleProxyClientProvider method getConnection.
@Override
public void getConnection(ProxyTarget target, HttpServerExchange exchange, ProxyCallback<ProxyConnection> callback, long timeout, TimeUnit timeUnit) {
ClientConnection existing = exchange.getConnection().getAttachment(clientAttachmentKey);
if (existing != null) {
if (existing.isOpen()) {
// this connection already has a client, re-use it
callback.completed(exchange, new ProxyConnection(existing, uri.getPath() == null ? "/" : uri.getPath()));
return;
} else {
exchange.getConnection().removeAttachment(clientAttachmentKey);
}
}
client.connect(new ConnectNotifier(callback, exchange), uri, exchange.getIoThread(), exchange.getConnection().getByteBufferPool(), OptionMap.EMPTY);
}
use of io.undertow.client.ClientConnection in project undertow by undertow-io.
the class H2CUpgradeContinuationTestCase method testDifferentSizes.
/**
* The real test that sends several GET and POST requests with different
* number of headers and different content length.
* @throws Exception Some error
*/
@Test
public void testDifferentSizes() throws Exception {
final UndertowClient client = UndertowClient.getInstance();
// the client connection uses the small byte-buffer of 1024 to force the continuation frames
final ClientConnection connection = client.connect(new URI("http://" + DefaultServer.getHostAddress() + ":" + (DefaultServer.getHostPort("default") + 1)), worker, new UndertowXnioSsl(worker.getXnio(), OptionMap.EMPTY, DefaultServer.getClientSSLContext()), smallPool, OptionMap.create(UndertowOptions.ENABLE_HTTP2, true)).get();
try {
// the first request triggers the upgrade to H2C
sendRequest(connection, 1, 0, 0);
// send several requests with different sizes for headers and data
sendRequest(connection, 10, 10, 0);
sendRequest(connection, 10, 100, 0);
sendRequest(connection, 10, 150, 0);
sendRequest(connection, 10, 1, 10);
sendRequest(connection, 10, 0, 2000);
sendRequest(connection, 10, 150, 2000);
} finally {
IoUtils.safeClose(connection);
}
}
use of io.undertow.client.ClientConnection in project undertow by undertow-io.
the class Http2ClientTestCase method testPostRequest.
@Test
public void testPostRequest() throws Exception {
//
final UndertowClient client = createClient();
final String postMessage = "This is a post request";
final List<String> responses = new CopyOnWriteArrayList<>();
final CountDownLatch latch = new CountDownLatch(10);
final ClientConnection connection = client.connect(ADDRESS, worker, new UndertowXnioSsl(worker.getXnio(), OptionMap.EMPTY, DefaultServer.getClientSSLContext()), DefaultServer.getBufferPool(), OptionMap.create(UndertowOptions.ENABLE_HTTP2, true)).get();
try {
connection.getIoThread().execute(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
final ClientRequest request = new ClientRequest().setMethod(Methods.POST).setPath(POST);
request.getRequestHeaders().put(Headers.HOST, DefaultServer.getHostAddress());
request.getRequestHeaders().put(Headers.TRANSFER_ENCODING, "chunked");
connection.sendRequest(request, new ClientCallback<ClientExchange>() {
@Override
public void completed(ClientExchange result) {
new StringWriteChannelListener(postMessage).setup(result.getRequestChannel());
result.setResponseListener(new ClientCallback<ClientExchange>() {
@Override
public void completed(ClientExchange result) {
new StringReadChannelListener(DefaultServer.getBufferPool()) {
@Override
protected void stringDone(String string) {
responses.add(string);
latch.countDown();
}
@Override
protected void error(IOException e) {
e.printStackTrace();
latch.countDown();
}
}.setup(result.getResponseChannel());
}
@Override
public void failed(IOException e) {
e.printStackTrace();
latch.countDown();
}
});
}
@Override
public void failed(IOException e) {
e.printStackTrace();
latch.countDown();
}
});
}
}
});
latch.await(10, TimeUnit.SECONDS);
Assert.assertEquals(10, responses.size());
for (final String response : responses) {
Assert.assertEquals(postMessage, response);
}
} finally {
IoUtils.safeClose(connection);
}
}
use of io.undertow.client.ClientConnection in project undertow by undertow-io.
the class AjpClientTestCase method testPostRequest.
@Test
public void testPostRequest() throws Exception {
//
final UndertowClient client = createClient();
final String postMessage = "This is a post request";
final List<String> responses = new CopyOnWriteArrayList<>();
final CountDownLatch latch = new CountDownLatch(10);
final ClientConnection connection = client.connect(ADDRESS, worker, DefaultServer.getBufferPool(), OptionMap.EMPTY).get();
try {
connection.getIoThread().execute(() -> {
for (int i = 0; i < 10; i++) {
final ClientRequest request = new ClientRequest().setMethod(Methods.POST).setPath(POST);
request.getRequestHeaders().put(Headers.HOST, DefaultServer.getHostAddress());
request.getRequestHeaders().put(Headers.TRANSFER_ENCODING, "chunked");
connection.sendRequest(request, new ClientCallback<ClientExchange>() {
@Override
public void completed(ClientExchange result) {
new StringWriteChannelListener(postMessage).setup(result.getRequestChannel());
result.setResponseListener(new ClientCallback<ClientExchange>() {
@Override
public void completed(ClientExchange result) {
new StringReadChannelListener(DefaultServer.getBufferPool()) {
@Override
protected void stringDone(String string) {
responses.add(string);
latch.countDown();
}
@Override
protected void error(IOException e) {
e.printStackTrace();
latch.countDown();
}
}.setup(result.getResponseChannel());
}
@Override
public void failed(IOException e) {
e.printStackTrace();
latch.countDown();
}
});
}
@Override
public void failed(IOException e) {
e.printStackTrace();
latch.countDown();
}
});
}
});
assertTrue(latch.await(10, TimeUnit.SECONDS));
Assert.assertEquals(10, responses.size());
for (final String response : responses) {
Assert.assertEquals(postMessage, response);
}
} finally {
IoUtils.safeClose(connection);
}
}
Aggregations