Android HttpClient hangs simultaneous requests until I execute request to another host - java

I have a problem using DefaultHttpClient.
If I execute some requests simultaneously to the same server (> 2) it will hang them (no responses will be received). All next requests will hang too.
Here is the code.
public class ConnectionService {
// Should be called once with application context
public static void initWithContext(Context ctx) {
// Creating custom multithread connection manager to handle multiple simultaneous requests
HttpParams params = new BasicHttpParams();
SchemeRegistry schemeRegistry = new SchemeRegistry();
schemeRegistry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
ClientConnectionManager cm = new ThreadSafeClientConnManager(params, schemeRegistry);
ConnManagerParams.setMaxTotalConnections(params, 200);
ConnPerRoute cpr = new ConnPerRoute() {
#Override
public int getMaxForRoute(HttpRoute httpRoute) {
return 50;
}
};
ConnManagerParams.setMaxConnectionsPerRoute(params, cpr);
httpClient = new DefaultHttpClient(cm, params);
httpClient.setCookieStore(new PersistentCookieStore(ctx));
}
static private DefaultHttpClient httpClient = null;
private JsonExecutorInterface requestExecutorForRelativePathAndParams(String path, WebParams params) throws UnsupportedEncodingException {
HttpPost postRequest = new HttpPost(rootUrl.toString() + path);
if(params != null) {
postRequest.setEntity(params.getFormEntity());
}
JsonExecutorProxy executor = new JsonExecutorProxy();
executor.setRequest(postRequest);
executor.setErrorsHandlerDelegate(this);
return executor;
}
}

This is most likely due to how you are constructing the ThreadSafeClientConnManager you are using. If you change the order slightly you should get a better result.
HttpParams params = new BasicHttpParams();
// The params are read in the ctor of the pool constructed by
// ThreadSafeClientConnManager, and need to be set before constructing it.
ConnManagerParams.setMaxTotalConnections(params, 200);
ConnPerRoute cpr = new ConnPerRoute() {
#Override
public int getMaxForRoute(HttpRoute httpRoute) {
return 50;
}
};
ConnManagerParams.setMaxConnectionsPerRoute(params, cpr);
SchemeRegistry schemeRegistry = new SchemeRegistry();
schemeRegistry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
ClientConnectionManager cm = new ThreadSafeClientConnManager(params, schemeRegistry);

Related

Apache HttpClient 4.0.1- HttpPut No content to map due to end-of-input\n Error

