Skip to content

Commit

Permalink
WebSocket: Allow relative URLs and http(s) scheme
Browse files Browse the repository at this point in the history
https://bugs.webkit.org/show_bug.cgi?id=247149
rdar://101929623

Reviewed by Antti Koivisto.

This implements the change proposed at whatwg/websockets#45, allowing HTTP(S) URLs to be used in the WebSocket constructor. They are immediately converted to use ws: or wss: schemes. It also ensures that the HTTP(S) URLs always use UTF-8 for the query component of the URL, as is expected.

The test changes are being upstreamed via web-platform-tests/wpt#39955.

* LayoutTests/TestExpectations:
* LayoutTests/http/tests/websocket/tests/hybi/url-parsing-expected.txt:
* LayoutTests/http/tests/websocket/tests/hybi/url-parsing.html:
* LayoutTests/imported/w3c/web-platform-tests/websockets/Create-http-urls.any-expected.txt: Added.
* LayoutTests/imported/w3c/web-platform-tests/websockets/Create-http-urls.any.html: Added.
* LayoutTests/imported/w3c/web-platform-tests/websockets/Create-http-urls.any.js: Added.
(test):
* LayoutTests/imported/w3c/web-platform-tests/websockets/Create-http-urls.any.worker-expected.txt: Added.
* LayoutTests/imported/w3c/web-platform-tests/websockets/Create-http-urls.any.worker.html: Added.
* LayoutTests/imported/w3c/web-platform-tests/websockets/Create-invalid-urls.any-expected.txt: Added.
* LayoutTests/imported/w3c/web-platform-tests/websockets/Create-invalid-urls.any.html:
* LayoutTests/imported/w3c/web-platform-tests/websockets/Create-invalid-urls.any.js:
(string_appeared_here.forEach.input.test):
(test): Deleted.
* LayoutTests/imported/w3c/web-platform-tests/websockets/Create-invalid-urls.any.worker-expected.txt: Added.
* LayoutTests/imported/w3c/web-platform-tests/websockets/Create-invalid-urls.any.worker.html:
* LayoutTests/imported/w3c/web-platform-tests/websockets/Create-invalid-urls.any.worker_wss-expected.txt: Removed.
* LayoutTests/imported/w3c/web-platform-tests/websockets/Create-invalid-urls.any_wss-expected.txt: Removed.
* LayoutTests/imported/w3c/web-platform-tests/websockets/Create-non-absolute-url.any-expected.txt: Added.
* LayoutTests/imported/w3c/web-platform-tests/websockets/Create-non-absolute-url.any.html:
* LayoutTests/imported/w3c/web-platform-tests/websockets/Create-non-absolute-url.any.js:
(forEach.input.test):
(test): Deleted.
* LayoutTests/imported/w3c/web-platform-tests/websockets/Create-non-absolute-url.any.worker-expected.txt: Added.
* LayoutTests/imported/w3c/web-platform-tests/websockets/Create-non-absolute-url.any.worker.html:
* LayoutTests/imported/w3c/web-platform-tests/websockets/Create-non-absolute-url.any.worker_wss-expected.txt: Removed.
* LayoutTests/imported/w3c/web-platform-tests/websockets/Create-non-absolute-url.any_wss-expected.txt: Removed.
* LayoutTests/imported/w3c/web-platform-tests/websockets/Create-url-with-windows-1252-encoding-expected.txt: Added.
* LayoutTests/imported/w3c/web-platform-tests/websockets/Create-url-with-windows-1252-encoding.html: Added.
* LayoutTests/imported/w3c/web-platform-tests/websockets/Create-wrong-scheme.any.html: Removed.
* LayoutTests/imported/w3c/web-platform-tests/websockets/Create-wrong-scheme.any.js: Removed.
* LayoutTests/imported/w3c/web-platform-tests/websockets/Create-wrong-scheme.any.worker.html: Removed.
* LayoutTests/imported/w3c/web-platform-tests/websockets/Create-wrong-scheme.any.worker_wss-expected.txt: Removed.
* LayoutTests/imported/w3c/web-platform-tests/websockets/Create-wrong-scheme.any_wss-expected.txt: Removed.
* LayoutTests/imported/w3c/web-platform-tests/websockets/constants.sub.js:
(CreateWebSocketNonAbsolute): Deleted.
(CreateWebSocketNonWsScheme): Deleted.
* LayoutTests/imported/w3c/web-platform-tests/websockets/constructor/002-expected.txt: Removed.
* LayoutTests/imported/w3c/web-platform-tests/websockets/constructor/002.html: Removed.
* LayoutTests/imported/w3c/web-platform-tests/websockets/constructor/002_wss-expected.txt: Removed.
* LayoutTests/imported/w3c/web-platform-tests/websockets/constructor/w3c-import.log:
* LayoutTests/imported/w3c/web-platform-tests/websockets/w3c-import.log:
* LayoutTests/platform/glib/TestExpectations:
* Source/WebCore/Modules/websockets/WebSocket.cpp:
(WebCore::WebSocket::create):
(WebCore::WebSocket::connect):

