package yuku.afw.rpc;
import android.util.Log;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.zip.GZIPInputStream;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import yuku.afw.rpc.Request.Method;
import yuku.afw.rpc.Request.OptionsKey;
import yuku.afw.rpc.Response.Validity;
public class HttpPerformer {
public static final String TAG = HttpPerformer.class.getSimpleName();
private final Request request;
private final AsyncRequest<?>.Task<?> task;
/**
* @param task can be null if cancel is not supported
*/
public HttpPerformer(@NullOk AsyncRequest<?>.Task<?> task, Request request) {
this.task = task;
this.request = request;
}
public Response perform() {
String url = request.url;
DefaultHttpClient client = new DefaultHttpClient();
HttpParams httpParams = client.getParams();
if (request.options != null && request.options.get(OptionsKey.connectionTimeout) != null) {
HttpConnectionParams.setConnectionTimeout(httpParams, (Integer) request.options.get(OptionsKey.connectionTimeout));
} else {
HttpConnectionParams.setConnectionTimeout(httpParams, 30000); // 30 seconds for connection timeout
}
if (request.options != null && request.options.get(OptionsKey.soTimeout) != null) {
HttpConnectionParams.setSoTimeout(httpParams, (Integer) request.options.get(OptionsKey.soTimeout));
} else {
HttpConnectionParams.setSoTimeout(httpParams, 15000); // 15 seconds for waiting for data
}
ByteArrayOutputStream os = new ByteArrayOutputStream(256); // TODO make it more efficient by not buffering byte[]
int httpResponseCode = 0;
try {
HttpRequestBase base = null;
if (request.method == Method.GET || request.method == Method.GET_RAW) {
url += request.params.toUrlEncodedStringWithOptionalQuestionMark();
base = new HttpGet(url);
} else if (request.method == Method.GET_DIGEST) {
client.getCredentialsProvider().setCredentials(new AuthScope(null, -1), new UsernamePasswordCredentials(request.params.getAndRemove("email"), request.params.getAndRemove("passwd"))); //$NON-NLS-1$//$NON-NLS-2$
url += request.params.toUrlEncodedStringWithOptionalQuestionMark();
base = new HttpGet(url);
} else if (request.method == Method.POST) {
HttpPost method = new HttpPost(url);
// use params as usual
ArrayList<NameValuePair> list = new ArrayList<NameValuePair>();
request.params.addAllTo(list);
method.setEntity(new UrlEncodedFormEntity(list, "utf-8")); //$NON-NLS-1$
base = method;
} else if (request.method == Method.DELETE) {
url += request.params.toUrlEncodedStringWithOptionalQuestionMark();
base = new HttpDelete(url);
} else {
throw new RuntimeException("http method " + request.method + " not supported yet"); //$NON-NLS-1$ //$NON-NLS-2$
}
request.headers.addTo(base);
base.addHeader("Cache-Control", "no-cache"); //$NON-NLS-1$//$NON-NLS-2$
base.addHeader("Accept-Encoding", "gzip"); //$NON-NLS-1$ //$NON-NLS-2$
HttpResponse response = client.execute(base);
httpResponseCode = response.getStatusLine().getStatusCode();
if (task != null && task.isCancelled()) {
base.abort();
} else {
Header encodingHeader = response.getFirstHeader("Content-Encoding"); //$NON-NLS-1$
HttpEntity entity = response.getEntity();
InputStream content = entity.getContent();
try {
if (encodingHeader != null && encodingHeader.getValue().equalsIgnoreCase("gzip")) { //$NON-NLS-1$
content = new GZIPInputStream(content);
}
byte[] buf = new byte[4096 * 4];
while (true) {
int read = content.read(buf);
if (read <= 0) break;
os.write(buf, 0, read);
if (task != null && task.isCancelled()) {
base.abort();
break;
}
}
} finally {
if (content != null) content.close();
}
}
} catch (IOException e) {
Log.d(TAG, "IoError: " + e.getClass().getSimpleName() + ": " + e.getMessage()); //$NON-NLS-1$ //$NON-NLS-2$
return new Response(this.request, Validity.IoError, e.getClass().getName() + ": " + e.getMessage()); //$NON-NLS-1$
}
if (task != null && task.isCancelled()) {
return new Response(this.request, Validity.Cancelled, "cancelled"); //$NON-NLS-1$
}
return new Response(this.request, os.toByteArray(), httpResponseCode);
}
}