-
Notifications
You must be signed in to change notification settings - Fork 25.1k
Description
Hi team,
Description
On Android, all HTTP HEAD requests for which the server returns a Content-Length header fail with a "TypeError: Network request failed". This is reproducible in a brand-new app created using create-react-native-app, as well as on Expo Snack.
React Native version:
This affects React Native 0.63.2. Click here to expand full react-native info output.
System:
OS: macOS Mojave 10.14.6
CPU: (4) x64 Intel(R) Core(TM) i5-4308U CPU @ 2.80GHz
Memory: 372.92 MB / 16.00 GB
Shell: 3.0.2 - /usr/local/bin/fish
Binaries:
Node: 12.16.3 - /var/folders/z8/xq1r3qcd7szbpx1_77xsgpqc0000gn/T/yarn--1601305570730-0.3968610362929228/node
Yarn: 1.22.0 - /var/folders/z8/xq1r3qcd7szbpx1_77xsgpqc0000gn/T/yarn--1601305570730-0.3968610362929228/yarn
npm: 6.14.4 - /usr/local/bin/npm
Watchman: 4.9.0 - /usr/local/bin/watchman
Managers:
CocoaPods: 1.8.4 - /usr/local/lib/ruby/gems/2.5.0/bin/pod
SDKs:
iOS SDK:
Platforms: iOS 13.2, DriverKit 19.0, macOS 10.15, tvOS 13.2, watchOS 6.1
Android SDK:
API Levels: 23, 25, 26, 28, 29
Build Tools: 28.0.3, 29.0.2
Android NDK: Not Found
IDEs:
Android Studio: 3.6 AI-192.7142.36.36.6200805
Xcode: 11.3.1/11C505 - /usr/bin/xcodebuild
Languages:
Java: 11.0.6 - /usr/local/opt/openjdk@11/bin/javac
Python: 2.7.16 - /usr/local/bin/python
npmPackages:
@react-native-community/cli: Not Found
react: 16.13.1 => 16.13.1
react-native: ~0.63.2 => 0.63.2
react-native-macos: Not Found
npmGlobalPackages:
*react-native*: Not Found
Steps To Reproduce
(Try this out in the Expo Snack)
Perform the following fetch call: await fetch('https://determined-panini-990054.netlify.app/demo-image.png', { method: 'HEAD' }). Any URL where the server returns a Content-Length header will do.
Expected result: Fetch promise should resolve with an 'ok' response.
Actual result: On Android, the fetch promise rejects with TypeError: Network request failed. On iOS, the fetch promise resolves as expected.
Snack, code example, screenshot, or link to a repository:
- Expo Snack: https://snack.expo.io/@picnic-devs/584fdb
- Repro using
create-react-native-app: https://github.com/lachenmayer/react-native-android-fetch-head-repro
Investigation
Click here for in-depth investigation.
Following the stack trace that's triggered in the repro app, the promise rejection is caused by the XMLHTTPRequest's onerror callback.
The XMLHTTPRequest implementation is in Libraries/Network/XMLHTTPRequest.js. Adding the following log statement in the __didCompleteResponse method:
...results in the following error being logged:
[Mon Sep 28 2020 16:32:47.618] LOG {"error": "Content-Length (9306) and stream length (0) disagree", "requestId": 1, "timeOutError": undefined}
The Content-Length of the demo image I uploaded is indeed 9306, which can be verified in a browser by looking at the response. As the request is a HEAD request, it is expected that the stream length is 0.
Digging deeper, it seems that this exception is thrown by OkHttp: https://github.com/square/okhttp/blob/19771365f25d986d125478a75c15d24d6e285e12/okhttp/src/main/kotlin/okhttp3/ResponseBody.kt#L148
My initial hunch (see above) is that this is caused by an issue in OkHttp, but I've decided to open this here, as this breaks a core part of React Native. This affects us severely currently, as there's not really any way we can change how we make HTTP requests, so would appreciate any pointers.
Thanks a lot for your help 😊