Http Request : Http Connection « Network « Android






Http Request

    
/*
 * This class was copied from this Stackoverflow Q&A:
 * http://stackoverflow.com/questions/2253061/secure-http-post-in-android/2253280#2253280
 * Thanks go to MattC!  
 */
//package org.acra.util;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketTimeoutException;
import java.net.URL;
import java.net.URLEncoder;
import java.security.GeneralSecurityException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Map;

import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import org.apache.http.HttpResponse;
import org.apache.http.StatusLine;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.HttpClient;
import org.apache.http.client.HttpRequestRetryHandler;
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.conn.ClientConnectionManager;
import org.apache.http.conn.scheme.LayeredSocketFactory;
import org.apache.http.conn.scheme.PlainSocketFactory;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.scheme.SocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.auth.BasicScheme;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
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;

public final class HttpRequest {

  // private static ACRALog log = new AndroidLogDelegate();

  private static class SocketTimeOutRetryHandler implements
      HttpRequestRetryHandler {

    private final HttpParams httpParams;
    private final int maxNrRetries;

    /**
     * @param httpParams
     *            HttpParams that will be used in the HttpRequest.
     * @param maxNrRetries
     *            Max number of times to retry Request on failure due to
     *            SocketTimeOutException.
     */
    private SocketTimeOutRetryHandler(HttpParams httpParams,
        int maxNrRetries) {
      this.httpParams = httpParams;
      this.maxNrRetries = maxNrRetries;
    }

    @Override
    public boolean retryRequest(IOException exception, int executionCount,
        HttpContext context) {
      if (exception instanceof SocketTimeoutException) {
        if (executionCount <= maxNrRetries) {

          if (httpParams != null) {
            final int newSocketTimeOut = HttpConnectionParams
                .getSoTimeout(httpParams) * 2;
            HttpConnectionParams.setSoTimeout(httpParams,
                newSocketTimeOut);
            // log.d(ACRA.LOG_TAG,
            // "SocketTimeOut - increasing time out to " +
            // newSocketTimeOut + " millis and trying again");
          } else {
            // log.d(ACRA.LOG_TAG,
            // "SocketTimeOut - no HttpParams, cannot increase time out. Trying again with current settings");
          }

          return true;
        }

        // log.d(ACRA.LOG_TAG,
        // "SocketTimeOut but exceeded max number of retries : " +
        // maxNrRetries);
      }

      return false; // To change body of implemented methods use File |
              // Settings | File Templates.
    }
  }

  private String login;
  private String password;
  private int connectionTimeOut = 3000;
  private int socketTimeOut = 3000;
  private int maxNrRetries = 3;

  public void setLogin(String login) {
    this.login = login;
  }

  public void setPassword(String password) {
    this.password = password;
  }

  public void setConnectionTimeOut(int connectionTimeOut) {
    this.connectionTimeOut = connectionTimeOut;
  }

  public void setSocketTimeOut(int socketTimeOut) {
    this.socketTimeOut = socketTimeOut;
  }

  /**
   * The default number of retries is 3.
   * 
   * @param maxNrRetries
   *            Max number of times to retry Request on failure due to
   *            SocketTimeOutException.
   */
  public void setMaxNrRetries(int maxNrRetries) {
    this.maxNrRetries = maxNrRetries;
  }

  /**
   * Posts to a URL.
   * 
   * @param url
   *            URL to which to post.
   * @param parameters
   *            Map of parameters to post to a URL.
   * @throws IOException
   *             if the data cannot be posted.
   */
  public void sendPost(URL url, Map<?, ?> parameters) throws IOException {

    final HttpClient httpClient = getHttpClient();
    final HttpPost httpPost = getHttpPost(url, parameters);

    // log.d(ACRA.LOG_TAG, "Sending request to " + url);

    // TODO Consider using a RequestRetryHandler and if its a
    // SocketTimeoutException to up the SocketTimeout and try again.
    // See
    // http://stackoverflow.com/questions/693997/how-to-set-httpresponse-timeout-for-android-in-java
    // I think SocketTimeOut while waiting for response may be the cause of
    // the multiple crash reports () - I
    final HttpResponse response = httpClient.execute(httpPost,
        new BasicHttpContext());
    if (response != null) {
      final StatusLine statusLine = response.getStatusLine();
      if (statusLine != null) {
        final String statusCode = Integer.toString(response
            .getStatusLine().getStatusCode());
        if (statusCode.startsWith("4") || statusCode.startsWith("5")) {
          throw new IOException("Host returned error code "
              + statusCode);
        }
      }
      final String ret = EntityUtils.toString(response.getEntity());
      // if (ACRA.DEV_LOGGING) log.d(ACRA.LOG_TAG,
      // "HTTP " + (statusLine != null ? statusLine.getStatusCode() :
      // "NoStatusLine#noCode") + " - Returning value:"
      // + ret.substring(0, Math.min(ret.length(), 200)));
    } else {
      // if (ACRA.DEV_LOGGING) log.d(ACRA.LOG_TAG, "HTTP no Response!!");
    }
  }

