diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshaker.java b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshaker.java index 0043c67b33..d9bdd93f11 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshaker.java +++ b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshaker.java @@ -40,6 +40,7 @@ import io.netty.util.ReferenceCountUtil; import java.net.URI; import java.nio.channels.ClosedChannelException; +import java.util.Locale; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; @@ -49,6 +50,8 @@ import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; */ public abstract class WebSocketClientHandshaker { + private static final String HTTP_SCHEME_PREFIX = HttpScheme.HTTP + "://"; + private static final String HTTPS_SCHEME_PREFIX = HttpScheme.HTTPS + "://"; protected static final int DEFAULT_FORCE_CLOSE_TIMEOUT_MILLIS = 10000; private final URI uri; @@ -573,4 +576,31 @@ public abstract class WebSocketClientHandshaker { // See http://tools.ietf.org/html/rfc6454#section-6.2 return NetUtil.toSocketAddressString(host, port); } + + static CharSequence websocketOriginValue(URI wsURL) { + String scheme = wsURL.getScheme(); + final String schemePrefix; + int port = wsURL.getPort(); + final int defaultPort; + if (WebSocketScheme.WSS.name().contentEquals(scheme) + || HttpScheme.HTTPS.name().contentEquals(scheme) + || (scheme == null && port == WebSocketScheme.WSS.port())) { + + schemePrefix = HTTPS_SCHEME_PREFIX; + defaultPort = WebSocketScheme.WSS.port(); + } else { + schemePrefix = HTTP_SCHEME_PREFIX; + defaultPort = WebSocketScheme.WS.port(); + } + + // Convert uri-host to lower case (by RFC 6454, chapter 4 "Origin of a URI") + String host = wsURL.getHost().toLowerCase(Locale.US); + + if (port != defaultPort && port != -1) { + // if the port is not standard (80/443) its needed to add the port to the header. + // See http://tools.ietf.org/html/rfc6454#section-6.2 + return schemePrefix + NetUtil.toSocketAddressString(host, port); + } + return schemePrefix + host; + } } diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshaker00.java b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshaker00.java index fbb0b5d2c8..8c609ed24e 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshaker00.java +++ b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshaker00.java @@ -193,6 +193,10 @@ public class WebSocketClientHandshaker00 extends WebSocketClientHandshaker { .set(HttpHeaderNames.SEC_WEBSOCKET_KEY1, key1) .set(HttpHeaderNames.SEC_WEBSOCKET_KEY2, key2); + if (!headers.contains(HttpHeaderNames.ORIGIN)) { + headers.set(HttpHeaderNames.ORIGIN, websocketOriginValue(wsURL)); + } + String expectedSubprotocol = expectedSubprotocol(); if (expectedSubprotocol != null && !expectedSubprotocol.isEmpty()) { headers.set(HttpHeaderNames.SEC_WEBSOCKET_PROTOCOL, expectedSubprotocol); diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshaker07.java b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshaker07.java index 219b8f6b52..a2fce7c911 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshaker07.java +++ b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshaker07.java @@ -187,6 +187,7 @@ public class WebSocketClientHandshaker07 extends WebSocketClientHandshaker { * Upgrade: websocket * Connection: Upgrade * Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ== + * Sec-WebSocket-Origin: http://example.com * Sec-WebSocket-Protocol: chat, superchat * Sec-WebSocket-Version: 7 * @@ -224,6 +225,10 @@ public class WebSocketClientHandshaker07 extends WebSocketClientHandshaker { .set(HttpHeaderNames.SEC_WEBSOCKET_KEY, key) .set(HttpHeaderNames.HOST, websocketHostValue(wsURL)); + if (!headers.contains(HttpHeaderNames.SEC_WEBSOCKET_ORIGIN)) { + headers.set(HttpHeaderNames.SEC_WEBSOCKET_ORIGIN, websocketOriginValue(wsURL)); + } + String expectedSubprotocol = expectedSubprotocol(); if (expectedSubprotocol != null && !expectedSubprotocol.isEmpty()) { headers.set(HttpHeaderNames.SEC_WEBSOCKET_PROTOCOL, expectedSubprotocol); diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshaker08.java b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshaker08.java index 5e8935809d..245eff8753 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshaker08.java +++ b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshaker08.java @@ -189,6 +189,7 @@ public class WebSocketClientHandshaker08 extends WebSocketClientHandshaker { * Upgrade: websocket * Connection: Upgrade * Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ== + * Sec-WebSocket-Origin: http://example.com * Sec-WebSocket-Protocol: chat, superchat * Sec-WebSocket-Version: 8 * @@ -226,6 +227,10 @@ public class WebSocketClientHandshaker08 extends WebSocketClientHandshaker { .set(HttpHeaderNames.SEC_WEBSOCKET_KEY, key) .set(HttpHeaderNames.HOST, websocketHostValue(wsURL)); + if (!headers.contains(HttpHeaderNames.SEC_WEBSOCKET_ORIGIN)) { + headers.set(HttpHeaderNames.SEC_WEBSOCKET_ORIGIN, websocketOriginValue(wsURL)); + } + String expectedSubprotocol = expectedSubprotocol(); if (expectedSubprotocol != null && !expectedSubprotocol.isEmpty()) { headers.set(HttpHeaderNames.SEC_WEBSOCKET_PROTOCOL, expectedSubprotocol); diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshaker13.java b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshaker13.java index 82a6049a0a..8efbb4a2e5 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshaker13.java +++ b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshaker13.java @@ -190,6 +190,7 @@ public class WebSocketClientHandshaker13 extends WebSocketClientHandshaker { * Upgrade: websocket * Connection: Upgrade * Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ== + * Origin: http://example.com * Sec-WebSocket-Protocol: chat, superchat * Sec-WebSocket-Version: 13 * @@ -227,6 +228,10 @@ public class WebSocketClientHandshaker13 extends WebSocketClientHandshaker { .set(HttpHeaderNames.SEC_WEBSOCKET_KEY, key) .set(HttpHeaderNames.HOST, websocketHostValue(wsURL)); + if (!headers.contains(HttpHeaderNames.ORIGIN)) { + headers.set(HttpHeaderNames.ORIGIN, websocketOriginValue(wsURL)); + } + String expectedSubprotocol = expectedSubprotocol(); if (expectedSubprotocol != null && !expectedSubprotocol.isEmpty()) { headers.set(HttpHeaderNames.SEC_WEBSOCKET_PROTOCOL, expectedSubprotocol); diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketServerHandshaker07.java b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketServerHandshaker07.java index 31f5fdb91b..54f8ff4fa7 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketServerHandshaker07.java +++ b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketServerHandshaker07.java @@ -109,6 +109,7 @@ public class WebSocketServerHandshaker07 extends WebSocketServerHandshaker { * Upgrade: websocket * Connection: Upgrade * Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ== + * Sec-WebSocket-Origin: http://example.com * Sec-WebSocket-Protocol: chat, superchat * Sec-WebSocket-Version: 7 * diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketServerHandshaker08.java b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketServerHandshaker08.java index 7ba5e34489..1e454f4339 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketServerHandshaker08.java +++ b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketServerHandshaker08.java @@ -116,6 +116,7 @@ public class WebSocketServerHandshaker08 extends WebSocketServerHandshaker { * Upgrade: websocket * Connection: Upgrade * Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ== + * Sec-WebSocket-Origin: http://example.com * Sec-WebSocket-Protocol: chat, superchat * Sec-WebSocket-Version: 8 * diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketServerHandshaker13.java b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketServerHandshaker13.java index 2f358cab93..8b445be922 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketServerHandshaker13.java +++ b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketServerHandshaker13.java @@ -115,6 +115,7 @@ public class WebSocketServerHandshaker13 extends WebSocketServerHandshaker { * Upgrade: websocket * Connection: Upgrade * Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ== + * Origin: http://example.com * Sec-WebSocket-Protocol: chat, superchat * Sec-WebSocket-Version: 13 * diff --git a/codec-http/src/test/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshakerTest.java b/codec-http/src/test/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshakerTest.java index e657ac4ba9..3cf81435a7 100644 --- a/codec-http/src/test/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshakerTest.java +++ b/codec-http/src/test/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshakerTest.java @@ -31,28 +31,20 @@ import io.netty.handler.codec.http.HttpHeaders; import io.netty.handler.codec.http.HttpObjectAggregator; import io.netty.handler.codec.http.HttpRequestEncoder; import io.netty.handler.codec.http.HttpResponseDecoder; -import io.netty.handler.codec.http.HttpScheme; import io.netty.util.CharsetUtil; -import io.netty.util.NetUtil; import org.junit.Test; import java.net.URI; -import java.util.Locale; import static org.junit.Assert.*; public abstract class WebSocketClientHandshakerTest { - private static final String HTTP_SCHEME_PREFIX = HttpScheme.HTTP + "://"; - private static final String HTTPS_SCHEME_PREFIX = HttpScheme.HTTPS + "://"; - protected abstract WebSocketClientHandshaker newHandshaker(URI uri, String subprotocol, HttpHeaders headers, boolean absoluteUpgradeUrl); protected WebSocketClientHandshaker newHandshaker(URI uri) { - HttpHeaders headers = new DefaultHttpHeaders() - .add(getOriginHeaderName(), websocketOriginValue(uri)); - return newHandshaker(uri, null, headers, false); + return newHandshaker(uri, null, null, false); } protected abstract CharSequence getOriginHeaderName(); @@ -369,31 +361,4 @@ public abstract class WebSocketClientHandshakerTest { request.release(); } - - static CharSequence websocketOriginValue(URI wsURL) { - String scheme = wsURL.getScheme(); - final String schemePrefix; - int port = wsURL.getPort(); - final int defaultPort; - if (WebSocketScheme.WSS.name().contentEquals(scheme) - || HttpScheme.HTTPS.name().contentEquals(scheme) - || (scheme == null && port == WebSocketScheme.WSS.port())) { - - schemePrefix = HTTPS_SCHEME_PREFIX; - defaultPort = WebSocketScheme.WSS.port(); - } else { - schemePrefix = HTTP_SCHEME_PREFIX; - defaultPort = WebSocketScheme.WS.port(); - } - - // Convert uri-host to lower case (by RFC 6454, chapter 4 "Origin of a URI") - String host = wsURL.getHost().toLowerCase(Locale.US); - - if (port != defaultPort && port != -1) { - // if the port is not standard (80/443) its needed to add the port to the header. - // See http://tools.ietf.org/html/rfc6454#section-6.2 - return schemePrefix + NetUtil.toSocketAddressString(host, port); - } - return schemePrefix + host; - } } diff --git a/codec-http/src/test/java/io/netty/handler/codec/http/websocketx/WebSocketHandshakeHandOverTest.java b/codec-http/src/test/java/io/netty/handler/codec/http/websocketx/WebSocketHandshakeHandOverTest.java index 8d5790e24b..b6f28d5f28 100644 --- a/codec-http/src/test/java/io/netty/handler/codec/http/websocketx/WebSocketHandshakeHandOverTest.java +++ b/codec-http/src/test/java/io/netty/handler/codec/http/websocketx/WebSocketHandshakeHandOverTest.java @@ -115,7 +115,7 @@ public class WebSocketHandshakeHandOverTest { assertTrue(serverReceivedHandshake); assertNotNull(serverHandshakeComplete); assertEquals("/test", serverHandshakeComplete.requestUri()); - assertEquals(7, serverHandshakeComplete.requestHeaders().size()); + assertEquals(8, serverHandshakeComplete.requestHeaders().size()); assertEquals("test-proto-2", serverHandshakeComplete.selectedSubprotocol()); // Transfer the handshake response and the websocket message to the client