HttpGet in Android/Java with GZip encoding - java

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

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.

HTTP request not returning desired json

I am trying to send a http request to a website which is supposed to return a json response. The problem is that i am not getting the json data. But when i paste the url in a browser it displays the json output. Am a newbie. Kindly help.
Here is my code
HttpClient client = new DefaultHttpClient();
String url="http://directclientvendors.com/news24/api/get.php?type=news";
HttpGet request = new HttpGet(url);
HttpResponse response;
response = client.execute(request);
BufferedReader br =
new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
String line = "";
while(br.ready())
{
line+=br.readLine();
}
System.out.println("line "+line);
You should be executing a GET request and not a POST. Please change the request type to HttpGet. The browser executes a GET on the URL when you paste it on the address bar and hit enter.
Additionally use a Reader + StringBuilder / JsonReader / GSON to read from the URL's response content. String concatenation leads to the creation of additional objects unnecessarily.
[EDIT]
To my astonishment the API call works even when a POST call is made to get the resource. The problem must be in your parsing logic. Using a JsonReader works fine for me. This is just template code, but you can fill in the rest to get the other JSON elements. Regardless of whether POST works or not, you should still use GET for this call.
HttpClient client = new DefaultHttpClient();
HttpGet request = new HttpGet("http://directclientvendors.com/news24/api/get.php?type=news");
HttpResponse response = client.execute(request);
InputStream content = response.getEntity().getContent();
JsonReader jsonReader = new JsonReader(new InputStreamReader(content, "UTF-8"));
jsonReader.beginObject();
if(jsonReader.hasNext())
{
System.out.println(jsonReader.nextName()); // prints 'news'
// BEGIN_ARRAY etc to parse the rest
}
// END_OBJECT and cleanup

How to upload data using POST-query?

I have following problem: I'm developing the application which need to authorize on server and upload data from my mobile into it. The server side is ready and works correctly. So, for authorizing I use the following code:
URL url = new URL(VALIDATING_URL);
URLConnection connection=url.openConnection();
connection.setDoOutput(true);
PrintWriter out=new PrintWriter(connection.getOutputStream());
out.print(POST_QUERY_EMAIL+email);
out.print("&");
out.print(POST_QUERY_PASS+password);
out.print("&");
out.print(POST_QUERY_CHANNEL+channel);
out.close();
Scanner in=new Scanner(connection.getInputStream());
StringBuilder result=new StringBuilder();
while (in.hasNextLine()) {
result.append(in.nextLine());
result.append("\n");
}
in.close();
It works correctly, and the application will get needed result if I enter correctly data. So, now I need to upload data into server using POST-query, but I don't know how I can do it. Using HTML forms, video is usually uploaded using 'userfile' variable and will be got from $_FILES array in PHP scipts. How can I upload do it from Java? Can I just print data into PrintStream from InputStream?
Thank you, I hope you can help me
Try this,
public void postData() throws Exception {
HttpClient client = new DefaultHttpClient();
HttpPost httppost = new HttpPost("https://www.xyz.com");
List<NameValuePair> list = new ArrayList<NameValuePair>(1);
list.add(new BasicNameValuePair("name","ABC");
httppost.setEntity(new UrlEncodedFormEntity(list));
HttpResponse r = client.execute(httppost);
}
I would suggest reading this. It shows you how to do a POST with URLConnection and explains what's going on.

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

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...

Java client has trouble to read big responses from wcf rest service

I am trying to consume a rest WCF service using java client on android 2.1.
It works perfectly on small responses. When i tried to push a little further by getting 1000+ char response reader.read(buffer) failed to read all the characters. This caused the last line of the script to return: JsonException unterminated string at character 8193 "{plate,...
My android device starts to get this error before the emulator android stars to get it (character 1194 instead of 8193). Anyone knows how get the full message?
Client Code:
HttpGet request = new HttpGet(SERVICE_URI + "/GetPlates");
request.setHeader("Accept", "application/json");
request.setHeader("Content-type", "application/json");
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpResponse response = httpClient.execute(request);
HttpEntity responseEntity = response.getEntity();
char[] buffer = new char[(int)responseEntity.getContentLength()];
InputStream stream = responseEntity.getContent();
InputStreamReader reader = new InputStreamReader(stream);
reader.read(buffer);
stream.close();
JSONArray plates = new JSONArray(new String(buffer));
Server Config:
<webHttpBinding>
<binding name="big_webHttpBinding" maxReceivedMessageSize="4097152" maxBufferSize="4097152" maxBufferPoolSize="4097152">
<readerQuotas maxStringContentLength="4097152" maxArrayLength="4097152" maxBytesPerRead="4097152" maxNameTableCharCount="4097152" maxDepth="4097152"/>
</binding>
</webHttpBinding>
Instead of
char[] buffer = new char[(int)responseEntity.getContentLength()];
InputStream stream = responseEntity.getContent();
InputStreamReader reader = new InputStreamReader(stream);
reader.read(buffer);
stream.close();
do this:
String jsonText = EntityUtils.toString(responseEntity, HTTP.UTF_8);

Categories