react-native/Libraries/WebSocket/WebSocket.js

282 lines
8.2 KiB
JavaScript
Raw Normal View History

/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule WebSocket
* @flow
*/
'use strict';
Add blob implementation with WebSocket integration 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
2017-07-26 15:12:12 +00:00
const Blob = require('Blob');
const EventTarget = require('event-target-shim');
const NativeEventEmitter = require('NativeEventEmitter');
Implement Blob support for XMLHttpRequest Summary: This PR is a followup to https://github.com/facebook/react-native/pull/11417 and should be merged after that one is merged. 1. Add support for creating blobs from strings, not just other blobs 1. Add the `File` constructor which is a superset of `Blob` 1. Add the `FileReader` API which can be used to read blobs as strings or data url (base64) 1. Add support for uploading and downloading blobs via `XMLHttpRequest` and `fetch` 1. Add ability to download local files on Android so you can do `fetch(uri).then(res => res.blob())` to get a blob for a local file (iOS already supported this) 1. Clone the repo https://github.com/expo/react-native-blob-test 1. Change the `package.json` and update `react-native` dependency to point to this branch, then run `npm install` 1. Run the `server.js` file with `node server.js` 1. Open the `index.common.js` file and replace `localhost` with your computer's IP address 1. Start the packager with `yarn start` and run the app on your device If everything went well, all tests should pass, and you should see a screen like this: ![screen shot 2017-06-08 at 7 53 08 pm](https://user-images.githubusercontent.com/1174278/26936407-435bbce2-4c8c-11e7-9ae3-eb104e46961e.png)! Pull to rerun all tests or tap on specific test to re-run it [GENERAL] [FEATURE] [Blob] - Implement blob support for XMLHttpRequest Closes https://github.com/facebook/react-native/pull/11573 Reviewed By: shergin Differential Revision: D6082054 Pulled By: hramos fbshipit-source-id: cc9c174fdefdfaf6e5d9fd7b300120a01a50e8c1
2018-01-26 17:06:14 +00:00
const BlobManager = require('BlobManager');
Add blob implementation with WebSocket integration 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
2017-07-26 15:12:12 +00:00
const NativeModules = require('NativeModules');
const Platform = require('Platform');
const WebSocketEvent = require('WebSocketEvent');
/* $FlowFixMe(>=0.54.0 site=react_native_oss) This comment suppresses an error
* found when Flow v0.54 was deployed. To see the error delete this comment and
* run Flow. */
const base64 = require('base64-js');
Add blob implementation with WebSocket integration 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
2017-07-26 15:12:12 +00:00
const binaryToBase64 = require('binaryToBase64');
const invariant = require('fbjs/lib/invariant');
const {WebSocketModule} = NativeModules;
import type EventSubscription from 'EventSubscription';
Add blob implementation with WebSocket integration 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
2017-07-26 15:12:12 +00:00
type ArrayBufferView =
| Int8Array
| Uint8Array
| Uint8ClampedArray
| Int16Array
| Uint16Array
| Int32Array
| Uint32Array
| Float32Array
| Float64Array
| DataView
type BinaryType = 'blob' | 'arraybuffer'
const CONNECTING = 0;
const OPEN = 1;
const CLOSING = 2;
const CLOSED = 3;
const CLOSE_NORMAL = 1000;
const WEBSOCKET_EVENTS = [
'close',
'error',
'message',
'open',
];
let nextWebSocketId = 0;
/**
* Browser-compatible WebSockets implementation.
*
* See https://developer.mozilla.org/en-US/docs/Web/API/WebSocket
* See https://github.com/websockets/ws
*/
class WebSocket extends EventTarget(...WEBSOCKET_EVENTS) {
static CONNECTING = CONNECTING;
static OPEN = OPEN;
static CLOSING = CLOSING;
static CLOSED = CLOSED;
CONNECTING: number = CONNECTING;
OPEN: number = OPEN;
CLOSING: number = CLOSING;
CLOSED: number = CLOSED;
_socketId: number;
_eventEmitter: NativeEventEmitter;
_subscriptions: Array<EventSubscription>;
Add blob implementation with WebSocket integration 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
2017-07-26 15:12:12 +00:00
_binaryType: ?BinaryType;
onclose: ?Function;
onerror: ?Function;
onmessage: ?Function;
onopen: ?Function;
bufferedAmount: number;
extension: ?string;
protocol: ?string;
readyState: number = CONNECTING;
url: ?string;
Add blob implementation with WebSocket integration 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
2017-07-26 15:12:12 +00:00
// This module depends on the native `WebSocketModule` module. If you don't include it,
// `WebSocket.isAvailable` will return `false`, and WebSocket constructor will throw an error
Add blob implementation with WebSocket integration 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
2017-07-26 15:12:12 +00:00
static isAvailable: boolean = !!WebSocketModule;
WebSocket API change to make room for other connection options (SSL pinning) Summary: This is a simple groundwork PR to allow options to be passed to the `WebSocket` constructor. It represents a minor change to an undocumented part of the API, moving `headers` to within `options`. This will be a BC for anyone manually specifying headers other than `origin` but a) that's not a common use case with WebSockets and b) it's not documented even in code and wouldn't currently pass a flow check. NB: The third argument to the WebSocket constructor isn't part of the W3C spec, so I think this is a good place for RN-specific named parameters, better than adding a fourth argument. `protocols` needs to stay where it is, in line with the spec. If this goes through I'd like to build on it by adding an additional connection option for SSL certificate pinning, as already supported by the underlying `okhttp` and `RCTSRWebSocket`. It could later be expanded for various other uses. Currently, there's no way for a `WebSocket` user to specify any connection options other than url, protocol and headers. The fact that `WebSocket` connects in its constructor means any options have to go in there. Connect to a websocket server using iOS and Android, observe the connection headers: 1. Without specifying `origin`, the default header should be set 2. Specifying it in the old way `new WebSocket(url, protocols, { origin: 'customorigin.com' })` 3. Specifying it in the new way `new WebSocket(url, protocols, { headers: { origin: 'customorigin.com' }})`. I've tested myself using the test app with iOS and Android. Closes https://github.com/facebook/react-native/pull/15334 Differential Revision: D5601675 Pulled By: javache fbshipit-source-id: 5959d03a3e1d269b2c6775f3e0cf071ff08617bf
2017-08-10 12:59:36 +00:00
constructor(url: string, protocols: ?string | ?Array<string>, options: ?{headers?: {origin?: string}}) {
super();
if (typeof protocols === 'string') {
protocols = [protocols];
}
WebSocket API change to make room for other connection options (SSL pinning) Summary: This is a simple groundwork PR to allow options to be passed to the `WebSocket` constructor. It represents a minor change to an undocumented part of the API, moving `headers` to within `options`. This will be a BC for anyone manually specifying headers other than `origin` but a) that's not a common use case with WebSockets and b) it's not documented even in code and wouldn't currently pass a flow check. NB: The third argument to the WebSocket constructor isn't part of the W3C spec, so I think this is a good place for RN-specific named parameters, better than adding a fourth argument. `protocols` needs to stay where it is, in line with the spec. If this goes through I'd like to build on it by adding an additional connection option for SSL certificate pinning, as already supported by the underlying `okhttp` and `RCTSRWebSocket`. It could later be expanded for various other uses. Currently, there's no way for a `WebSocket` user to specify any connection options other than url, protocol and headers. The fact that `WebSocket` connects in its constructor means any options have to go in there. Connect to a websocket server using iOS and Android, observe the connection headers: 1. Without specifying `origin`, the default header should be set 2. Specifying it in the old way `new WebSocket(url, protocols, { origin: 'customorigin.com' })` 3. Specifying it in the new way `new WebSocket(url, protocols, { headers: { origin: 'customorigin.com' }})`. I've tested myself using the test app with iOS and Android. Closes https://github.com/facebook/react-native/pull/15334 Differential Revision: D5601675 Pulled By: javache fbshipit-source-id: 5959d03a3e1d269b2c6775f3e0cf071ff08617bf
2017-08-10 12:59:36 +00:00
const {headers = {}, ...unrecognized} = options || {};
// Preserve deprecated backwards compatibility for the 'origin' option
if (unrecognized && typeof unrecognized.origin === 'string') {
console.warn('Specifying `origin` as a WebSocket connection option is deprecated. Include it under `headers` instead.');
/* $FlowFixMe(>=0.54.0 site=react_native_fb,react_native_oss) This
* comment suppresses an error found when Flow v0.54 was deployed. To see
* the error delete this comment and run Flow. */
WebSocket API change to make room for other connection options (SSL pinning) Summary: This is a simple groundwork PR to allow options to be passed to the `WebSocket` constructor. It represents a minor change to an undocumented part of the API, moving `headers` to within `options`. This will be a BC for anyone manually specifying headers other than `origin` but a) that's not a common use case with WebSockets and b) it's not documented even in code and wouldn't currently pass a flow check. NB: The third argument to the WebSocket constructor isn't part of the W3C spec, so I think this is a good place for RN-specific named parameters, better than adding a fourth argument. `protocols` needs to stay where it is, in line with the spec. If this goes through I'd like to build on it by adding an additional connection option for SSL certificate pinning, as already supported by the underlying `okhttp` and `RCTSRWebSocket`. It could later be expanded for various other uses. Currently, there's no way for a `WebSocket` user to specify any connection options other than url, protocol and headers. The fact that `WebSocket` connects in its constructor means any options have to go in there. Connect to a websocket server using iOS and Android, observe the connection headers: 1. Without specifying `origin`, the default header should be set 2. Specifying it in the old way `new WebSocket(url, protocols, { origin: 'customorigin.com' })` 3. Specifying it in the new way `new WebSocket(url, protocols, { headers: { origin: 'customorigin.com' }})`. I've tested myself using the test app with iOS and Android. Closes https://github.com/facebook/react-native/pull/15334 Differential Revision: D5601675 Pulled By: javache fbshipit-source-id: 5959d03a3e1d269b2c6775f3e0cf071ff08617bf
2017-08-10 12:59:36 +00:00
headers.origin = unrecognized.origin;
/* $FlowFixMe(>=0.54.0 site=react_native_fb,react_native_oss) This
* comment suppresses an error found when Flow v0.54 was deployed. To see
* the error delete this comment and run Flow. */
WebSocket API change to make room for other connection options (SSL pinning) Summary: This is a simple groundwork PR to allow options to be passed to the `WebSocket` constructor. It represents a minor change to an undocumented part of the API, moving `headers` to within `options`. This will be a BC for anyone manually specifying headers other than `origin` but a) that's not a common use case with WebSockets and b) it's not documented even in code and wouldn't currently pass a flow check. NB: The third argument to the WebSocket constructor isn't part of the W3C spec, so I think this is a good place for RN-specific named parameters, better than adding a fourth argument. `protocols` needs to stay where it is, in line with the spec. If this goes through I'd like to build on it by adding an additional connection option for SSL certificate pinning, as already supported by the underlying `okhttp` and `RCTSRWebSocket`. It could later be expanded for various other uses. Currently, there's no way for a `WebSocket` user to specify any connection options other than url, protocol and headers. The fact that `WebSocket` connects in its constructor means any options have to go in there. Connect to a websocket server using iOS and Android, observe the connection headers: 1. Without specifying `origin`, the default header should be set 2. Specifying it in the old way `new WebSocket(url, protocols, { origin: 'customorigin.com' })` 3. Specifying it in the new way `new WebSocket(url, protocols, { headers: { origin: 'customorigin.com' }})`. I've tested myself using the test app with iOS and Android. Closes https://github.com/facebook/react-native/pull/15334 Differential Revision: D5601675 Pulled By: javache fbshipit-source-id: 5959d03a3e1d269b2c6775f3e0cf071ff08617bf
2017-08-10 12:59:36 +00:00
delete unrecognized.origin;
}
// Warn about and discard anything else
if (Object.keys(unrecognized).length > 0) {
console.warn('Unrecognized WebSocket connection option(s) `' + Object.keys(unrecognized).join('`, `') + '`. '
+ 'Did you mean to put these under `headers`?');
}
if (!Array.isArray(protocols)) {
protocols = null;
}
if (!WebSocket.isAvailable) {
throw new Error('Cannot initialize WebSocket module. ' +
Add blob implementation with WebSocket integration 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
2017-07-26 15:12:12 +00:00
'Native module WebSocketModule is missing.');
}
Add blob implementation with WebSocket integration 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
2017-07-26 15:12:12 +00:00
this._eventEmitter = new NativeEventEmitter(WebSocketModule);
this._socketId = nextWebSocketId++;
this._registerEvents();
WebSocket API change to make room for other connection options (SSL pinning) Summary: This is a simple groundwork PR to allow options to be passed to the `WebSocket` constructor. It represents a minor change to an undocumented part of the API, moving `headers` to within `options`. This will be a BC for anyone manually specifying headers other than `origin` but a) that's not a common use case with WebSockets and b) it's not documented even in code and wouldn't currently pass a flow check. NB: The third argument to the WebSocket constructor isn't part of the W3C spec, so I think this is a good place for RN-specific named parameters, better than adding a fourth argument. `protocols` needs to stay where it is, in line with the spec. If this goes through I'd like to build on it by adding an additional connection option for SSL certificate pinning, as already supported by the underlying `okhttp` and `RCTSRWebSocket`. It could later be expanded for various other uses. Currently, there's no way for a `WebSocket` user to specify any connection options other than url, protocol and headers. The fact that `WebSocket` connects in its constructor means any options have to go in there. Connect to a websocket server using iOS and Android, observe the connection headers: 1. Without specifying `origin`, the default header should be set 2. Specifying it in the old way `new WebSocket(url, protocols, { origin: 'customorigin.com' })` 3. Specifying it in the new way `new WebSocket(url, protocols, { headers: { origin: 'customorigin.com' }})`. I've tested myself using the test app with iOS and Android. Closes https://github.com/facebook/react-native/pull/15334 Differential Revision: D5601675 Pulled By: javache fbshipit-source-id: 5959d03a3e1d269b2c6775f3e0cf071ff08617bf
2017-08-10 12:59:36 +00:00
WebSocketModule.connect(url, protocols, { headers }, this._socketId);
Add blob implementation with WebSocket integration 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
2017-07-26 15:12:12 +00:00
}
get binaryType(): ?BinaryType {
return this._binaryType;
}
set binaryType(binaryType: BinaryType): void {
if (binaryType !== 'blob' && binaryType !== 'arraybuffer') {
throw new Error('binaryType must be either \'blob\' or \'arraybuffer\'');
}
if (this._binaryType === 'blob' || binaryType === 'blob') {
Implement Blob support for XMLHttpRequest Summary: This PR is a followup to https://github.com/facebook/react-native/pull/11417 and should be merged after that one is merged. 1. Add support for creating blobs from strings, not just other blobs 1. Add the `File` constructor which is a superset of `Blob` 1. Add the `FileReader` API which can be used to read blobs as strings or data url (base64) 1. Add support for uploading and downloading blobs via `XMLHttpRequest` and `fetch` 1. Add ability to download local files on Android so you can do `fetch(uri).then(res => res.blob())` to get a blob for a local file (iOS already supported this) 1. Clone the repo https://github.com/expo/react-native-blob-test 1. Change the `package.json` and update `react-native` dependency to point to this branch, then run `npm install` 1. Run the `server.js` file with `node server.js` 1. Open the `index.common.js` file and replace `localhost` with your computer's IP address 1. Start the packager with `yarn start` and run the app on your device If everything went well, all tests should pass, and you should see a screen like this: ![screen shot 2017-06-08 at 7 53 08 pm](https://user-images.githubusercontent.com/1174278/26936407-435bbce2-4c8c-11e7-9ae3-eb104e46961e.png)! Pull to rerun all tests or tap on specific test to re-run it [GENERAL] [FEATURE] [Blob] - Implement blob support for XMLHttpRequest Closes https://github.com/facebook/react-native/pull/11573 Reviewed By: shergin Differential Revision: D6082054 Pulled By: hramos fbshipit-source-id: cc9c174fdefdfaf6e5d9fd7b300120a01a50e8c1
2018-01-26 17:06:14 +00:00
invariant(BlobManager.isAvailable, 'Native module BlobModule is required for blob support');
if (binaryType === 'blob') {
BlobManager.addWebSocketHandler(this._socketId);
} else {
BlobManager.removeWebSocketHandler(this._socketId);
Add blob implementation with WebSocket integration 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
2017-07-26 15:12:12 +00:00
}
}
this._binaryType = binaryType;
}
Implement Blob support for XMLHttpRequest Summary: This PR is a followup to https://github.com/facebook/react-native/pull/11417 and should be merged after that one is merged. 1. Add support for creating blobs from strings, not just other blobs 1. Add the `File` constructor which is a superset of `Blob` 1. Add the `FileReader` API which can be used to read blobs as strings or data url (base64) 1. Add support for uploading and downloading blobs via `XMLHttpRequest` and `fetch` 1. Add ability to download local files on Android so you can do `fetch(uri).then(res => res.blob())` to get a blob for a local file (iOS already supported this) 1. Clone the repo https://github.com/expo/react-native-blob-test 1. Change the `package.json` and update `react-native` dependency to point to this branch, then run `npm install` 1. Run the `server.js` file with `node server.js` 1. Open the `index.common.js` file and replace `localhost` with your computer's IP address 1. Start the packager with `yarn start` and run the app on your device If everything went well, all tests should pass, and you should see a screen like this: ![screen shot 2017-06-08 at 7 53 08 pm](https://user-images.githubusercontent.com/1174278/26936407-435bbce2-4c8c-11e7-9ae3-eb104e46961e.png)! Pull to rerun all tests or tap on specific test to re-run it [GENERAL] [FEATURE] [Blob] - Implement blob support for XMLHttpRequest Closes https://github.com/facebook/react-native/pull/11573 Reviewed By: shergin Differential Revision: D6082054 Pulled By: hramos fbshipit-source-id: cc9c174fdefdfaf6e5d9fd7b300120a01a50e8c1
2018-01-26 17:06:14 +00:00
get binaryType(): ?BinaryType {
return this._binaryType;
}
close(code?: number, reason?: string): void {
if (this.readyState === this.CLOSING ||
this.readyState === this.CLOSED) {
return;
}
this.readyState = this.CLOSING;
this._close(code, reason);
}
Add blob implementation with WebSocket integration 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
2017-07-26 15:12:12 +00:00
send(data: string | ArrayBuffer | ArrayBufferView | Blob): void {
if (this.readyState === this.CONNECTING) {
throw new Error('INVALID_STATE_ERR');
}
Add blob implementation with WebSocket integration 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
2017-07-26 15:12:12 +00:00
if (data instanceof Blob) {
Implement Blob support for XMLHttpRequest Summary: This PR is a followup to https://github.com/facebook/react-native/pull/11417 and should be merged after that one is merged. 1. Add support for creating blobs from strings, not just other blobs 1. Add the `File` constructor which is a superset of `Blob` 1. Add the `FileReader` API which can be used to read blobs as strings or data url (base64) 1. Add support for uploading and downloading blobs via `XMLHttpRequest` and `fetch` 1. Add ability to download local files on Android so you can do `fetch(uri).then(res => res.blob())` to get a blob for a local file (iOS already supported this) 1. Clone the repo https://github.com/expo/react-native-blob-test 1. Change the `package.json` and update `react-native` dependency to point to this branch, then run `npm install` 1. Run the `server.js` file with `node server.js` 1. Open the `index.common.js` file and replace `localhost` with your computer's IP address 1. Start the packager with `yarn start` and run the app on your device If everything went well, all tests should pass, and you should see a screen like this: ![screen shot 2017-06-08 at 7 53 08 pm](https://user-images.githubusercontent.com/1174278/26936407-435bbce2-4c8c-11e7-9ae3-eb104e46961e.png)! Pull to rerun all tests or tap on specific test to re-run it [GENERAL] [FEATURE] [Blob] - Implement blob support for XMLHttpRequest Closes https://github.com/facebook/react-native/pull/11573 Reviewed By: shergin Differential Revision: D6082054 Pulled By: hramos fbshipit-source-id: cc9c174fdefdfaf6e5d9fd7b300120a01a50e8c1
2018-01-26 17:06:14 +00:00
invariant(BlobManager.isAvailable, 'Native module BlobModule is required for blob support');
BlobManager.sendOverSocket(data, this._socketId);
Add blob implementation with WebSocket integration 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
2017-07-26 15:12:12 +00:00
return;
}
if (typeof data === 'string') {
Add blob implementation with WebSocket integration 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
2017-07-26 15:12:12 +00:00
WebSocketModule.send(data, this._socketId);
return;
}
if (data instanceof ArrayBuffer || ArrayBuffer.isView(data)) {
Add blob implementation with WebSocket integration 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
2017-07-26 15:12:12 +00:00
WebSocketModule.sendBinary(binaryToBase64(data), this._socketId);
return;
}
throw new Error('Unsupported data type');
}
ping(): void {
if (this.readyState === this.CONNECTING) {
throw new Error('INVALID_STATE_ERR');
}
Add blob implementation with WebSocket integration 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
2017-07-26 15:12:12 +00:00
WebSocketModule.ping(this._socketId);
}
_close(code?: number, reason?: string): void {
if (Platform.OS === 'android') {
// See https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent
const statusCode = typeof code === 'number' ? code : CLOSE_NORMAL;
const closeReason = typeof reason === 'string' ? reason : '';
Add blob implementation with WebSocket integration 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
2017-07-26 15:12:12 +00:00
WebSocketModule.close(statusCode, closeReason, this._socketId);
} else {
Add blob implementation with WebSocket integration 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
2017-07-26 15:12:12 +00:00
WebSocketModule.close(this._socketId);
}
Implement Blob support for XMLHttpRequest Summary: This PR is a followup to https://github.com/facebook/react-native/pull/11417 and should be merged after that one is merged. 1. Add support for creating blobs from strings, not just other blobs 1. Add the `File` constructor which is a superset of `Blob` 1. Add the `FileReader` API which can be used to read blobs as strings or data url (base64) 1. Add support for uploading and downloading blobs via `XMLHttpRequest` and `fetch` 1. Add ability to download local files on Android so you can do `fetch(uri).then(res => res.blob())` to get a blob for a local file (iOS already supported this) 1. Clone the repo https://github.com/expo/react-native-blob-test 1. Change the `package.json` and update `react-native` dependency to point to this branch, then run `npm install` 1. Run the `server.js` file with `node server.js` 1. Open the `index.common.js` file and replace `localhost` with your computer's IP address 1. Start the packager with `yarn start` and run the app on your device If everything went well, all tests should pass, and you should see a screen like this: ![screen shot 2017-06-08 at 7 53 08 pm](https://user-images.githubusercontent.com/1174278/26936407-435bbce2-4c8c-11e7-9ae3-eb104e46961e.png)! Pull to rerun all tests or tap on specific test to re-run it [GENERAL] [FEATURE] [Blob] - Implement blob support for XMLHttpRequest Closes https://github.com/facebook/react-native/pull/11573 Reviewed By: shergin Differential Revision: D6082054 Pulled By: hramos fbshipit-source-id: cc9c174fdefdfaf6e5d9fd7b300120a01a50e8c1
2018-01-26 17:06:14 +00:00
if (BlobManager.isAvailable && this._binaryType === 'blob') {
BlobManager.removeWebSocketHandler(this._socketId);
}
}
_unregisterEvents(): void {
this._subscriptions.forEach(e => e.remove());
this._subscriptions = [];
}
_registerEvents(): void {
this._subscriptions = [
this._eventEmitter.addListener('websocketMessage', ev => {
if (ev.id !== this._socketId) {
return;
}
Add blob implementation with WebSocket integration 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
2017-07-26 15:12:12 +00:00
let data = ev.data;
switch (ev.type) {
case 'binary':
data = base64.toByteArray(ev.data).buffer;
break;
case 'blob':
Implement Blob support for XMLHttpRequest Summary: This PR is a followup to https://github.com/facebook/react-native/pull/11417 and should be merged after that one is merged. 1. Add support for creating blobs from strings, not just other blobs 1. Add the `File` constructor which is a superset of `Blob` 1. Add the `FileReader` API which can be used to read blobs as strings or data url (base64) 1. Add support for uploading and downloading blobs via `XMLHttpRequest` and `fetch` 1. Add ability to download local files on Android so you can do `fetch(uri).then(res => res.blob())` to get a blob for a local file (iOS already supported this) 1. Clone the repo https://github.com/expo/react-native-blob-test 1. Change the `package.json` and update `react-native` dependency to point to this branch, then run `npm install` 1. Run the `server.js` file with `node server.js` 1. Open the `index.common.js` file and replace `localhost` with your computer's IP address 1. Start the packager with `yarn start` and run the app on your device If everything went well, all tests should pass, and you should see a screen like this: ![screen shot 2017-06-08 at 7 53 08 pm](https://user-images.githubusercontent.com/1174278/26936407-435bbce2-4c8c-11e7-9ae3-eb104e46961e.png)! Pull to rerun all tests or tap on specific test to re-run it [GENERAL] [FEATURE] [Blob] - Implement blob support for XMLHttpRequest Closes https://github.com/facebook/react-native/pull/11573 Reviewed By: shergin Differential Revision: D6082054 Pulled By: hramos fbshipit-source-id: cc9c174fdefdfaf6e5d9fd7b300120a01a50e8c1
2018-01-26 17:06:14 +00:00
data = BlobManager.createFromOptions(ev.data);
Add blob implementation with WebSocket integration 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
2017-07-26 15:12:12 +00:00
break;
}
this.dispatchEvent(new WebSocketEvent('message', { data }));
}),
this._eventEmitter.addListener('websocketOpen', ev => {
if (ev.id !== this._socketId) {
return;
}
this.readyState = this.OPEN;
this.dispatchEvent(new WebSocketEvent('open'));
}),
this._eventEmitter.addListener('websocketClosed', ev => {
if (ev.id !== this._socketId) {
return;
}
this.readyState = this.CLOSED;
this.dispatchEvent(new WebSocketEvent('close', {
code: ev.code,
reason: ev.reason,
}));
this._unregisterEvents();
this.close();
}),
this._eventEmitter.addListener('websocketFailed', ev => {
if (ev.id !== this._socketId) {
return;
}
this.readyState = this.CLOSED;
this.dispatchEvent(new WebSocketEvent('error', {
message: ev.message,
}));
this.dispatchEvent(new WebSocketEvent('close', {
message: ev.message,
}));
this._unregisterEvents();
this.close();
})
];
}
}
module.exports = WebSocket;