Canonical link: https://commits.webkit.org/263968@main
  • Loading branch information
annevk committed May 11, 2023
1 parent dc42c0d commit b5e7897
Show file tree
Hide file tree
Showing 37 changed files with 141 additions and 183 deletions.
3 changes: 0 additions & 3 deletions LayoutTests/TestExpectations
Original file line number Diff line number Diff line change
Expand Up @@ -3448,7 +3448,6 @@ imported/w3c/web-platform-tests/websockets/closing-handshake/004.html?wpt_flags=
imported/w3c/web-platform-tests/websockets/constructor.any.html?wpt_flags=h2 [ Skip ]
imported/w3c/web-platform-tests/websockets/constructor.any.worker.html?wpt_flags=h2 [ Skip ]
imported/w3c/web-platform-tests/websockets/constructor/001.html?wpt_flags=h2 [ Skip ]
imported/w3c/web-platform-tests/websockets/constructor/002.html?wpt_flags=h2 [ Skip ]
imported/w3c/web-platform-tests/websockets/constructor/004.html?wpt_flags=h2 [ Skip ]
imported/w3c/web-platform-tests/websockets/constructor/005.html?wpt_flags=h2 [ Skip ]
imported/w3c/web-platform-tests/websockets/constructor/006.html?wpt_flags=h2 [ Skip ]
Expand Down Expand Up @@ -3504,8 +3503,6 @@ imported/w3c/web-platform-tests/websockets/Create-valid-url-protocol.any.html?wp
imported/w3c/web-platform-tests/websockets/Create-valid-url-protocol.any.worker.html?wpt_flags=h2 [ Skip ]
imported/w3c/web-platform-tests/websockets/Create-valid-url.any.html?wpt_flags=h2 [ Skip ]
imported/w3c/web-platform-tests/websockets/Create-valid-url.any.worker.html?wpt_flags=h2 [ Skip ]
imported/w3c/web-platform-tests/websockets/Create-wrong-scheme.any.html?wpt_flags=h2 [ Skip ]
imported/w3c/web-platform-tests/websockets/Create-wrong-scheme.any.worker.html?wpt_flags=h2 [ Skip ]
imported/w3c/web-platform-tests/websockets/eventhandlers.any.html?wpt_flags=h2 [ Skip ]
imported/w3c/web-platform-tests/websockets/eventhandlers.any.worker.html?wpt_flags=h2 [ Skip ]
imported/w3c/web-platform-tests/websockets/extended-payload-length.html?wpt_flags=h2 [ Skip ]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
CONSOLE MESSAGE: Wrong url scheme for WebSocket http://127.0.0.1:8000/websocket/tests/hybi/null
CONSOLE MESSAGE: Invalid url for WebSocket ws://javascript:a
CONSOLE MESSAGE: Wrong url scheme for WebSocket http://127.0.0.1:8000/applet
CONSOLE MESSAGE: Wrong url scheme for WebSocket javascript:a
CONSOLE MESSAGE: URL has fragment component ws://127.0.0.1/path#
CONSOLE MESSAGE: URL has fragment component ws://127.0.0.1/path#fragment
Expand All @@ -9,13 +7,15 @@ Test WebSocket URL parsing.
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".