  /**
   * @return HttpClient to use with this HttpRequest.
   */
  private HttpClient getHttpClient() {
    final HttpParams httpParams = new BasicHttpParams();
    httpParams.setParameter(ClientPNames.COOKIE_POLICY,
        CookiePolicy.RFC_2109);
    HttpConnectionParams
        .setConnectionTimeout(httpParams, connectionTimeOut);
    HttpConnectionParams.setSoTimeout(httpParams, socketTimeOut);
    HttpConnectionParams.setSocketBufferSize(httpParams, 8192);

    final SchemeRegistry registry = new SchemeRegistry();
    registry.register(new Scheme("http", new PlainSocketFactory(), 80));
    registry.register(new Scheme("https", (new FakeSocketFactory()), 443));

    final ClientConnectionManager clientConnectionManager = new ThreadSafeClientConnManager(
        httpParams, registry);
    final DefaultHttpClient httpClient = new DefaultHttpClient(
        clientConnectionManager, httpParams);

    final HttpRequestRetryHandler retryHandler = new SocketTimeOutRetryHandler(
        httpParams, maxNrRetries);
    httpClient.setHttpRequestRetryHandler(retryHandler);

    return httpClient;
  }

  /**
   * @return Credentials to use with this HttpRequest or null if no
   *         credentials were supplied.
   */
  private UsernamePasswordCredentials getCredentials() {
    if (login != null || password != null) {
      return new UsernamePasswordCredentials(login, password);
    }

    return null;
  }

  private HttpPost getHttpPost(URL url, Map<?, ?> parameters)
      throws UnsupportedEncodingException {

    final HttpPost httpPost = new HttpPost(url.toString());

    // log.d(ACRA.LOG_TAG, "Setting httpPost headers");
    final UsernamePasswordCredentials creds = getCredentials();
    if (creds != null) {
      httpPost.addHeader(BasicScheme.authenticate(creds, "UTF-8", false));
    }
    httpPost.setHeader("User-Agent", "Android");
    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");
    httpPost.setHeader("Content-Type", "application/x-www-form-urlencoded");

    final String paramsAsString = getParamsAsString(parameters);
    httpPost.setEntity(new StringEntity(paramsAsString, "UTF-8"));

    return httpPost;
  }

  /**
   * Converts a Map of parameters into a URL encoded Sting.
   * 
   * @param parameters
   *            Map of parameters to convert.
   * @return URL encoded String representing the parameters.
   * @throws UnsupportedEncodingException
   *             if one of the parameters couldn't be converted to UTF-8.
   */
  private String getParamsAsString(Map<?, ?> parameters)
      throws UnsupportedEncodingException {

    final StringBuilder dataBfr = new StringBuilder();
    for (final Object key : parameters.keySet()) {
      if (dataBfr.length() != 0) {
        dataBfr.append('&');
      }
      final Object preliminaryValue = parameters.get(key);
      final Object value = (preliminaryValue == null) ? ""
          : preliminaryValue;
      dataBfr.append(URLEncoder.encode(key.toString(), "UTF-8"));
      dataBfr.append('=');
      dataBfr.append(URLEncoder.encode(value.toString(), "UTF-8"));
    }

    return dataBfr.toString();
  }
}

/**
 * Accepts any certificate, ideal for self-signed certificates.
 */
