commit 77cd2bd4edabe1d58c087483bf725e198014ba81
parent 26058b267b89eaf03dbf6cb3d8e38d25e796f773
Author: Valentin Gosu <valentin.gosu@gmail.com>
Date: Tue, 25 Nov 2025 14:42:47 +0000
Bug 2001617 - Add WebSocket with maque proxy test r=necko-reviewers,kershaw
Differential Revision: https://phabricator.services.mozilla.com/D273812
Diffstat:
4 files changed, 110 insertions(+), 22 deletions(-)
diff --git a/netwerk/test/unit/http3_proxy_common.js b/netwerk/test/unit/http3_proxy_common.js
@@ -16,6 +16,8 @@ const {
NodeHTTPSServer,
NodeHTTP2Server,
NodeHTTP2ProxyServer,
+ NodeWebSocketHttp2Server,
+ WebSocketConnection,
} = ChromeUtils.importESModule("resource://testing-common/NodeServer.sys.mjs");
function makeChan(uri) {
@@ -431,6 +433,70 @@ async function test_http_connect_fallback() {
await server.stop();
}
+/**
+ * Helper function to open a WebSocket connection
+ */
+async function wsChannelOpenPromise(url, msg) {
+ let conn = new WebSocketConnection();
+ let statusObj = await Promise.race([conn.open(url), conn.finished()]);
+ if (statusObj && statusObj.status != Cr.NS_OK) {
+ return [statusObj.status, ""];
+ }
+ let finalStatusPromise = conn.finished();
+ conn.send(msg);
+ let res = await conn.receiveMessages();
+ conn.close();
+ let finalStatus = await finalStatusPromise;
+ return [finalStatus.status, res];
+}
+
+/**
+ * Test WebSocket through H3 proxy using H2 WebSocket server
+ */
+async function test_http_connect_websocket() {
+ info("Running test_http_connect_websocket");
+ Services.prefs.setBoolPref("network.http.http2.websockets", true);
+
+ let wss = new NodeWebSocketHttp2Server();
+ await wss.start();
+
+ registerCleanupFunction(async () => {
+ await wss.stop();
+ });
+
+ Assert.notEqual(wss.port(), null);
+ await wss.registerMessageHandler((data, ws) => {
+ ws.send(data);
+ });
+
+ let url = `wss://alt1.example.com:${wss.port()}`;
+ const msg = "test h2 websocket through h3 proxy";
+ let [status, res] = await wsChannelOpenPromise(url, msg);
+ Assert.equal(status, Cr.NS_OK);
+ Assert.deepEqual(res, [msg]);
+
+ // Test multiple messages
+ let conn = new WebSocketConnection();
+ await conn.open(url);
+ conn.send("message1");
+ let mess1 = await conn.receiveMessages();
+ Assert.deepEqual(mess1, ["message1"]);
+
+ conn.send("message2");
+ conn.send("message3");
+ let mess2 = [];
+ while (mess2.length < 2) {
+ mess2 = mess2.concat(await conn.receiveMessages());
+ }
+ Assert.deepEqual(mess2, ["message2", "message3"]);
+
+ conn.close();
+ let { status: finalStatus } = await conn.finished();
+ Assert.equal(finalStatus, Cr.NS_OK);
+
+ await wss.stop();
+}
+
async function test_inner_connection_fallback() {
info("Running test_inner_connection_fallback");
let h3Port = Services.env.get("MOZHTTP3_PORT_NO_RESPONSE");
diff --git a/netwerk/test/unit/test_http3_proxy.js b/netwerk/test/unit/test_http3_proxy.js
@@ -20,6 +20,7 @@ add_task(test_http_connect_invalid_host);
add_task(test_concurrent_http_connect_tunnels);
// TODO: Proxy needs to close the stream properly when socket failures occur
// add_task(test_http_connect_stream_closure);
+add_task(test_http_connect_websocket);
add_task(test_connect_udp);
add_task(test_http_connect_fallback);
add_task(test_inner_connection_fallback);
diff --git a/netwerk/test/unit/test_websocket_proxy.js b/netwerk/test/unit/test_websocket_proxy.js
@@ -4,18 +4,24 @@
"use strict";
+/* import-globals-from http3_proxy_common.js */
+
const {
NodeWebSocketPlainServer,
NodeWebSocketServer,
- NodeWebSocketHttp2Server,
NodeHTTPProxyServer,
NodeHTTPSProxyServer,
- NodeHTTP2ProxyServer,
- WebSocketConnection,
- with_node_servers,
} = ChromeUtils.importESModule("resource://testing-common/NodeServer.sys.mjs");
-async function channelOpenPromise(url, msg) {
+const { AppConstants } = ChromeUtils.importESModule(
+ "resource://gre/modules/AppConstants.sys.mjs"
+);
+
+add_setup(async function setup() {
+ do_get_profile();
+});
+
+async function wsChannelOpen(url, msg) {
let conn = new WebSocketConnection();
let statusObj = await Promise.race([conn.open(url), conn.finished()]);
if (statusObj && statusObj.status != Cr.NS_OK) {
@@ -39,23 +45,27 @@ registerCleanupFunction(() => {
Services.prefs.clearUserPref("network.proxy.allow_hijacking_localhost");
});
-async function do_ws_requests(expectedProxyType) {
- await with_node_servers(
- [NodeWebSocketPlainServer, NodeWebSocketServer, NodeWebSocketHttp2Server],
- async server => {
- Assert.notEqual(server.port(), null);
- await server.registerMessageHandler((data, ws) => {
- ws.send(data);
- });
-
- let url = `${server.protocol()}://localhost:${server.port()}`;
- const msg = `test ${server.constructor.name} with proxy`;
- let [status, res, proxyType] = await channelOpenPromise(url, msg);
- Assert.equal(status, Cr.NS_OK);
- Assert.deepEqual(res, [msg]);
- Assert.equal(proxyType, expectedProxyType, "WebSocket should use proxy");
- }
- );
+async function do_ws_requests(
+ expectedProxyType,
+ servers = [
+ NodeWebSocketPlainServer,
+ NodeWebSocketServer,
+ NodeWebSocketHttp2Server,
+ ]
+) {
+ await with_node_servers(servers, async server => {
+ Assert.notEqual(server.port(), null);
+ await server.registerMessageHandler((data, ws) => {
+ ws.send(data);
+ });
+
+ let url = `${server.protocol()}://localhost:${server.port()}`;
+ const msg = `test ${server.constructor.name} with proxy`;
+ let [status, res, proxyType] = await wsChannelOpen(url, msg);
+ Assert.equal(status, Cr.NS_OK);
+ Assert.deepEqual(res, [msg]);
+ Assert.equal(proxyType, expectedProxyType, "WebSocket should use proxy");
+ });
}
add_task(async function test_http_proxy() {
@@ -93,3 +103,13 @@ add_task(async function test_http2_proxy() {
await proxy.stop();
});
+
+// Skipped on Android due to H3 proxy server not working - Bug 1982955
+add_task(
+ { skip_if: () => AppConstants.platform == "android" },
+ async function test_masque_proxy() {
+ await setup_http3_proxy();
+
+ await do_ws_requests("masque");
+ }
+);
diff --git a/netwerk/test/unit/xpcshell.toml b/netwerk/test/unit/xpcshell.toml
@@ -1604,6 +1604,7 @@ run-sequentially = ["true"] # node server exceptions dont replay well
["test_websocket_offline.js"]
["test_websocket_proxy.js"]
+head = "head_cookies.js head_channels.js head_cache.js head_http3.js http3_proxy_common.js"
["test_websocket_server.js"]
run-sequentially = ["true"] # node server exceptions dont replay well