Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Secure HTTP Post in Android

I have a pretty basic helper class that I'm using to do all my Http Get/Post stuff. I'm using HttpGet, HttpPost, and HttpClient from the org.apache.http library. All of my stuff works fine over HTTP, but as soon as I tried to consume a service that works over HTTPS, I get a ClientProtocolException when executing the request. The only message in the exception is "The server failed to respond with a valid HTTP response".

To test, I sent the exact same payload from a browser using a simple html form and Fiddler2 using the RequestBuilder. I've sent invalid and empty payloads and even sent all of the above with and without headers to see if there was something funky about the way the objects were building the request.

Everything I've used in testing gives me a valid 200 status HTTP response. The service just gives me a structure describing the error if I give it something other than what it expects.

Is there something special I need to add to the HttpPost or HttpClient object(s) to tell it to use HTTPS? Do I have to explicitly tell it to use a different port?

EDIT:

I indeed registered the wrong socket factory for https communication. Here is the updated method that I use to create my HttpClient object with the correct socket factory just in case someone searches this kind of problem in the future:

private HttpClient createHttpClient() {     HttpParams params = new BasicHttpParams();     HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);     HttpProtocolParams.setContentCharset(params, HTTP.DEFAULT_CONTENT_CHARSET);     HttpProtocolParams.setUseExpectContinue(params, true);      SchemeRegistry schReg = new SchemeRegistry();     schReg.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));     schReg.register(new Scheme("https", SSLSocketFactory.getSocketFactory(), 443));     ClientConnectionManager conMgr = new ThreadSafeClientConnManager(params, schReg);      return new DefaultHttpClient(conMgr, params); } 
like image 532
Rich Avatar asked Feb 12 '10 15:02

Rich


1 Answers

I'm not sure why you can't handle HTTPS. I wrote a helper class for my own applications and I am able to GET/POST to HTTPS without a problem. I will post the code here and perhaps you can see if there are differences between my code and yours.

import java.io.IOException; import java.io.InputStream; import java.io.UnsupportedEncodingException; import java.net.HttpURLConnection; import java.net.URL; import java.net.URLConnection;  import org.apache.http.HttpResponse; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.apache.http.client.params.ClientPNames; import org.apache.http.client.params.CookiePolicy; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.params.BasicHttpParams; import org.apache.http.params.HttpConnectionParams; import org.apache.http.params.HttpParams; import org.apache.http.protocol.BasicHttpContext; import org.apache.http.protocol.HttpContext; import org.apache.http.util.EntityUtils; import org.json.JSONObject;  import android.util.Log;  public class HttpRequest{      DefaultHttpClient httpClient;     HttpContext localContext;     private String ret;      HttpResponse response = null;     HttpPost httpPost = null;     HttpGet httpGet = null;      public HttpRequest(){         HttpParams myParams = new BasicHttpParams();          HttpConnectionParams.setConnectionTimeout(myParams, 10000);         HttpConnectionParams.setSoTimeout(myParams, 10000);         httpClient = new DefaultHttpClient(myParams);                localContext = new BasicHttpContext();         }      public void clearCookies() {         httpClient.getCookieStore().clear();     }      public void abort() {         try {             if (httpClient != null) {                 System.out.println("Abort.");                 httpPost.abort();             }         } catch (Exception e) {             System.out.println("Your App Name Here" + e);         }     }      public String sendPost(String url, String data) {         return sendPost(url, data, null);     }      public String sendJSONPost(String url, JSONObject data) {         return sendPost(url, data.toString(), "application/json");     }      public String sendPost(String url, String data, String contentType) {         ret = null;          httpClient.getParams().setParameter(ClientPNames.COOKIE_POLICY, CookiePolicy.RFC_2109);          httpPost = new HttpPost(url);         response = null;          StringEntity tmp = null;                  Log.d("Your App Name Here", "Setting httpPost headers");          httpPost.setHeader("User-Agent", "SET YOUR USER AGENT STRING HERE");         httpPost.setHeader("Accept", "text/html,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5");          if (contentType != null) {             httpPost.setHeader("Content-Type", contentType);         } else {             httpPost.setHeader("Content-Type", "application/x-www-form-urlencoded");         }          try {             tmp = new StringEntity(data,"UTF-8");         } catch (UnsupportedEncodingException e) {             Log.e("Your App Name Here", "HttpUtils : UnsupportedEncodingException : "+e);         }          httpPost.setEntity(tmp);          Log.d("Your App Name Here", url + "?" + data);          try {             response = httpClient.execute(httpPost,localContext);              if (response != null) {                 ret = EntityUtils.toString(response.getEntity());             }         } catch (Exception e) {             Log.e("Your App Name Here", "HttpUtils: " + e);         }          Log.d("Your App Name Here", "Returning value:" + ret);          return ret;     }      public String sendGet(String url) {         httpGet = new HttpGet(url);            try {             response = httpClient.execute(httpGet);           } catch (Exception e) {             Log.e("Your App Name Here", e.getMessage());         }          //int status = response.getStatusLine().getStatusCode();            // we assume that the response body contains the error message           try {             ret = EntityUtils.toString(response.getEntity());           } catch (IOException e) {             Log.e("Your App Name Here", e.getMessage());         }          return ret;     }      public InputStream getHttpStream(String urlString) throws IOException {         InputStream in = null;         int response = -1;          URL url = new URL(urlString);          URLConnection conn = url.openConnection();          if (!(conn instanceof HttpURLConnection))                                  throw new IOException("Not an HTTP connection");          try{             HttpURLConnection httpConn = (HttpURLConnection) conn;             httpConn.setAllowUserInteraction(false);             httpConn.setInstanceFollowRedirects(true);             httpConn.setRequestMethod("GET");             httpConn.connect();               response = httpConn.getResponseCode();                               if (response == HttpURLConnection.HTTP_OK) {                 in = httpConn.getInputStream();                                              }                              } catch (Exception e) {             throw new IOException("Error connecting");                     } // end try-catch          return in;          } } 
like image 56
MattC Avatar answered Sep 22 '22 04:09

MattC