Android: How to determine if an HTTP PUT request has finished processing - java

Just wondering if anyone knows how to determine when a HTTP PUT request is complete. For eg:
HttpClient http = new DefaultHttpClient();
HttpPut putmethod = new HttpPut("http://abc.com/SETTINGS.TXT");
putmethod.setEntity(new StringEntity(data));
HttpResponse response = http.execute(putmethod);
How can I tell when the file has completely transferred/written. Do I need to monitor the HttpResponse? If so, what I am looking for?
Thanks

If your request is successfully complete then http client will return the success code 200 if it fails then it returns the another code (401 page not fount etc).
so you can check the code with the response and log appropriate message .
Example
HttpClient http = new DefaultHttpClient();
HttpPut putmethod = new HttpPut("http://abc.com/SETTINGS.TXT");
putmethod.setEntity(new StringEntity(data));
HttpResponse response = http.execute(putmethod);
if (response.getStatusLine().getStatusCode() == 200)
{
is = response.getEntity().getContent();
int ch;
sb = new StringBuffer();
while ((ch = is.read()) != -1) {
sb.append((char) ch);
}
// Log sb . it prints the response you get.
}

if you want check that file has completely transferred then try this..
String data = EntityUtils.toString(response.getEntity());
System.out.println("Data in .."+data);
in data you will get response from server...

Related

How can I forward HttpResponse to an open client socket? (Java Program acts as a proxy)

