10
10
import androidx .annotation .Nullable ;
11
11
import com .facebook .common .logging .FLog ;
12
12
import com .facebook .infer .annotation .Assertions ;
13
+ import com .facebook .infer .annotation .Nullsafe ;
13
14
import com .facebook .react .common .DebugServerException ;
14
15
import com .facebook .react .common .ReactConstants ;
15
16
import com .facebook .react .devsupport .interfaces .DevBundleDownloadListener ;
32
33
import org .json .JSONException ;
33
34
import org .json .JSONObject ;
34
35
36
+ @ Nullsafe (Nullsafe .Mode .LOCAL )
35
37
public class BundleDownloader {
36
38
private static final String TAG = "BundleDownloader" ;
37
39
@@ -140,26 +142,29 @@ public void onResponse(Call call, final Response response) throws IOException {
140
142
final String url = response .request ().url ().toString ();
141
143
// Make sure the result is a multipart response and parse the boundary.
142
144
String contentType = response .header ("content-type" );
145
+ if (contentType == null ) {
146
+ // fallback to empty string for nullability
147
+ contentType = "" ;
148
+ }
143
149
Pattern regex = Pattern .compile ("multipart/mixed;.*boundary=\" ([^\" ]+)\" " );
144
- // NULLSAFE_FIXME[Parameter Not Nullable]
145
150
Matcher match = regex .matcher (contentType );
146
- if (match .find ()) {
147
- // NULLSAFE_FIXME[Parameter Not Nullable]
148
- processMultipartResponse (url , r , match . group ( 1 ) , outputFile , bundleInfo , callback );
151
+ if (! contentType . isEmpty () && match .find ()) {
152
+ String boundary = Assertions . assertNotNull ( match . group ( 1 ));
153
+ processMultipartResponse (url , r , boundary , outputFile , bundleInfo , callback );
149
154
} else {
150
155
// In case the server doesn't support multipart/mixed responses, fallback to normal
151
156
// download.
152
157
try (ResponseBody body = r .body ()) {
153
- processBundleResult (
154
- url ,
155
- r . code () ,
156
- r . headers (),
157
- // NULLSAFE_FIXME[Nullable Dereference]
158
- r . body () .source (),
159
- outputFile ,
160
- // NULLSAFE_FIXME[Parameter Not Nullable]
161
- bundleInfo ,
162
- callback );
158
+ if ( body != null ) {
159
+ processBundleResult (
160
+ url ,
161
+ r . code (),
162
+ r . headers (),
163
+ body .source (),
164
+ outputFile ,
165
+ bundleInfo ,
166
+ callback );
167
+ }
163
168
}
164
169
}
165
170
}
@@ -175,9 +180,18 @@ private void processMultipartResponse(
175
180
@ Nullable final BundleInfo bundleInfo ,
176
181
final DevBundleDownloadListener callback )
177
182
throws IOException {
178
-
183
+ if (response .body () == null ) {
184
+ callback .onFailure (
185
+ new DebugServerException (
186
+ "Error while reading multipart response.\n \n Response body was empty: "
187
+ + response .code ()
188
+ + "\n \n "
189
+ + "URL: "
190
+ + url .toString ()
191
+ + "\n \n " ));
192
+ return ;
193
+ }
179
194
MultipartStreamReader bodyReader =
180
- // NULLSAFE_FIXME[Nullable Dereference]
181
195
new MultipartStreamReader (response .body ().source (), boundary );
182
196
boolean completed =
183
197
bodyReader .readAllParts (
@@ -197,7 +211,6 @@ public void onChunkComplete(
197
211
status = Integer .parseInt (headers .get ("X-Http-Status" ));
198
212
}
199
213
processBundleResult (
200
- // NULLSAFE_FIXME[Parameter Not Nullable]
201
214
url , status , Headers .of (headers ), body , outputFile , bundleInfo , callback );
202
215
} else {
203
216
if (!headers .containsKey ("Content-Type" )
@@ -249,7 +262,7 @@ private void processBundleResult(
249
262
Headers headers ,
250
263
BufferedSource body ,
251
264
File outputFile ,
252
- BundleInfo bundleInfo ,
265
+ @ Nullable BundleInfo bundleInfo ,
253
266
DevBundleDownloadListener callback )
254
267
throws IOException {
255
268
// Check for server errors. If the server error has the expected form, fail with more info.
0 commit comments