HTTPS POST working on Gingerbread but not on Froyo? - android

Here's a section of code in question:
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
HttpClient mHttpClient = new DefaultHttpClient();
nameValuePairs.add(new BasicNameValuePair(strName1, strValue1));
nameValuePairs.add(new BasicNameValuePair(strName2, strValue2));
post = new HttpPost(strPostURL);
post.setEntity(new UrlEncodedFormEntity(nameValuePairs, HTTP.UTF_8));
HttpResponse response = mHttpClient.execute(post);
strPostURL begins with "https://".
This code fails on the last line - throws the following exception:
WARN/System.err(7151): org.apache.http.client.ClientProtocolException
WARN/System.err(7151): Caused by: org.apache.http.ProtocolException: The server failed to respond with a valid HTTP response
I've tried this code against both Froyo (2.2) and Gingerbread (2.3.3) platform and it only works on 2.3.3. Same results on emulators as well.
When I tried the regular HTTP POST on my test server, both Froyo and Gingerbread works fine, so there must be something particular about HTTPS that is causing this issue.
If matters, I am also using httpmime-4.1.2.jar for handling multi-part attachments at a later part of the code, so this jar is included in my build path.
Could someone kindly point out what am I doing wrong please?

Related

HttpClient request to HTTPS host goes to default nameserver

I am using Apache httpClient library in my android project to send get/post requests to the server. My server is set up using apache namevirtualhost - there are multiple virtual hosts on the same server.
For those not familiar with how apache namevirtualhost works, the simple explanation is that there are multiple configurations defined in the server config, and apache uses Host request header to determine which configuration to use. When multiple hosts are defined, the first one is considered default and all requests with Host request header not explicitly matching one of the defined namevirtualhosts will be handled using the default configuration.
Now, the server I'm trying to connect to is not the default one. When my app runs and the request is made to the server, it does not go to my virtual host but instead is handled by the default one, resulting in the certificate name mismatch. (Note that I do have the correct certificates set up.)
Here's my code - copy/paste, except for the actual URL:
String targetUrl = getTargetUrl();
//this returns something like https://www.example.com/api/1/orders (without spaces, of course)
HttpClient client = new DefaultHttpClient();
HttpPost post = new HttpPost(targetUrl);
List<NameValuePair> data = new ArrayList<NameValuePair>(1);
data.add(new BasicNameValuePair("orders", json.toString()));
data.add(new BasicNameValuePair("username", username));
data.add(new BasicNameValuePair("password", password));
post.setEntity(new UrlEncodedFormEntity(data));
HttpResponse response = client.execute(post);
This results in an error message saying that certificate name doesn't match the requested url and shows the requested url and the certificate url - the certificate url is the default one in the apache config.
I added this code right before the line to execute the request:
Header[] hds = post.getAllHeaders();
for(Header h : hds) {
Log.d("PasteneOrers", h.getName() + ": " + h.getValue());
}
to see what headers are included. Interesting, Host header is not shown. I then added this code before executing the request:
URL url = new URL(targetUrl);
post.setHeader("Host", url.getHost());
Now the above debugging output correctly shows the Host header - but it doesn't help and the request is still going to the default one.
To verify that this is not a problem with the server misconfiguration, I copied the target URL and pasted it into the browser running on the same android emulator - this works correctly and I get the right results. Hence it's definitely something in my code - but what? At this point I'm stuck. Any suggestions would be appreciated.
In the interest of others having this problem, I couldn't resolve it with apache httpclient. I switched to using HttpUrlConnection and everything worked correctly.

Genymotion unable to connect to server?

I have an app that sends a http request to a server and receives a JSON for processing. I test it on both a physical device and Genymotion.
The app runs fine on the physical device but on Genymotion throws NetworkOnMainThreadException.
I tracked the exception and this is the part with the issue:
..
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(url);
httpPost.setEntity(new UrlEncodedFormEntity(params,"UTF-8"));
// Exception on this line:
HttpResponse httpResponse = httpClient.execute(httpPost);
//
HttpEntity httpEntity = httpResponse.getEntity();
...
It seems that the Genymotion can't connect to server to execute the request. But its browser loads the sites just fine.
So, anyone knows what's going wrong here?
I found what the problem was:
As explained in this answer, since API 11, the NetworkOnMainThreadException is thrown to inform using long-running tasks (like http communications) in the main thread.
By using AsyncTask the problem was resolved and everything worked as it should.

HTTP POST and RESPONSE specific case study