I am using httpclient lib from apache. I managed to get an HttpResponse by sending a GET request to the server. Now what I am trying to do is to send that response that I got to a clientSocket output stream.
So basically I want to send whatever I received from the server to the open client connection. Since I am using HttpClient I get the response in the form of an HttpResponse object. I tried the following:
private void forwardRequest(String header, String url){
try {
CloseableHttpClient httpclient = HttpClients.createDefault();
HttpGet httpget = new HttpGet(url);
CloseableHttpResponse response;
//Adding the request headers to httpget
String lines[] = header.split("\\n");
for (String str : lines) {
String parts[] = str.split(":", 2);
httpget.addHeader(parts[0], parts[1]);
}
HttpResponse respone;
response = httpclient.execute(httpget);
//It works till here I can read from the response and print out the html page
//But after this I don't know how to send it to client
OutputStream bos = clientSocket.getOutputStream();
PrintWriter pw = new PrintWriter(bos);
BufferedReader rd = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
while ((line = rd.readLine()) != null) {
pw.println(line);
//bos.write(line.getBytes()); //This also doesn't work
}
response.close();
}
Also clientSocket is a global variable which is associcated with a ServerSocket like:
clientSocket = serverSocket.accept();
I don't expect a full solution. Just point me in the right direction.. Thanks a ton!
EDIT:
I tried the following based on what EJP suggested.. It's still not working. I was wondering if it was correctly implemented?
int portNumber = 8012; // port on which the program listens
ServerSocket serverSocket =
new ServerSocket(portNumber); //the socket at which the program listens
Socket clientSocket = serverSocket.accept(); //clientSocket of the program
Socket toServer = new Socket("localhost", 8089); //proxy server to which program connects
PrintWriter out =
new PrintWriter(toServer.getOutputStream(), true);
PrintWriter outClient =
new PrintWriter(clientSocket.getOutputStream(), true);
BufferedReader in = new BufferedReader(
new InputStreamReader(clientSocket.getInputStream()));
BufferedReader inServer = new BufferedReader(
new InputStreamReader(toServer.getInputStream()));
) {
String inputLine;
while ((inputLine = in.readLine()) != null) {
out.println(inputLine); //Writing to proxy server
outClient.println(inServer.readLine()); //writing back to original request sender
System.out.println(inputLine);
}
The client made an HTTP request, so it will be expecting an HTTP response. If the global clientSocket is just a raw TCP socket and not an HttpClient, then you need to add the HTTP response protocol header yourself.
You have the content from the server, you'll want to first return an HTTP response 200 OK, then empty line with carriage return + linefeed (CR+LF), then Content-length: , then the document. If you are just proxying text documents, then you could convert to a string here, but otherwise, I would just pass the mime type, charset, and entity through as the raw bytes as the web server responded, that way you can proxy any document, including images or binary files.
It will look something like this:
HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: length
<html> ...
</html>
To pass the http headers through from the server:
HttpEntity entity = response.getEntity();
// technically you should check the HTTP response rather than assume it is a 200
int statusCode = httpResp.getStatusLine().getStatusCode();
if(statusCode != 200)
... // do something with non 200 responses ?
clientSocket.write("HTTP/1.1 200 OK\r\n");
Header[] responseHeaders = response.getAllHeaders();
for(Header header : responseHeaders) {
clientSocket.write(header.toString() + "\r\n");
}
clientSocket.write("\r\n"); // empty line required
// Use BufferedInputStream to deal in bytes
BufferedInputStream input = new BufferedInputStream(entity.getContent());
byte[] buf = new byte[8192];
int bytesRead;
while ((bytesRead = input.read(buf, 8192)) > 0) {
clientSocket.write(buf, bytesRead);
}
I say "something like this", don't take this literal, I doubt it compiles. I don't have dev station in front of me, but this is the general idea.
NOTE: Since you are using the Apache client lib, you should be able to use the specific HTTP client instead of writing the raw protocol. This will abstract the HTTP protocol away somewhat. I'll update the answer later if nobody else provides a better one.
If you're just forwarding requests and responses you don't have any need to engage in the HTTP protocol at all beyond the first line of the request. If the client knows you're the proxy you will get either a GET request with the full URL or else a CONNECT request ditto. All you have to do is connect to the target and then just copy bytes in both directions simultaneously.

HttpGet in Android/Java with GZip encoding

I am running MVC 4 on my server and to save a bit of data for my users I figured I would enable GZip encoding, to do this I simply used:
(C#)
Response.AddHeader("Content-Encoding", "gzip");
Response.Filter = new GZipStream(Response.Filter, CompressionMode.Compress);
In my android application I use:
(Java)
String response = "";
DefaultHttpClient client = new DefaultHttpClient();
HttpGet httpGet = new HttpGet(url);
try {
HttpResponse execute = client.execute(httpGet);
InputStream content = execute.getEntity().getContent();
BufferedReader buffer = new BufferedReader(
new InputStreamReader(content));
String s = "";
while ((s = buffer.readLine()) != null) {
response += s;
}
} catch (Exception e) {
e.printStackTrace();
}
return response;
When I use GZip the Java code nuts out and causes GC to run, I was never patient enough to wait for it to return.
When I took off GZip from the server it ran perfectly fine. The function to get the response returns straight away with no problem.
I tried adding this to the java code:
httpGet.addHeader("Accept-Encoding", "gzip");
With no success.
Question is, is there something I'm not getting? Can I not put the response in a stream if it is using GZip? Am I meant to use the stream and uncompress it after?
What am I doing wrong?
Instead of using
DefaultHttpClient client = new DefaultHttpClient();
you can use
ContentEncodingHttpClient client = new ContentEncodingHttpClient();
which is a subclass of DefaultHttpClient and supports GZIP content.
You need Apache HttpClient 4.1 for this.
If you have Apache HttpClient 4.2, you should use
DecompressingHttpClient client = new DecompressingHttpClient();
if you have Apache HttpClient 4.3, you should use the HttpClientBuilder

how to set parameters to server from android application?

I have the following code to connect from my android application to zappos api server and search for some stuff. But It either returns error 404 or We are unable to process the request from the input feilds given.
When I execute the same query it works on the web browser.
The query is:
http://api.zappos.com/Search&term=boots&key=<my_key_inserted_here>
Code:
HttpClient client = new DefaultHttpClient();
HttpPost post = new HttpPost("http://api.zappos.com/Search");
NameValuePair keypair = new BasicNameValuePair("key",KEY);
NameValuePair termpair = new BasicNameValuePair("term",data);
List<NameValuePair> params = new ArrayList<NameValuePair>(2);
params.add(keypair);
params.add(termpair);
post.setEntity(new UrlEncodedFormEntity(params));
HttpResponse response = client.execute(post);
String str;
StringBuilder sb = new StringBuilder();
HttpEntity entity =response.getEntity();
if (entity != null) {
DataInputStream in = new DataInputStream(entity.getContent());
while (( str = in.readLine()) != null){
sb.append(str);
}
in.close();
}
Log.i("serverInterface","response from server is :"+sb.toString());
What am I doing wrong?
If I am correct, what you want to do is a GET request with parameters.
Then,the code would looks like something like that:
HttpClient client = new DefaultHttpClient();
HttpGet get = new HttpGet("http://api.zappos.com/Search");
HttpParams params = new BasicHttpParams();
params.setParameter("key", "KEY");
params.setParameter("term", "data");
get.setParams(params);
HttpResponse response;
response = client.execute(get);
String str;
StringBuilder sb = new StringBuilder();
HttpEntity entity = response.getEntity();
if (entity != null) {
DataInputStream in;
in = new DataInputStream(entity.getContent());
while ((str = in.readLine()) != null) {
sb.append(str);
}
in.close();
}
Log.i("serverInterface", "response from server is :" + sb.toString());
I found an answer to the question based on ALL of your help. I got the hint that I must search how to connect to REST service and I also used this result. This is the exact result I was looking for. Sadly it resembles too much to what I'm trying to achieve that I think whoever asked it might be applying to the same position :(

Cleartrip Flight API - "Not authorized to access the service" error

I am using Cleartrip Flight API to get flight fare details. When request the URL with API key, i am getting "Not authorized to access the service" error. Here is my Java code using Apache HttpComponents
HttpHost proxy = new HttpHost("My IP", Port No, "http");
String url = "https://api.cleartrip.com/air/1.0/search?from=BOM&to=DEL&depart-date=2013-06-06&return-date=2013-06-06";
//String url = "http://www.google.com/search?q=developer";
HttpClient client = new DefaultHttpClient();
client.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY, proxy);
HttpGet request = new HttpGet(url);
// add request header
request.addHeader("X-CT-API-KEY", "My API Key");
request.addHeader("User-Agent", "Mozilla/5.0");
System.out.println(" header "+request.getHeaders("X-CT-API-KEY")[0]);
HttpResponse response = client.execute(request);
System.out.println("\nSending 'GET' request to URL : " + url);
System.out.println("Response Code : " +
response.getStatusLine().getStatusCode());
BufferedReader rd = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
StringBuffer result = new StringBuffer();
String line = "";
while ((line = rd.readLine()) != null) {
result.append(line);
}
System.out.println(result.toString());
}
Can anyone help me !!!
Even i had the same issue. Later i came to know that all the api (which you get during singn up process) are blocked by default. You have to write a mail to api.support#cleartrip.com
They will ask your company details, business model and business case. If they are satisfied with those details then they will unblock your api key.
Since my project is for my final semester they have rejected my api key query.
Here i am sharing my java code. So that it might be useful for some one.
HttpClient client = new DefaultHttpClient();
String getURL =URL;
Log.d("URL",getURL);
HttpGet get = new HttpGet(getURL);
get.setHeader("X-CT-API-KEY", (my api key));
HttpResponse responseGet = client.execute(get);
HttpEntity resEntityGet = responseGet.getEntity();
if (resEntityGet != null)
{
Log.i("GET ", EntityUtils.toString(resEntityGet));
}
Since i was not authorized to use this api i got the following response.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><faults xmlns="http://www.cleartrip.com/apigateway/common"><fault><fault-message>Not authorized to access the service</fault-message></fault></faults>
HTTP URL is as follows
https://api.cleartrip.com/air/1.0/search?from=BOM&to=DEL&depart-date=2013-11-11&return-date=2013-12-12

