I am trying to login to my TLS1.2 server on an old Android device running Jellybean 4.1.2, with the BouncyCastle (SpongyCastle) library, but it doesn't work. That version of Android does not have TLS enabled by default, so I needed the 3rd party lib to use it.
There are two problems.
1. I get a HTTP 302 instead of a JSON response.
2. I don't know how to send a JSON payload (for other endpoints I'll be using
With the HTTP 302, I get the following response:
Result: HTTP/1.1 302 Found
Server: Apache-Coyote/1.1
Cache-Control: private
Expires: Thu, 01 Jan 1970 00:00:00 UTC
Set-Cookie: JSESSIONID=83C535625CDEF9DEC3D7890F1A9C86B0; Path=/; Secure; HttpOnly
Location: https://www.google.com/login/auth Content-Length: 0
Date: Wed, 14 Mar 2018 15:32:19 GMT
Via: 1.1 google
Set-Cookie: GCLB=CMfzgbfeh7bLpwE; path=/; HttpOnly
Alt-Svc: clear
Connection: close
So it seems its trying to redirect to some sort of Google login, which is weird.
Also, with number 2 above, where I'm trying to send a payload, do I just add another output.write(myJSONPayload); or do I have to do something else?
My code is as follows:
{
java.security.SecureRandom secureRandom = new java.security.SecureRandom();
Socket socket = new Socket("www.myserver.com", 443);
TlsClientProtocol protocol = new TlsClientProtocol(socket.getInputStream(), socket.getOutputStream(), secureRandom);
DefaultTlsClient client = new DefaultTlsClient() {
public TlsAuthentication getAuthentication() throws IOException {
TlsAuthentication auth = new TlsAuthentication() {
// Capture the server certificate information!
public void notifyServerCertificate(Certificate serverCertificate) throws IOException {
}
public TlsCredentials getClientCredentials(CertificateRequest certificateRequest) throws IOException {
return null;
}
};
return auth;
}
};
protocol.connect(client);
java.io.OutputStream output = protocol.getOutputStream();
output.write("GET / HTTP/1.1\r\n".getBytes("UTF-8"));
//Get auth with my own class to generate base 64 encoding
output.write(("Authorization: " + BasicAuthentication.getAuthenticationHeader("myuser", "mypass")).getBytes());
output.write("Host: www.myserver.com/logon\r\n".getBytes("UTF-8"));
output.write("Connection: close\r\n".getBytes("UTF-8")); // So the server will close socket immediately.
output.write("\r\n".getBytes("UTF-8")); // HTTP1.1 requirement: last line must be empty line.
output.flush();
java.io.InputStream input = protocol.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(input));
String line;
StringBuilder sb = new StringBuilder();
try {
while ((line = reader.readLine()) != null) {
Log.d(TAG, "--> " + line);
sb.append(line).append("\n");
}
} catch (TlsNoCloseNotifyException e) {
Log.d(TAG, "End of stream");
}
String result = sb.toString();
Log.d(TAG, "Result: " + result);
}
Another question, do I have the correct HOST specified? Am I right to have the base URL in the Socket, and the full URL in the OutputStream?
The solution here was to add this method to my custom SSLSocketFactory:
private static void setupSecurityForTLS() {
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.KITKAT) {
Log.d(TAG, "Adding new security provider");
Security.insertProviderAt(new BouncyCastleJsseProvider(), 1);
Security.insertProviderAt(new BouncyCastleProvider(), 2);
}
}
and call it BEFORE I initialise the socket.
You can also add the 2 lines to a static initialiser at the top of the class, eg:
static {
Security.insertProviderAt(new BouncyCastleJsseProvider(), 1);
Security.insertProviderAt(new BouncyCastleProvider(), 2);
}
Related
I've been using in my app HttpResponseCache successfully, but when my phone updated to Lollipop I realized that HttpResponseCache now never get "hit", always do the network request. I've confirmed that in Android versions pre Lollipop are still working well.
Maybe it's something that I did wrong and with new Android changes it has been appeared.
Has anyone any idea?
My code:
Application class, onCreate...
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
try {
File httpCacheDir = new File(getApplicationContext().getCacheDir()
, "http");
long httpCacheSize = 10 * 1024 * 1024;
HttpResponseCache.install(httpCacheDir, httpCacheSize);
} catch (IOException e) {
Log.i(TAG, "HTTP response cache installation failed:" + e);
}
} else {
try {
File httpCacheDir = new File(getCacheDir(), "http");
long httpCacheSize = 10 * 1024 * 1024;
Class.forName("android.net.http.HttpResponseCache")
.getMethod("install", File.class, long.class)
.invoke(null, httpCacheDir, httpCacheSize);
} catch (Exception e) {
Log.i(TAG, "HTTP response cache installation failed:" +
}
}
Function to manage request
public static InputStream fetchInputStream(String strURL, boolean forceRefresh)
throws IOException {
HttpURLConnection mHttpConn = null;
InputStream inputStream = null;
URL url = new URL(strURL);
HttpResponseCache cache;
try {
mHttpConn = (HttpURLConnection) url.openConnection();
if (forceRefresh) {
mHttpConn.addRequestProperty("Cache-Control", "no-cache");
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
cache = HttpResponseCache.getInstalled();
if (cache != null) {
Log.i("TEST CACHE", "TEST PETICION: Req count: "
+ cache.getRequestCount() + ", hit count "
+ cache.getHitCount() + ", netWork count "
+ cache.getNetworkCount() + " size = "
+ cache.size() + " <-----------------");
}
}
mHttpConn.setUseCaches(true);
mHttpConn.setDefaultUseCaches(true);
mHttpConn.setRequestMethod("GET");
mHttpConn.setConnectTimeout(30000);
mHttpConn.setReadTimeout(30000);
mHttpConn.connect();
if (mHttpConn.getResponseCode() == HttpURLConnection.HTTP_OK) {
inputStream = mHttpConn.getInputStream();
}
} catch (IOException ex) {
Log.e("NetworkConnectionManager InputStream", "Exception opening ["
+ strURL + "] ->", ex);
mHttpConn.disconnect();
throw ex;
}
return inputStream;
}
After every request
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
HttpResponseCache cache = HttpResponseCache.getInstalled();
if (cache != null) {
cache.flush();
}
}
Example request header:
Cache-Control → max-age=300
Connection → keep-alive
Content-Encoding → gzip
Content-Type → application/json; charset=utf-8
Date → Wed, 08 Apr 2015 12:37:35 GMT
Expires → Wed, 08 Apr 2015 12:42:35 GMT
Last-Modified → Wed, 08 Apr 2015 12:37:35 GMT
Server → nginx
Transfer-Encoding → chunked
Vary → Accept-Encoding
X-Cached → MISS
After having this problem for days I ran into this issue. It is fixed again in Marshmallow.
It is a bug in lollipop where the Vary - > Accept-Encoding header breaks the cache because Accept-Encoding gets filled in by default but not written away.
Here is a link to the issue:
https://code.google.com/p/android/issues/detail?id=162475
The fix is to set the Accept-Encoding explicitly:
Accept-Encoding -> gzip
or
Accept-Encoding -> identity
On the reading side you have to add this to the reading of the input stream:
String encoding = urlConnection.getHeaderField("Content-Encoding");
boolean gzipped = encoding!=null && encoding.toLowerCase().contains("gzip");
Inputstream inputStream;
if(gzipped)
inputStream = new GZIPInputStream(urlConnection.getInputStream());
else
inputstream = urlConnection.getInputStream();
I've had similar problem. I was expecting images to be cached but they weren't.
What turned out to be the problem was that I was not closing InputStream after it being read into a Bitmap.
Your fetchInputStream returns an InputStream that it got from http connection, make sure you close it properly.
The android http cache will not save a resource until you close the connection's InputStream.
My current app is taking a picture. Once the picture has been taken, it should automatically send the picture to my webservice so i can see it being saved on my computer, just for a starter.
My current code for the android part is as follows:
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE_CONTENT_RESOLVER) {
if (resultCode == RESULT_OK) {
String[] projection = { MediaStore.MediaColumns._ID,
MediaStore.Images.ImageColumns.ORIENTATION,
MediaStore.Images.Media.DATA };
Cursor cursor = getContentResolver().query(imageFilePath,
projection, null, null, null);
cursor.moveToFirst();
imageFileName = cursor.getString(cursor
.getColumnIndexOrThrow(MediaStore.Images.Media.DATA));
Toast.makeText(this, imageFileName, Toast.LENGTH_LONG).show();
Log.i("Image", imageFileName);
Log.i("Image", imageFilePath.toString());
try {
bm = BitmapFactory.decodeFile(imageFileName);
if (bm == null) {
throw new Exception("no picture!");
}
new FetchItemsTask().execute();
} catch (Exception e) {
e.printStackTrace();
}
}
}
};
class FetchItemsTask extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... params) {
try {
Log.i("Response", "Entered doInBackground");
ByteArrayOutputStream bos = new ByteArrayOutputStream();
bm.compress(CompressFormat.JPEG, 50, bos);
byte[] data = bos.toByteArray();
HttpClient httpClient = new DefaultHttpClient();
HttpPut putRequest = new HttpPut(URL_SERVER);
Log.i("Response", "Sending HTTP to "
+ putRequest.getURI().toASCIIString());
File file = new File(imageFileName);
ByteArrayBody bab = new ByteArrayBody(data, file.getName());
MultipartEntity reqEntity = new MultipartEntity(
HttpMultipartMode.BROWSER_COMPATIBLE);
reqEntity.addPart("image", bab);
putRequest.setEntity(reqEntity);
Log.i("Response", "postRequest is: " + putRequest);
HttpResponse response = httpClient.execute(putRequest);
Log.i("Response", "Response is: " + response);
Log.i("Response", "Status is: " + response.getStatusLine());
BufferedReader newReader = new BufferedReader(new FileReader(imageFileName));
//BufferedReader reader = new BufferedReader(
// new InputStreamReader(
// response.getEntity().getContent(), "UTF-8"));
String sResponse;
StringBuilder s = new StringBuilder();
while ((sResponse = newReader.readLine()) != null) {
s = s.append(sResponse);
}
} catch (Exception e) {
// handle exception here
e.printStackTrace();
}
return null;
}
}
For my webservice, the code i have is this:
#PUT
#Consumes({MediaType.MULTIPART_FORM_DATA})
#Produces({MediaType.TEXT_PLAIN})
#Path("/image")
public Response uploadImage(
#FormDataParam("image") InputStream fileInputStream,
#FormDataParam("image") FormDataContentDisposition contentDispositionHeader) {
String filePath = SERVER_UPLOAD_LOCATION_FOLDER + contentDispositionHeader.getFileName();
// save the file to the server
saveToFile(fileInputStream, filePath);
String output = "File saved to server location : " + filePath;
return Response.status(200).entity(output).build();
}
My log file tells me this, and i cannot figure out where the problem lies.
HTTP/1.1 500 Internal Server Error
Server: Apache-Coyote/1.1
Content-Type: text/html;charset=utf-8
Content-Language: en
Content-Length: 8100
Date: Fri, 28 Nov 2014 13:02:30 GMT
Connection: close
<!DOCTYPE html><html><head><title>Apache Tomcat/8.0.15 - Error report</title><style type="text/css">H1 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:22px;} H2 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:16px;} H3 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:14px;} BODY {font-family:Tahoma,Arial,sans-serif;color:black;background-color:white;} B {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;} P {font-family:Tahoma,Arial,sans-serif;background:white;color:black;font-size:12px;}A {color : black;}A.name {color : black;}.line {height: 1px; background-color: #525D76; border: none;}</style> </head><body><h1>HTTP Status 500 - org.glassfish.jersey.server.ContainerException: java.lang.NoSuchMethodError: org.glassfish.jersey.server.CloseableService.add(Ljava/io/Closeable;)V</h1><div class="line"></div><p><b>type</b> Exception report</p><p><b>message</b> <u>org.glassfish.jersey.server.ContainerException: java.lang.NoSuchMethodError: org.glassfish.jersey.server.CloseableService.add(Ljava/io/Closeable;)V</u></p><p><b>description</b> <u>The server encountered an internal error that prevented it from fulfilling this request.</u></p><p><b>exception</b></p><pre>javax.servlet.ServletException: org.glassfish.jersey.server.ContainerException: java.lang.NoSuchMethodError: org.glassfish.jersey.server.CloseableService.add(Ljava/io/Closeable;)V
org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:393)
org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:381)
org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:344)
org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:221)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
com.google.inject.servlet.FilterChainInvocation.doFilter(FilterChainInvocation.java:66)
com.google.inject.servlet.ManagedFilterPipeline.dispatch(ManagedFilterPipeline.java:118)
com.google.inject.servlet.GuiceFilter.doFilter(GuiceFilter.java:113)
</pre><p><b>root cause</b></p><pre>org.glassfish.jersey.server.ContainerException: java.lang.NoSuchMethodError: org.glassfish.jersey.server.CloseableService.add(Ljava/io/Closeable;)V
org.glassfish.jersey.servlet.internal.ResponseWriter.rethrow(ResponseWriter.java:256)
org.glassfish.jersey.servlet.internal.ResponseWriter.failure(ResponseWriter.java:238)
org.glassfish.jersey.server.ServerRuntime$Responder.process(ServerRuntime.java:439)
org.glassfish.jersey.server.ServerRuntime$1.run(ServerRuntime.java:277)
org.glassfish.jersey.internal.Errors$1.call(Errors.java:271)
org.glassfish.jersey.internal.Errors$1.call(Errors.java:267)
org.glassfish.jersey.internal.Errors.process(Errors.java:315)
org.glassfish.jersey.internal.Errors.process(Errors.java:297)
org.glassfish.jersey.internal.Errors.process(Errors.java:267)
org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:297)
org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:254)
org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:1030)
org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:373)
org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:381)
org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:344)
org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:221)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
com.google.inject.servlet.FilterChainInvocation.doFilter(FilterChainInvocation.java:66)
com.google.inject.servlet.ManagedFilterPipeline.dispatch(ManagedFilterPipeline.java:118)
com.google.inject.servlet.GuiceFilter.doFilter(GuiceFilter.java:113)
</pre><p><b>root cause</b></p><pre>java.lang.NoSuchMethodError: org.glassfish.jersey.server.CloseableService.add(Ljava/io/Closeable;)V
org.glassfish.jersey.media.multipart.internal.MultiPartReaderServerSide.readMultiPart(MultiPartReaderServerSide.java:90)
org.glassfish.jersey.media.multipart.internal.MultiPartReaderClientSide.readFrom(MultiPartReaderClientSide.java:179)
org.glassfish.jersey.media.multipart.internal.MultiPartReaderClientSide.readFrom(MultiPartReaderClientSide.java:91)
org.glassfish.jersey.message.internal.ReaderInterceptorExecutor$TerminalReaderInterceptor.invokeReadFrom(ReaderInterceptorExecutor.java:258)
org.glassfish.jersey.message.internal.ReaderInterceptorExecutor$TerminalReaderInterceptor.aroundReadFrom(ReaderInterceptorExecutor.java:234)
org.glassfish.jersey.message.internal.ReaderInterceptorExecutor.proceed(ReaderInterceptorExecutor.java:154)
org.glassfish.jersey.server.internal.MappableExceptionWrapperInterceptor.aroundReadFrom(MappableExceptionWrapperInterceptor.java:73)
org.glassfish.jersey.message.internal.ReaderInterceptorExecutor.proceed(ReaderInterceptorExecutor.java:154)
org.glassfish.jersey.message.internal.MessageBodyFactory.readFrom(MessageBodyFactory.java:1124)
org.glassfish.jersey.message.internal.InboundMessageContext.readEntity(InboundMessageContext.java:851)
org.glassfish.jersey.message.internal.InboundMessageContext.readEntity(InboundMessageContext.java:783)
org.glassfish.jersey.server.ContainerRequest.readEntity(ContainerRequest.java:233)
org.glassfish.jersey.media.multipart.internal.FormDataParamValueFactoryProvider.getEntity(FormDataParamValueFactoryProvider.java:369)
org.glassfish.jersey.media.multipart.internal.FormDataParamValueFactoryProvider.access$000(FormDataParamValueFactoryProvider.java:86)
org.glassfish.jersey.media.multipart.internal.FormDataParamValueFactoryProvider$FormDataParamValueFactory.provide(FormDataParamValueFactoryProvider.java:201)
org.glassfish.jersey.server.spi.internal.ParameterValueHelper.getParameterValues(ParameterValueHelper.java:81)
org.glassfish.jersey.server.model.internal.JavaResourceMethodDispatcherProvider$AbstractMethodParamInvoker.getParamValues(JavaResourceMethodDispatcherProvider.java:121)
org.glassfish.jersey.server.model.internal.JavaResourceMethodDispatcherProvider$ResponseOutInvoker.doDispatch(JavaResourceMethodDispatcherProvider.java:152)
org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.dispatch(AbstractJavaResourceMethodDispatcher.java:104)
org.glassfish.jersey.server.model.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:384)
org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:342)
org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:101)
org.glassfish.jersey.server.ServerRuntime$1.run(ServerRuntime.java:271)
org.glassfish.jersey.internal.Errors$1.call(Errors.java:271)
org.glassfish.jersey.internal.Errors$1.call(Errors.java:267)
org.glassfish.jersey.internal.Errors.process(Errors.java:315)
org.glassfish.jersey.internal.Errors.process(Errors.java:297)
org.glassfish.jersey.internal.Errors.process(Errors.java:267)
org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:297)
org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:254)
org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:1030)
org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:373)
org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:381)
org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:344)
org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:221)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
com.google.inject.servlet.FilterChainInvocation.doFilter(FilterChainInvocation.java:66)
com.google.inject.servlet.ManagedFilterPipeline.dispatch(ManagedFilterPipeline.java:118)
com.google.inject.servlet.GuiceFilter.doFilter(GuiceFilter.java:113)
</pre><p><b>note</b> <u>The full stack trace of the root cause is available in the Apache Tomcat/8.0.15 logs.</u></p><hr class="line"><h3>Apache Tomcat/8.0.15</h3></body></html>
And this :
28-Nov-2014 14:02:30.252 INFO [http-nio-8080-exec-161] org.glassfish.jersey.filter.LoggingFilter.log 6 * Server has received a request on thread http-nio-8080-exec-161
6 > PUT http://127.0.0.1:9876/webservice-1.0-SNAPSHOT/DirectorResource/image
6 > connection: Keep-Alive
6 > content-length: 16038
6 > content-type: multipart/form-data; boundary=IdmG6B4wBROo8soEP9rPHGgqDxSThQJGb
6 > host: 127.0.0.1:9876
6 > user-agent: Apache-HttpClient/UNAVAILABLE (java 1.4)
--IdmG6B4wBROo8soEP9rPHGgqDxSThQJGb
Content-Disposition: form-data; name="image"; filename="1417179326131.jpg"
Content-Type: application/octet-stream
If you need any more code, let me know, but i thought this was what was needed. Thanks!
I had this problem as well, and I fixed it by upgrading all my Jersey libs to 2.9 in my pom.xml file. I think the root cause of my problem was that the jersey-container-servlet, jersey-container-servlet-core, and jersey-media-multipart libs were not the same version. I had 2.8 jersey-container-servlet-core and jersey-container-servlet, and 2.7 of jersey-media-multipart.
The funny thing is: I may have accidentally found the solution for Is it possible to send HTTP request using plain socket connection and receive response without headers?. I hope I'm overlooking something.
Anyway, I'm connecting to a web server, send a HTTP request, receive the response and close the connection. The actual HTTP conversation (tcpdump on the server side) looks like this:
GET /blah.php?param1=test1t¶m2=test2 HTTP/1.0
HTTP/1.1 200 OK
Date: Sat, 22 Sep 2012 10:16:46 GMT
Server: Apache/2.2.17 (Ubuntu)
X-Powered-By: PHP/5.3.5-1ubuntu7.8
Vary: Accept-Encoding
Content-Length: 17
Connection: close
Content-Type: text/html
<pre>173364</pre>
Cool. It works... so far. Now this is the code. The string szRetval contains only "<pre>173364</pre>".
Socket s = new Socket("1.2.3.4", 80);
//DataInputStream in = new DataInputStream(s.getInputStream());
BufferedReader bin = new BufferedReader(new InputStreamReader(s.getInputStream()));
DataOutputStream out = new DataOutputStream(s.getOutputStream());
out.writeBytes(szRequest);
String szRetval = "";
String szLine = "";
while((szLine=bin.readLine())!=null) {
szRetval += szLine;
}
s.close();
return szRetval;
As you can see from the code sample, I've already switched from DataInputStream to BufferedReader. It makes no difference, so I guess this has to do with the Socket class itself.
Why o why are the http response headers not returned by a (raw) socket??
Android 2.3.3, Network I/O in AsyncTask, not using proxy.
I have a following class
public class MyHttpClient {
private static HttpClient httpClient = null;
public static HttpClient getHttpClient() {
if (httpClient == null)
httpClient = new DefaultHttpClient();
return httpClient;
}
public static String HttpGetRequest(String url) throws IOException {
HttpGet request = new HttpGet(url);
HttpResponse response = null;
InputStream stream = null;
String result = "";
try {
response = getHttpClient().execute(request);
if (response.getStatusLine().getStatusCode() != 200)
response = null;
else
stream = response.getEntity().getContent();
String line = "";
StringBuilder total = new StringBuilder();
BufferedReader rd = new BufferedReader(new InputStreamReader(stream));
while ((line = rd.readLine()) != null) {
total.append(line);
}
// Return full string
result = total.toString();
} catch (ClientProtocolException e) {
response = null;
stream = null;
result = null;
} catch (IllegalStateException e) {
response = null;
stream = null;
result = null;
}
return result;
}
}
and a web-service which response header is (I can't provide direct link because of privacy)
Status: HTTP/1.1 200
OK Cache-Control: private
Content-Type: application/json;
charset=utf-8
Content-Encoding: gzip
Server: Microsoft-IIS/7.5
X-AspNetMvc-Version: 3.0
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Date: Sun, 03
Jul 2011 11:00:43 GMT
Connection: close
Content-Length: 8134
In the end I get as a result series of weird, unreadable characters (I should get regular JSON like I get in regular desktop browser).
Where is the problem? (The same code for ex. google.com works perfectly and I get nice result)
EDIT: Solution (see below for description)
Replace
HttpGet request = new HttpGet(url);
with
HttpUriRequest request = new HttpGet(url);
request.addHeader("Accept-Encoding", "gzip");
and replace
stream = response.getEntity().getContent();
with
stream = response.getEntity().getContent();
Header contentEncoding = response.getFirstHeader("Content-Encoding");
if (contentEncoding != null && contentEncoding.getValue().equalsIgnoreCase("gzip")) {
stream = new GZIPInputStream(stream);
}
The problem is here:
Content-Encoding: gzip
This means the weird characters you are getting are the gzip compressed version of the expected JSON. Your browser does the decmpression so there you see the decoded result. You should have a look at your request header and at the configuration of your server.
Well, gzip encoding is generally good practice - for JSON data (especially big one) it can actually get between 10x and 20x decrease in the amount of data to transfer (which is a GOOD THING).. So better is to let HttpClient to handle GZIP compression nicely. For example here:
http://forrst.com/posts/Enabling_GZip_compression_with_HttpClient-u0X
BTW. It seems wrong however on the server side to provide GZIP compressed data when the client does not say "Accept-Encoding: gzip", which seems to be the case... So some things have to be corrected on the server as well. The example above adds Accept-Encoding header for you.
I'm going to create mobile application that works with CommuniGate Pro server.
For example, I need to make the following Android Client C - CGP Server S conversation and get XIMSS.nonce node value:
C:GET /ximsslogin/ HTTP/1.1
Host: myserver.com
Content-Type: text/xml
Content-Length: 42
<XIMSS><listFeatures id="list" /><XIMSS>
S:HTTP/1.1 200 OK
Content-Length: 231
Connection: keep-alive
Content-Type: text/xml;charset=utf-8
Server: CommuniGatePro/5.3
<XIMSS><nonce>2C3E575E5498CE63574D40F18D00C873</nonce><language>german</language><response id="s"/></XIMSS>
Example, in ActionScript 3.0 it looks this way:
var loader:Loader = new Loader();
loader.addEventListener(Event.COMPLETE, completeHandler);
var urlRequest:URLRequest = new URLRequest(...);
urlRequest.method = ...;
urlRequest.data = ...;
loader.load(urlRequest);
private function completeHandler(...):void { ... };
How will it look in Java for Android 2.1?
As Schnapple says your question seems very broad and is confusing to read and understand.
Here is some general code to send a HTTP POST and get a response from a server though that may be helpful.
public String postPage(String url, File data, boolean returnAddr) {
ret = null;
httpClient.getParams().setParameter(ClientPNames.COOKIE_POLICY, CookiePolicy.RFC_2109);
httpPost = new HttpPost(url);
response = null;
FileEntity tmp = null;
tmp = new FileEntity(data,"UTF-8");
httpPost.setEntity(tmp);
try {
response = httpClient.execute(httpPost,localContext);
} catch (ClientProtocolException e) {
System.out.println("HTTPHelp : ClientProtocolException : "+e);
} catch (IOException e) {
System.out.println("HTTPHelp : IOException : "+e);
}
ret = response.getStatusLine().toString();
return ret;
}