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 https://github.com/facebook/react-native/pull/4629

Reviewed By: svcscm

Differential Revision: D2839951

Pulled By: mkonicek

fb-gh-sync-id: 3578af4343f90572b8851ff28342a05945498ef6
This commit is contained in:
Andy Prock
2016-01-20 11:00:21 -08:00
committed by facebook-github-bot-4
parent 15f806957f
commit 9b87e6c860
6 changed files with 49 additions and 20 deletions

View File

@@ -60,10 +60,12 @@ extern NSString *const RCTSRHTTPResponseErrorKey;
@property (nonatomic, readonly, copy) NSString *protocol;
// Protocols should be an array of strings that turn into Sec-WebSocket-Protocol.
- (instancetype)initWithURLRequest:(NSURLRequest *)request protocols:(NSArray<NSString *> *)protocols NS_DESIGNATED_INITIALIZER;
// options can contain a custom "origin" NSString
- (instancetype)initWithURLRequest:(NSURLRequest *)request protocols:(NSArray<NSString *> *)protocols options:(NSDictionary<NSString *, NSString *> *)options NS_DESIGNATED_INITIALIZER;
- (instancetype)initWithURLRequest:(NSURLRequest *)request;
// Some helper constructors.
- (instancetype)initWithURL:(NSURL *)url protocols:(NSArray<NSString *> *)protocols options:(NSDictionary<NSString *, NSString *> *)options;
- (instancetype)initWithURL:(NSURL *)url protocols:(NSArray<NSString *> *)protocols;
- (instancetype)initWithURL:(NSURL *)url;

View File

@@ -234,6 +234,7 @@ typedef void (^data_callback)(RCTSRWebSocket *webSocket, NSData *data);
__strong RCTSRWebSocket *_selfRetain;
NSArray<NSString *> *_requestedProtocols;
NSDictionary<NSString *, NSString *> *_requestedOptions;
RCTSRIOConsumerPool *_consumerPool;
}
@@ -244,7 +245,7 @@ static __strong NSData *CRLFCRLF;
CRLFCRLF = [[NSData alloc] initWithBytes:"\r\n\r\n" length:4];
}
- (instancetype)initWithURLRequest:(NSURLRequest *)request protocols:(NSArray<NSString *> *)protocols;
- (instancetype)initWithURLRequest:(NSURLRequest *)request protocols:(NSArray<NSString *> *)protocols options:(NSDictionary<NSString *, NSString *> *)options
{
RCTAssertParam(request);
@@ -253,6 +254,7 @@ static __strong NSData *CRLFCRLF;
_urlRequest = request;
_requestedProtocols = [protocols copy];
_requestedOptions = [options copy];
[self _RCTSR_commonInit];
}
@@ -263,18 +265,23 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init)
- (instancetype)initWithURLRequest:(NSURLRequest *)request;
{
return [self initWithURLRequest:request protocols:nil];
return [self initWithURLRequest:request protocols:nil options: nil];
}
- (instancetype)initWithURL:(NSURL *)URL;
{
return [self initWithURL:URL protocols:nil];
return [self initWithURL:URL protocols:nil options:nil];
}
- (instancetype)initWithURL:(NSURL *)URL protocols:(NSArray<NSString *> *)protocols;
{
return [self initWithURL:URL protocols:protocols options:nil];
}
- (instancetype)initWithURL:(NSURL *)URL protocols:(NSArray<NSString *> *)protocols options:(NSDictionary<NSString *, id> *)options
{
NSURLRequest *request = URL ? [NSURLRequest requestWithURL:URL] : nil;
return [self initWithURLRequest:request protocols:protocols];
return [self initWithURLRequest:request protocols:protocols options:options];
}
- (void)_RCTSR_commonInit;
@@ -465,12 +472,12 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init)
CFHTTPMessageSetHeaderFieldValue(request, CFSTR("Sec-WebSocket-Key"), (__bridge CFStringRef)_secKey);
CFHTTPMessageSetHeaderFieldValue(request, CFSTR("Sec-WebSocket-Version"), (__bridge CFStringRef)[NSString stringWithFormat:@"%ld", (long)_webSocketVersion]);
CFHTTPMessageSetHeaderFieldValue(request, CFSTR("Origin"), (__bridge CFStringRef)_url.RCTSR_origin);
if (_requestedProtocols) {
CFHTTPMessageSetHeaderFieldValue(request, CFSTR("Sec-WebSocket-Protocol"), (__bridge CFStringRef)[_requestedProtocols componentsJoinedByString:@", "]);
}
CFHTTPMessageSetHeaderFieldValue(request, CFSTR("Origin"), (__bridge CFStringRef)(_requestedOptions[@"origin"] ?: _url.RCTSR_origin));
[_urlRequest.allHTTPHeaderFields enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
CFHTTPMessageSetHeaderFieldValue(request, (__bridge CFStringRef)key, (__bridge CFStringRef)obj);
}];

View File

@@ -44,9 +44,9 @@ RCT_EXPORT_MODULE()
}
}
RCT_EXPORT_METHOD(connect:(NSURL *)URL socketID:(nonnull NSNumber *)socketID)
RCT_EXPORT_METHOD(connect:(NSURL *)URL protocols:(NSArray *)protocols options:(NSDictionary *)options socketID:(nonnull NSNumber *)socketID)
{
RCTSRWebSocket *webSocket = [[RCTSRWebSocket alloc] initWithURL:URL];
RCTSRWebSocket *webSocket = [[RCTSRWebSocket alloc] initWithURL:URL protocols:protocols options:options];
webSocket.delegate = self;
webSocket.reactTag = socketID;
if (!_sockets) {

View File

@@ -26,15 +26,16 @@ var CLOSE_NORMAL = 1000;
* Browser-compatible WebSockets implementation.
*
* See https://developer.mozilla.org/en-US/docs/Web/API/WebSocket
* See https://github.com/websockets/ws
*/
class WebSocket extends WebSocketBase {
_socketId: number;
_subs: any;
connectToSocketImpl(url: string): void {
connectToSocketImpl(url: string, protocols: ?Array<string>, options: ?{origin?: string}): void {
this._socketId = WebSocketId++;
RCTWebSocketModule.connect(url, this._socketId);
RCTWebSocketModule.connect(url, protocols, options, this._socketId);
this._registerEvents(this._socketId);
}

View File

@@ -33,19 +33,23 @@ class WebSocketBase extends EventTarget {
readyState: number;
url: ?string;
constructor(url: string, protocols: ?any) {
constructor(url: string, protocols: ?string | ?Array<string>, options: ?{origin?: string}) {
super();
this.CONNECTING = 0;
this.OPEN = 1;
this.CLOSING = 2;
this.CLOSED = 3;
if (!protocols) {
protocols = [];
if (typeof protocols === 'string') {
protocols = [protocols];
}
if (!Array.isArray(protocols)) {
protocols = null;
}
this.readyState = this.CONNECTING;
this.connectToSocketImpl(url);
this.connectToSocketImpl(url, protocols, options);
}
close(): void {