Getting URL after a redirect using HttpClient.Execute(HttpGet)

I have searched for a while and I am not finding a clear answer. I am trying to log into a webstie.
https://hrlink.healthnet.com/
This website redirects to a login page that is not consitent. I have to post my login credentials to the redirected URL.
Im am trying to code this in Java but I do not understand how to get the URL from the response. It may look a bit messy but I have it this way while I am testing.
HttpGet httpget = new HttpGet("https://hrlink.healthnet.com/");
HttpResponse response = httpclient.execute(httpget);HttpEntity entity = response.getEntity();
String redirectURL = "";
for(org.apache.http.Header header : response.getHeaders("Location")) {
redirectURL += "Location: " + header.getValue()) + "\r\n";
}
InputStream is;
is = entity.getContent();
BufferedReader reader = new BufferedReader(new InputStreamReader(is,"iso-8859-1"),8);
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null) {
sb.append(line + "\n");
}
is.close();
String result = sb.toString();
I know i get redirected because my result string shows be the actual login page but I am not able to get the new URL.
In FireFox I am using TamperData. When I navigate to this website https://hrlink.healthnet.com/ I have a GET with a 302 - Found and the Location of the Login Page. Then another GET to the actual Login Page
Any help is greatly appreciated thank you.
Check out w3c documentation:
10.3.3 302 Found
The temporary URI SHOULD be given by the Location field in the response. Unless the request method was HEAD, the entity of the response SHOULD contain a short hypertext note with a hyperlink to the new URI(s).
If the 302 status code is received in response to a request other than GET or HEAD, the user agent MUST NOT automatically redirect the request unless it can be confirmed by the user, since this might change the conditions under which the request was issued.
One solution is to use POST method to break auto-redirecting at client side:
HttpPost request1 = new HttpPost("https://hrlink.healthnet.com/");
HttpResponse response1 = httpclient.execute(request1);
// expect a 302 response.
if (response1.getStatusLine().getStatusCode() == 302) {
String redirectURL = response1.getFirstHeader("Location").getValue();
// no auto-redirecting at client side, need manual send the request.
HttpGet request2 = new HttpGet(redirectURL);
HttpResponse response2 = httpclient.execute(request2);
... ...
}
Hope this helps.

Categories