Skip to content

Commit 9b87e6c

Browse files
aprockfacebook-github-bot-4
authored andcommitted
Added an optional options parameter for WebSockets
Summary: This enables overriding origin, and other request headers. Similar to the https://github.com/websockets/ws api. Closes #4629 Reviewed By: svcscm Differential Revision: D2839951 Pulled By: mkonicek fb-gh-sync-id: 3578af4343f90572b8851ff28342a05945498ef6
1 parent 15f8069 commit 9b87e6c

File tree

6 files changed

+49
-20
lines changed

6 files changed

+49
-20
lines changed

Libraries/WebSocket/RCTSRWebSocket.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,10 +60,12 @@ extern NSString *const RCTSRHTTPResponseErrorKey;
6060
@property (nonatomic, readonly, copy) NSString *protocol;
6161

6262
// Protocols should be an array of strings that turn into Sec-WebSocket-Protocol.
63-
- (instancetype)initWithURLRequest:(NSURLRequest *)request protocols:(NSArray<NSString *> *)protocols NS_DESIGNATED_INITIALIZER;
63+
// options can contain a custom "origin" NSString
64+
- (instancetype)initWithURLRequest:(NSURLRequest *)request protocols:(NSArray<NSString *> *)protocols options:(NSDictionary<NSString *, NSString *> *)options NS_DESIGNATED_INITIALIZER;
6465
- (instancetype)initWithURLRequest:(NSURLRequest *)request;
6566

6667
// Some helper constructors.
68+
- (instancetype)initWithURL:(NSURL *)url protocols:(NSArray<NSString *> *)protocols options:(NSDictionary<NSString *, NSString *> *)options;
6769
- (instancetype)initWithURL:(NSURL *)url protocols:(NSArray<NSString *> *)protocols;
6870
- (instancetype)initWithURL:(NSURL *)url;
6971

Libraries/WebSocket/RCTSRWebSocket.m

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,7 @@ @implementation RCTSRWebSocket
234234
__strong RCTSRWebSocket *_selfRetain;
235235

236236
NSArray<NSString *> *_requestedProtocols;
237+
NSDictionary<NSString *, NSString *> *_requestedOptions;
237238
RCTSRIOConsumerPool *_consumerPool;
238239
}
239240

@@ -244,7 +245,7 @@ + (void)initialize;
244245
CRLFCRLF = [[NSData alloc] initWithBytes:"\r\n\r\n" length:4];
245246
}
246247

247-
- (instancetype)initWithURLRequest:(NSURLRequest *)request protocols:(NSArray<NSString *> *)protocols;
248+
- (instancetype)initWithURLRequest:(NSURLRequest *)request protocols:(NSArray<NSString *> *)protocols options:(NSDictionary<NSString *, NSString *> *)options
248249
{
249250
RCTAssertParam(request);
250251

@@ -253,6 +254,7 @@ - (instancetype)initWithURLRequest:(NSURLRequest *)request protocols:(NSArray<NS
253254
_urlRequest = request;
254255

255256
_requestedProtocols = [protocols copy];
257+
_requestedOptions = [options copy];
256258

257259
[self _RCTSR_commonInit];
258260
}
@@ -263,18 +265,23 @@ - (instancetype)initWithURLRequest:(NSURLRequest *)request protocols:(NSArray<NS
263265

264266
- (instancetype)initWithURLRequest:(NSURLRequest *)request;
265267
{
266-
return [self initWithURLRequest:request protocols:nil];
268+
return [self initWithURLRequest:request protocols:nil options: nil];
267269
}
268270

269271
- (instancetype)initWithURL:(NSURL *)URL;
270272
{
271-
return [self initWithURL:URL protocols:nil];
273+
return [self initWithURL:URL protocols:nil options:nil];
272274
}
273275

274276
- (instancetype)initWithURL:(NSURL *)URL protocols:(NSArray<NSString *> *)protocols;
277+
{
278+
return [self initWithURL:URL protocols:protocols options:nil];
279+
}
280+
281+
- (instancetype)initWithURL:(NSURL *)URL protocols:(NSArray<NSString *> *)protocols options:(NSDictionary<NSString *, id> *)options
275282
{
276283
NSURLRequest *request = URL ? [NSURLRequest requestWithURL:URL] : nil;
277-
return [self initWithURLRequest:request protocols:protocols];
284+
return [self initWithURLRequest:request protocols:protocols options:options];
278285
}
279286

280287
- (void)_RCTSR_commonInit;
@@ -465,12 +472,12 @@ - (void)didConnect
465472
CFHTTPMessageSetHeaderFieldValue(request, CFSTR("Sec-WebSocket-Key"), (__bridge CFStringRef)_secKey);
466473
CFHTTPMessageSetHeaderFieldValue(request, CFSTR("Sec-WebSocket-Version"), (__bridge CFStringRef)[NSString stringWithFormat:@"%ld", (long)_webSocketVersion]);
467474

468-
CFHTTPMessageSetHeaderFieldValue(request, CFSTR("Origin"), (__bridge CFStringRef)_url.RCTSR_origin);
469-
470475
if (_requestedProtocols) {
471476
CFHTTPMessageSetHeaderFieldValue(request, CFSTR("Sec-WebSocket-Protocol"), (__bridge CFStringRef)[_requestedProtocols componentsJoinedByString:@", "]);
472477
}
473478

479+
CFHTTPMessageSetHeaderFieldValue(request, CFSTR("Origin"), (__bridge CFStringRef)(_requestedOptions[@"origin"] ?: _url.RCTSR_origin));
480+
474481
[_urlRequest.allHTTPHeaderFields enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
475482
CFHTTPMessageSetHeaderFieldValue(request, (__bridge CFStringRef)key, (__bridge CFStringRef)obj);
476483
}];

Libraries/WebSocket/RCTWebSocketModule.m

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,9 @@ - (void)dealloc
4444
}
4545
}
4646

