Apache HttpClient Persistent Connection usage - java

What is the right way for me to use the same TCP connection when using Apache HttpClient?
My code currently is:
CloseableHttpClient httpClient = HttpClients.createDefault();
HttpClientContext httpContext = HttpClientContext.create();
for (int i = 0; i < 100; i++)
{
CloseableHttpResponse response = httpClient.execute(new HttpGet("http://www.google.co.uk"), httpContext);
String responseBody = EntityUtils.toString(response.getEntity());
EntityUtils.consume(response.getEntity());
response.close();
}
I have tried using the code with and without response.close() but the times vary each run that I can't figure out which one is keeping the connection open.
Can somebody please explain to me how I can keep the connection open?

So after messing around with TCPView I figured out that placing the lines:
CloseableHttpClient httpClient = HttpClients.createDefault();
HttpClientContext httpContext = HttpClientContext.create();
inside of the loop used a new TCP connection each time. Turns out that HttpClient will automatically try and reuse the connection for the same 'HttpClient' object.

Related

How to Get Cached HttpResponse (Apache HttpClient)

I need to compare the results of my old (cached) response and the new response I got from a certain request. But I have no idea how to get the cached response.
CloseableHttpClient httpClient = CachingHttpClients.createMemoryBound();
CloseableHttpResponse httpResponse = httpClient(new HttpGet("http://www.example.com/path/to/file.json"));
InputStream fromUpstream = response.getEntity().getContent();
InputStream fromCache = ???;
// Compare fromUpstream and fromCache
...
What I’ve been doing up until now is use an HttpCacheStorage to do this, like so:
HttpCacheStorage cacheStorage = new BasicHttpCacheStorage(CacheConfig.DEFAULT);
CloseableHttpClient httpClient = CachingHttpClients.custom()
.setHttpCacheStorage(cacheStorage)
.build();
String url = "http://www.example.com/path/to/file.json";
CloseableHttpResponse httpResponse = httpClient(new HttpGet(url));
InputStream fromUpstream = httpResponse.getEntity().getContent();
InputStream fromCache = cacheStorage.getEntry(constructCacheEntryKeyFromUrl(url)).getResource().getInputStream();
And this works. But what I hate about it is the fact that the key for the cached entry is not-so-straightforward. I have to reconstruct the URL to include a port number (i.e. http://www.example.com:80/path/to/file.json).
I know that technically, I'm comparing InputStreams, but it'd be great if I can compare actual HttpResponses.

Android/PHP/APACHE - POST method doesn't work only with HTTPRequest from Android

I've got a problem. I configured myself a Debian server with an Apache/MySQL/PHPMyAdmin and PHP5. Everything is working very well when I do some test from my browser on my PC.
But this server will be used as a Web Service for my Android Application. And when I try to send my POST HTTPRequest from my Android app, the server doesn't read any POST data.
This is my HTTPRequest code:
HttpParams httpParameters = new BasicHttpParams();
HttpConnectionParams.setConnectionTimeout(httpParameters, timeoutConnection);
HttpConnectionParams.setSoTimeout(httpParameters, timeoutSocket);
HttpClient httpClient = new DefaultHttpClient(httpParameters);
HttpPost httpPost = new HttpPost(AbstractServiceKeys.URL);
try {
MultipartEntityBuilder entity = MultipartEntityBuilder.create();
for(int index=0; index < params.size(); index++) {
if(params.get(index).getName().equalsIgnoreCase("avatar")) {
entity.addPart(params.get(index).getName(), new FileBody( new File (params.get(index).getValue())) );
} else {
entity.addTextBody(params.get(index).getName(), params.get(index).getValue());
}
}
entity.addTextBody("lang", Locale.getDefault().getLanguage());
httpPost.setEntity(entity.build());
HttpResponse httpResponse = httpClient.execute(httpPost);
HttpEntity httpEntity = httpResponse.getEntity();
.....
To see if datas have been correctly sent, I do this on the PHP server side :
print_r($_POST);
print_r($_REQUEST);
It answer me :
Array()
Array()
I know that the problem comes from my server because I tested this on an another server from a friend. But now, I don't know what to do.
Please help mens !
[EDIT] : I found the problem but I can't understand why it didn't work before.
My URL was :
http: //[server_domain_name.com]/index.php
I change it to :
http: //[server_ip]/index.php
And it worked. I don't understand. It's really strange...

connection persistence using httpclient

i do multiple request to the same url using httpclient.execute(request).
Can I re-use the connection for the consecutive requests?
how can i optimise the code without declaring HttpClient again and again.
for(int i=0;i<=50;i++)
{
HttpClient client = new DefaultHttpClient();
HttpGet request = new HttpGet("my_url");
HttpResponse response = client.execute(request);
System.out.println(response.getStatusLine().getStatusCode());
}
In order to use a single client in your code (based on Exception using HttpRequest.execute(): Invalid use of SingleClientConnManager: connection still allocated and Lars Vogel Apache HttpClient - Tutorial):
Step 1. Move the client generation outside the for-loop.
Step 2. You should read the response content and close the stream. If you don't do this you will get the following exception
Exception in thread "main" java.lang.IllegalStateException:
Invalid use of SingleClientConnManager: connection still allocated.
In code:
//step 1
HttpClient client = new DefaultHttpClient();
for(int i=0;i<=50;i++) {
HttpGet request = new HttpGet("my_url");
HttpResponse response = client.execute(request);
System.out.println(response.getStatusLine().getStatusCode());
//step 2
BufferedReader br = new BufferedReader(
new InputStreamReader(response.getEntity().getContent()));
//since you won't use the response content, just close the stream
br.close();
}
try below.
HttpUriRequest httpGet = new HttpGet(uri);
DefaultHttpClient defaultHttpClient = new DefaultHttpClient();
HttpResponse httpResponse = defaultHttpClient.execute(httpGet);

Android HttpClient and Cookies

I have a problem with the HttpClient in Android: By using the following code, I want to use the cookies which are already set before by logging in through a webview. So the login data should be there and is indeed there, I tested it. But when I use the cookies in an httppost or httpget it doesn't use the login data. but these cookies actually should be enough to receive that page for which a login is necessary, shouldn't they? I'm not really sure if I need to send the cookies in a special way to the server or so or if it is enough to load it into the httpcontext. Here is the code:
DefaultHttpClient httpclient = new DefaultHttpClient();
CookieStore lCS = new BasicCookieStore();
if (CookieManager.getInstance().getCookie(pUrl) != null) {
String cookieString = CookieManager.getInstance().getCookie(pUrl);
String[] urlCookieArray = cookieString.split(";");
for (int i = 0; i < urlCookieArray.length; i++) {
System.out.println(urlCookieArray[i]);
String[] singleCookie = urlCookieArray[i].split("=");
Cookie urlCookie = new BasicClientCookie(singleCookie[0], singleCookie[1]);
lCS.addCookie(urlCookie);
}
}
HttpContext localContext = new BasicHttpContext();
httpclient.setCookieStore(lCS);
localContext.setAttribute(ClientContext.COOKIE_STORE, lCS);
HttpPost httppost = new HttpPost(pUrl);
// get the url connection
try {
StringBuilder sb = new StringBuilder();
HttpResponse response = httpclient.execute(httppost, localContext);
InputStream is = response.getEntity().getContent();
InputStreamReader isr = new InputStreamReader(is);
And if I run the code I only receive the login page of that site, so it didn't accept the cookie.
Thanks for help in advance
Greets, timo
I had the same problem and I used similar approach as in the question with no luck.
The thing that made it work for me was to add the domain for each copied cookie.
(BasicClientCookie cookie.setDomain(String))
My util function:
public static BasicCookieStore getCookieStore(String cookies, String domain) {
String[] cookieValues = cookies.split(";");
BasicCookieStore cs = new BasicCookieStore();
BasicClientCookie cookie;
for (int i = 0; i < cookieValues.length; i++) {
String[] split = cookieValues[i].split("=");
if (split.length == 2)
cookie = new BasicClientCookie(split[0], split[1]);
else
cookie = new BasicClientCookie(split[0], null);
cookie.setDomain(domain);
cs.addCookie(cookie);
}
return cs;
}
String cookies = CookieManager.getInstance().getCookie(url);
BasicCookieStore lCS = getCookieStore(cookies, MyApp.sDomain);
HttpContext localContext = new BasicHttpContext();
DefaultHttpClient httpclient = new DefaultHttpClient();
httpclient.setCookieStore(lCS);
localContext.setAttribute(ClientContext.COOKIE_STORE, lCS);
...
if you still have this problem, be careful with the given cookies, some might be malformed, check these two sites out:
http://www.codeproject.com/Articles/3106/On-The-Care-and-Handling-of-Cookies
this one helped me:
Getting "Set-Cookie" header
It seems you are copying the cookies correctly, and generally you don't need to do anything special for HttpClient to send the cookies. However, some of those may be bound to a session, and when you open a new connection with HttpClient you open a new session. The server will probably ignore cookies that don't match the current session. This might work if the session ID is in a cookie and you are able to get into the same session, but you really need to know exactly what the server does.

Multiple GET requests to a single site (canonical) (java)

Hi I am trying to make 2 GET requests to a single connection. ie
HttpGet get1 = new HttpGet("http://www.google.com/search?q=HelloWorld");
HttpGet get2 = new HttpGet("http://www.google.com/search?q=SecondSearch");
HttpResponse response = null;
response = client.execute(get1);
response = client.execute(get2);
I would like to get the body from the second execution. Obviously this fails, because it says you must release the connection first. I need to maintain the exact session - for instance, if I navigate to a site where the first step is to login, I need to navigate to any subsequent pages with the same cookie.
It's probably something incredibly simple that I am doing wrong!
You need to use a CookieStore
CookieStore cookieStore = new BasicCookieStore();
DefaultHttpClient client1 = new DefaultHttpClient();
client1.setCookieStore(cookieStore);
HttpGet httpGet1 = new HttpGet("...");
HttpResponse response1 = client1.execute(httpGet1);
DefaultHttpClient client2 = new DefaultHttpClient();
client2.setCookieStore(cookieStore);
HttpGet httpGet2 = new HttpGet("...");
HttpResponse response2 = client2.execute(httpGet2);
In the above code, both client2 will re-use cookies from the client1 request.

Categories

Resources