PASS new WebSocket() threw exception TypeError: Not enough arguments.
PASS new WebSocket(null) threw exception SyntaxError: The string did not match the expected pattern..
PASS new WebSocket("ws://javascript:a") threw exception SyntaxError: The string did not match the expected pattern..
PASS new WebSocket("/applet") threw exception SyntaxError: The string did not match the expected pattern..
PASS new WebSocket(null).url is url.href
PASS new WebSocket("/applet").url is url.href
PASS new WebSocket("javascript:a") threw exception SyntaxError: The string did not match the expected pattern..
PASS (new WebSocket("ws://127.0.0.1:8880/a/../websocket/tests/hybi/simple")).url is "ws://127.0.0.1:8880/websocket/tests/hybi/simple"
PASS (new WebSocket("ws://127.0.0.1:8880/websocket/tests/hybi/simple?")).url is "ws://127.0.0.1:8880/websocket/tests/hybi/simple?"
PASS (new WebSocket("ws://127.0.0.1:8880/websocket/tests/hybi/simple?k=v")).url is "ws://127.0.0.1:8880/websocket/tests/hybi/simple?k=v"
PASS (new WebSocket("http://127.0.0.1:8880/websocket/tests/hybi/simple?")).url is "ws://127.0.0.1:8880/websocket/tests/hybi/simple?"
PASS (new WebSocket("https://127.0.0.1:8880/websocket/tests/hybi/simple?")).url is "wss://127.0.0.1:8880/websocket/tests/hybi/simple?"
PASS new WebSocket("ws://127.0.0.1/path#") threw exception SyntaxError: The string did not match the expected pattern..
PASS new WebSocket("ws://127.0.0.1/path#fragment") threw exception SyntaxError: The string did not match the expected pattern..
PASS successfullyParsed is true
Expand Down
13 changes: 8 additions & 5 deletions LayoutTests/http/tests/websocket/tests/hybi/url-parsing.html
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,15 @@
// Not enough arguments.
shouldThrow('new WebSocket()');

// Null URL
shouldThrow('new WebSocket(null)');

// Invalid url will fail to be parsed.
shouldThrow('new WebSocket("ws://javascript:a")');

// Can't use relative URLs - because spec says so, and because the scheme is different anyway.
shouldThrow('new WebSocket("/applet")');
// Relative URLs behave like HTTP(S) URLs
let url = new URL("null", location);
url.protocol = "ws";
shouldBe('new WebSocket(null).url', 'url.href');
url.pathname = "/applet"
shouldBe('new WebSocket("/applet").url', 'url.href');

// Non ws URL is not allowed.
shouldThrow('new WebSocket("javascript:a")');
Expand All @@ -29,6 +30,8 @@
shouldBe('(new WebSocket("ws://127.0.0.1:8880/a/../websocket/tests/hybi/simple")).url', '"ws://127.0.0.1:8880/websocket/tests/hybi/simple"');
shouldBe('(new WebSocket("ws://127.0.0.1:8880/websocket/tests/hybi/simple?")).url', '"ws://127.0.0.1:8880/websocket/tests/hybi/simple?"');
shouldBe('(new WebSocket("ws://127.0.0.1:8880/websocket/tests/hybi/simple?k=v")).url', '"ws://127.0.0.1:8880/websocket/tests/hybi/simple?k=v"');
shouldBe('(new WebSocket("http://127.0.0.1:8880/websocket/tests/hybi/simple?")).url', '"ws://127.0.0.1:8880/websocket/tests/hybi/simple?"');
shouldBe('(new WebSocket("https://127.0.0.1:8880/websocket/tests/hybi/simple?")).url', '"wss://127.0.0.1:8880/websocket/tests/hybi/simple?"');

