summaryrefslogtreecommitdiffstats
path: root/netwerk/test/unit/test_http2-proxy-failing.js
diff options
context:
space:
mode:
Diffstat (limited to 'netwerk/test/unit/test_http2-proxy-failing.js')
-rw-r--r--netwerk/test/unit/test_http2-proxy-failing.js174
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);
+});