test_http2-proxy-failing.js (5248B)
1 /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ 2 /* vim:set ts=2 sw=2 sts=2 et: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 /* Test stream failure on the session to the proxy: 8 * - Test the case the error closes the affected stream only 9 * - Test the case the error closes the whole session and cancels existing 10 * streams. 11 */ 12 13 /* eslint-env node */ 14 15 "use strict"; 16 17 const pps = Cc["@mozilla.org/network/protocol-proxy-service;1"].getService(); 18 19 let filter; 20 21 class ProxyFilter { 22 constructor(type, host, port, flags) { 23 this._type = type; 24 this._host = host; 25 this._port = port; 26 this._flags = flags; 27 this.QueryInterface = ChromeUtils.generateQI(["nsIProtocolProxyFilter"]); 28 } 29 applyFilter(uri, pi, cb) { 30 cb.onProxyFilterResult( 31 pps.newProxyInfo( 32 this._type, 33 this._host, 34 this._port, 35 null, 36 null, 37 this._flags, 38 1000, 39 null 40 ) 41 ); 42 } 43 } 44 45 function createPrincipal(url) { 46 var ssm = Services.scriptSecurityManager; 47 try { 48 return ssm.createContentPrincipal(Services.io.newURI(url), {}); 49 } catch (e) { 50 return null; 51 } 52 } 53 54 function make_channel(url) { 55 return Services.io.newChannelFromURIWithProxyFlags( 56 Services.io.newURI(url), 57 null, 58 16, 59 null, 60 createPrincipal(url), 61 createPrincipal(url), 62 Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_INHERITS_SEC_CONTEXT, 63 Ci.nsIContentPolicy.TYPE_OTHER 64 ); 65 } 66 67 function get_response(channel, flags = CL_ALLOW_UNKNOWN_CL, delay = 0) { 68 return new Promise(resolve => { 69 var listener = new ChannelListener( 70 (request, data) => { 71 request.QueryInterface(Ci.nsIHttpChannel); 72 const status = request.status; 73 const http_code = status ? undefined : request.responseStatus; 74 request.QueryInterface(Ci.nsIProxiedChannel); 75 const proxy_connect_response_code = 76 request.httpProxyConnectResponseCode; 77 resolve({ status, http_code, data, proxy_connect_response_code }); 78 }, 79 null, 80 flags 81 ); 82 if (delay > 0) { 83 do_timeout(delay, function () { 84 channel.asyncOpen(listener); 85 }); 86 } else { 87 channel.asyncOpen(listener); 88 } 89 }); 90 } 91 92 add_task(async function setup() { 93 // Set to allow the cert presented by our H2 server 94 do_get_profile(); 95 96 // The moz-http2 cert is for foo.example.com and is signed by http2-ca.pem 97 // so add that cert to the trust list as a signing cert. 98 let certdb = Cc["@mozilla.org/security/x509certdb;1"].getService( 99 Ci.nsIX509CertDB 100 ); 101 addCertFromFile(certdb, "http2-ca.pem", "CTu,u,u"); 102 103 let proxy_port = Services.env.get("MOZHTTP2_PORT"); 104 Assert.notEqual(proxy_port, null); 105 106 Services.prefs.setBoolPref("network.http.http2.enabled", true); 107 // make all native resolve calls "secretly" resolve localhost instead 108 Services.prefs.setBoolPref("network.dns.native-is-localhost", true); 109 110 filter = new ProxyFilter("https", "localhost", proxy_port, 16); 111 pps.registerFilter(filter, 10); 112 }); 113 114 registerCleanupFunction(async () => { 115 Services.prefs.clearUserPref("network.http.http2.enabled"); 116 Services.prefs.clearUserPref("network.dns.native-is-localhost"); 117 118 pps.unregisterFilter(filter); 119 }); 120 121 add_task( 122 async function proxy_server_stream_soft_failure_multiple_streams_not_affected() { 123 let should_succeed = get_response(make_channel(`http://750.example.com`)); 124 const failed = await get_response( 125 make_channel(`http://illegalhpacksoft.example.com`), 126 CL_EXPECT_FAILURE, 127 20 128 ); 129 130 const succeeded = await should_succeed; 131 132 Assert.equal(failed.status, Cr.NS_ERROR_ILLEGAL_VALUE); 133 Assert.equal(failed.proxy_connect_response_code, 0); 134 Assert.equal(failed.http_code, undefined); 135 Assert.equal(succeeded.status, Cr.NS_OK); 136 Assert.equal(succeeded.proxy_connect_response_code, 200); 137 Assert.equal(succeeded.http_code, 200); 138 } 139 ); 140 141 add_task( 142 async function proxy_server_stream_hard_failure_multiple_streams_affected() { 143 let should_failed = get_response( 144 make_channel(`http://750.example.com`), 145 CL_EXPECT_FAILURE 146 ); 147 const failed1 = await get_response( 148 make_channel(`http://illegalhpackhard.example.com`), 149 CL_EXPECT_FAILURE 150 ); 151 152 const failed2 = await should_failed; 153 154 Assert.equal(failed1.status, 0x804b0053); 155 Assert.equal(failed1.proxy_connect_response_code, 0); 156 Assert.equal(failed1.http_code, undefined); 157 Assert.equal(failed2.status, 0x804b0053); 158 Assert.equal(failed2.proxy_connect_response_code, 0); 159 Assert.equal(failed2.http_code, undefined); 160 } 161 ); 162 163 add_task(async function test_http2_h11required_stream() { 164 let should_failed = await get_response( 165 make_channel(`http://h11required.com`), 166 CL_EXPECT_FAILURE 167 ); 168 169 // See HTTP/1.1 connect handler in moz-http2.js. The handler returns 170 // "404 Not Found", so the expected error code is NS_ERROR_UNKNOWN_HOST. 171 Assert.equal(should_failed.status, Cr.NS_ERROR_UNKNOWN_HOST); 172 Assert.equal(should_failed.proxy_connect_response_code, 404); 173 Assert.equal(should_failed.http_code, undefined); 174 });