Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

IllegalArgumentException: "Auth scheme may not be null" in CloseableHttpAsyncClient

I'm running some asynchronous GET requests using a proxy with authentication. When doing HTTPS requests, I'm always running into an exception after 2 successful asyncronous requests: java.lang.IllegalArgumentException: Auth scheme may not be null

When executing the GET requests without a proxy, or using http instead of https, the exception never occurred.

Example from Apache HttpAsyncClient Examples

HttpHost proxy = new HttpHost("proxyname", 3128);
CredentialsProvider credsProvider = new BasicCredentialsProvider();
credsProvider.setCredentials(new AuthScope(proxy), new UsernamePasswordCredentials("proxyuser", "proxypass"));

CloseableHttpAsyncClient httpClient = HttpAsyncClients.custom().setDefaultCredentialsProvider(credsProvider).build();

httpClient.start();
RequestConfig config = RequestConfig.custom().setProxy(proxy).build();

for (int i = 0; i < 3; i++) {
  HttpGet httpGet = new HttpGet(url);
  httpGet.setConfig(config);

  httpClient.execute(httpGet, new FutureCallback<HttpResponse>() {

    public void failed(Exception ex) {
      ex.printStackTrace(); // Exception occures here afther 2nd iteration
    }

    public void completed(HttpResponse result) {
      // works for the first and second iteration
    }

    public void cancelled() {
    }
  });
}

httpClient.close();

If I run the code above with 'http://httpbin.org/get', there is no exception, but if I run it with 'https://httpbin.org/get', I get the following exception after 2 successful requests:

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:44)
    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:151)
    at org.apache.http.nio.protocol.HttpAsyncRequestExecutor.responseReceived(HttpAsyncRequestExecutor.java:315)
    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:591)
    at java.lang.Thread.run(Thread.java:748)

Note: I'm using httpasyncclient 4.1.4

like image 254
Martin Avatar asked Nov 06 '22 19:11

Martin


1 Answers

If this is the exact code you have been executing then the problem is quite apparent. Welcome to the world of even-driven programming.

Essentially what happens is the following:

  1. The client initiates 3 message exchanges by submitting 3 requests to the client execution pipeline in a tight loop
  2. 3 message exchanges get queued up for execution
  3. The loop exits
  4. Client shutdown is initiated
  5. Now the client is racing to execute 3 initiated message exchanges and to shut itself down at the same time
  6. If one is lucky and the target server is fast enough one might get all 3 exchanges before the client shuts down its i/o event processing threads
  7. If unlucky or when the request execution is relatively slow, for instance due, to the use of TLS transport security, some of message exchanges might get terminated in the middle of the process. This is the reason you are seeing the failure when using https scheme but not http.
like image 184
ok2c Avatar answered Dec 09 '22 05:12

ok2c