// draft-hixie-thewebsocketprotocol-60 says If /url/ has a <fragment>
// component, then fail the parsing Web Socket URLs, so throw a SYNTAX_ERR
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@

PASS WebSocket: ensure both HTTP schemes are supported

Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<!-- This file is required for WebKit test infrastructure to run the templated test -->
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
test(() => {
const url = new URL ("/", location);
url.protocol = "http";
const httpURL = url.href;
url.protocol = "https";
const httpsURL = url.href;
url.protocol = "ws";
const wsURL = url.href;
url.protocol = "wss";
const wssURL = url.href;

let ws = new WebSocket(httpURL);
assert_equals(ws.url, wsURL);
ws.close();

ws = new WebSocket(httpsURL);
assert_equals(ws.url, wssURL);
ws.close();
}, "WebSocket: ensure both HTTP schemes are supported");
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@

PASS WebSocket: ensure both HTTP schemes are supported

Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<!-- This file is required for WebKit test infrastructure to run the templated test -->
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@

PASS new WebSocket("ws://foo bar.com/") should throw a "SyntaxError" DOMException
PASS new WebSocket("wss://foo bar.com/") should throw a "SyntaxError" DOMException
PASS new WebSocket("ftp://localhost:8800/") should throw a "SyntaxError" DOMException
PASS new WebSocket("mailto:example@example.org") should throw a "SyntaxError" DOMException
PASS new WebSocket("about:blank") should throw a "SyntaxError" DOMException
PASS new WebSocket("http://localhost:8800/#") should throw a "SyntaxError" DOMException
PASS new WebSocket("http://localhost:8800/#test") should throw a "SyntaxError" DOMException
PASS new WebSocket("#test") should throw a "SyntaxError" DOMException

Original file line number Diff line number Diff line change
@@ -1,4 +1 @@
<!-- This file is required for WebKit test infrastructure to run the templated test -->
<!-- META: variant= -->
<!-- META: variant=?wss -->
<!-- META: variant=?wpt_flags=h2 -->
<!-- This file is required for WebKit test infrastructure to run the templated test -->
Original file line number Diff line number Diff line change
@@ -1,34 +1,14 @@
// META: variant=
// META: variant=?wss
// META: variant=?wpt_flags=h2

var wsocket;
test(function() {
assert_throws_dom("SYNTAX_ERR", function() {
wsocket = new WebSocket("/echo")
});
}, "Url is /echo - should throw SYNTAX_ERR");

test(function() {
assert_throws_dom("SYNTAX_ERR", function() {
wsocket = new WebSocket("mailto:microsoft@microsoft.com")
});
}, "Url is a mail address - should throw SYNTAX_ERR");

test(function() {
assert_throws_dom("SYNTAX_ERR", function() {
wsocket = new WebSocket("about:blank")
});
}, "Url is about:blank - should throw SYNTAX_ERR");

test(function() {
assert_throws_dom("SYNTAX_ERR", function() {
wsocket = new WebSocket("?test")
});
}, "Url is ?test - should throw SYNTAX_ERR");

