diff options
Diffstat (limited to 'netwerk/test/unit/test_http2-proxy-failing.js')
-rw-r--r-- | netwerk/test/unit/test_http2-proxy-failing.js | 174 |
1 files changed, 174 insertions, 0 deletions
diff --git a/netwerk/test/unit/test_http2-proxy-failing.js b/netwerk/test/unit/test_http2-proxy-failing.js new file mode 100644 index 0000000000..8530f55373 --- /dev/null +++ b/netwerk/test/unit/test_http2-proxy-failing.js @@ -0,0 +1,174 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* vim:set ts=2 sw=2 sts=2 et: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* Test stream failure on the session to the proxy: + * - Test the case the error closes the affected stream only + * - Test the case the error closes the whole session and cancels existing + * streams. + */ + +/* eslint-env node */ + +"use strict"; + +const pps = Cc["@mozilla.org/network/protocol-proxy-service;1"].getService(); + +let filter; + +class ProxyFilter { + constructor(type, host, port, flags) { + this._type = type; + this._host = host; + this._port = port; + this._flags = flags; + this.QueryInterface = ChromeUtils.generateQI(["nsIProtocolProxyFilter"]); + } + applyFilter(uri, pi, cb) { + cb.onProxyFilterResult( + pps.newProxyInfo( + this._type, + this._host, + this._port, + null, + null, + this._flags, + 1000, + null + ) + ); + } +} + +function createPrincipal(url) { + var ssm = Services.scriptSecurityManager; + try { + return ssm.createContentPrincipal(Services.io.newURI(url), {}); + } catch (e) { + return null; + } +} + +function make_channel(url) { + return Services.io.newChannelFromURIWithProxyFlags( + Services.io.newURI(url), + null, + 16, + null, + createPrincipal(url), + createPrincipal(url), + Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_INHERITS_SEC_CONTEXT, + Ci.nsIContentPolicy.TYPE_OTHER + ); +} + +function get_response(channel, flags = CL_ALLOW_UNKNOWN_CL, delay = 0) { + return new Promise(resolve => { + var listener = new ChannelListener( + (request, data) => { + request.QueryInterface(Ci.nsIHttpChannel); + const status = request.status; + const http_code = status ? undefined : request.responseStatus; + request.QueryInterface(Ci.nsIProxiedChannel); + const proxy_connect_response_code = + request.httpProxyConnectResponseCode; + resolve({ status, http_code, data, proxy_connect_response_code }); + }, + null, + flags + ); + if (delay > 0) { + do_timeout(delay, function () { + channel.asyncOpen(listener); + }); + } else { + channel.asyncOpen(listener); + } + }); +} + +add_task(async function setup() { + // Set to allow the cert presented by our H2 server + do_get_profile(); + + // The moz-http2 cert is for foo.example.com and is signed by http2-ca.pem + // so add that cert to the trust list as a signing cert. + let certdb = Cc["@mozilla.org/security/x509certdb;1"].getService( + Ci.nsIX509CertDB + ); + addCertFromFile(certdb, "http2-ca.pem", "CTu,u,u"); + + let proxy_port = Services.env.get("MOZHTTP2_PORT"); + Assert.notEqual(proxy_port, null); + + Services.prefs.setBoolPref("network.http.http2.enabled", true); + // make all native resolve calls "secretly" resolve localhost instead + Services.prefs.setBoolPref("network.dns.native-is-localhost", true); + + filter = new ProxyFilter("https", "localhost", proxy_port, 16); + pps.registerFilter(filter, 10); +}); + +registerCleanupFunction(async () => { + Services.prefs.clearUserPref("network.http.http2.enabled"); + Services.prefs.clearUserPref("network.dns.native-is-localhost"); + + pps.unregisterFilter(filter); +}); + +add_task( + async function proxy_server_stream_soft_failure_multiple_streams_not_affected() { + let should_succeed = get_response(make_channel(`http://750.example.com`)); + const failed = await get_response( + make_channel(`http://illegalhpacksoft.example.com`), + CL_EXPECT_FAILURE, + 20 + ); + + const succeeded = await should_succeed; + + Assert.equal(failed.status, Cr.NS_ERROR_ILLEGAL_VALUE); + Assert.equal(failed.proxy_connect_response_code, 0); + Assert.equal(failed.http_code, undefined); + Assert.equal(succeeded.status, Cr.NS_OK); + Assert.equal(succeeded.proxy_connect_response_code, 200); + Assert.equal(succeeded.http_code, 200); + } +); + +add_task( + async function proxy_server_stream_hard_failure_multiple_streams_affected() { + let should_failed = get_response( + make_channel(`http://750.example.com`), + CL_EXPECT_FAILURE + ); + const failed1 = await get_response( + make_channel(`http://illegalhpackhard.example.com`), + CL_EXPECT_FAILURE + ); + + const failed2 = await should_failed; + + Assert.equal(failed1.status, 0x804b0053); + Assert.equal(failed1.proxy_connect_response_code, 0); + Assert.equal(failed1.http_code, undefined); + Assert.equal(failed2.status, 0x804b0053); + Assert.equal(failed2.proxy_connect_response_code, 0); + Assert.equal(failed2.http_code, undefined); + } +); + +add_task(async function test_http2_h11required_stream() { + let should_failed = await get_response( + make_channel(`http://h11required.com`), + CL_EXPECT_FAILURE + ); + + // See HTTP/1.1 connect handler in moz-http2.js. The handler returns + // "404 Not Found", so the expected error code is NS_ERROR_UNKNOWN_HOST. + Assert.equal(should_failed.status, Cr.NS_ERROR_UNKNOWN_HOST); + Assert.equal(should_failed.proxy_connect_response_code, 404); + Assert.equal(should_failed.http_code, undefined); +}); |