[
https://issues.apache.org/jira/browse/HTTPASYNC-110?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Oleg Kalnichevski resolved HTTPASYNC-110.
-----------------------------------------
Resolution: Fixed
Fix Version/s: 4.1.3
Fixed in SVN 4.1.x branch. Please re-test and close.
Oleg
> Proxy reuses a fully established routed authenticated connection in attempt
> to CONNECT to target again causing 400 and NPE
> --------------------------------------------------------------------------------------------------------------------------
>
> Key: HTTPASYNC-110
> URL: https://issues.apache.org/jira/browse/HTTPASYNC-110
> Project: HttpComponents HttpAsyncClient
> Issue Type: Bug
> Reporter: Andrey K
> Fix For: 4.1.3
>
> Attachments: buglog.txt
>
>
> First I noticed I was getting sporadic errors when attempting to make an
> HTTPS call via HTTP Proxy that requires authentication:
> java.lang.IllegalArgumentException: Auth scheme may not be null
> at org.apache.http.util.Args.notNull(Args.java:54)
> at
> org.apache.http.impl.client.AuthenticationStrategyImpl.authSucceeded(AuthenticationStrategyImpl.java:215)
> at
> org.apache.http.impl.client.ProxyAuthenticationStrategy.authSucceeded(ProxyAuthenticationStrategy.java:43)
> at
> org.apache.http.impl.auth.HttpAuthenticator.isAuthenticationRequested(HttpAuthenticator.java:88)
> at
> org.apache.http.impl.nio.client.MainClientExec.needAuthentication(MainClientExec.java:629)
> at
> org.apache.http.impl.nio.client.MainClientExec.handleResponse(MainClientExec.java:569)
> at
> org.apache.http.impl.nio.client.MainClientExec.responseReceived(MainClientExec.java:309)
> at
> org.apache.http.impl.nio.client.DefaultClientExchangeHandlerImpl.responseReceived(DefaultClientExchangeHandlerImpl.java:147)
> at
> org.apache.http.nio.protocol.HttpAsyncRequestExecutor.responseReceived(HttpAsyncRequestExecutor.java:303)
> at
> org.apache.http.impl.nio.DefaultNHttpClientConnection.consumeInput(DefaultNHttpClientConnection.java:255)
> at
> org.apache.http.impl.nio.client.InternalIODispatch.onInputReady(InternalIODispatch.java:81)
> at
> org.apache.http.impl.nio.client.InternalIODispatch.onInputReady(InternalIODispatch.java:39)
> at
> org.apache.http.impl.nio.reactor.AbstractIODispatch.inputReady(AbstractIODispatch.java:121)
> at
> org.apache.http.impl.nio.reactor.BaseIOReactor.readable(BaseIOReactor.java:162)
> at
> org.apache.http.impl.nio.reactor.AbstractIOReactor.processEvent(AbstractIOReactor.java:337)
> at
> org.apache.http.impl.nio.reactor.AbstractIOReactor.processEvents(AbstractIOReactor.java:315)
> at
> org.apache.http.impl.nio.reactor.AbstractIOReactor.execute(AbstractIOReactor.java:276)
> at
> org.apache.http.impl.nio.reactor.BaseIOReactor.execute(BaseIOReactor.java:104)
> at
> org.apache.http.impl.nio.reactor.AbstractMultiworkerIOReactor$Worker.run(AbstractMultiworkerIOReactor.java:588)
> Upon closer look with trace debug, I saw that it was breaking on an
> unexpected 400 status code coming back against a CONNECT+AUTH request. When I
> traced the connection that was used for this connect, I saw that it was a
> fully connected routed connection. What happened was the HttpClient got a 407
> after attempting to do a CONNECT and that 407 contained instruction to close
> connection. HttpClient discarded the connection and obtained a new one from
> the pool but the one that was leased was already fully authenticated and
> tunneled. Thus the CONNECT request was sent to the actual tunneled target and
> returned with a 400.
> As a workaround I have enhanced a custom ProxyAuthenticationStrategy to
> rename the USER_TOKEN context value to a temporary unique value to prevent
> reusing a fully established connection and then revert it back after
> authentication is sucessful:
> static AtomicLong counter = new AtomicLong(0);
> static final String ORIGINAL_USER_TOKEN = "ORIGINAL_USER_TOKEN";
> @Override
> public Map<String, Header> getChallenges(HttpHost authhost, HttpResponse
> response, HttpContext context) throws MalformedChallengeException {
> String originalUserToken =
> (String)context.getAttribute(ORIGINAL_USER_TOKEN);
> if (originalUserToken == null) {
> originalUserToken =
> (String)context.getAttribute(HttpClientContext.USER_TOKEN);
> context.setAttribute(ORIGINAL_USER_TOKEN, originalUserToken);
> String temporaryName = "NON-REUSABLE-" + counter.incrementAndGet();
> context.setAttribute(HttpClientContext.USER_TOKEN, temporaryName);
> log.trace("OnAuth: Renaming connection from {} to {}",
> originalUserToken, temporaryName);
> }
> return super.getChallenges(authhost, response, context);
> }
> @Override
> public void authSucceeded(HttpHost authhost, AuthScheme authScheme,
> HttpContext context) {
> String originalUserToken =
> (String)context.getAttribute(ORIGINAL_USER_TOKEN);
> if (originalUserToken != null) {
> String tempUserToken =
> (String)context.getAttribute(HttpClientContext.USER_TOKEN);
> context.setAttribute(HttpClientContext.USER_TOKEN, originalUserToken);
> context.removeAttribute(ORIGINAL_USER_TOKEN);
> log.trace("OnAuthSucc: Renaming connection from {} to {}",
> tempUserToken, originalUserToken);
> }
> super.authSucceeded(authhost, authScheme, context);
> }
--
This message was sent by Atlassian JIRA
(v6.3.15#6346)
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]