test(function() {
assert_throws_dom("SYNTAX_ERR", function() {
wsocket = new WebSocket("#test")
});
}, "Url is #test - should throw SYNTAX_ERR");
[
"ws://foo bar.com/",
"wss://foo bar.com/",
"ftp://"+location.host+"/",
"mailto:example@example.org",
"about:blank",
location.origin + "/#",
location.origin + "/#test",
"#test"
].forEach(input => {
test(() => {
assert_throws_dom("SyntaxError", () => new WebSocket(input));
}, `new WebSocket("${input}") should throw a "SyntaxError" DOMException`);
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@

PASS new WebSocket("ws://foo bar.com/") should throw a "SyntaxError" DOMException
PASS new WebSocket("wss://foo bar.com/") should throw a "SyntaxError" DOMException
PASS new WebSocket("ftp://localhost:8800/") should throw a "SyntaxError" DOMException
PASS new WebSocket("mailto:example@example.org") should throw a "SyntaxError" DOMException
PASS new WebSocket("about:blank") should throw a "SyntaxError" DOMException
PASS new WebSocket("http://localhost:8800/#") should throw a "SyntaxError" DOMException
PASS new WebSocket("http://localhost:8800/#test") should throw a "SyntaxError" DOMException
PASS new WebSocket("#test") should throw a "SyntaxError" DOMException

Original file line number Diff line number Diff line change
@@ -1,4 +1 @@
<!-- This file is required for WebKit test infrastructure to run the templated test -->
<!-- META: variant= -->
<!-- META: variant=?wss -->
<!-- META: variant=?wpt_flags=h2 -->
<!-- This file is required for WebKit test infrastructure to run the templated test -->

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@

PASS Create WebSocket - Pass a non absolute URL: test
PASS Create WebSocket - Pass a non absolute URL: ?
PASS Create WebSocket - Pass a non absolute URL: null
PASS Create WebSocket - Pass a non absolute URL: 123

Original file line number Diff line number Diff line change
@@ -1,4 +1 @@
<!-- This file is required for WebKit test infrastructure to run the templated test -->
<!-- META: variant= -->
<!-- META: variant=?wss -->
<!-- META: variant=?wpt_flags=h2 -->
<!-- This file is required for WebKit test infrastructure to run the templated test -->
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
// META: script=constants.sub.js
// META: variant=
// META: variant=?wss
// META: variant=?wpt_flags=h2

test(function() {
var wsocket;
assert_throws_dom("SYNTAX_ERR", function() {
wsocket = CreateWebSocketNonAbsolute()
});
}, "Create WebSocket - Pass a non absolute URL - SYNTAX_ERR is thrown")
[
"test",
"?",
null,
123,
].forEach(input => {
test(() => {
const url = new URL(input, location);
url.protocol = "ws";
const ws = new WebSocket(input);
assert_equals(ws.url, url.href);
ws.close();
}, `Create WebSocket - Pass a non absolute URL: ${input}`);
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@

PASS Create WebSocket - Pass a non absolute URL: test
PASS Create WebSocket - Pass a non absolute URL: ?
PASS Create WebSocket - Pass a non absolute URL: null
PASS Create WebSocket - Pass a non absolute URL: 123

Original file line number Diff line number Diff line change
@@ -1,4 +1 @@
<!-- This file is required for WebKit test infrastructure to run the templated test -->
<!-- META: variant= -->
<!-- META: variant=?wss -->
<!-- META: variant=?wpt_flags=h2 -->
<!-- This file is required for WebKit test infrastructure to run the templated test -->

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@

PASS URL's percent-encoding is always in UTF-8 for WebSocket

Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<!doctype html>
<meta charset=windows-1252>
<script src=/resources/testharness.js></script>
<script src=/resources/testharnessreport.js></script>
<script>
test(() => {
const url = new URL("/", location);
url.protocol = "ws";
const input = "?\u20AC";
const expected = url.href + "?%E2%82%AC";

let ws = new WebSocket(url.href + input);
assert_equals(ws.url, expected);
ws.close();

ws = new WebSocket("/" + input);
assert_equals(ws.url, expected);
ws.close();
}, "URL's percent-encoding is always in UTF-8 for WebSocket");
</script>

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -32,18 +32,6 @@ function IsWebSocket() {
}
}

function CreateWebSocketNonAbsolute() {
IsWebSocket();
const url = __SERVER__NAME;
return new WebSocket(url);
}

function CreateWebSocketNonWsScheme() {
IsWebSocket();
const url = "http://" + __SERVER__NAME + ":" + __PORT + "/" + __PATH;
return new WebSocket(url);
}

function CreateWebSocketNonAsciiProtocol(nonAsciiProtocol) {
IsWebSocket();
const url = SCHEME_DOMAIN_PORT + "/" + __PATH;
Expand Down

This file was deleted.

This file was deleted.

This file was deleted.

Loading

0 comments on commit b5e7897

Please sign in to comment.