Site: http://na.leagueoflegends.com/ladders/solo-5x5
Search for a a player (example: Jaiybe)
You get redirected (in this case to: http://na.leagueoflegends.com/ladders/solo-5x5?highlight=28&page=1)
Read the content
And I want to do that in java/android.
I analyze the sites POST request when searching, result:
op:Search
player:Jaiybe
ladder_id:3
form_build_id:form-fff5e6e2569f1e15e5a5caf2a61c15e2
form_id:ladders_filter_form
Build a simple HTTP POST mixture and lets read the content...
The CODE:
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost("http://na.leagueoflegends.com/ladders/solo-5x5");
// Add your POST METHOD attributes
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
nameValuePairs.add(new BasicNameValuePair("op", "Search"));
nameValuePairs.add(new BasicNameValuePair("player", Jaiybe));
nameValuePairs.add(new BasicNameValuePair("ladder_id", "3"));
nameValuePairs.add(new BasicNameValuePair("form_build_id","form-daca6fff89cedc352ccc3f533afa3804"));
nameValuePairs.add(new BasicNameValuePair("form_id","ladders_filter_form"));
httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
// Execute HTTP Post Request
HttpResponse response = httpclient.execute(httppost);
responseBody = EntityUtils.toString(response.getEntity());
return responseBody;
And when I run it - I get so some kind of a offline page...
The number form_build_id - is constantly changing, but this was no problem, to use still the same one, and also If I would like to "test" if this could be the problem, I have no Idea how would I...
OR: Is there any other - FAST - way how to get same results?
What is strange is that the "error" site source code that I get on android is different as if I run the same on my PC (Win7, Eclipse, Java) or in my browser. As if there would be two versions of offline sites - for mobile and for PC - but my question: HOW WOULD the server know that the code runs on a Android device? Is there a way how to set this up in HttpClient?
form_build_id:form-fff5e6e2569f1e15e5a5caf2a61c15e2
This is an auto generated token that is valid for a certain time period. This is probably the source of your problem and the reason the token exists in the first place (to prevent post spams).
As this token does not seem session based, you could actually use an HTTP Get on the page that generates the form and parse out the generated token each time for your HTTP Post.
About OS detection, browsers usually provide information about the OS using the HTTP User-Agent header.

Error of ssl certificate not trusted in Android

my code is this to post data to server
MakeValue = (String) s2.getSelectedItem();
MakeValue = MakeValue.replace(" ", "%20");
DefaultHttpClient hc=new DefaultHttpClient();
ResponseHandler res=new BasicResponseHandler();
HttpPost postMethod=new HttpPost(AppUrl.AppUrl+"dealer_service.php?action=saveCreateNewInventory");
List nameValuePairs = new ArrayList(2);
nameValuePairs.add(new BasicNameValuePair("POSTDATA", Login.GetUserID +"~"+ VinNumber.getText()
. . .
postMethod.setEntity(new UrlEncodedFormEntity(nameValuePairs));
response=hc.execute(postMethod,res);
but after executing this i have an exception of ssl not trusted so please help me to solve my probs please help i spent too many days in this. how can i remove this exception.
It's probably the typical error with certificate being signed for another domain. See question Https Connection Android
One cause can be the clock on your device. If the time is years off, SSL certificates will be invalid. So if that's the case, fix is as easy as setting your device to the correct date.

How to get a response from a https server using android sdk?

I have a problem of ssl exception when i upload data to a https server. It uploaded the data to the server correctly but when i get the response after uploading it throws an exception of ssl certificate is not trusted. I'm using the SAX parser for parsing xml file and i am using httppost method().
you have to add a new scheme to accept Secure site connections
check this, and there you will find another useful sample without checking the cetificate...
Https Connection Android
Android comes with the apache commons http library included. Setting up a https post request is quite easy:
HttpPost post = new HttpPost("https://yourdomain.com/yourskript.xyz");
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
nameValuePairs.add(new BasicNameValuePair("postValue1", "my Value"));
nameValuePairs.add(new BasicNameValuePair("postValue2", "2nd Value"));
post.setEntity(new UrlEncodedFormEntity(nameValuePairs));
HttpClient client = new DefaultHttpClient();
HttpResponse response = client.execute(post);
HttpEntity entity = response.getEntity();
String responseText = EntityUtils.toString(entity);
Android uses a version 4.x of the commons http library as all versions below 4.0 are out of their lifecycle.
I can't tell exactly how to register a self-signed certificate to the HttpClient, but mybe the commons http documentation helps:
http://hc.apache.org/httpcomponents-client-ga/tutorial/html/connmgmt.html#d4e506

Categories

Resources