I am using httpclient 4.1.3 in my project.

I am creating single httpclient instance with ThreadSafeClientConnManager.
I don't see alternative to ThreadSafeClientConnManager in httpclient 4.1.3.

Intermittently I am experiencing that http request being made for another
user which is not the intended user. I am setting credentials in AuthState
and using localHttpClient.

My test includes -
 - Six threads running in parallel each calling REST API 10 time
 - Endpoint URL is same for all request so HttpHost is same.
 - There are six authenticating users. Each thread correspond to 1 thread.

Pasting code below. Please let me know if i am missing anything in main
code. I am not printing my test code here.

import java.io.IOException;

import java.security.cert.CertificateException;

import java.security.cert.X509Certificate;


import org.apache.http.HttpException;

import org.apache.http.HttpHost;

import org.apache.http.HttpRequest;

import org.apache.http.HttpRequestInterceptor;

import org.apache.http.auth.AuthScope;

import org.apache.http.auth.AuthState;

import org.apache.http.client.CredentialsProvider;

import org.apache.http.client.params.HttpClientParams;

import org.apache.http.client.protocol.ClientContext;

import org.apache.http.conn.ClientConnectionManager;

import org.apache.http.conn.scheme.Scheme;

import org.apache.http.conn.scheme.SchemeRegistry;

import org.apache.http.conn.ssl.SSLSocketFactory;

import org.apache.http.conn.ssl.TrustStrategy;

import org.apache.http.impl.auth.BasicScheme;

import org.apache.http.impl.client.DefaultHttpClient;

import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;

import org.apache.http.params.HttpConnectionParams;

import org.apache.http.protocol.ExecutionContext;

import org.apache.http.protocol.HttpContext;

import org.apache.log4j.Logger;


public class BasicAuthRestClient extends AbstractRestClient{

private static int HTTP_CONN_TIMEOUT = 30*1000; //30 second

private static int HTTP_SOCKET_TIMEOUT = 5*60*1000;  //5 minute

private static int HTTP_MAX_CONN = 1000;

private static int HTTP_MAX_PER_ROUTE = 100;


    public BasicAuthRestClient(String baseUrl){


    this.baseUrl = baseUrl;

        SchemeRegistry registry = new SchemeRegistry();

        SSLSocketFactory socketFactory;

try {

socketFactory = new SSLSocketFactory(new TrustStrategy() {

@Override

public boolean isTrusted(X509Certificate[] arg0, String arg1)

throws CertificateException {

return true;

}

}, org.apache.http.conn.ssl.SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);

         registry.register(new Scheme("https", HTTP_SSL_PORT,
socketFactory));

} catch (Exception e) {

logger.error("exception in creating SSLSocketFactory", e);

}


 ClientConnectionManager connMgr = new
ThreadSafeClientConnManager(registry);

        ((ThreadSafeClientConnManager)connMgr).setMaxTotal(HTTP_MAX_CONN);

        ((ThreadSafeClientConnManager)connMgr).setDefaultMaxPerRoute(
HTTP_MAX_PER_ROUTE);



    httpClient = new DefaultHttpClient(connMgr);

    //setting request interceptor

    ((DefaultHttpClient)httpClient).addRequestInterceptor(new
HttpBasicAuthInterceptor(), 0);


        HttpConnectionParams.setConnectionTimeout(httpClient.getParams(),
HTTP_CONN_TIMEOUT);

        HttpConnectionParams.setSoTimeout(httpClient.getParams(),
HTTP_SOCKET_TIMEOUT);

        HttpConnectionParams.setStaleCheckingEnabled(httpClient.getParams(),
true);

        HttpConnectionParams.setTcpNoDelay(httpClient.getParams(), true);


        HttpClientParams.setAuthenticating(httpClient.getParams(), true);

        HttpClientParams.setRedirecting(httpClient.getParams(), false);

    }


    static class HttpBasicAuthInterceptor implements HttpRequestInterceptor
{

        public void process(

                final HttpRequest request,

                final HttpContext context) throws HttpException,
IOException {

            AuthState authState = (AuthState)
context.getAttribute(ClientContext.TARGET_AUTH_STATE);

            CredentialsProvider credProvider =
(CredentialsProvider)context.getAttribute(

            ClientContext.CREDS_PROVIDER);



            HttpHost targetHost = (HttpHost)context.getAttribute(

            ExecutionContext.HTTP_TARGET_HOST);



            authState.setCredentials(credProvider.getCredentials(

                       new AuthScope(targetHost.getHostName(),
targetHost.getPort())));



            authState.setAuthScheme((BasicScheme)context.getAttribute(
"preemptive-auth"));

        }

    }


    private HttpContext createHttpContext(String userName, String password){

String host = Utils.getHostName(baseUrl);


BasicHttpContext localcontext = new BasicHttpContext();

BasicScheme basicAuth = new BasicScheme();

localcontext.setAttribute("preemptive-auth", basicAuth);

CredentialsProvider credProvider = new BasicCredentialsProvider();

credProvider.setCredentials(

          new AuthScope(host, HTTP_SSL_PORT),

          new UsernamePasswordCredentials(userName, password));

localcontext.setAttribute(ClientContext.CREDS_PROVIDER, credProvider);

 localcontext.setAttribute(

          ClientContext.TARGET_AUTH_STATE, new AuthState());

HttpHost targetHost = new HttpHost(host, HTTP_SSL_PORT, "https");

localcontext.setAttribute(ExecutionContext.HTTP_TARGET_HOST, targetHost);

return localcontext;

 }



    public String doGet(final String url,

    final String userName, final String password) throws
RestClientException {

        HttpGet httpget = new HttpGet(this.baseUrl + url);

        HttpResponse response = null;

try {

    HttpContext localcontext = createHttpContext(userName, password);


response = httpClient.execute(httpget, localcontext);

return handleHttpResponse(response);

} catch (ClientProtocolException e) {

throw new RestClientException(e);

} catch (IllegalStateException e) {

throw new RestClientException(e);

} catch (IOException e) {

throw new RestClientException(e);

} catch (Exception e){

throw new RestClientException(e);

}finally{

try {

EntityUtils.consume(response.getEntity());

} catch (Exception e) {

logger.warn("Exception in EntityUtils.consume - ", e);

}

 httpClient.getConnectionManager().closeIdleConnections(60000,

TimeUnit.MILLISECONDS);

httpClient.getConnectionManager().closeExpiredConnections();

}

    }

}


Regards
Sukhdev

Reply via email to