double_submit.sjs (1877B)
1 "use strict"; 2 3 let self = this; 4 5 let { setTimeout } = ChromeUtils.importESModule( 6 "resource://gre/modules/Timer.sys.mjs" 7 ); 8 9 const CC = Components.Constructor; 10 const BinaryInputStream = CC( 11 "@mozilla.org/binaryinputstream;1", 12 "nsIBinaryInputStream", 13 "setInputStream" 14 ); 15 16 function log() { 17 // dump(`LOG: ${str}\n`); 18 } 19 20 function readStream(inputStream) { 21 let available = 0; 22 let result = []; 23 while ((available = inputStream.available()) > 0) { 24 result.push(inputStream.readBytes(available)); 25 } 26 27 return result.join(""); 28 } 29 30 function now() { 31 return Date.now(); 32 } 33 34 async function handleRequest(request, response) { 35 log("Get query parameters"); 36 let params = new URLSearchParams(request.queryString); 37 38 let start = now(); 39 let delay = parseInt(params.get("delay")) || 0; 40 log(`Delay for ${delay}`); 41 42 let message = "good"; 43 if (request.method !== "POST") { 44 message = "bad"; 45 } else { 46 log("Read POST body"); 47 let body = new URLSearchParams( 48 readStream(new BinaryInputStream(request.bodyInputStream)) 49 ); 50 message = body.get("token") || "bad"; 51 log(`The result was ${message}`); 52 } 53 54 let body = `<!doctype html> 55 <script> 56 "use strict"; 57 let target = (opener || parent); 58 target.postMessage(${JSON.stringify(message)}, '*'); 59 </script>`; 60 61 // Sieze power from the response to allow manually transmitting data at any 62 // rate we want, so we can delay transmitting headers. 63 response.seizePower(); 64 65 log(`Writing HTTP status line at ${now() - start}`); 66 response.write("HTTP/1.1 200 OK\r\n"); 67 68 await new Promise(resolve => setTimeout(() => resolve(), delay)); 69 70 log(`Delay completed at ${now() - start}`); 71 response.write("Content-Type: text/html\r\n"); 72 response.write(`Content-Length: ${body.length}\r\n`); 73 response.write("\r\n"); 74 response.write(body); 75 response.finish(); 76 77 log("Finished"); 78 }