I have a spring restful api and, I am trying to do the update over restful api using HttpPut method with Apache HttpClient 4.0.1 as below
import groovy.json.JsonBuilder
import org.apache.http.client.methods.HttpPut
import org.apache.http.entity.StringEntity
import groovy.json.JsonSlurper
import org.apache.commons.io.output.ByteArrayOutputStream;
def httpConnector = applicationContext.getBean('httpConnector')
String apiURL = "https://localhost:7443/api/ruleConfigurations/29"
def putRequest = new HttpPut(apiURL);
def testJson = new JsonBuilder()
root = testJson name: "test_name", displayName: "test_display_name", active: "false" , value: "test_value"
println "testJson = "+testJson.toString()
def stringEntity = new StringEntity(testJson.toString());
putRequest.setHeader("Accept", "application/json");
putRequest.setHeader("Content-type", "application/json");
def httpClient = httpConnector.getHttpClient()
def putResponse = httpClient.execute(putRequest)
def resCode = putResponse.getStatusLine().getStatusCode()
if(resCode==200){
println "succesfully updated Rule config"
}
else {
println "Response Code = ${resCode} Error in updating Rule config"
println "error message = "+getResponseData(putResponse)
}
def getResponseData(def response) throws java.io.IOException {
byte[] responseData
InputStream responseStream = response.getEntity().getContent()
try {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()
byteArrayOutputStream.write(responseStream)
responseData = byteArrayOutputStream.toByteArray()
} finally {
responseStream.close()
}
return new String(responseData,'utf-8')
}
Below is the method for httpConnector.getHttpClient()
private DefaultHttpClient getHttpClient() {
if (httpClient != null) return httpClient;
final int MAX_CONNECTIONS = 300;
CookieStore cookieStore = new BasicCookieStore();
httpContext = new BasicHttpContext();
httpContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore);
HttpParams params = new BasicHttpParams();
ConnManagerParams.setMaxTotalConnections(params,MAX_CONNECTIONS);
ConnManagerParams.setTimeout(params, 20000);
HttpConnectionParams.setSoTimeout(params, 240000);
HttpConnectionParams.setConnectionTimeout(params,30000);
ConnPerRouteBean connPerRoute = new ConnPerRouteBean(MAX_CONNECTIONS);
ConnManagerParams.setMaxConnectionsPerRoute(params, connPerRoute);
SchemeRegistry schemeRegistry = new SchemeRegistry();
schemeRegistry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 8080));
schemeRegistry.register(new Scheme("https", getSockectFactory(), 8443));
ClientConnectionManager cm = new ThreadSafeClientConnManager(params, schemeRegistry);
def httpClient = new DefaultHttpClient(cm, params);
return httpClient;
}
Below is the output am getting while trying to do the update over restful api
testJson = {"name":"test_name","displayName":"test_display_name","active":"false","value":"test_value"}
Response Code = 400 Error in updating Rule config
error message = {
"cause":{
"cause":null,
"message":"No content to map due to end-of-input\n at [Source: org.apache.catalina.connector.CoyoteInputStream#5438c5f7; line: 1, column: 0]"
},
"message":"Could not read an object of type class com.validation.entity.RuleConfiguration from the request!; nested exception is com.fasterxml.jackson.databind.JsonMappingException: No content to map due to end-of-input\n at [Source: org.apache.catalina.connector.CoyoteInputStream#5438c5f7; line: 1, column: 0]"
}
If I use the same testJson for HttpPut in postman it works fine
Am not sure why am getting No content to map due to end-of-input\n error for HttpPut with the Apache HttpClient 4.0.1, can someone please help?
In the example you have shown you are not calling
putRequest.setEntity(stringEntity)
so the request you send has empty body.

It does not take a multi-threaded query

