From f31be51774f49091020a007b0537fa30a99bad0c Mon Sep 17 00:00:00 2001 From: Norman Maurer Date: Thu, 26 Nov 2015 22:29:28 +0100 Subject: [PATCH] [#4505] Correctly handle whitespaces in websocket uri's. Motivation: If a uri contains whitespaces we need to ensure we correctly escape these when creating the request for the handshake. Modifications: - Correctly encode path for uri - Add tests Result: Correctly handle whitespaces when doing websocket upgrade requests. --- .../websocketx/WebSocketClientHandshaker.java | 13 +++++++ .../WebSocketClientHandshaker00.java | 9 +---- .../WebSocketClientHandshaker07.java | 9 +---- .../WebSocketClientHandshaker08.java | 9 +---- .../WebSocketClientHandshaker13.java | 9 +---- .../WebSocketClientHandshaker00Test.java | 25 ++++++++++++ .../WebSocketClientHandshaker07Test.java | 25 ++++++++++++ .../WebSocketClientHandshaker08Test.java | 25 ++++++++++++ .../WebSocketClientHandshaker13Test.java | 25 ++++++++++++ .../WebSocketClientHandshakerTest.java | 39 +++++++++++++++++++ 10 files changed, 156 insertions(+), 32 deletions(-) create mode 100644 codec-http/src/test/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshaker00Test.java create mode 100644 codec-http/src/test/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshaker07Test.java create mode 100644 codec-http/src/test/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshaker08Test.java create mode 100644 codec-http/src/test/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshaker13Test.java create mode 100644 codec-http/src/test/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshakerTest.java 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 493b645a37..9931fa619a 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 @@ -406,4 +406,17 @@ public abstract class WebSocketClientHandshaker { } return channel.writeAndFlush(frame, promise); } + + /** + * Return the constructed raw path for the give {@link URI}. + */ + static String rawPath(URI wsURL) { + String path = wsURL.getRawPath(); + String query = wsURL.getQuery(); + if (query != null && !query.isEmpty()) { + path = path + '?' + query; + } + + return path == null || path.isEmpty() ? "/" : path; + } } 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 b1de3e3bbd..322f7cfc22 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 @@ -126,14 +126,7 @@ public class WebSocketClientHandshaker00 extends WebSocketClientHandshaker { // Get path URI wsURL = uri(); - String path = wsURL.getPath(); - if (wsURL.getQuery() != null && !wsURL.getQuery().isEmpty()) { - path = wsURL.getPath() + '?' + wsURL.getQuery(); - } - - if (path == null || path.isEmpty()) { - path = "/"; - } + String path = rawPath(wsURL); // Format request FullHttpRequest request = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, path); 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 820a080876..6b97ea34f9 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 @@ -125,14 +125,7 @@ public class WebSocketClientHandshaker07 extends WebSocketClientHandshaker { protected FullHttpRequest newHandshakeRequest() { // Get path URI wsURL = uri(); - String path = wsURL.getPath(); - if (wsURL.getQuery() != null && !wsURL.getQuery().isEmpty()) { - path = wsURL.getPath() + '?' + wsURL.getQuery(); - } - - if (path == null || path.isEmpty()) { - path = "/"; - } + String path = rawPath(wsURL); // Get 16 bit nonce and base 64 encode it byte[] nonce = WebSocketUtil.randomBytes(16); 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 a8ff02ede0..4a41bae85a 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 @@ -126,14 +126,7 @@ public class WebSocketClientHandshaker08 extends WebSocketClientHandshaker { protected FullHttpRequest newHandshakeRequest() { // Get path URI wsURL = uri(); - String path = wsURL.getPath(); - if (wsURL.getQuery() != null && !wsURL.getQuery().isEmpty()) { - path = wsURL.getPath() + '?' + wsURL.getQuery(); - } - - if (path == null || path.isEmpty()) { - path = "/"; - } + String path = rawPath(wsURL); // Get 16 bit nonce and base 64 encode it byte[] nonce = WebSocketUtil.randomBytes(16); 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 52fa9a5df8..75de865f06 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 @@ -126,14 +126,7 @@ public class WebSocketClientHandshaker13 extends WebSocketClientHandshaker { protected FullHttpRequest newHandshakeRequest() { // Get path URI wsURL = uri(); - String path = wsURL.getPath(); - if (wsURL.getQuery() != null && !wsURL.getQuery().isEmpty()) { - path = wsURL.getPath() + '?' + wsURL.getQuery(); - } - - if (path == null || path.isEmpty()) { - path = "/"; - } + String path = rawPath(wsURL); // Get 16 bit nonce and base 64 encode it byte[] nonce = WebSocketUtil.randomBytes(16); diff --git a/codec-http/src/test/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshaker00Test.java b/codec-http/src/test/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshaker00Test.java new file mode 100644 index 0000000000..100abf694d --- /dev/null +++ b/codec-http/src/test/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshaker00Test.java @@ -0,0 +1,25 @@ +/* + * Copyright 2015 The Netty Project + * + * The Netty Project licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.netty.handler.codec.http.websocketx; + +import java.net.URI; + +public class WebSocketClientHandshaker00Test extends WebSocketClientHandshakerTest { + @Override + protected WebSocketClientHandshaker newHandshaker(URI uri) { + return new WebSocketClientHandshaker00(uri, WebSocketVersion.V00, null, null, 1024); + } +} diff --git a/codec-http/src/test/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshaker07Test.java b/codec-http/src/test/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshaker07Test.java new file mode 100644 index 0000000000..168a2458d1 --- /dev/null +++ b/codec-http/src/test/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshaker07Test.java @@ -0,0 +1,25 @@ +/* + * Copyright 2015 The Netty Project + * + * The Netty Project licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.netty.handler.codec.http.websocketx; + +import java.net.URI; + +public class WebSocketClientHandshaker07Test extends WebSocketClientHandshakerTest { + @Override + protected WebSocketClientHandshaker newHandshaker(URI uri) { + return new WebSocketClientHandshaker07(uri, WebSocketVersion.V07, null, false, null, 1024); + } +} diff --git a/codec-http/src/test/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshaker08Test.java b/codec-http/src/test/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshaker08Test.java new file mode 100644 index 0000000000..249bd958fb --- /dev/null +++ b/codec-http/src/test/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshaker08Test.java @@ -0,0 +1,25 @@ +/* + * Copyright 2015 The Netty Project + * + * The Netty Project licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.netty.handler.codec.http.websocketx; + +import java.net.URI; + +public class WebSocketClientHandshaker08Test extends WebSocketClientHandshakerTest { + @Override + protected WebSocketClientHandshaker newHandshaker(URI uri) { + return new WebSocketClientHandshaker07(uri, WebSocketVersion.V08, null, false, null, 1024); + } +} diff --git a/codec-http/src/test/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshaker13Test.java b/codec-http/src/test/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshaker13Test.java new file mode 100644 index 0000000000..2bc2e691b2 --- /dev/null +++ b/codec-http/src/test/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshaker13Test.java @@ -0,0 +1,25 @@ +/* + * Copyright 2015 The Netty Project + * + * The Netty Project licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.netty.handler.codec.http.websocketx; + +import java.net.URI; + +public class WebSocketClientHandshaker13Test extends WebSocketClientHandshakerTest { + @Override + protected WebSocketClientHandshaker newHandshaker(URI uri) { + return new WebSocketClientHandshaker13(uri, WebSocketVersion.V13, null, false, null, 1024); + } +} 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 new file mode 100644 index 0000000000..e45c92349e --- /dev/null +++ b/codec-http/src/test/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshakerTest.java @@ -0,0 +1,39 @@ +/* + * Copyright 2015 The Netty Project + * + * The Netty Project licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.netty.handler.codec.http.websocketx; + +import io.netty.handler.codec.http.FullHttpRequest; +import org.junit.Test; + +import java.net.URI; + +import static org.junit.Assert.assertEquals; + +public abstract class WebSocketClientHandshakerTest { + protected abstract WebSocketClientHandshaker newHandshaker(URI uri); + + @Test + public void testRawPath() { + URI uri = URI.create("ws://localhost:9999/path%20with%20ws"); + WebSocketClientHandshaker handshaker = newHandshaker(uri); + FullHttpRequest request = handshaker.newHandshakeRequest(); + try { + assertEquals("/path%20with%20ws", request.getUri()); + } finally { + request.release(); + } + } +}