class NaiveTrustManager implements X509TrustManager {
  /*
   * (non-Javadoc)
   * 
   * @see javax.net.ssl.X509TrustManager#getAcceptedIssuers()
   */
  @Override
  public X509Certificate[] getAcceptedIssuers() {
    return new X509Certificate[0];
  }

  /*
   * (non-Javadoc)
   * 
   * @see
   * javax.net.ssl.X509TrustManager#checkClientTrusted(java.security.cert.
   * X509Certificate[], java.lang.String)
   */
  @Override
  public void checkClientTrusted(X509Certificate[] x509CertificateArray,
      String string) throws CertificateException {
  }

  /*
   * (non-Javadoc)
   * 
   * @see
   * javax.net.ssl.X509TrustManager#checkServerTrusted(java.security.cert.
   * X509Certificate[], java.lang.String)
   */
  @Override
  public void checkServerTrusted(X509Certificate[] x509CertificateArray,
      String string) throws CertificateException {
  }
}

class FakeSocketFactory implements SocketFactory, LayeredSocketFactory {

  private SSLContext sslcontext = null;

  private static SSLContext createEasySSLContext() throws IOException {
    try {
      final SSLContext context = SSLContext.getInstance("TLS");
      context.init(null, new TrustManager[] { new NaiveTrustManager() },
          null);
      return context;
    } catch (GeneralSecurityException e) {
      throw new IOException(e);
    }
  }

  private SSLContext getSSLContext() throws IOException {
    if (this.sslcontext == null) {
      this.sslcontext = createEasySSLContext();
    }
    return this.sslcontext;
  }

  @Override
  public Socket connectSocket(Socket sock, String host, int port,
      InetAddress localAddress, int localPort, HttpParams params)
      throws IOException {
    final int connTimeout = HttpConnectionParams
        .getConnectionTimeout(params);
    final int soTimeout = HttpConnectionParams.getSoTimeout(params);

    final InetSocketAddress remoteAddress = new InetSocketAddress(host,
        port);
    final SSLSocket sslsock = (SSLSocket) ((sock != null) ? sock
        : createSocket());

    if ((localAddress != null) || (localPort > 0)) {
      // we need to bind explicitly
      if (localPort < 0) {
        localPort = 0; // indicates "any"
      }
      final InetSocketAddress isa = new InetSocketAddress(localAddress,
          localPort);
      sslsock.bind(isa);
    }

    sslsock.connect(remoteAddress, connTimeout);
    sslsock.setSoTimeout(soTimeout);

    return sslsock;
  }

  @Override
  public Socket createSocket() throws IOException {
    return getSSLContext().getSocketFactory().createSocket();
  }

  @Override
  public boolean isSecure(Socket arg0) throws IllegalArgumentException {
    return true;
  }

  @Override
  public Socket createSocket(Socket socket, String host, int port,
      boolean autoClose) throws IOException {
    return getSSLContext().getSocketFactory().createSocket(socket, host,
        port, autoClose);
  }

}

   
    
    
    
  








Related examples in the same category

1.Http Connection
2.Using HttpGet to get the web response
3.Create Http connection
4.Http connection with
5.HttpGet and DefaultHttpClient
6.Http Post
7.Simple HTTP Request
8.Http Request Class
9.Http Get and Http Post
10.Get Text from HttpResponse
11.Http Downloader
12.Is Http Url Available
13.Http Retriever
14.Receive Response from HttpURLConnection
15.Print http headers. Useful for debugging.
16.Return the base URL from the given URL. Example: http://foo.org/abc.html -> http://foo.org/
17.Send message with HttpPost
18.Get Http Stream
19.Generic Object Http Loader
20.Http Get and DefaultHttpClient
21.Gets http output from URL
22.Util for Http Get
23.do Http Get Request and return the status code
24.Http Get
25.implements HttpClient
26.Get File From HTTP
27.Make all redirects to go to http in stead of https
28.New Http Client Manager
29.Http Client Manager
30.Multipart Post
31.Get Server Data
32.Yahoo News Crawler
33.Send Packet
34.Read a web page
35.parse Request Header
36.Data Send Utils
37.This class is in charge of synchronizing the events (with due dates) with Google Calendar
38.Update Favicon
39.Converts key-value pair to appropriate signature for Facebook.