Return-Path: X-Original-To: archive-asf-public-internal@cust-asf2.ponee.io Delivered-To: archive-asf-public-internal@cust-asf2.ponee.io Received: from cust-asf.ponee.io (cust-asf.ponee.io [163.172.22.183]) by cust-asf2.ponee.io (Postfix) with ESMTP id 18988200B60 for ; Sun, 14 Aug 2016 21:04:22 +0200 (CEST) Received: by cust-asf.ponee.io (Postfix) id 176D0160AA9; Sun, 14 Aug 2016 19:04:22 +0000 (UTC) Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by cust-asf.ponee.io (Postfix) with SMTP id 5D737160A8B for ; Sun, 14 Aug 2016 21:04:21 +0200 (CEST) Received: (qmail 62230 invoked by uid 500); 14 Aug 2016 19:04:20 -0000 Mailing-List: contact dev-help@hc.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: "HttpComponents Project" Delivered-To: mailing list dev@hc.apache.org Received: (qmail 62219 invoked by uid 99); 14 Aug 2016 19:04:20 -0000 Received: from arcas.apache.org (HELO arcas) (140.211.11.28) by apache.org (qpsmtpd/0.29) with ESMTP; Sun, 14 Aug 2016 19:04:20 +0000 Received: from arcas.apache.org (localhost [127.0.0.1]) by arcas (Postfix) with ESMTP id 70FDC2C02A1 for ; Sun, 14 Aug 2016 19:04:20 +0000 (UTC) Date: Sun, 14 Aug 2016 19:04:20 +0000 (UTC) From: "Oleg Kalnichevski (JIRA)" To: dev@hc.apache.org Message-ID: In-Reply-To: References: Subject: [jira] [Commented] (HTTPCLIENT-1762) Proxy reuses a fully established routed authenticated connection in attempt to CONNECT to target again causing 400 and NPE MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 7bit X-JIRA-FingerPrint: 30527f35849b9dde25b450d4833f0394 archived-at: Sun, 14 Aug 2016 19:04:22 -0000 [ https://issues.apache.org/jira/browse/HTTPCLIENT-1762?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=15420453#comment-15420453 ] Oleg Kalnichevski commented on HTTPCLIENT-1762: ----------------------------------------------- Please confirm your application code either does not explicitly use HttpContext instances or correctly synchronizes access to HttpContext instances shared by multiple requests before I start analyzing the log. Oleg > Proxy reuses a fully established routed authenticated connection in attempt to CONNECT to target again causing 400 and NPE > -------------------------------------------------------------------------------------------------------------------------- > > Key: HTTPCLIENT-1762 > URL: https://issues.apache.org/jira/browse/HTTPCLIENT-1762 > Project: HttpComponents HttpClient > Issue Type: Bug > Components: HttpClient > Reporter: Andrey K > 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 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.4#6332) --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscribe@hc.apache.org For additional commands, e-mail: dev-help@hc.apache.org