test_progress_no_proxy_and_proxy.js (6071B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 "use strict"; 5 6 const { 7 NodeHTTPServer, 8 NodeHTTPSServer, 9 NodeHTTP2Server, 10 NodeHTTPProxyServer, 11 NodeHTTPSProxyServer, 12 NodeHTTP2ProxyServer, 13 with_node_servers, 14 } = ChromeUtils.importESModule("resource://testing-common/NodeServer.sys.mjs"); 15 16 // We don't normally allow localhost channels to be proxied, but this 17 // is easier than updating all the certs and/or domains. 18 Services.prefs.setBoolPref("network.proxy.allow_hijacking_localhost", true); 19 registerCleanupFunction(() => { 20 Services.prefs.clearUserPref("network.proxy.allow_hijacking_localhost"); 21 }); 22 23 // This test can be merged with test_progress.js once HTTP/3 tests are 24 // enabled on all plaforms. 25 26 var last = 0; 27 var max = 0; 28 var using_proxy = false; 29 30 const RESPONSE_LENGTH = 3000000; 31 const STATUS_RECEIVING_FROM = 0x4b0006; 32 33 const TYPE_ONSTATUS = 1; 34 const TYPE_ONPROGRESS = 2; 35 const TYPE_ONSTARTREQUEST = 3; 36 const TYPE_ONDATAAVAILABLE = 4; 37 const TYPE_ONSTOPREQUEST = 5; 38 39 var ProgressCallback = function () {}; 40 41 ProgressCallback.prototype = { 42 _listener: null, 43 _got_onstartrequest: false, 44 _got_onstatus_after_onstartrequest: false, 45 _last_callback_handled: null, 46 statusArg: "", 47 finish: null, 48 49 QueryInterface: ChromeUtils.generateQI([ 50 "nsIProgressEventSink", 51 "nsIStreamListener", 52 "nsIRequestObserver", 53 ]), 54 55 getInterface(iid) { 56 if ( 57 iid.equals(Ci.nsIProgressEventSink) || 58 iid.equals(Ci.nsIStreamListener) || 59 iid.equals(Ci.nsIRequestObserver) 60 ) { 61 return this; 62 } 63 throw Components.Exception("", Cr.NS_ERROR_NO_INTERFACE); 64 }, 65 66 onStartRequest(request) { 67 Assert.equal(this._last_callback_handled, TYPE_ONSTATUS); 68 this._got_onstartrequest = true; 69 this._last_callback_handled = TYPE_ONSTARTREQUEST; 70 71 this._listener = new ChannelListener(checkRequest, request); 72 this._listener.onStartRequest(request); 73 }, 74 75 onDataAvailable(request, data, offset, count) { 76 Assert.equal(this._last_callback_handled, TYPE_ONPROGRESS); 77 this._last_callback_handled = TYPE_ONDATAAVAILABLE; 78 79 this._listener.onDataAvailable(request, data, offset, count); 80 }, 81 82 onStopRequest(request, status) { 83 Assert.equal(this._last_callback_handled, TYPE_ONDATAAVAILABLE); 84 Assert.ok(this._got_onstatus_after_onstartrequest); 85 this._last_callback_handled = TYPE_ONSTOPREQUEST; 86 87 this._listener.onStopRequest(request, status); 88 delete this._listener; 89 90 check_http_info(request, this.expected_httpVersion, using_proxy); 91 92 this.finish(); 93 }, 94 95 onProgress(request, progress, progressMax) { 96 Assert.equal(this._last_callback_handled, TYPE_ONSTATUS); 97 this._last_callback_handled = TYPE_ONPROGRESS; 98 99 Assert.equal(this.mStatus, STATUS_RECEIVING_FROM); 100 last = progress; 101 max = progressMax; 102 }, 103 104 onStatus(request, status, statusArg) { 105 if (!this._got_onstartrequest) { 106 // Ensure that all messages before onStartRequest are onStatus 107 if (this._last_callback_handled) { 108 Assert.equal(this._last_callback_handled, TYPE_ONSTATUS); 109 } 110 } else if (this._last_callback_handled == TYPE_ONSTARTREQUEST) { 111 this._got_onstatus_after_onstartrequest = true; 112 } else { 113 Assert.equal(this._last_callback_handled, TYPE_ONDATAAVAILABLE); 114 } 115 this._last_callback_handled = TYPE_ONSTATUS; 116 117 Assert.equal(statusArg, this.statusArg); 118 this.mStatus = status; 119 }, 120 121 mStatus: 0, 122 }; 123 124 function chanPromise(uri, statusArg, version) { 125 return new Promise(resolve => { 126 var chan = makeHTTPChannel(uri, using_proxy); 127 chan.requestMethod = "GET"; 128 let listener = new ProgressCallback(); 129 listener.statusArg = statusArg; 130 chan.notificationCallbacks = listener; 131 listener.expected_httpVersion = version; 132 listener.finish = resolve; 133 chan.asyncOpen(listener); 134 }); 135 } 136 137 function checkRequest() { 138 Assert.equal(last, RESPONSE_LENGTH); 139 Assert.equal(max, RESPONSE_LENGTH); 140 } 141 142 async function check_progress(server) { 143 info(`Testing ${server.constructor.name}`); 144 await server.registerPathHandler("/test", (req, resp) => { 145 // Generate a post. 146 function generateContent(size) { 147 return "0".repeat(size); 148 } 149 150 resp.writeHead(200, { 151 "content-type": "application/json", 152 "content-length": "3000000", 153 }); 154 resp.end(generateContent(3000000)); 155 }); 156 await chanPromise( 157 `${server.origin()}/test`, 158 `${server.domain()}`, 159 server.version() 160 ); 161 } 162 163 add_task(async function setup() { 164 let certdb = Cc["@mozilla.org/security/x509certdb;1"].getService( 165 Ci.nsIX509CertDB 166 ); 167 addCertFromFile(certdb, "http2-ca.pem", "CTu,u,u"); 168 addCertFromFile(certdb, "proxy-ca.pem", "CTu,u,u"); 169 }); 170 171 add_task(async function test_http_1_and_2() { 172 await with_node_servers( 173 [NodeHTTPServer, NodeHTTPSServer, NodeHTTP2Server], 174 check_progress 175 ); 176 }); 177 178 add_task(async function test_http_proxy() { 179 using_proxy = true; 180 let proxy = new NodeHTTPProxyServer(); 181 await proxy.start(); 182 await with_node_servers( 183 [NodeHTTPServer, NodeHTTPSServer, NodeHTTP2Server], 184 check_progress 185 ); 186 await proxy.stop(); 187 using_proxy = false; 188 }); 189 190 add_task(async function test_https_proxy() { 191 using_proxy = true; 192 let proxy = new NodeHTTPSProxyServer(); 193 await proxy.start(); 194 await with_node_servers( 195 [NodeHTTPServer, NodeHTTPSServer, NodeHTTP2Server], 196 check_progress 197 ); 198 await proxy.stop(); 199 using_proxy = false; 200 }); 201 202 add_task(async function test_http2_proxy() { 203 using_proxy = true; 204 let proxy = new NodeHTTP2ProxyServer(); 205 await proxy.start(); 206 await with_node_servers( 207 [NodeHTTPServer, NodeHTTPSServer, NodeHTTP2Server], 208 check_progress 209 ); 210 await proxy.stop(); 211 using_proxy = false; 212 }); 213 214 add_task(async function test_http3() { 215 await http3_setup_tests("h3"); 216 await chanPromise( 217 "https://foo.example.com/" + RESPONSE_LENGTH, 218 "foo.example.com", 219 "h3" 220 ); 221 http3_clear_prefs(); 222 });