47-
RCT_EXPORT_METHOD(connect:(NSURL *)URL socketID:(nonnull NSNumber *)socketID)
47+
RCT_EXPORT_METHOD(connect:(NSURL *)URL protocols:(NSArray *)protocols options:(NSDictionary *)options socketID:(nonnull NSNumber *)socketID)
4848
{
49-
RCTSRWebSocket *webSocket = [[RCTSRWebSocket alloc] initWithURL:URL];
49+
RCTSRWebSocket *webSocket = [[RCTSRWebSocket alloc] initWithURL:URL protocols:protocols options:options];
5050
webSocket.delegate = self;
5151
webSocket.reactTag = socketID;
5252
if (!_sockets) {

Libraries/WebSocket/WebSocket.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,15 +26,16 @@ var CLOSE_NORMAL = 1000;
2626
* Browser-compatible WebSockets implementation.
2727
*
2828
* See https://developer.mozilla.org/en-US/docs/Web/API/WebSocket
29+
* See https://github.com/websockets/ws
2930
*/
3031
class WebSocket extends WebSocketBase {
3132
_socketId: number;
3233
_subs: any;
3334

34-
connectToSocketImpl(url: string): void {
35+
connectToSocketImpl(url: string, protocols: ?Array<string>, options: ?{origin?: string}): void {
3536
this._socketId = WebSocketId++;
3637

37-
RCTWebSocketModule.connect(url, this._socketId);
38+
RCTWebSocketModule.connect(url, protocols, options, this._socketId);
3839

3940
this._registerEvents(this._socketId);
4041
}

Libraries/WebSocket/WebSocketBase.js

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,19 +33,23 @@ class WebSocketBase extends EventTarget {
3333
readyState: number;
3434
url: ?string;
3535

36-
constructor(url: string, protocols: ?any) {
36+
constructor(url: string, protocols: ?string | ?Array<string>, options: ?{origin?: string}) {
3737
super();
3838
this.CONNECTING = 0;
3939
this.OPEN = 1;
4040
this.CLOSING = 2;
4141
this.CLOSED = 3;
4242

43-
if (!protocols) {
44-
protocols = [];
43+
if (typeof protocols === 'string') {
44+
protocols = [protocols];
45+
}
46+
47+
if (!Array.isArray(protocols)) {
48+
protocols = null;
4549
}
4650

4751
this.readyState = this.CONNECTING;
48-
this.connectToSocketImpl(url);
52+
this.connectToSocketImpl(url, protocols, options);
4953
}
5054

5155
close(): void {

ReactAndroid/src/main/java/com/facebook/react/modules/websocket/WebSocketModule.java

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,18 @@
1010
package com.facebook.react.modules.websocket;
1111

1212
import java.io.IOException;
13+
import javax.annotation.Nullable;
1314

1415
import com.facebook.common.logging.FLog;
1516
import com.facebook.react.bridge.Arguments;
1617
import com.facebook.react.bridge.ReactApplicationContext;
1718
import com.facebook.react.bridge.ReactContext;
1819
import com.facebook.react.bridge.ReactContextBaseJavaModule;
1920
import com.facebook.react.bridge.ReactMethod;
21+
import com.facebook.react.bridge.ReadableArray;
22+
import com.facebook.react.bridge.ReadableMap;
23+
import com.facebook.react.bridge.ReadableMapKeySetIterator;
24+
import com.facebook.react.bridge.ReadableType;
2025
import com.facebook.react.bridge.WritableMap;
2126
import com.facebook.react.common.ReactConstants;
2227
import com.facebook.react.modules.core.DeviceEventManagerModule;
@@ -57,20 +62,30 @@ public String getName() {
5762
}
5863

5964
@ReactMethod
60-
public void connect(final String url, final int id) {
65+
public void connect(final String url, @Nullable final ReadableArray protocols, @Nullable final ReadableMap options, final int id) {
66+
// ignoring protocols, since OKHttp overrides them.
6167
OkHttpClient client = new OkHttpClient();
6268

6369
client.setConnectTimeout(10, TimeUnit.SECONDS);
6470
client.setWriteTimeout(10, TimeUnit.SECONDS);
6571
// Disable timeouts for read
6672
client.setReadTimeout(0, TimeUnit.MINUTES);
6773

68-
Request request = new Request.Builder()
74+
Request.Builder builder = new Request.Builder()
6975
.tag(id)
70-
.url(url)
71-
.build();
76+
.url(url);
77+
78+
if (options != null && options.hasKey("origin")) {
79+
if (ReadableType.String.equals(options.getType("origin"))) {
80+
builder.addHeader("Origin", options.getString("origin"));
81+
} else {
82+
FLog.w(
83+
ReactConstants.TAG,
84+
"Ignoring: requested origin, value not a string");
85+
}
86+
}
7287

73-
WebSocketCall.create(client, request).enqueue(new WebSocketListener() {
88+
WebSocketCall.create(client, builder.build()).enqueue(new WebSocketListener() {
7489

7590
@Override
7691
public void onOpen(WebSocket webSocket, Response response) {

0 commit comments

Comments
 (0)