mirror of https://github.com/tasks/tasks
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
250 lines
8.3 KiB
Java
250 lines
8.3 KiB
Java
/**
|
|
* Copyright (c) 2012 Todoroo Inc
|
|
*
|
|
* See the file "LICENSE" for the full license governing this code.
|
|
*/
|
|
package com.todoroo.andlib.service;
|
|
|
|
import java.io.IOException;
|
|
import java.io.InputStream;
|
|
import java.lang.ref.WeakReference;
|
|
import java.util.zip.GZIPInputStream;
|
|
|
|
import org.apache.http.Header;
|
|
import org.apache.http.HeaderElement;
|
|
import org.apache.http.HttpEntity;
|
|
import org.apache.http.HttpException;
|
|
import org.apache.http.HttpRequest;
|
|
import org.apache.http.HttpRequestInterceptor;
|
|
import org.apache.http.HttpResponse;
|
|
import org.apache.http.HttpResponseInterceptor;
|
|
import org.apache.http.HttpVersion;
|
|
import org.apache.http.client.HttpClient;
|
|
import org.apache.http.client.methods.HttpGet;
|
|
import org.apache.http.client.methods.HttpPost;
|
|
import org.apache.http.conn.params.ConnManagerPNames;
|
|
import org.apache.http.conn.params.ConnPerRouteBean;
|
|
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.ssl.SSLSocketFactory;
|
|
import org.apache.http.entity.HttpEntityWrapper;
|
|
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.params.HttpProtocolParams;
|
|
import org.apache.http.protocol.HttpContext;
|
|
|
|
import android.util.Log;
|
|
|
|
import com.todoroo.andlib.utility.AndroidUtilities;
|
|
|
|
/**
|
|
* RestClient allows Android to consume web requests.
|
|
*
|
|
* @author Tim Su <tim@todoroo.com>
|
|
*
|
|
*/
|
|
public class HttpRestClient implements RestClient {
|
|
|
|
private static final int HTTP_UNAVAILABLE_END = 599;
|
|
private static final int HTTP_UNAVAILABLE_START = 500;
|
|
private static final int HTTP_OK = 200;
|
|
|
|
private static final int TIMEOUT_MILLIS = 60000;
|
|
|
|
private WeakReference<HttpClient> httpClient = null;
|
|
|
|
protected boolean debug = false;
|
|
|
|
private int timeout = TIMEOUT_MILLIS;
|
|
|
|
@SuppressWarnings("nls")
|
|
public HttpRestClient() {
|
|
DependencyInjectionService.getInstance().inject(this);
|
|
|
|
SchemeRegistry schemeRegistry = new SchemeRegistry();
|
|
schemeRegistry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
|
|
schemeRegistry.register(new Scheme("https", SSLSocketFactory.getSocketFactory(), 443));
|
|
|
|
params = new BasicHttpParams();
|
|
HttpConnectionParams.setConnectionTimeout(params, timeout);
|
|
HttpConnectionParams.setSoTimeout(params, timeout);
|
|
params.setParameter(ConnManagerPNames.MAX_TOTAL_CONNECTIONS, 30);
|
|
params.setParameter(ConnManagerPNames.MAX_CONNECTIONS_PER_ROUTE, new ConnPerRouteBean(30));
|
|
params.setParameter(HttpProtocolParams.USE_EXPECT_CONTINUE, false);
|
|
HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
|
|
|
|
cm = new ThreadSafeClientConnManager(params, schemeRegistry);
|
|
}
|
|
|
|
public HttpRestClient(int timeout) {
|
|
super();
|
|
this.timeout = timeout;
|
|
|
|
HttpConnectionParams.setConnectionTimeout(params, timeout);
|
|
HttpConnectionParams.setSoTimeout(params, timeout);
|
|
}
|
|
|
|
private HttpParams params;
|
|
private ThreadSafeClientConnManager cm;
|
|
|
|
private synchronized HttpClient getClient() {
|
|
if (httpClient == null || httpClient.get() == null) {
|
|
DefaultHttpClient client = new DefaultHttpClient(cm, params);
|
|
httpClient = new WeakReference<HttpClient>(client);
|
|
actsAsGzippable(client);
|
|
return client;
|
|
}
|
|
return httpClient.get();
|
|
}
|
|
|
|
@SuppressWarnings("nls")
|
|
protected void actsAsGzippable(DefaultHttpClient client) {
|
|
client.addRequestInterceptor(new HttpRequestInterceptor() {
|
|
@Override
|
|
public void process(
|
|
final HttpRequest request,
|
|
final HttpContext context) throws HttpException, IOException {
|
|
if (!request.containsHeader("Accept-Encoding")) {
|
|
request.addHeader("Accept-Encoding", "gzip");
|
|
}
|
|
}
|
|
|
|
});
|
|
|
|
client.addResponseInterceptor(new HttpResponseInterceptor() {
|
|
@Override
|
|
public void process(
|
|
final HttpResponse response,
|
|
final HttpContext context) throws HttpException, IOException {
|
|
HttpEntity entity = response.getEntity();
|
|
Header ceheader = entity.getContentEncoding();
|
|
if (ceheader != null) {
|
|
HeaderElement[] codecs = ceheader.getElements();
|
|
for (int i = 0; i < codecs.length; i++) {
|
|
if (codecs[i].getName().equalsIgnoreCase("gzip")) {
|
|
response.setEntity(
|
|
new GzipDecompressingEntity(response.getEntity()));
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
private static class GzipDecompressingEntity extends HttpEntityWrapper {
|
|
|
|
public GzipDecompressingEntity(final HttpEntity entity) {
|
|
super(entity);
|
|
}
|
|
|
|
@Override
|
|
public InputStream getContent()
|
|
throws IOException, IllegalStateException {
|
|
|
|
// the wrapped entity's getContent() decides about repeatability
|
|
InputStream wrappedin = wrappedEntity.getContent();
|
|
|
|
return new GZIPInputStream(wrappedin);
|
|
}
|
|
|
|
@Override
|
|
public long getContentLength() {
|
|
// length of ungzipped content is not known
|
|
return -1;
|
|
}
|
|
|
|
}
|
|
|
|
private String processHttpResponse(HttpResponse response) throws IOException {
|
|
int statusCode = response.getStatusLine().getStatusCode();
|
|
if(statusCode >= HTTP_UNAVAILABLE_START && statusCode <= HTTP_UNAVAILABLE_END) {
|
|
throw new HttpUnavailableException();
|
|
}
|
|
|
|
HttpEntity entity = response.getEntity();
|
|
|
|
String body = null;
|
|
if (entity != null) {
|
|
InputStream contentStream = entity.getContent();
|
|
try {
|
|
body = AndroidUtilities.readInputStream(contentStream);
|
|
} finally {
|
|
contentStream.close();
|
|
}
|
|
}
|
|
|
|
if(statusCode != HTTP_OK) {
|
|
System.out.println(body);
|
|
throw new HttpErrorException(response.getStatusLine().getStatusCode(),
|
|
response.getStatusLine().getReasonPhrase());
|
|
}
|
|
|
|
return body;
|
|
}
|
|
|
|
/**
|
|
* Issue an HTTP GET for the given URL, return the response
|
|
*
|
|
* @param url url with url-encoded params
|
|
* @return response, or null if there was no response
|
|
* @throws IOException
|
|
*/
|
|
@Override
|
|
public synchronized String get(String url) throws IOException {
|
|
if(debug) {
|
|
Log.d("http-rest-client-get", url); //$NON-NLS-1$
|
|
}
|
|
|
|
try {
|
|
HttpGet httpGet = new HttpGet(url);
|
|
HttpResponse response = getClient().execute(httpGet);
|
|
|
|
return processHttpResponse(response);
|
|
} catch (IOException e) {
|
|
throw e;
|
|
} catch (Exception e) {
|
|
IOException ioException = new IOException(e.getMessage());
|
|
ioException.initCause(e);
|
|
throw ioException;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Issue an HTTP POST for the given URL, return the response
|
|
*
|
|
* @param url
|
|
* @param data
|
|
* url-encoded data
|
|
* @throws IOException
|
|
*/
|
|
@Override
|
|
public synchronized String post(String url, HttpEntity data, Header... headers) throws IOException {
|
|
if(debug) {
|
|
Log.d("http-rest-client-post", url + " | " + data); //$NON-NLS-1$ //$NON-NLS-2$
|
|
}
|
|
|
|
try {
|
|
HttpPost httpPost = new HttpPost(url);
|
|
httpPost.setEntity(data);
|
|
for(Header header : headers) {
|
|
httpPost.addHeader(header);
|
|
}
|
|
HttpResponse response = getClient().execute(httpPost);
|
|
|
|
return processHttpResponse(response);
|
|
} catch (IOException e) {
|
|
throw e;
|
|
} catch (Exception e) {
|
|
IOException ioException = new IOException(e.getMessage());
|
|
ioException.initCause(e);
|
|
throw ioException;
|
|
}
|
|
}
|
|
|
|
}
|