Update options parameter to headers. Update to spec.

Summary:This is a follow up of 9b87e6c860.

- Allows custom headers on connection request
- Adds a default `origin` header to Android, just like iOS

**Introduces no breaking changes.**

I was working on something similar and would like to propose a few changes that make the API more consistent across both iOS and Android platforms and brings this closer to [spec](https://tools.ietf.org/html/rfc6455).

I believe aprock first implementation of adding custom `headers` was correct. It makes sense naming this argument `headers` since we have no other general options available, and the current `options` field is being used to pass in a header anyway.

My use case for custom headers was attaching a token to the `Authorization` header on the connection request. I have been testing this by passing a JWT inside the `Authorization` header and verifying it on the server before establishing a connection.
Closes https://github.com/facebook/react-native/pull/6016

Differential Revision: D3040735

Pulled By: nicklockwood

fb-gh-sync-id: f81bd14ccbdba36309b9d4b4850fb66fe4deae11
shipit-source-id: f81bd14ccbdba36309b9d4b4850fb66fe4deae11
This commit is contained in:
Christopher Dro
2016-03-15 05:13:51 -07:00
committed by Facebook Github Bot 6
parent 79d6ced103
commit 205b5d4732
5 changed files with 73 additions and 30 deletions

View File

@@ -34,6 +34,8 @@ import com.squareup.okhttp.ws.WebSocket;
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;
@@ -63,7 +65,7 @@ public class WebSocketModule extends ReactContextBaseJavaModule {
}
@ReactMethod
public void connect(final String url, @Nullable final ReadableArray protocols, @Nullable final ReadableMap options, final int id) {
public void connect(final String url, @Nullable final ReadableArray protocols, @Nullable final ReadableMap headers, final int id) {
// ignoring protocols, since OKHttp overrides them.
OkHttpClient client = new OkHttpClient();
@@ -76,14 +78,25 @@ public class WebSocketModule extends ReactContextBaseJavaModule {
.tag(id)
.url(url);
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");
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");
}
}
} else {
builder.addHeader("origin", setDefaultOrigin(url));
}
WebSocketCall.create(client, builder.build()).enqueue(new WebSocketListener() {
@@ -188,4 +201,37 @@ public class WebSocketModule extends ReactContextBaseJavaModule {
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.");
}
}
}