faced with multi-threading when sending HTTP requests
a feeling that they are still waiting for the completion of each other ..
because the speed of queries is not impressed (compared to C # \ Perl)
For the first time faced with a similar to C #, it turned out that the problem was solved by removing limits on connections
ServicePointManager.DefaultConnectionLimit = 100;
Can someone tell what is wrong in my example?
whether there are such limits in java?
public static String requester(String url, String param, int head, String cook, int ajax) {
HttpClient client = getHttpsClient(new DefaultHttpClient());
HttpPost httppost = new HttpPost(url);
String ans = new String();
if(ajax == 1) {
httppost.setHeader("Content-Type", "application/json;charset=utf-8");
httppost.setHeader("Accept", "application/json");
}
httppost.setHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.114 Safari/537.36");
if(cook != "") {
httppost.setHeader("Cookie", cook);
}
try {
StringEntity se = new StringEntity(param);
se.setContentEncoding(new BasicHeader(HTTP.CONTENT_TYPE, "application/json"));
httppost.setEntity(se);
HttpResponse response = client.execute(httppost);
if(head == 1) {
ans = TextUtils.join("\r\n", response.getAllHeaders());
}
StringBuilder builder = new StringBuilder();
BufferedReader reader = new BufferedReader(new InputStreamReader(response.getEntity().getContent(), "UTF-8"));
for (String line = null; (line = reader.readLine()) != null;) {
builder.append(line).append("\n");
}
ans += builder.toString();
} catch (ClientProtocolException e) {
Log.d("ClientProtocolException","Some Wrong 1");
} catch (IOException e) {
Log.d("ClientProtocolException", e.getLocalizedMessage());
}
return ans;
}
....
public void brute(View v)
{
flag = 0;
for(int i = 0; i < 100; i++)
{
new TheTask().execute();
}
}
class TheTask extends AsyncTask<Void,Void,Void>
{
#Override
protected Void doInBackground(Void... params) {
while(true)
{
..........
public static HttpClient getHttpsClient(HttpClient client) {
try{
X509TrustManager x509TrustManager = new X509TrustManager() {
#Override
public void checkClientTrusted(X509Certificate[] chain,
String authType) throws CertificateException {
}
#Override
public void checkServerTrusted(X509Certificate[] chain,
String authType) throws CertificateException {
}
#Override
public X509Certificate[] getAcceptedIssuers() {
return null;
}
};
HttpParams params = new BasicHttpParams();
ConnManagerParams.setMaxConnectionsPerRoute(params, new ConnPerRouteBean(100));
ConnManagerParams.setMaxTotalConnections(params, 10000);
HttpConnectionParams.setSocketBufferSize(params,8192);
HttpConnectionParams.setTcpNoDelay(params, true);
SchemeRegistry registry = new SchemeRegistry();
registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
ClientConnectionManager clientConnectionManager = new ThreadSafeClientConnManager(params, registry);
clientConnectionManager.setMaxTotal (1000);
clientConnectionManager.setDefaultMaxPerRoute (100);
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, new TrustManager[]{x509TrustManager}, null);
SSLSocketFactory sslSocketFactory = new ExSSLSocketFactory(sslContext);
sslSocketFactory.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
//ClientConnectionManager clientConnectionManager = client.getConnectionManager();
SchemeRegistry schemeRegistry = clientConnectionManager.getSchemeRegistry();
schemeRegistry.register(new Scheme("https", sslSocketFactory, 443));
//return new DefaultHttpClient(clientConnectionManager, client.getParams());
return new DefaultHttpClient(clientConnectionManager, params);
} catch (Exception ex) {
return null;
}
}
See: See http://hc.apache.org/httpclient-3.x/performance.html and http://hc.apache.org/httpclient-3.x/threading.html.
I can't tell from your post, but you appear not to be re-using the HttpClient, but you're definitely not giving it a thread safe connection manager. There are other performance considerations you may need, depending on your application (but are detailed in the above links).
Also, from my own personal, anecdotal evidence, HttpClient 4.x is generally faster than HttpClient 3.x (again, it's not clear which you're using).
Solved
ConnPerRoute perRoute = new ConnPerRouteBean(100);
ConnManagerParams.setMaxConnectionsPerRoute(params, perRoute);
ConnManagerParams.setMaxTotalConnections(params, 100);
ConnManagerParams.setTimeout(params, 15000);

Android 4.0.3 https post returns empty, http works, both works on 2.0.3

I'm connecting my Application to a REST type webservice. I'm using the apache http library, the request is a standard post request, ran in a background thread.
Now my problem is that if I'm using
http://myserver.com/api/command
it works and I get the proper response, but the same url with https:
https://myserver.com/api/command
I get an empty response. The http header is even 200 OK.
BOTH of these work on 2.0.3 but not on 4.0.3. On 4.0.3 the API seems to work only if I use plain http, with https I get empty responses.
This is the code:
#Override
protected HttpResponse doInBackground(String... params) {
String link = params[0];
HttpClient client = createHttpClient();
try {
HashMap<String, ContentBody> files = ApiManager.getFiles();
MultipartEntity mpEntity = new MultipartEntity();
if(files != null) {
for(String i : files.keySet()) {
ContentBody k = files.get(i);
mpEntity.addPart(i, k);
}
}
if(this.callParameters != null) {
for(NameValuePair i : this.callParameters) {
StringBody sb = new StringBody((String)i.getValue(),"text/plain",Charset.forName("UTF-8"));
mpEntity.addPart(i.getName(), sb);
}
}
httppost.setEntity(mpEntity);
// Execute HTTP Post Request
Log.d("ApiTask","Executing request: "+httppost.getRequestLine());
HttpResponse response = null;
response = client.execute(httppost);
client.getConnectionManager().shutdown();
return response;
}
catch(UnknownHostException e) {
exception = e;
return null;
}
catch (IOException e) {
exception = e;
return null;
}
catch(Exception e) {
return null;
}
}
#Override
protected void onPostExecute(HttpResponse result) {
System.out.println("STATUS:"+result.getStatusLine());
try {
StringBuilder responseText = this.inputStreamToString(result.getEntity().getContent());
System.out.println("RESPONSE:"+responseText);
}
catch(Exception e) {
System.out.println("Error");
}
}
private HttpClient createHttpClient() {
HttpParams params = new BasicHttpParams();
HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
HttpProtocolParams.setContentCharset(params, HTTP.DEFAULT_CONTENT_CHARSET);
HttpProtocolParams.setUseExpectContinue(params, true);
HttpConnectionParams.setConnectionTimeout(params, 10000);
HttpConnectionParams.setSoTimeout(params, 10000);
SchemeRegistry schReg = new SchemeRegistry();
schReg.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
schReg.register(new Scheme("https", SSLSocketFactory.getSocketFactory(), 443));
ClientConnectionManager conMgr = new ThreadSafeClientConnManager(params, schReg);
return new DefaultHttpClient(conMgr, params);
}
Thank you in advance

DefaultHttpClient - Avoiding multiple Attempts to execute request [duplicate]

Is there an easier way to setup the http client for preemptive basic authentication than what described here?
In previous version (3.x) it used to be a simple method call (eg, httpClient.getParams().setAuthenticationPreemptive(true)).
The main thing I want to avoid is adding the BasicHttpContext to each method I execute.
If you are looking to force HttpClient 4 to authenticate with a single request, the following will work:
String username = ...
String password = ...
UsernamePasswordCredentials creds = new UsernamePasswordCredentials(username, password);
HttpRequest request = ...
request.addHeader(new BasicScheme().authenticate(creds, request));
It's difficult to do this without passing a context through every time, but you can probably do it by using a request interceptor. Here is some code that we use (found from their JIRA, iirc):
// Pre-emptive authentication to speed things up
BasicHttpContext localContext = new BasicHttpContext();
BasicScheme basicAuth = new BasicScheme();
localContext.setAttribute("preemptive-auth", basicAuth);
httpClient.addRequestInterceptor(new PreemptiveAuthInterceptor(), 0);
(...)
static class PreemptiveAuthInterceptor implements HttpRequestInterceptor {
public void process(final HttpRequest request, final HttpContext context) throws HttpException, IOException {
AuthState authState = (AuthState) context.getAttribute(ClientContext.TARGET_AUTH_STATE);
// If no auth scheme avaialble yet, try to initialize it
// preemptively
if (authState.getAuthScheme() == null) {
AuthScheme authScheme = (AuthScheme) context.getAttribute("preemptive-auth");
CredentialsProvider credsProvider = (CredentialsProvider) context.getAttribute(ClientContext.CREDS_PROVIDER);
HttpHost targetHost = (HttpHost) context.getAttribute(ExecutionContext.HTTP_TARGET_HOST);
if (authScheme != null) {
Credentials creds = credsProvider.getCredentials(new AuthScope(targetHost.getHostName(), targetHost.getPort()));
if (creds == null) {
throw new HttpException("No credentials for preemptive authentication");
}
authState.setAuthScheme(authScheme);
authState.setCredentials(creds);
}
}
}
}
This is the same solution as Mat's Mannion's, but you don't have to put localContext to each request. It's simpler, but it adds authentication to ALL requests. Useful, if you don't have control over individual requests, as in my case when using Apache Solr, which uses HttpClient internally.
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.auth.Credentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.impl.auth.BasicScheme;
import org.apache.http.protocol.HttpContext;
import org.apache.http.protocol.HttpCoreContext;
httpClient.addRequestInterceptor(new PreemptiveAuthInterceptor(), 0);
(...)
static class PreemptiveAuthInterceptor implements HttpRequestInterceptor {
public void process(final HttpRequest request, final HttpContext context) throws HttpException, IOException {
AuthState authState = (AuthState) context.getAttribute(HttpClientContext.TARGET_AUTH_STATE);
// If no auth scheme available yet, try to initialize it
// preemptively
if (authState.getAuthScheme() == null) {
CredentialsProvider credsProvider = (CredentialsProvider) context.getAttribute(HttpClientContext.CREDS_PROVIDER);
HttpHost targetHost = (HttpHost) context.getAttribute(HttpCoreContext.HTTP_TARGET_HOST);
Credentials creds = credsProvider.getCredentials(new AuthScope(targetHost.getHostName(), targetHost.getPort()));
if (creds == null) {
throw new HttpException("No credentials for preemptive authentication");
}
authState.update(new BasicScheme(), creds);
}
}
}
Of course, you have to set the credentials provider:
httpClient.getCredentialsProvider().setCredentials(
new AuthScope(url.getHost(), url.getPort()),
new UsernamePasswordCredentials(username, password))
The AuthScope must not contain realm, as it is not known in advance.
A lot of the answers above use deprecated code. I am using Apache SOLRJ version 5.0.0.
My code consists of
private HttpSolrClient solrClient;
private void initialiseSOLRClient() {
URL solrURL = null;
try {
solrURL = new URL(urlString);
} catch (MalformedURLException e) {
LOG.error("Cannot parse the SOLR URL!!" + urlString);
throw new SystemException("Cannot parse the SOLR URL!! " + urlString, e);
}
String host = solrURL.getHost();
int port = solrURL.getPort();
AuthScope authScope = new AuthScope(host, port);
BasicTextEncryptor textEncryptor = new BasicTextEncryptor();
textEncryptor.setPassword("red bananas in the spring");
String decryptPass = textEncryptor.decrypt(pass);
UsernamePasswordCredentials creds = new UsernamePasswordCredentials(userName, decryptPass);
CredentialsProvider credsProvider = new BasicCredentialsProvider();
credsProvider.setCredentials(
authScope,
creds);
HttpClientBuilder builder = HttpClientBuilder.create();
builder.addInterceptorFirst(new PreemptiveAuthInterceptor());
builder.setDefaultCredentialsProvider(credsProvider);
CloseableHttpClient httpClient = builder.build();
solrClient = new HttpSolrClient(urlString, httpClient);
}
The PreemptiveAuthInterceptor is now as follows:-
static class PreemptiveAuthInterceptor implements HttpRequestInterceptor {
public void process(final HttpRequest request, final HttpContext context) throws HttpException, IOException {
AuthState authState = (AuthState) context.getAttribute(HttpClientContext.TARGET_AUTH_STATE);
// If no auth scheme available yet, try to initialize it
// preemptively
if (authState.getAuthScheme() == null) {
CredentialsProvider credsProvider = (CredentialsProvider)
context.getAttribute(HttpClientContext.CREDS_PROVIDER);
HttpHost targetHost = (HttpHost) context.getAttribute(HttpCoreContext.HTTP_TARGET_HOST);
AuthScope authScope = new AuthScope(targetHost.getHostName(), targetHost.getPort());
Credentials creds = credsProvider.getCredentials(authScope);
if(creds == null){
}
authState.update(new BasicScheme(), creds);
}
}
}
A little late to the party but I came accross the thread trying to solve this for proxy pre-authorization of a post request. To add to Adam's response, I found the following worked for me:
HttpPost httppost = new HttpPost(url);
UsernamePasswordCredentials creds = new UsernamePasswordCredentials(username, password);
Header bs = new BasicScheme().authenticate(creds, httppost);
httppost.addHeader("Proxy-Authorization", bs.getValue());
Thought that might be helpful for anyone else who runs into this.
I think the best way may be to just do it manually. I added the following function
Classic Java:
import javax.xml.bind.DatatypeConverter;
...
private static void addAuthHeader(HttpRequestBase http, String username, String password) throws UnsupportedEncodingException {
String encoded = DatatypeConverter.printBase64Binary((username + ":" + password).getBytes("UTF-8"));
http.addHeader("AUTHORIZATION", "Basic " + encoded);
}
HTTPRequestBase can be an instance of HttpGet or HttpPost
Android:
import android.util.Base64;
...
private static void addAuthHeader(HttpRequestBase http, String username, String password) throws UnsupportedEncodingException {
String encoded = Base64.encodeToString((username + ":" + password).getBytes("UTF-8"), Base64.NO_WRAP);
http.addHeader("AUTHORIZATION", "Basic " + encoded);
}
I'm using this code, based on my reading of the HTTPClient 4.5 docs:
HttpClientContext ctx = HttpClientContext.create()
ctx.setCredentialsProvider(new BasicCredentialsProvider())
ctx.setAuthCache(new BasicAuthCache())
UsernamePasswordCredentials creds = new UsernamePasswordCredentials(user, pass)
AuthScope authScope = new AuthScope(host, port)
ctx.getCredentialsProvider.setCredentials(authScope, credentials)
// This part makes authentication preemptive:
HttpHost targetHost = new HttpHost(host, port, scheme)
ctx.getAuthCache.put(targetHost, new BasicScheme())
...and make sure you always pass that context to HTTPClient.execute().
I don't quite get your closing comment. It's the HttpClient that has all of that machinery for doing preemptive auth, and you only have to do that once (when you construct and configure your HttpClient). Once you've done that, you construct your method instances the same way as always. You don't "add the BasicHttpContext" to the method.
Your best bet, I'd think, is to have your own object that sets up all of the junk required for preemptive auth, and has a simple method or methods for executing requests on given HTTPMethod objects.
in android,Mat Mannion's answer can't resolve https,still send two requests,you can do like below,the trick is append authHeader with user-agent:
public static DefaultHttpClient createProxyHttpClient() {
try {
final DefaultHttpClient client = createPlaintHttpClient();
client.setRoutePlanner(new HttpRoutePlanner() {
#Override
public HttpRoute determineRoute(HttpHost target, HttpRequest request, HttpContext context) throws HttpException {
boolean isSecure = "https".equalsIgnoreCase(target.getSchemeName());
if (needProxy) {
Header header = isSecure ? ProxyUtils.createHttpsAuthHeader() : ProxyUtils.createAuthHeader();
if (isSecure) {
client.getParams().setParameter(CoreProtocolPNames.USER_AGENT, com.netease.cloudmusic.utils.HttpRequest.USER_AGENT + "\r\n" + header.getName() + ":" + header.getValue());
} else {
client.getParams().setParameter(CoreProtocolPNames.USER_AGENT, com.netease.cloudmusic.utils.HttpRequest.USER_AGENT);
if (request instanceof RequestWrapper) {
request = ((RequestWrapper) request).getOriginal();
}
request.setHeader(header);
}
String host = isSecure ? ProxyUtils.SECURE_HOST : ProxyUtils.HOST;
int port = isSecure ? ProxyUtils.SECURE_PORT : ProxyUtils.PORT;
return new HttpRoute(target, null, new HttpHost(host, port), isSecure);
} else {
client.getParams().setParameter(CoreProtocolPNames.USER_AGENT, com.netease.cloudmusic.utils.HttpRequest.USER_AGENT);
return new HttpRoute(target, null, isSecure);
}
}
});
return client;
} catch (Exception e) {
e.printStackTrace();
return new DefaultHttpClient();
}
}
public static DefaultHttpClient createPlaintHttpClient() {
try {
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
trustStore.load(null, null);
PlainSSLSocketFactory socketFactory = new PlainSSLSocketFactory(trustStore);
socketFactory.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
BasicHttpParams params = new BasicHttpParams();
HttpConnectionParams.setConnectionTimeout(params, 30000);
HttpConnectionParams.setSoTimeout(params, 30000);
HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
HttpProtocolParams.setContentCharset(params, HTTP.UTF_8);
SchemeRegistry registry = new SchemeRegistry();
registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
registry.register(new Scheme("https", socketFactory, 443));
ThreadSafeClientConnManager ccm = new ThreadSafeClientConnManager(params, registry);
HttpClientParams.setCookiePolicy(params, CookiePolicy.BROWSER_COMPATIBILITY);
final DefaultHttpClient client = new DefaultHttpClient(ccm, params);
client.setRoutePlanner(new HttpRoutePlanner() {
#Override
public HttpRoute determineRoute(HttpHost target, HttpRequest arg1, HttpContext arg2) throws HttpException {
client.getParams().setParameter(CoreProtocolPNames.USER_AGENT, com.netease.cloudmusic.utils.HttpRequest.USER_AGENT);
return new HttpRoute(target, null, "https".equalsIgnoreCase(target.getSchemeName()));
}
});
return client;
} catch (Exception e) {
e.printStackTrace();
return new DefaultHttpClient();
}
}
SolrConfig:
#Configuration
public class SolrConfig {
#Value("${solr.http.url}")
private String solrUrl;
#Value("${solr.http.username}")
private String solrUser;
#Value("${solr.http.password}")
private String solrPassword;
#Value("${solr.http.pool.maxTotal}")
private int poolMaxTotal;
#Value("${solr.http.pool.maxPerRoute}")
private int pollMaxPerRoute;
#Bean
public SolrClient solrClient() {
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager();
connectionManager.setMaxTotal(poolMaxTotal);
connectionManager.setDefaultMaxPerRoute(pollMaxPerRoute);
CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(solrUser, solrPassword));
CloseableHttpClient httpClient = HttpClientBuilder.create()
.addInterceptorFirst(new PreemptiveAuthInterceptor())
.setConnectionManager(connectionManager)
.setDefaultCredentialsProvider(credentialsProvider)
.build();
return new HttpSolrClient.Builder(solrUrl).withHttpClient(httpClient).build();
}
}
PreemptiveAuthInterceptor:
public class PreemptiveAuthInterceptor implements HttpRequestInterceptor {
public void process(final HttpRequest request, final HttpContext context)
throws HttpException {
AuthState authState = (AuthState) context
.getAttribute(HttpClientContext.TARGET_AUTH_STATE);
// If no auth scheme available yet, try to initialize it
// preemptively
if (authState.getAuthScheme() == null) {
CredentialsProvider credentialsProvider = (CredentialsProvider) context
.getAttribute(HttpClientContext.CREDS_PROVIDER);
HttpHost targetHost = (HttpHost) context
.getAttribute(HttpCoreContext.HTTP_TARGET_HOST);
Credentials credentials = credentialsProvider.getCredentials(new AuthScope(
targetHost.getHostName(), targetHost.getPort()));
if (credentials == null) {
throw new HttpException(
"No credentials for preemptive authentication");
}
authState.update(new BasicScheme(), credentials);
}
}
}

Android HttpEntry read hang on Droid x

I've been working on a web-based android app , and we want the app to post data to server and read the response as JSONString , the code was tested on 3 different devices and all result ok , except for Droid X , it just hangs up on reading the inputStream from HttpResponse.
Here is my code :
HttpResponse response = mClient.execute(mPost);
StatusLine status_line = response.getStatusLine();
int status_code = status_line.getStatusCode();
/*
* Not ok Response
*/
if (status_code != 200){
mBusy = false;
mListener.log("Error Status code = "+String.valueOf(status_code));
return false;
}
HttpEntity entry = response.getEntity();
BufferedReader reader = new BufferedReader(new InputStreamReader(response.getEntity().getContent(), "UTF-8"));
mResponse = reader.readLine();
Any ideas what should I do ?
I found out that the problem source was using android's default HTTP Client.
instead I used :
HttpParams params = new BasicHttpParams();
HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
HttpProtocolParams.setContentCharset(params, HTTP.UTF_8);
HttpProtocolParams.setUseExpectContinue(params, false);
HttpConnectionParams.setConnectionTimeout(params, 10000);
HttpConnectionParams.setSoTimeout(params, 10000);
ConnManagerParams.setMaxTotalConnections(params, 100);
ConnManagerParams.setTimeout(params, 30000);
SchemeRegistry registry = new SchemeRegistry();
registry.register(new Scheme("http",PlainSocketFactory.getSocketFactory(), 80));
registry.register(new Scheme("https",PlainSocketFactory.getSocketFactory(), 80));
ThreadSafeClientConnManager manager = new ThreadSafeClientConnManager(params, registry);
mClient = new DefaultHttpClient(manager, params);
instead of :
mClient = new DefaultHttpClient();
hope that helps someone.

Categories

Resources