Isa Muqattash created HTTPASYNC-143:
---------------------------------------
Summary: Connection closed randomly during NTLM authorization
Key: HTTPASYNC-143
URL: https://issues.apache.org/jira/browse/HTTPASYNC-143
Project: HttpComponents HttpAsyncClient
Issue Type: Bug
Affects Versions: 4.1.4
Reporter: Isa Muqattash
Attachments: asyncHttpClient_failed.log, asyncHttpClient_success.log
Recently switched from the (synchronous) HttpClient to HttpAsyncClient, and I'm
dealing with a HTTP 401 error returned from an HTTP POST that involves NTLM
authentication.
The issue sporadically occurs, more frequently with HttpAsyncClient 4.1.3, and
still occurs in 4.1.4 but less frequently.
The HTTP POST request incorrectly includes a "Content-Type: Application/JSON"
header and the body is a ZIP file binary, and removing that header seems to
make the issue go away, or at least I cannot reproduce the random behavior when
the head is not specified. However, all this worked fine with the synchronous
HttpClient and it will be difficult to go to many many applications and remove
that additional header, which I'm not sure why it would cause this issue
described here.
I enabled context and wire logs, and what I'm seeing is that the three-step
NTLM handshake takes place. When the issue does not reproduce, all three steps
occur on the same connection. But when the issue reproduces, the context and
wire logs show that the connection is closed between each of the three steps.
Furthermore, I looked into this for several days and the issue reproduces more
frequently with some zip binaries than other.
Perhaps there is some JSON parsing taking place that randomly causes issues and
causes the connection to be closed? (I'm just rambling now but just trying to
give as much info as possible...)
Sample success and failure handshake logs attached.
Source code I'm using is as follows (stripped down):
{code:java}
val httpclientB = HttpAsyncClients.custom().setRedirectStrategy(new
LaxRedirectStrategy() {
override def createLocationURI(location: String): URI = {
super.createLocationURI(location)
}
override def isRedirected(req: HttpRequest, resp: HttpResponse, ctxt:
HttpContext): Boolean = {
super.isRedirected(req, resp, ctxt)
}
override def getRedirect(req: HttpRequest, resp: HttpResponse, ctxt:
HttpContext): HttpUriRequest = {
val x = super.getRedirect(req, resp, ctxt)
if (x.containsHeader("Content-Length")) {
x.removeHeaders("Content-Length")
}
x
}
})
val credsProvider = new BasicCredentialsProvider()
credsProvider.setCredentials(AuthScope.ANY, new NTCredentials("foo", "bar",
"baz", "domain"))
httpclientB.setDefaultCredentialsProvider(credsProvider)
val httpClient = httpclientB.useSystemProperties().build()
httpClient.start()
val future = httpClient.execute(httpRequest, null)
future.get(Long.MaxValue, TimeUnit.MILLISECONDS))
{code}
--
This message was sent by Atlassian JIRA
(v7.6.3#76005)
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]