Summary:
This is the first PR from a series of PRs grabbou and me will make to add blob support to React Native. The next PR will include blob support for XMLHttpRequest.
I'd like to get this merged with minimal changes to preserve the attribution. My next PR can contain bigger changes.
Blobs are used to transfer binary data between server and client. Currently React Native lacks a way to deal with binary data. The only thing that comes close is uploading files through a URI.
Current workarounds to transfer binary data includes encoding and decoding them to base64 and and transferring them as string, which is not ideal, since it increases the payload size and the whole payload needs to be sent via the bridge every time changes are made.
The PR adds a way to deal with blobs via a new native module. The blob is constructed on the native side and the data never needs to pass through the bridge. Currently the only way to create a blob is to receive a blob from the server via websocket.
The PR is largely a direct port of https://github.com/silklabs/silk/tree/master/react-native-blobs by philikon into RN (with changes to integrate with RN), and attributed as such.
> **Note:** This is a breaking change for all people running iOS without CocoaPods. You will have to manually add `RCTBlob.xcodeproj` to your `Libraries` and then, add it to Build Phases. Just follow the process of manual linking. We'll also need to document this process in the release notes.
Related discussion - https://github.com/facebook/react-native/issues/11103
- `Image` can't show image when `URL.createObjectURL` is used with large images on Android
The websocket integration can be tested via a simple server,
```js
const fs = require('fs');
const http = require('http');
const WebSocketServer = require('ws').Server;
const wss = new WebSocketServer({
server: http.createServer().listen(7232),
});
wss.on('connection', (ws) => {
ws.on('message', (d) => {
console.log(d);
});
ws.send(fs.readFileSync('./some-file'));
});
```
Then on the client,
```js
var ws = new WebSocket('ws://localhost:7232');
ws.binaryType = 'blob';
ws.onerror = (error) => {
console.error(error);
};
ws.onmessage = (e) => {
console.log(e.data);
ws.send(e.data);
};
```
cc brentvatne ide
Closes https://github.com/facebook/react-native/pull/11417
Reviewed By: sahrens
Differential Revision: D5188484
Pulled By: javache
fbshipit-source-id: 6afcbc4d19aa7a27b0dc9d52701ba400e7d7e98f
Summary:
I discovered this while trying to pinpoint why Nuclide Inspector integration with RN is so flaky. It turns out that, for some reason, if I create a `WebSocket` instance early enough (which I need to when setting up DevTools integration), and the connection is fast enough (which it is on localhost), the `websocketOpen` message may arrive earlier than an `onopen` event handler is registered, causing the `onopen` handler to never fire.
```
mkdir ~/my-server
cd ~/my-server
npm i ws
nano index.js
```
Paste this code:
```js
const ws = require('ws');
const wss = new ws.Server({
port: 8099
});
```
Run the server:
```js
node index.js
```
Now, inside React Native, paste right after [these lines](57010d63b6/Libraries/Core/InitializeCore.js (L193-L194)):
```js
const ws = new window.WebSocket('ws://localhost:8099');
ws.onopen = function() {
alert('open!');
};
```
Closes https://github.com/facebook/react-native/pull/12305
Differential Revision: D4536554
Pulled By: gaearon
fbshipit-source-id: 3021fa26b3bf275cba3704a7f3a30c77db69a1f8
Summary:
Support `xhr.send(data)` for typed arrays.
**Test plan:** run UIExplorer example on iOS and Android.
Closes https://github.com/facebook/react-native/pull/11904
Differential Revision: D4425551
fbshipit-source-id: 065ab5873407a406ca4a831068ab138606c3361b
Summary:
Fix for https://github.com/facebook/react-native/issues/9465
We are building a react-native based application which extensively uses WebSockets. The Android app crashes right after waking up being in suspended mode for a coupe of days and throws an exception:
"Cannot send a message. Unknown WebSocket id 1"
Before calling WebSocket.send(...) method from WebSocket.js we always check its readyState. I believe the problem is caused by not updating readyState if case of 'websocketFailed' event. this.close() cause the current used websocket ID to be removed from mWebSocketConnections HashMap (WebSocketModule.java), but readyState stays the same.
Closes https://github.com/facebook/react-native/pull/9487
Differential Revision: D3838675
Pulled By: mkonicek
fbshipit-source-id: e833cef9f1b94c6f7236077241cacf5a56f5824b
Summary:
JSC on iOS 8 and above includes TypedArrays so there's no need for the guard statement anymore since React Native officially does not support iOS 7 moving forward.
Closes https://github.com/facebook/react-native/pull/9780
Differential Revision: D3834979
Pulled By: mkonicek
fbshipit-source-id: 6e28a47702d6e3d604fedb9d2d00fe1c539a6926
Summary:
Idle WebSocket connections get reset after a few minutes of inactivity. To prevent this, most WebSocket implementations offer sending special ping messages. This PR adds a method `sendPing()` to WebSocket. Ping payloads are not supported.
Manual testing can be done by adding `connection.on('ping', _ => console.log('Received ping'));` to a ws connection or using a packet sniffer while sending pings.
Closes https://github.com/facebook/react-native/pull/8505
Differential Revision: D3516260
Pulled By: dmmiller
fbshipit-source-id: cfebf5899188ae53254d5be6b666a9075e0eed89
Summary:
event-target-shim versions before 1.1.0 do not support taking an array for `EventTarget`. react-native requires `^1.0.5`, so this fixes compatibility with those earlier versions.
**Test Plan:** ran WebSocket UIExplorer example with earlier version of event-target-shim.
Closes https://github.com/facebook/react-native/pull/7261
Differential Revision: D3230881
Pulled By: martinbigio
fb-gh-sync-id: 6a22d58841a4b401a200fece64d13a70043fb09a
fbshipit-source-id: 6a22d58841a4b401a200fece64d13a70043fb09a
Summary:This is a reprise of #6327, but with iOS 7.0 compatibility and less `package.json` changes.
**Test Plan:** Load WebSocketExample in UIExplorer app and start websocket test server script (both provided in #6889) and test sending binary data on both iOS and Android
Closes https://github.com/facebook/react-native/pull/6961
Differential Revision: D3202022
Pulled By: mkonicek
fb-gh-sync-id: 38843d0a9c0172971c5c70a5139ded04042b280a
fbshipit-source-id: 38843d0a9c0172971c5c70a5139ded04042b280a
Summary:- Get rid of no longer necessary WebSocket.js v WebSocketBase.js split
- Use `EventTarget(list, of, events)` as base class to auto-generate `oneventname` getters/setters that get invoked along with other event handlers
- Type annotation `any` considered harmful, especially when we can easily spell out the actual type
- Throw in some `const` goodness for free
**Test Plan:** Launch UIExplorer example app, supplied `websocket_test_server` script, and try different combinations of sending and receiving text and binary data on both iOS and Android.
Closes https://github.com/facebook/react-native/pull/6889
Differential Revision: D3184835
Pulled By: mkonicek
fb-gh-sync-id: f21707f4e97aa5a79847f5157e0a9f132a1a01cd
fbshipit-source-id: f21707f4e97aa5a79847f5157e0a9f132a1a01cd
Summary:This is a follow up of 9b87e6c860.
- Allows custom headers on connection request
- Adds a default `origin` header to Android, just like iOS
**Introduces no breaking changes.**
I was working on something similar and would like to propose a few changes that make the API more consistent across both iOS and Android platforms and brings this closer to [spec](https://tools.ietf.org/html/rfc6455).
I believe aprock first implementation of adding custom `headers` was correct. It makes sense naming this argument `headers` since we have no other general options available, and the current `options` field is being used to pass in a header anyway.
My use case for custom headers was attaching a token to the `Authorization` header on the connection request. I have been testing this by passing a JWT inside the `Authorization` header and verifying it on the server before establishing a connection.
Closes https://github.com/facebook/react-native/pull/6016
Differential Revision: D3040735
fb-gh-sync-id: 183744d2415b895f9d9fd8ecf6023a546e18a546
shipit-source-id: 183744d2415b895f9d9fd8ecf6023a546e18a546
Summary:This is a follow up of 9b87e6c860.
- Allows custom headers on connection request
- Adds a default `origin` header to Android, just like iOS
**Introduces no breaking changes.**
I was working on something similar and would like to propose a few changes that make the API more consistent across both iOS and Android platforms and brings this closer to [spec](https://tools.ietf.org/html/rfc6455).
I believe aprock first implementation of adding custom `headers` was correct. It makes sense naming this argument `headers` since we have no other general options available, and the current `options` field is being used to pass in a header anyway.
My use case for custom headers was attaching a token to the `Authorization` header on the connection request. I have been testing this by passing a JWT inside the `Authorization` header and verifying it on the server before establishing a connection.
Closes https://github.com/facebook/react-native/pull/6016
Differential Revision: D3040735
Pulled By: nicklockwood
fb-gh-sync-id: f81bd14ccbdba36309b9d4b4850fb66fe4deae11
shipit-source-id: f81bd14ccbdba36309b9d4b4850fb66fe4deae11
Summary:Motivation: Developer expects `onclose` to be called before/during close of the websocket. The `websocketFailed` event triggers a close but does not invoke onclose.
Testplan: Connect to a websocket server from android, terminate the server, observe that onerror is called, the websocket is closed, but onclose is not called.
Note: the observed bug is in android only because in iOS the underlying websocket implementation fires the `websocketClosed` rather than `websocketFailed` event when the server terminates. Nevertheless, the justification for this change stands that regardless of the cause of the close, if `this.close` is called it is expected this.onclose should be called as well.
Closes https://github.com/facebook/react-native/pull/6307
Differential Revision: D3017458
fb-gh-sync-id: c9e2dfefa597b4e99ee85eaa991667c347f86d83
shipit-source-id: c9e2dfefa597b4e99ee85eaa991667c347f86d83
Summary: Check that the WS state is set to OPEN before trying to close it when the ```websocketFailed``` event fires. Otherwise the app throws an error at the Android level.
Fixes#3346
Closes https://github.com/facebook/react-native/pull/3347
Reviewed By: @svcscm
Differential Revision: D2535807
Pulled By: @mkonicek
fb-gh-sync-id: bb70c551ea2e582cfaa80139a265dbbca6d990d2
Summary: The JavaScript code for Android is same as the iOS counterpart, I just added few new lines and used arrow functions instead of binding `this`.
Closes https://github.com/facebook/react-native/pull/2839
Reviewed By: @svcscm, @vjeux
Differential Revision: D2498703
Pulled By: @mkonicek
fb-gh-sync-id: 3fe958dd5af0efba00df07515f8e33b5d87eb05b