test_proxy-slow-upload.js (3902B)
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 5 "use strict"; 6 7 const { 8 NodeHTTPProxyServer, 9 NodeHTTPSProxyServer, 10 NodeHTTP2ProxyServer, 11 with_node_servers, 12 NodeHTTPServer, 13 NodeHTTPSServer, 14 NodeHTTP2Server, 15 } = ChromeUtils.importESModule("resource://testing-common/NodeServer.sys.mjs"); 16 17 /* import-globals-from head_cache.js */ 18 /* import-globals-from head_cookies.js */ 19 /* import-globals-from head_channels.js */ 20 21 // We don't normally allow localhost channels to be proxied, but this 22 // is easier than updating all the certs and/or domains. 23 Services.prefs.setBoolPref("network.proxy.allow_hijacking_localhost", true); 24 registerCleanupFunction(() => { 25 Services.prefs.clearUserPref("network.proxy.allow_hijacking_localhost"); 26 }); 27 28 const SIZE = 4096; 29 const CONTENT = "x".repeat(SIZE); 30 31 add_task(async function test_slow_upload() { 32 let certdb = Cc["@mozilla.org/security/x509certdb;1"].getService( 33 Ci.nsIX509CertDB 34 ); 35 addCertFromFile(certdb, "http2-ca.pem", "CTu,u,u"); 36 addCertFromFile(certdb, "proxy-ca.pem", "CTu,u,u"); 37 38 let proxies = [ 39 NodeHTTPProxyServer, 40 NodeHTTPSProxyServer, 41 NodeHTTP2ProxyServer, 42 ]; 43 for (let p of proxies) { 44 let proxy = new p(); 45 await proxy.start(); 46 registerCleanupFunction(async () => { 47 await proxy.stop(); 48 }); 49 50 await with_node_servers( 51 [NodeHTTPServer, NodeHTTPSServer, NodeHTTP2Server], 52 async server => { 53 info(`Testing ${p.name} with ${server.constructor.name}`); 54 await server.execute( 55 `global.server_name = "${server.constructor.name}";` 56 ); 57 await server.registerPathHandler("/test", (req, resp) => { 58 let content = ""; 59 req.on("data", data => { 60 global.data_count = (global.data_count || 0) + 1; 61 content += data; 62 }); 63 req.on("end", () => { 64 resp.writeHead(200); 65 resp.end(content); 66 }); 67 }); 68 69 let sstream = Cc[ 70 "@mozilla.org/io/string-input-stream;1" 71 ].createInstance(Ci.nsIStringInputStream); 72 sstream.setByteStringData(CONTENT); 73 74 let mime = Cc[ 75 "@mozilla.org/network/mime-input-stream;1" 76 ].createInstance(Ci.nsIMIMEInputStream); 77 mime.addHeader("Content-Type", "multipart/form-data; boundary=zzzzz"); 78 mime.setData(sstream); 79 80 let tq = Cc["@mozilla.org/network/throttlequeue;1"].createInstance( 81 Ci.nsIInputChannelThrottleQueue 82 ); 83 // Make sure the request takes more than one read. 84 tq.init(100 + SIZE / 2, 100 + SIZE / 2); 85 86 let chan = NetUtil.newChannel({ 87 uri: `${server.origin()}/test`, 88 loadUsingSystemPrincipal: true, 89 }).QueryInterface(Ci.nsIHttpChannel); 90 91 let tic = chan.QueryInterface(Ci.nsIThrottledInputChannel); 92 tic.throttleQueue = tq; 93 94 chan 95 .QueryInterface(Ci.nsIUploadChannel) 96 .setUploadStream(mime, "", mime.available()); 97 chan.requestMethod = "POST"; 98 99 let { req, buff } = await new Promise(resolve => { 100 chan.asyncOpen( 101 new ChannelListener( 102 (req1, buff1) => resolve({ req: req1, buff: buff1 }), 103 null, 104 CL_ALLOW_UNKNOWN_CL 105 ) 106 ); 107 }); 108 equal(req.status, Cr.NS_OK); 109 equal(req.QueryInterface(Ci.nsIHttpChannel).responseStatus, 200); 110 Assert.equal(buff, CONTENT, "Content must match"); 111 ok(!!req.QueryInterface(Ci.nsIProxiedChannel).proxyInfo); 112 greater( 113 await server.execute(`global.data_count`), 114 1, 115 "Content should have been streamed to the server in several chunks" 116 ); 117 } 118 ); 119 await proxy.stop(); 120 } 121 });