Skip to content
This repository was archived by the owner on Aug 8, 2023. It is now read-only.

Commit ea525fd

Browse files
committed
[android] - check for null body on http request, cleanup code
1 parent 91de483 commit ea525fd

File tree

2 files changed

+89
-77
lines changed

2 files changed

+89
-77
lines changed

platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/http/HTTPRequest.java

+88-76
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@
44
import android.content.Context;
55
import android.content.pm.PackageInfo;
66
import android.os.Build;
7+
import android.support.annotation.NonNull;
78
import android.text.TextUtils;
9+
import android.util.Log;
810

911
import com.mapbox.mapboxsdk.BuildConfig;
1012
import com.mapbox.mapboxsdk.Mapbox;
@@ -27,54 +29,42 @@
2729
import okhttp3.OkHttpClient;
2830
import okhttp3.Request;
2931
import okhttp3.Response;
32+
import okhttp3.ResponseBody;
3033
import okhttp3.internal.Util;
3134
import timber.log.Timber;
3235

3336
import static android.util.Log.DEBUG;
37+
import static android.util.Log.ERROR;
3438
import static android.util.Log.INFO;
39+
import static android.util.Log.VERBOSE;
3540
import static android.util.Log.WARN;
3641

3742
class HTTPRequest implements Callback {
3843

39-
private static OkHttpClient mClient = new OkHttpClient.Builder().dispatcher(getDispatcher()).build();
40-
private static boolean logEnabled = true;
41-
private static boolean logRequestUrl = false;
42-
43-
private String USER_AGENT_STRING = null;
44-
4544
private static final int CONNECTION_ERROR = 0;
4645
private static final int TEMPORARY_ERROR = 1;
4746
private static final int PERMANENT_ERROR = 2;
4847

49-
// Reentrancy is not needed, but "Lock" is an
50-
// abstract class.
51-
private ReentrantLock mLock = new ReentrantLock();
52-
53-
private long mNativePtr = 0;
54-
55-
private Call mCall;
56-
private Request mRequest;
57-
58-
private static Dispatcher getDispatcher() {
59-
Dispatcher dispatcher = new Dispatcher();
60-
// Matches core limit set on
61-
// https://github.com/mapbox/mapbox-gl-native/blob/master/platform/android/src/http_file_source.cpp#L192
62-
dispatcher.setMaxRequestsPerHost(20);
63-
return dispatcher;
64-
}
65-
66-
private native void nativeOnFailure(int type, String message);
48+
private static OkHttpClient client = new OkHttpClient.Builder().dispatcher(getDispatcher()).build();
49+
private static boolean logEnabled = true;
50+
private static boolean logRequestUrl = false;
6751

68-
private native void nativeOnResponse(int code, String etag, String modified, String cacheControl, String expires,
69-
String retryAfter, String xRateLimitReset, byte[] body);
52+
// Reentrancy is not needed, but "Lock" is an abstract class.
53+
private ReentrantLock lock = new ReentrantLock();
54+
private String userAgentString;
55+
private long nativePtr = 0;
56+
private Call call;
7057

7158
private HTTPRequest(long nativePtr, String resourceUrl, String etag, String modified) {
72-
mNativePtr = nativePtr;
59+
this.nativePtr = nativePtr;
7360

7461
try {
7562
HttpUrl httpUrl = HttpUrl.parse(resourceUrl);
76-
final String host = httpUrl.host().toLowerCase(MapboxConstants.MAPBOX_LOCALE);
63+
if (httpUrl == null) {
64+
log(Log.ERROR, String.format("[HTTP] Unable to parse resourceUrl %s", resourceUrl));
65+
}
7766

67+
final String host = httpUrl.host().toLowerCase(MapboxConstants.MAPBOX_LOCALE);
7868
// Don't try a request to remote server if we aren't connected
7969
if (!Mapbox.isConnected() && !host.equals("127.0.0.1") && !host.equals("localhost")) {
8070
throw new NoRouteToHostException("No Internet connection available.");
@@ -99,56 +89,59 @@ private HTTPRequest(long nativePtr, String resourceUrl, String etag, String modi
9989
} else if (modified.length() > 0) {
10090
builder = builder.addHeader("If-Modified-Since", modified);
10191
}
102-
mRequest = builder.build();
103-
mCall = mClient.newCall(mRequest);
104-
mCall.enqueue(this);
92+
Request request = builder.build();
93+
call = client.newCall(request);
94+
call.enqueue(this);
10595
} catch (Exception exception) {
106-
handleFailure(mCall, exception);
96+
handleFailure(call, exception);
10797
}
10898
}
10999

110100
public void cancel() {
111-
// mCall can be null if the constructor gets aborted (e.g, under a NoRouteToHostException).
112-
if (mCall != null) {
113-
mCall.cancel();
101+
// call can be null if the constructor gets aborted (e.g, under a NoRouteToHostException).
102+
if (call != null) {
103+
call.cancel();
114104
}
115105

116106
// TODO: We need a lock here because we can try
117107
// to cancel at the same time the request is getting
118108
// answered on the OkHTTP thread. We could get rid of
119109
// this lock by using Runnable when we move Android
120110
// implementation of mbgl::RunLoop to Looper.
121-
mLock.lock();
122-
mNativePtr = 0;
123-
mLock.unlock();
111+
lock.lock();
112+
nativePtr = 0;
113+
lock.unlock();
124114
}
125115

126116
@Override
127-
public void onResponse(Call call, Response response) throws IOException {
117+
public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException {
118+
if (response.isSuccessful()) {
119+
log(VERBOSE, String.format("[HTTP] Request was successful (code = %s).", response.code()));
120+
} else {
121+
// We don't want to call this unsuccessful because a 304 isn't really an error
122+
String message = !TextUtils.isEmpty(response.message()) ? response.message() : "No additional information";
123+
log(DEBUG, String.format("[HTTP] Request with response code = %s: %s", response.code(), message));
124+
}
128125

129-
if (logEnabled) {
130-
if (response.isSuccessful()) {
131-
Timber.v("[HTTP] Request was successful (code = %s).", response.code());
132-
} else {
133-
// We don't want to call this unsuccessful because a 304 isn't really an error
134-
String message = !TextUtils.isEmpty(response.message()) ? response.message() : "No additional information";
135-
Timber.d("[HTTP] Request with response code = %s: %s", response.code(), message);
136-
}
126+
ResponseBody responseBody = response.body();
127+
if (responseBody == null) {
128+
log(ERROR, "[HTTP] Received empty response body");
129+
return;
137130
}
138131

139132
byte[] body;
140133
try {
141-
body = response.body().bytes();
134+
body = responseBody.bytes();
142135
} catch (IOException ioException) {
143136
onFailure(call, ioException);
144137
// throw ioException;
145138
return;
146139
} finally {
147-
response.body().close();
140+
response.close();
148141
}
149142

150-
mLock.lock();
151-
if (mNativePtr != 0) {
143+
lock.lock();
144+
if (nativePtr != 0) {
152145
nativeOnResponse(response.code(),
153146
response.header("ETag"),
154147
response.header("Last-Modified"),
@@ -158,14 +151,34 @@ public void onResponse(Call call, Response response) throws IOException {
158151
response.header("x-rate-limit-reset"),
159152
body);
160153
}
161-
mLock.unlock();
154+
lock.unlock();
162155
}
163156

164157
@Override
165-
public void onFailure(Call call, IOException e) {
158+
public void onFailure(@NonNull Call call, @NonNull IOException e) {
166159
handleFailure(call, e);
167160
}
168161

162+
static void enableLog(boolean enabled) {
163+
logEnabled = enabled;
164+
}
165+
166+
static void enablePrintRequestUrlOnFailure(boolean enabled) {
167+
logRequestUrl = enabled;
168+
}
169+
170+
static void setOKHttpClient(OkHttpClient client) {
171+
HTTPRequest.client = client;
172+
}
173+
174+
private static Dispatcher getDispatcher() {
175+
Dispatcher dispatcher = new Dispatcher();
176+
// Matches core limit set on
177+
// https://github.com/mapbox/mapbox-gl-native/blob/master/platform/android/src/http_file_source.cpp#L192
178+
dispatcher.setMaxRequestsPerHost(20);
179+
return dispatcher;
180+
}
181+
169182
private void handleFailure(Call call, Exception e) {
170183
String errorMessage = e.getMessage() != null ? e.getMessage() : "Error processing the request";
171184
int type = getFailureType(e);
@@ -175,11 +188,11 @@ private void handleFailure(Call call, Exception e) {
175188
logFailure(type, errorMessage, requestUrl);
176189
}
177190

178-
mLock.lock();
179-
if (mNativePtr != 0) {
191+
lock.lock();
192+
if (nativePtr != 0) {
180193
nativeOnFailure(type, errorMessage);
181194
}
182-
mLock.unlock();
195+
lock.unlock();
183196
}
184197

185198
private int getFailureType(Exception e) {
@@ -192,29 +205,35 @@ private int getFailureType(Exception e) {
192205
return PERMANENT_ERROR;
193206
}
194207

208+
private void log(int type, String errorMessage) {
209+
if (logEnabled) {
210+
Timber.log(type, errorMessage);
211+
}
212+
}
213+
195214
private void logFailure(int type, String errorMessage, String requestUrl) {
196-
Timber.log(
197-
type == TEMPORARY_ERROR ? DEBUG : type == CONNECTION_ERROR ? INFO : WARN,
198-
"Request failed due to a %s error: %s %s",
199-
type == TEMPORARY_ERROR ? "temporary" : type == CONNECTION_ERROR ? "connection" : "permanent",
200-
errorMessage,
201-
logRequestUrl ? requestUrl : ""
215+
log(type == TEMPORARY_ERROR ? DEBUG : type == CONNECTION_ERROR ? INFO : WARN,
216+
String.format(
217+
"Request failed due to a %s error: %s %s",
218+
type == TEMPORARY_ERROR ? "temporary" : type == CONNECTION_ERROR ? "connection" : "permanent",
219+
errorMessage,
220+
logRequestUrl ? requestUrl : ""
221+
)
202222
);
203223
}
204224

205225
private String getUserAgent() {
206-
if (USER_AGENT_STRING == null) {
207-
return USER_AGENT_STRING = Util.toHumanReadableAscii(
226+
if (userAgentString == null) {
227+
userAgentString = Util.toHumanReadableAscii(
208228
String.format("%s %s (%s) Android/%s (%s)",
209229
getApplicationIdentifier(),
210230
BuildConfig.MAPBOX_VERSION_STRING,
211231
BuildConfig.GIT_REVISION_SHORT,
212232
Build.VERSION.SDK_INT,
213233
Build.CPU_ABI)
214234
);
215-
} else {
216-
return USER_AGENT_STRING;
217235
}
236+
return userAgentString;
218237
}
219238

220239
private String getApplicationIdentifier() {
@@ -227,15 +246,8 @@ private String getApplicationIdentifier() {
227246
}
228247
}
229248

230-
static void enableLog(boolean enabled) {
231-
logEnabled = enabled;
232-
}
233-
234-
static void enablePrintRequestUrlOnFailure(boolean enabled) {
235-
logRequestUrl = enabled;
236-
}
249+
private native void nativeOnFailure(int type, String message);
237250

238-
static void setOKHttpClient(OkHttpClient client) {
239-
mClient = client;
240-
}
251+
private native void nativeOnResponse(int code, String etag, String modified, String cacheControl, String expires,
252+
String retryAfter, String xRateLimitReset, byte[] body);
241253
}

platform/android/src/http_file_source.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ void RegisterNativeHTTPRequest(jni::JNIEnv& env) {
6161

6262
#define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name)
6363

64-
jni::RegisterNativePeer<HTTPRequest>(env, HTTPRequest::javaClass, "mNativePtr",
64+
jni::RegisterNativePeer<HTTPRequest>(env, HTTPRequest::javaClass, "nativePtr",
6565
METHOD(&HTTPRequest::onFailure, "nativeOnFailure"),
6666
METHOD(&HTTPRequest::onResponse, "nativeOnResponse"));
6767
}

0 commit comments

Comments
 (0)