[ 
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]

Reply via email to