[
https://issues.apache.org/jira/browse/HTTPASYNC-103?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=15177600#comment-15177600
]
Oleg Kalnichevski commented on HTTPASYNC-103:
---------------------------------------------
Fae,
Handling of state-ful connections is explained here. Connections carrying state
that represents a user identity does not get re-used by default unless
logically related requests share the same context and the same user identity.
Please have a look
http://hc.apache.org/httpcomponents-client-4.5.x/tutorial/html/advanced.html#stateful_conn
Oleg
> Connections reuse does not work when using TLS client certs
> -----------------------------------------------------------
>
> Key: HTTPASYNC-103
> URL: https://issues.apache.org/jira/browse/HTTPASYNC-103
> Project: HttpComponents HttpAsyncClient
> Issue Type: Bug
> Affects Versions: 4.1.1
> Reporter: Fae Hutter
>
> When using TLS client certs,
> {{PoolingNHttpClientConnectionManager.requestConnection()}} is called with
> {{state=null}} but
> {{PoolingNHttpClientConnectionManager.releaseConnection()}} is called with
> {{state=X500Principal}}.
> What I think it happening...
> {{org.apache.http.impl.nio.client.AbstractClientExchangeHandler.requestConnection()}}
> has:
> {code:java}
> final Object userToken = this.localContext.getUserToken();
> this.connmgr.requestConnection( ... userToken, ...
> {code}
> At this point the user token has not been set.
> Then {{org.apache.http.impl.nio.client.MainClientExec.responseCompleted()}}
> has this which sets the user token:
> {code:java}
> Object userToken = localContext.getUserToken();
> if (userToken == null) {
> userToken = this.userTokenHandler.getUserToken(localContext);
> localContext.setAttribute(HttpClientContext.USER_TOKEN, userToken);
> }
> {code}
> And
> {{org.apache.http.impl.nio.client.AbstractClientExchangeHandler.releaseConnection()}}
> then with:
> {code:java}
> final Object userToken = this.localContext.getUserToken();
> this.connmgr.releaseConnection(localConn, userToken, validDuration,
> TimeUnit.MILLISECONDS);
> {code}
> And because the state does not match, the call to {{releaseConnection()}} has
> no effect.
> There is an assertion for this at
> {{org.apache.http.nio.pool.RouteSpecificPool.free()}}, but the assertion is
> never called because
> {{org.apache.http.nio.pool.AbstractNIOConnPool.release()}} first checks the
> response of:
> {code:java}
> if (this.leased.remove(entry)) { ...
> {code}
> And there is no else statement.
> In case this is useful for anyone else, for now I have worked around the
> issue using this:
> {code:java}
> /**
> * This is a hackaround for connections not being release (and thus not
> reused) when using TLS client certs.
> * The problem is that the connection is requested with state==null but
> released with state==javax.security.auth.x500.X500Principal.
> * Since our use case does not require the state value to be none null,
> enforce that assumption and override it when releasing connections.
> */
> private static class MyPoolingNHttpClientConnectionManager extends
> PoolingNHttpClientConnectionManager {
> public MyPoolingNHttpClientConnectionManager(final ConnectingIOReactor
> ioreactor, final NHttpConnectionFactory<ManagedNHttpClientConnection>
> connFactory,
> final Registry<SchemeIOSessionStrategy> iosessionFactoryRegistry,
> final DnsResolver dnsResolver) {
> super(ioreactor, connFactory, iosessionFactoryRegistry, dnsResolver);
> }
> @Override
> public Future<NHttpClientConnection> requestConnection(final HttpRoute
> route, final Object state, final long connectTimeout, final long
> leaseTimeout, final TimeUnit tunit,
> final FutureCallback<NHttpClientConnection> callback) {
> if (state != null) throw new
> UnsupportedOperationException("Requesting connections with state!=null is not
> supported by this work around.");
> new Exception().printStackTrace();
> return super.requestConnection(route, state, connectTimeout,
> leaseTimeout, tunit, callback);
> }
> @Override
> public void releaseConnection(final NHttpClientConnection managedConn,
> final Object state, final long keepalive, final TimeUnit tunit) {
> new Exception().printStackTrace();
> super.releaseConnection(managedConn, null, keepalive, tunit); // XXX
> Deliberately replace state with null.
> }
> }
> {code}
--
This message was sent by Atlassian JIRA
(v6.3.4#6332)
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]