From e674e45c2e090d5c2ea6ba6d1a783471ff4675de Mon Sep 17 00:00:00 2001 From: Christopher Dro Date: Tue, 15 Mar 2016 07:19:05 -0700 Subject: [PATCH] Reverted commit D3040735 Summary:This is a follow up of https://github.com/facebook/react-native/commit/9b87e6c860a95fe3d55285314d3d56be06cb7833. - Allows custom headers on connection request - Adds a default `origin` header to Android, just like iOS **Introduces no breaking changes.** I was working on something similar and would like to propose a few changes that make the API more consistent across both iOS and Android platforms and brings this closer to [spec](https://tools.ietf.org/html/rfc6455). I believe aprock first implementation of adding custom `headers` was correct. It makes sense naming this argument `headers` since we have no other general options available, and the current `options` field is being used to pass in a header anyway. My use case for custom headers was attaching a token to the `Authorization` header on the connection request. I have been testing this by passing a JWT inside the `Authorization` header and verifying it on the server before establishing a connection. Closes https://github.com/facebook/react-native/pull/6016 Differential Revision: D3040735 fb-gh-sync-id: 183744d2415b895f9d9fd8ecf6023a546e18a546 shipit-source-id: 183744d2415b895f9d9fd8ecf6023a546e18a546 --- Libraries/WebSocket/RCTSRWebSocket.h | 8 ++- Libraries/WebSocket/RCTSRWebSocket.m | 19 ++++-- Libraries/WebSocket/RCTWebSocketModule.m | 10 +-- Libraries/WebSocket/WebSocket.js | 4 +- .../modules/websocket/WebSocketModule.java | 62 +++---------------- 5 files changed, 30 insertions(+), 73 deletions(-) diff --git a/Libraries/WebSocket/RCTSRWebSocket.h b/Libraries/WebSocket/RCTSRWebSocket.h index 1b17cffaf47c08..12753043470e32 100644 --- a/Libraries/WebSocket/RCTSRWebSocket.h +++ b/Libraries/WebSocket/RCTSRWebSocket.h @@ -60,17 +60,19 @@ 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 *)protocols NS_DESIGNATED_INITIALIZER; +// options can contain a custom "origin" NSString +- (instancetype)initWithURLRequest:(NSURLRequest *)request protocols:(NSArray *)protocols options:(NSDictionary *)options NS_DESIGNATED_INITIALIZER; - (instancetype)initWithURLRequest:(NSURLRequest *)request; // Some helper constructors. +- (instancetype)initWithURL:(NSURL *)url protocols:(NSArray *)protocols options:(NSDictionary *)options; - (instancetype)initWithURL:(NSURL *)url protocols:(NSArray *)protocols; - (instancetype)initWithURL:(NSURL *)url; // Delegate queue will be dispatch_main_queue by default. // You cannot set both OperationQueue and dispatch_queue. -- (void)setDelegateOperationQueue:(NSOperationQueue *)queue; -- (void)setDelegateDispatchQueue:(dispatch_queue_t)queue; +- (void)setDelegateOperationQueue:(NSOperationQueue*) queue; +- (void)setDelegateDispatchQueue:(dispatch_queue_t) queue; // By default, it will schedule itself on +[NSRunLoop RCTSR_networkRunLoop] using defaultModes. - (void)scheduleInRunLoop:(NSRunLoop *)aRunLoop forMode:(NSString *)mode; diff --git a/Libraries/WebSocket/RCTSRWebSocket.m b/Libraries/WebSocket/RCTSRWebSocket.m index fe02d069768db7..bf67c3b14e3748 100644 --- a/Libraries/WebSocket/RCTSRWebSocket.m +++ b/Libraries/WebSocket/RCTSRWebSocket.m @@ -234,6 +234,7 @@ @implementation RCTSRWebSocket __strong RCTSRWebSocket *_selfRetain; NSArray *_requestedProtocols; + NSDictionary *_requestedOptions; RCTSRIOConsumerPool *_consumerPool; } @@ -244,7 +245,7 @@ + (void)initialize; CRLFCRLF = [[NSData alloc] initWithBytes:"\r\n\r\n" length:4]; } -- (instancetype)initWithURLRequest:(NSURLRequest *)request protocols:(NSArray *)protocols +- (instancetype)initWithURLRequest:(NSURLRequest *)request protocols:(NSArray *)protocols options:(NSDictionary *)options { RCTAssertParam(request); @@ -253,6 +254,7 @@ - (instancetype)initWithURLRequest:(NSURLRequest *)request protocols:(NSArray *)protocols; +{ + return [self initWithURL:URL protocols:protocols options:nil]; +} + +- (instancetype)initWithURL:(NSURL *)URL protocols:(NSArray *)protocols options:(NSDictionary *)options { NSMutableURLRequest *request; if (URL) { @@ -290,7 +297,7 @@ - (instancetype)initWithURL:(NSURL *)URL protocols:(NSArray *)protoc NSArray *cookies = [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookiesForURL:components.URL]; [request setAllHTTPHeaderFields:[NSHTTPCookie requestHeaderFieldsWithCookies:cookies]]; } - return [self initWithURLRequest:request protocols:protocols]; + return [self initWithURLRequest:request protocols:protocols options:options]; } - (void)_RCTSR_commonInit; @@ -481,12 +488,12 @@ - (void)didConnect 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); }]; diff --git a/Libraries/WebSocket/RCTWebSocketModule.m b/Libraries/WebSocket/RCTWebSocketModule.m index aa5d0e412c5e50..6e057f78b148c7 100644 --- a/Libraries/WebSocket/RCTWebSocketModule.m +++ b/Libraries/WebSocket/RCTWebSocketModule.m @@ -11,7 +11,6 @@ #import "RCTBridge.h" #import "RCTEventDispatcher.h" -#import "RCTConvert.h" #import "RCTUtils.h" @implementation RCTSRWebSocket (React) @@ -45,14 +44,9 @@ - (void)dealloc } } -RCT_EXPORT_METHOD(connect:(NSURL *)URL protocols:(NSArray *)protocols headers:(NSDictionary *)headers socketID:(nonnull NSNumber *)socketID) +RCT_EXPORT_METHOD(connect:(NSURL *)URL protocols:(NSArray *)protocols options:(NSDictionary *)options socketID:(nonnull NSNumber *)socketID) { - NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:URL]; - [headers enumerateKeysAndObjectsUsingBlock:^(NSString *key, id value, BOOL *stop) { - [request addValue:[RCTConvert NSString:value] forHTTPHeaderField:key]; - }]; - - RCTSRWebSocket *webSocket = [[RCTSRWebSocket alloc] initWithURLRequest:request protocols:protocols]; + RCTSRWebSocket *webSocket = [[RCTSRWebSocket alloc] initWithURL:URL protocols:protocols options:options]; webSocket.delegate = self; webSocket.reactTag = socketID; if (!_sockets) { diff --git a/Libraries/WebSocket/WebSocket.js b/Libraries/WebSocket/WebSocket.js index 905a9f6558f78b..ec6f722ef7a8ab 100644 --- a/Libraries/WebSocket/WebSocket.js +++ b/Libraries/WebSocket/WebSocket.js @@ -33,10 +33,10 @@ class WebSocket extends WebSocketBase { _socketId: number; _subs: any; - connectToSocketImpl(url: string, protocols: ?Array, headers: ?Object): void { + connectToSocketImpl(url: string, protocols: ?Array, options: ?{origin?: string}): void { this._socketId = WebSocketId++; - RCTWebSocketModule.connect(url, protocols, headers, this._socketId); + RCTWebSocketModule.connect(url, protocols, options, this._socketId); this._registerEvents(this._socketId); } diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/websocket/WebSocketModule.java b/ReactAndroid/src/main/java/com/facebook/react/modules/websocket/WebSocketModule.java index 1d9d1dda124e80..af8d79597884e5 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/websocket/WebSocketModule.java +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/websocket/WebSocketModule.java @@ -34,8 +34,6 @@ import com.squareup.okhttp.ws.WebSocketCall; import com.squareup.okhttp.ws.WebSocketListener; -import java.net.URISyntaxException; -import java.net.URI; import java.util.HashMap; import java.util.Map; import java.util.concurrent.TimeUnit; @@ -65,7 +63,7 @@ public String getName() { } @ReactMethod - public void connect(final String url, @Nullable final ReadableArray protocols, @Nullable final ReadableMap headers, final int id) { + public void connect(final String url, @Nullable final ReadableArray protocols, @Nullable final ReadableMap options, final int id) { // ignoring protocols, since OKHttp overrides them. OkHttpClient client = new OkHttpClient(); @@ -78,25 +76,14 @@ public void connect(final String url, @Nullable final ReadableArray protocols, @ .tag(id) .url(url); - if (headers != null) { - ReadableMapKeySetIterator iterator = headers.keySetIterator(); - - if (!headers.hasKey("origin")) { - builder.addHeader("origin", setDefaultOrigin(url)); - } - - while (iterator.hasNextKey()) { - String key = iterator.nextKey(); - if (ReadableType.String.equals(headers.getType(key))) { - builder.addHeader(key, headers.getString(key)); - } else { - FLog.w( - ReactConstants.TAG, - "Ignoring: requested " + key + ", value not a string"); - } + if (options != null && options.hasKey("origin")) { + if (ReadableType.String.equals(options.getType("origin"))) { + builder.addHeader("Origin", options.getString("origin")); + } else { + FLog.w( + ReactConstants.TAG, + "Ignoring: requested origin, value not a string"); } - } else { - builder.addHeader("origin", setDefaultOrigin(url)); } WebSocketCall.create(client, builder.build()).enqueue(new WebSocketListener() { @@ -201,37 +188,4 @@ private void notifyWebSocketFailed(int id, String message) { params.putString("message", message); sendEvent("websocketFailed", params); } - - /** - * Set a default origin - * - * @param Websocket connection endpoint - * @return A string of the endpoint converted to HTTP protocol - */ - - private static String setDefaultOrigin(String uri) { - try { - String defaultOrigin; - String scheme = ""; - - URI requestURI = new URI(uri); - if (requestURI.getScheme().equals("wss")) { - scheme += "https"; - } else if (requestURI.getScheme().equals("ws")) { - scheme += "http"; - } - - if (requestURI.getPort() != -1) { - defaultOrigin = String.format("%s://%s:%s", scheme, requestURI.getHost(), requestURI.getPort()); - } else { - defaultOrigin = String.format("%s://%s/", scheme, requestURI.getHost()); - } - - return defaultOrigin; - - } catch(URISyntaxException e) { - throw new IllegalArgumentException("Unable to set " + uri + " as default origin header."); - } - } - }