summaryrefslogtreecommitdiff
path: root/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/module/http/HttpRequestImpl.java
diff options
context:
space:
mode:
Diffstat (limited to 'platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/module/http/HttpRequestImpl.java')
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/module/http/HttpRequestImpl.java179
1 files changed, 179 insertions, 0 deletions
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/module/http/HttpRequestImpl.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/module/http/HttpRequestImpl.java
new file mode 100644
index 0000000000..3195022d3a
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/module/http/HttpRequestImpl.java
@@ -0,0 +1,179 @@
+package com.mapbox.mapboxsdk.module.http;
+
+import android.os.Build;
+import android.support.annotation.NonNull;
+import android.text.TextUtils;
+import android.util.Log;
+import com.mapbox.mapboxsdk.BuildConfig;
+import com.mapbox.mapboxsdk.constants.MapboxConstants;
+import com.mapbox.mapboxsdk.http.HttpRequest;
+import com.mapbox.mapboxsdk.http.HttpIdentifier;
+import com.mapbox.mapboxsdk.http.HttpLogger;
+import com.mapbox.mapboxsdk.http.HttpResponder;
+import com.mapbox.mapboxsdk.http.HttpRequestUrl;
+import okhttp3.Call;
+import okhttp3.Callback;
+import okhttp3.Dispatcher;
+import okhttp3.HttpUrl;
+import okhttp3.OkHttpClient;
+import okhttp3.Request;
+import okhttp3.Response;
+import okhttp3.ResponseBody;
+
+import javax.net.ssl.SSLException;
+import java.io.IOException;
+import java.io.InterruptedIOException;
+import java.net.NoRouteToHostException;
+import java.net.ProtocolException;
+import java.net.SocketException;
+import java.net.UnknownHostException;
+
+import static com.mapbox.mapboxsdk.module.http.HttpRequestUtil.toHumanReadableAscii;
+
+public class HttpRequestImpl implements HttpRequest {
+
+ private static final String userAgentString = toHumanReadableAscii(
+ String.format("%s %s (%s) Android/%s (%s)",
+ HttpIdentifier.getIdentifier(),
+ BuildConfig.MAPBOX_VERSION_STRING,
+ BuildConfig.GIT_REVISION_SHORT,
+ Build.VERSION.SDK_INT,
+ Build.CPU_ABI)
+ );
+
+ private static OkHttpClient client = new OkHttpClient.Builder().dispatcher(getDispatcher()).build();
+
+ private Call call;
+
+ @Override
+ public void executeRequest(HttpResponder httpRequest, long nativePtr, String resourceUrl,
+ String etag, String modified) {
+ OkHttpCallback callback = new OkHttpCallback(httpRequest);
+ try {
+ HttpUrl httpUrl = HttpUrl.parse(resourceUrl);
+ if (httpUrl == null) {
+ HttpLogger.log(Log.ERROR, String.format("[HTTP] Unable to parse resourceUrl %s", resourceUrl));
+ return;
+ }
+
+ final String host = httpUrl.host().toLowerCase(MapboxConstants.MAPBOX_LOCALE);
+ resourceUrl = HttpRequestUrl.buildResourceUrl(host, resourceUrl, httpUrl.querySize());
+
+ final Request.Builder builder = new Request.Builder()
+ .url(resourceUrl)
+ .tag(resourceUrl.toLowerCase(MapboxConstants.MAPBOX_LOCALE))
+ .addHeader("User-Agent", userAgentString);
+ if (etag.length() > 0) {
+ builder.addHeader("If-None-Match", etag);
+ } else if (modified.length() > 0) {
+ builder.addHeader("If-Modified-Since", modified);
+ }
+
+ final Request request = builder.build();
+ call = client.newCall(request);
+ call.enqueue(callback);
+ } catch (Exception exception) {
+ callback.handleFailure(call, exception);
+ }
+ }
+
+ @Override
+ public void cancelRequest() {
+ // call can be null if the constructor gets aborted (e.g, under a NoRouteToHostException).
+ if (call != null) {
+ call.cancel();
+ }
+ }
+
+ public static void enablePrintRequestUrlOnFailure(boolean enabled) {
+ HttpLogger.logRequestUrl = enabled;
+ }
+
+ public static void enableLog(boolean enabled) {
+ HttpLogger.logEnabled = enabled;
+ }
+
+ public static void setOkHttpClient(OkHttpClient okHttpClient) {
+ HttpRequestImpl.client = okHttpClient;
+ }
+
+ private static class OkHttpCallback implements Callback {
+
+ private HttpResponder httpRequest;
+
+ OkHttpCallback(HttpResponder httpRequest) {
+ this.httpRequest = httpRequest;
+ }
+
+ @Override
+ public void onFailure(@NonNull Call call, @NonNull IOException e) {
+ handleFailure(call, e);
+ }
+
+ @Override
+ public void onResponse(@NonNull Call call, @NonNull Response response) {
+ if (response.isSuccessful()) {
+ HttpLogger.log(Log.VERBOSE, String.format("[HTTP] Request was successful (code = %s).", response.code()));
+ } else {
+ // We don't want to call this unsuccessful because a 304 isn't really an error
+ String message = !TextUtils.isEmpty(response.message()) ? response.message() : "No additional information";
+ HttpLogger.log(Log.DEBUG, String.format("[HTTP] Request with response = %s: %s", response.code(), message));
+ }
+
+ ResponseBody responseBody = response.body();
+ if (responseBody == null) {
+ HttpLogger.log(Log.ERROR, "[HTTP] Received empty response body");
+ return;
+ }
+
+ byte[] body;
+ try {
+ body = responseBody.bytes();
+ } catch (IOException ioException) {
+ onFailure(call, ioException);
+ // throw ioException;
+ return;
+ } finally {
+ response.close();
+ }
+
+ httpRequest.onResponse(response.code(),
+ response.header("ETag"),
+ response.header("Last-Modified"),
+ response.header("Cache-Control"),
+ response.header("Expires"),
+ response.header("Retry-After"),
+ response.header("x-rate-limit-reset"),
+ body);
+ }
+
+ private void handleFailure(Call call, Exception e) {
+ String errorMessage = e.getMessage() != null ? e.getMessage() : "Error processing the request";
+ int type = getFailureType(e);
+
+ if (HttpLogger.logEnabled && call != null && call.request() != null) {
+ String requestUrl = call.request().url().toString();
+ HttpLogger.logFailure(type, errorMessage, requestUrl);
+ }
+ httpRequest.handleFailure(type, errorMessage);
+ }
+
+ private int getFailureType(Exception e) {
+ if ((e instanceof NoRouteToHostException) || (e instanceof UnknownHostException) || (e instanceof SocketException)
+ || (e instanceof ProtocolException) || (e instanceof SSLException)) {
+ return CONNECTION_ERROR;
+ } else if ((e instanceof InterruptedIOException)) {
+ return TEMPORARY_ERROR;
+ }
+ return PERMANENT_ERROR;
+ }
+ }
+
+ private static Dispatcher getDispatcher() {
+ Dispatcher dispatcher = new Dispatcher();
+ // Matches core limit set on
+ // https://github.com/mapbox/mapbox-gl-native/blob/master/platform/android/src/http_file_source.cpp#L192
+ dispatcher.setMaxRequestsPerHost(20);
+ return dispatcher;
+ }
+} \ No newline at end of file