Skip to content

Commit 6bbaff2

Browse files
AndrewJackFacebook Github Bot 1
authored andcommitted
Upgrade to OkHttp3
Summary: Update to [OkHttp](https://github.com/square/okhttp) to [OkHttp3](https://publicobject.com/2015/12/12/com-squareup-okhttp3/) We must also update: - Fresco to 0.10.0 - okio to 1.8.0 **Motivation** Reasons for upgrading: * Issue facebook#4021 * "We discovered that RN Android sometimes fails to connect to the latest stable version of NGINX when HTTP/2 is enabled. We aren't seeing errors with other HTTP clients so we think it's specific to RN and OkHttp. Square has fixed several HTTP/2 bugs over the past eight months." - ide * OkHttp3 will be maintained & improved, but OkHttp2 will only receive [security fixes](https://publicobject.com/2016/02/11/okhttp-certificate-pinning-vulnerability/) * Cleaner APIs - "Get and Set prefixes are avoided" * Deprecated/Removed - HttpURLConnection & Apache HTTP * React Native apps are currently being forced to bundle two versions of OkHttp (v2 & v3), if another library uses v3 * Improved WebSocket performance - [CHANGELOG.md](https://github.com/square/okhttp/blob/master Closes facebook#6113 Reviewed By: andreicoman11, lexs Differential Revision: D3292375 Pulled By: bestander fbshipit-source-id: 7c7043eaa2ea63f95854108b401c4066098d67f7
1 parent 5047f6f commit 6bbaff2

File tree

29 files changed

+378
-273
lines changed

29 files changed

+378
-273
lines changed

ReactAndroid/build.gradle

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -259,13 +259,14 @@ dependencies {
259259
compile fileTree(dir: 'src/main/third-party/java/infer-annotations/', include: ['*.jar'])
260260
compile 'com.android.support:appcompat-v7:23.0.1'
261261
compile 'com.android.support:recyclerview-v7:23.0.1'
262-
compile 'com.facebook.fresco:fresco:0.8.1'
263-
compile 'com.facebook.fresco:imagepipeline-okhttp:0.8.1'
262+
compile 'com.facebook.fresco:fresco:0.10.0'
263+
compile 'com.facebook.fresco:imagepipeline-okhttp3:0.10.0'
264264
compile 'com.fasterxml.jackson.core:jackson-core:2.2.3'
265265
compile 'com.google.code.findbugs:jsr305:3.0.0'
266-
compile 'com.squareup.okhttp:okhttp:2.5.0'
267-
compile 'com.squareup.okhttp:okhttp-ws:2.5.0'
268-
compile 'com.squareup.okio:okio:1.6.0'
266+
compile 'com.squareup.okhttp3:okhttp:3.2.0'
267+
compile 'com.squareup.okhttp3:okhttp-urlconnection:3.2.0'
268+
compile 'com.squareup.okhttp3:okhttp-ws:3.2.0'
269+
compile 'com.squareup.okio:okio:1.8.0'
269270
compile 'org.webkit:android-jsc:r174650'
270271

271272
testCompile "junit:junit:${JUNIT_VERSION}"

ReactAndroid/src/main/java/com/facebook/react/bridge/BUCK

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,16 +21,16 @@ android_library(
2121
react_native_dep('java/com/facebook/proguard/annotations:annotations'),
2222
],
2323
deps = [
24-
react_native_target('java/com/facebook/react/common:common'),
2524
react_native_dep('java/com/facebook/systrace:systrace'),
2625
react_native_dep('libraries/fbcore/src/main/java/com/facebook/common/logging:logging'),
2726
react_native_dep('libraries/soloader/java/com/facebook/soloader:soloader'),
2827
react_native_dep('third-party/java/infer-annotations:infer-annotations'),
2928
react_native_dep('third-party/java/jackson:core'),
3029
react_native_dep('third-party/java/jsr-305:jsr-305'),
30+
react_native_dep('third-party/java/okhttp:okhttp3'),
31+
react_native_dep('third-party/java/okhttp:okhttp3-ws'),
3132
react_native_dep('third-party/java/okio:okio'),
32-
react_native_dep('third-party/java/okhttp:okhttp'),
33-
react_native_dep('third-party/java/okhttp:okhttp-ws'),
33+
react_native_target('java/com/facebook/react/common:common'),
3434
],
3535
visibility = [
3636
'PUBLIC',

ReactAndroid/src/main/java/com/facebook/react/bridge/JSDebuggerWebSocketClient.java

Lines changed: 19 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,15 @@
2525
import com.fasterxml.jackson.core.JsonGenerator;
2626
import com.fasterxml.jackson.core.JsonParser;
2727
import com.fasterxml.jackson.core.JsonToken;
28-
import com.squareup.okhttp.OkHttpClient;
29-
import com.squareup.okhttp.Request;
30-
import com.squareup.okhttp.Response;
31-
import com.squareup.okhttp.ws.WebSocket;
32-
import com.squareup.okhttp.ws.WebSocketCall;
33-
import com.squareup.okhttp.ws.WebSocketListener;
28+
import okhttp3.OkHttpClient;
29+
import okhttp3.Request;
30+
import okhttp3.RequestBody;
31+
import okhttp3.Response;
32+
import okhttp3.ResponseBody;
33+
import okhttp3.ws.WebSocket;
34+
import okhttp3.ws.WebSocketCall;
35+
import okhttp3.ws.WebSocketListener;
3436
import okio.Buffer;
35-
import okio.BufferedSource;
3637

3738
/**
3839
* A wrapper around WebSocketClient that recognizes RN debugging message format.
@@ -59,11 +60,11 @@ public void connect(String url, JSDebuggerCallback callback) {
5960
throw new IllegalStateException("JSDebuggerWebSocketClient is already initialized.");
6061
}
6162
mConnectCallback = callback;
62-
mHttpClient = new OkHttpClient();
63-
mHttpClient.setConnectTimeout(10, TimeUnit.SECONDS);
64-
mHttpClient.setWriteTimeout(10, TimeUnit.SECONDS);
65-
// Disable timeouts for read
66-
mHttpClient.setReadTimeout(0, TimeUnit.MINUTES);
63+
mHttpClient = new OkHttpClient.Builder()
64+
.connectTimeout(10, TimeUnit.SECONDS)
65+
.writeTimeout(10, TimeUnit.SECONDS)
66+
.readTimeout(0, TimeUnit.MINUTES) // Disable timeouts for read
67+
.build();
6768

6869
Request request = new Request.Builder().url(url).build();
6970
WebSocketCall call = WebSocketCall.create(mHttpClient, request);
@@ -162,10 +163,8 @@ private void sendMessage(int requestID, String message) {
162163
new IllegalStateException("WebSocket connection no longer valid"));
163164
return;
164165
}
165-
Buffer messageBuffer = new Buffer();
166-
messageBuffer.writeUtf8(message);
167166
try {
168-
mWebSocket.sendMessage(WebSocket.PayloadType.TEXT, messageBuffer);
167+
mWebSocket.sendMessage(RequestBody.create(WebSocket.TEXT, message));
169168
} catch (IOException e) {
170169
triggerRequestFailure(requestID, e);
171170
}
@@ -188,17 +187,17 @@ private void triggerRequestSuccess(int requestID, @Nullable String response) {
188187
}
189188

190189
@Override
191-
public void onMessage(BufferedSource payload, WebSocket.PayloadType type) throws IOException {
192-
if (type != WebSocket.PayloadType.TEXT) {
193-
FLog.w(TAG, "Websocket received unexpected message with payload of type " + type);
190+
public void onMessage(ResponseBody response) throws IOException {
191+
if (response.contentType() != WebSocket.TEXT) {
192+
FLog.w(TAG, "Websocket received unexpected message with payload of type " + response.contentType());
194193
return;
195194
}
196195

197196
String message = null;
198197
try {
199-
message = payload.readUtf8();
198+
message = response.source().readUtf8();
200199
} finally {
201-
payload.close();
200+
response.close();
202201
}
203202
Integer replyID = null;
204203

ReactAndroid/src/main/java/com/facebook/react/bridge/webworkers/WebWorkers.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@
1818
import com.facebook.react.bridge.queue.ProxyQueueThreadExceptionHandler;
1919
import com.facebook.react.common.build.ReactBuildConfig;
2020

21-
import com.squareup.okhttp.OkHttpClient;
22-
import com.squareup.okhttp.Request;
23-
import com.squareup.okhttp.Response;
21+
import okhttp3.OkHttpClient;
22+
import okhttp3.Request;
23+
import okhttp3.Response;
2424
import okio.Okio;
2525
import okio.Sink;
2626

ReactAndroid/src/main/java/com/facebook/react/common/BUCK

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ android_library(
77
':build_config',
88
react_native_dep('third-party/java/infer-annotations:infer-annotations'),
99
react_native_dep('third-party/java/jsr-305:jsr-305'),
10+
react_native_dep('third-party/java/okhttp:okhttp3'),
1011
],
1112
exported_deps = [
1213
react_native_dep('java/com/facebook/proguard/annotations:annotations'),
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/**
2+
* Copyright (c) 2015-present, Facebook, Inc.
3+
* All rights reserved.
4+
* <p/>
5+
* This source code is licensed under the BSD-style license found in the
6+
* LICENSE file in the root directory of this source tree. An additional grant
7+
* of patent rights can be found in the PATENTS file in the same directory.
8+
*/
9+
10+
package com.facebook.react.common.network;
11+
12+
import okhttp3.Call;
13+
import okhttp3.OkHttpClient;
14+
15+
/**
16+
* Helper class that provides the necessary methods for canceling queued and running OkHttp calls
17+
*/
18+
public class OkHttpCallUtil {
19+
20+
private OkHttpCallUtil() {
21+
}
22+
23+
public static void cancelTag(OkHttpClient client, Object tag) {
24+
for (Call call : client.dispatcher().queuedCalls()) {
25+
if (tag.equals(call.request().tag())) {
26+
call.cancel();
27+
}
28+
}
29+
for (Call call : client.dispatcher().runningCalls()) {
30+
if (tag.equals(call.request().tag())) {
31+
call.cancel();
32+
}
33+
}
34+
}
35+
}

ReactAndroid/src/main/java/com/facebook/react/devsupport/BUCK

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,16 @@ android_library(
55
manifest = 'AndroidManifest.xml',
66
srcs = glob(['**/*.java']),
77
deps = [
8-
react_native_target('res:devsupport'),
9-
react_native_target('java/com/facebook/react/bridge:bridge'),
10-
react_native_target('java/com/facebook/react/common:common'),
11-
react_native_target('java/com/facebook/react/modules/debug:debug'),
12-
react_native_target('java/com/facebook/react/modules/systeminfo:systeminfo'),
138
react_native_dep('libraries/fbcore/src/main/java/com/facebook/common/logging:logging'),
149
react_native_dep('third-party/java/infer-annotations:infer-annotations'),
1510
react_native_dep('third-party/java/jsr-305:jsr-305'),
16-
react_native_dep('third-party/java/okhttp:okhttp'),
11+
react_native_dep('third-party/java/okhttp:okhttp3'),
1712
react_native_dep('third-party/java/okio:okio'),
18-
13+
react_native_target('java/com/facebook/react/bridge:bridge'),
14+
react_native_target('java/com/facebook/react/common:common'),
15+
react_native_target('java/com/facebook/react/modules/debug:debug'),
16+
react_native_target('java/com/facebook/react/modules/systeminfo:systeminfo'),
17+
react_native_target('res:devsupport'),
1918
],
2019
visibility = [
2120
'PUBLIC',

ReactAndroid/src/main/java/com/facebook/react/devsupport/DevServerHelper.java

Lines changed: 28 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,8 @@
1717
import com.facebook.infer.annotation.Assertions;
1818
import com.facebook.react.bridge.UiThreadUtil;
1919
import com.facebook.react.common.ReactConstants;
20+
import com.facebook.react.common.network.OkHttpCallUtil;
2021
import com.facebook.react.modules.systeminfo.AndroidInfoHelpers;
21-
import com.squareup.okhttp.Call;
22-
import com.squareup.okhttp.Callback;
23-
import com.squareup.okhttp.ConnectionPool;
24-
import com.squareup.okhttp.OkHttpClient;
25-
import com.squareup.okhttp.Request;
26-
import com.squareup.okhttp.Response;
27-
import com.squareup.okhttp.ResponseBody;
2822

2923
import java.io.File;
3024
import java.io.IOException;
@@ -33,6 +27,13 @@
3327

3428
import javax.annotation.Nullable;
3529

30+
import okhttp3.Call;
31+
import okhttp3.Callback;
32+
import okhttp3.ConnectionPool;
33+
import okhttp3.OkHttpClient;
34+
import okhttp3.Request;
35+
import okhttp3.Response;
36+
import okhttp3.ResponseBody;
3637
import okio.Okio;
3738
import okio.Sink;
3839

@@ -91,12 +92,12 @@ public interface PackagerStatusCallback {
9192

9293
public DevServerHelper(DevInternalSettings settings) {
9394
mSettings = settings;
94-
mClient = new OkHttpClient();
95-
mClient.setConnectTimeout(HTTP_CONNECT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
95+
mClient = new OkHttpClient.Builder()
96+
.connectTimeout(HTTP_CONNECT_TIMEOUT_MS, TimeUnit.MILLISECONDS)
97+
.readTimeout(0, TimeUnit.MILLISECONDS)
98+
.writeTimeout(0, TimeUnit.MILLISECONDS)
99+
.build();
96100

97-
// No read or write timeouts by default
98-
mClient.setReadTimeout(0, TimeUnit.MILLISECONDS);
99-
mClient.setWriteTimeout(0, TimeUnit.MILLISECONDS);
100101
mRestartOnChangePollingHandler = new Handler();
101102
}
102103

@@ -176,7 +177,7 @@ public void downloadBundleFromURL(
176177
mDownloadBundleFromURLCall = Assertions.assertNotNull(mClient.newCall(request));
177178
mDownloadBundleFromURLCall.enqueue(new Callback() {
178179
@Override
179-
public void onFailure(Request request, IOException e) {
180+
public void onFailure(Call call, IOException e) {
180181
// ignore callback if call was cancelled
181182
if (mDownloadBundleFromURLCall == null || mDownloadBundleFromURLCall.isCanceled()) {
182183
mDownloadBundleFromURLCall = null;
@@ -191,12 +192,12 @@ public void onFailure(Request request, IOException e) {
191192
.append("\u2022 Ensure that your device/emulator is connected to your machine and has USB debugging enabled - run 'adb devices' to see a list of connected devices\n")
192193
.append("\u2022 If you're on a physical device connected to the same machine, run 'adb reverse tcp:8081 tcp:8081' to forward requests from your device\n")
193194
.append("\u2022 If your device is on the same Wi-Fi network, set 'Debug server host & port for device' in 'Dev settings' to your machine's IP address and the port of the local dev server - e.g. 10.0.1.1:8081\n\n")
194-
.append("URL: ").append(request.urlString());
195+
.append("URL: ").append(call.request().url().toString());
195196
callback.onFailure(new DebugServerException(sb.toString()));
196197
}
197198

198199
@Override
199-
public void onResponse(Response response) throws IOException {
200+
public void onResponse(Call call, Response response) throws IOException {
200201
// ignore callback if call was cancelled
201202
if (mDownloadBundleFromURLCall == null || mDownloadBundleFromURLCall.isCanceled()) {
202203
mDownloadBundleFromURLCall = null;
@@ -213,7 +214,7 @@ public void onResponse(Response response) throws IOException {
213214
} else {
214215
StringBuilder sb = new StringBuilder();
215216
sb.append("The development server returned response error code: ").append(response.code()).append("\n\n")
216-
.append("URL: ").append(request.urlString()).append("\n\n")
217+
.append("URL: ").append(call.request().url().toString()).append("\n\n")
217218
.append("Body:\n")
218219
.append(body);
219220
callback.onFailure(new DebugServerException(sb.toString()));
@@ -251,7 +252,7 @@ public void isPackagerRunning(final PackagerStatusCallback callback) {
251252
mClient.newCall(request).enqueue(
252253
new Callback() {
253254
@Override
254-
public void onFailure(Request request, IOException e) {
255+
public void onFailure(Call call, IOException e) {
255256
FLog.w(
256257
ReactConstants.TAG,
257258
"The packager does not seem to be running as we got an IOException requesting " +
@@ -260,7 +261,7 @@ public void onFailure(Request request, IOException e) {
260261
}
261262

262263
@Override
263-
public void onResponse(Response response) throws IOException {
264+
public void onResponse(Call call, Response response) throws IOException {
264265
if (!response.isSuccessful()) {
265266
FLog.e(
266267
ReactConstants.TAG,
@@ -297,7 +298,7 @@ public void stopPollingOnChangeEndpoint() {
297298
mOnChangePollingEnabled = false;
298299
mRestartOnChangePollingHandler.removeCallbacksAndMessages(null);
299300
if (mOnChangePollingClient != null) {
300-
mOnChangePollingClient.cancel(this);
301+
OkHttpCallUtil.cancelTag(mOnChangePollingClient, this);
301302
mOnChangePollingClient = null;
302303
}
303304
mOnServerContentChangeListener = null;
@@ -311,10 +312,10 @@ public void startPollingOnChangeEndpoint(
311312
}
312313
mOnChangePollingEnabled = true;
313314
mOnServerContentChangeListener = onServerContentChangeListener;
314-
mOnChangePollingClient = new OkHttpClient();
315-
mOnChangePollingClient
316-
.setConnectionPool(new ConnectionPool(1, LONG_POLL_KEEP_ALIVE_DURATION_MS))
317-
.setConnectTimeout(HTTP_CONNECT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
315+
mOnChangePollingClient = new OkHttpClient.Builder()
316+
.connectionPool(new ConnectionPool(1, LONG_POLL_KEEP_ALIVE_DURATION_MS, TimeUnit.MINUTES))
317+
.connectTimeout(HTTP_CONNECT_TIMEOUT_MS, TimeUnit.MILLISECONDS)
318+
.build();
318319
enqueueOnChangeEndpointLongPolling();
319320
}
320321

@@ -338,7 +339,7 @@ private void enqueueOnChangeEndpointLongPolling() {
338339
Request request = new Request.Builder().url(createOnChangeEndpointUrl()).tag(this).build();
339340
Assertions.assertNotNull(mOnChangePollingClient).newCall(request).enqueue(new Callback() {
340341
@Override
341-
public void onFailure(Request request, IOException e) {
342+
public void onFailure(Call call, IOException e) {
342343
if (mOnChangePollingEnabled) {
343344
// this runnable is used by onchange endpoint poller to delay subsequent requests in case
344345
// of a failure, so that we don't flood network queue with frequent requests in case when
@@ -356,7 +357,7 @@ public void run() {
356357
}
357358

358359
@Override
359-
public void onResponse(Response response) throws IOException {
360+
public void onResponse(Call call, Response response) throws IOException {
360361
handleOnChangePollingResponse(response.code() == 205);
361362
}
362363
});
@@ -376,13 +377,13 @@ public void launchJSDevtools() {
376377
.build();
377378
mClient.newCall(request).enqueue(new Callback() {
378379
@Override
379-
public void onFailure(Request request, IOException e) {
380+
public void onFailure(Call call, IOException e) {
380381
// ignore HTTP call response, this is just to open a debugger page and there is no reason
381382
// to report failures from here
382383
}
383384

384385
@Override
385-
public void onResponse(Response response) throws IOException {
386+
public void onResponse(Call call, Response response) throws IOException {
386387
// ignore HTTP call response - see above
387388
}
388389
});

ReactAndroid/src/main/java/com/facebook/react/devsupport/RedBoxDialog.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,10 @@
3030
import com.facebook.react.common.ReactConstants;
3131
import com.facebook.react.devsupport.StackTraceHelper.StackFrame;
3232

33-
import com.squareup.okhttp.MediaType;
34-
import com.squareup.okhttp.OkHttpClient;
35-
import com.squareup.okhttp.Request;
36-
import com.squareup.okhttp.RequestBody;
33+
import okhttp3.MediaType;
34+
import okhttp3.OkHttpClient;
35+
import okhttp3.Request;
36+
import okhttp3.RequestBody;
3737
import org.json.JSONObject;
3838

3939
/**

ReactAndroid/src/main/java/com/facebook/react/modules/fresco/BUCK

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,21 +4,21 @@ android_library(
44
name = 'fresco',
55
srcs = glob(['**/*.java']),
66
deps = [
7-
react_native_target('java/com/facebook/react/bridge:bridge'),
8-
react_native_target('java/com/facebook/react/modules/common:common'),
9-
react_native_target('java/com/facebook/react/modules/network:network'),
107
react_native_dep('java/com/facebook/systrace:systrace'),
8+
react_native_dep('libraries/fresco/fresco-react-native:fbcore'),
9+
react_native_dep('libraries/fresco/fresco-react-native:fresco-drawee'),
1110
react_native_dep('libraries/fresco/fresco-react-native:fresco-react-native'),
1211
react_native_dep('libraries/fresco/fresco-react-native:imagepipeline'),
13-
react_native_dep('libraries/fresco/fresco-react-native:imagepipeline-okhttp'),
12+
react_native_dep('libraries/fresco/fresco-react-native:imagepipeline-okhttp3'),
1413
react_native_dep('libraries/soloader/java/com/facebook/soloader:soloader'),
1514
react_native_dep('third-party/android/support-annotations:android-support-annotations'),
1615
react_native_dep('third-party/android/support/v4:lib-support-v4'),
1716
react_native_dep('third-party/java/jsr-305:jsr-305'),
18-
react_native_dep('third-party/java/okhttp:okhttp'),
19-
react_native_dep('libraries/fresco/fresco-react-native:fbcore'),
20-
react_native_dep('libraries/fresco/fresco-react-native:fresco-drawee'),
21-
],
17+
react_native_dep('third-party/java/okhttp:okhttp3'),
18+
react_native_target('java/com/facebook/react/bridge:bridge'),
19+
react_native_target('java/com/facebook/react/modules/common:common'),
20+
react_native_target('java/com/facebook/react/modules/network:network'),
21+
],
2222
visibility = [
2323
'PUBLIC',
2424
],

0 commit comments

Comments
 (0)