webtransport-test-helpers.sub.js (4136B)
1 // The file including this must also include /common/get-host-info.sub.js to 2 // pick up the necessary constants. 3 4 const HOST = get_host_info().ORIGINAL_HOST; 5 const PORT = '{{ports[webtransport-h3][0]}}'; 6 const BASE = `https://${HOST}:${PORT}`; 7 8 // Wait for the given number of milliseconds (ms). 9 function wait(ms) { return new Promise(res => step_timeout(res, ms)); } 10 11 // Create URL for WebTransport session. 12 function webtransport_url(handler) { 13 return `${BASE}/webtransport/handlers/${handler}`; 14 } 15 16 // Converts WebTransport stream error code to HTTP/3 error code. 17 // https://ietf-wg-webtrans.github.io/draft-ietf-webtrans-http3/draft-ietf-webtrans-http3.html#section-4.3 18 function webtransport_code_to_http_code(n) { 19 const first = 0x52e4a40fa8db; 20 return first + n + Math.floor(n / 0x1e); 21 } 22 23 // Read all chunks from |readable_stream| and return as an array of arrays 24 async function read_stream(readable_stream) { 25 const reader = readable_stream.getReader(); 26 27 let chunks = []; 28 while (true) { 29 const {value: chunk, done} = await reader.read(); 30 if (done) { 31 break; 32 } 33 chunks.push(chunk); 34 } 35 reader.releaseLock(); 36 37 return chunks; 38 } 39 40 // Read all chunks from |readable_stream|, decode chunks to a utf-8 string, then 41 // return the string. 42 async function read_stream_as_string(readable_stream) { 43 const decoder = new TextDecoderStream(); 44 const decode_stream = readable_stream.pipeThrough(decoder); 45 const reader = decode_stream.getReader(); 46 47 let chunks = ''; 48 while (true) { 49 const {value: chunk, done} = await reader.read(); 50 if (done) { 51 break; 52 } 53 chunks += chunk; 54 } 55 reader.releaseLock(); 56 57 return chunks; 58 } 59 60 // Decode all chunks in a given ReadableStream, and parse the data using JSON. 61 async function read_stream_as_json(readable_stream) { 62 const text = await read_stream_as_string(readable_stream); 63 return JSON.parse(text); 64 } 65 66 // Check the standard request headers and delete them, leaving any "unique" 67 // headers to check in the test. 68 function check_and_remove_standard_headers(headers) { 69 assert_equals(headers[':scheme'], 'https'); 70 delete headers[':scheme']; 71 assert_equals(headers[':method'], 'CONNECT'); 72 delete headers[':method']; 73 assert_equals(headers[':authority'], `${HOST}:${PORT}`); 74 delete headers[':authority']; 75 assert_equals(headers[':path'], '/webtransport/handlers/echo-request-headers.py'); 76 delete headers[':path']; 77 assert_equals(headers[':protocol'], 'webtransport'); 78 delete headers[':protocol']; 79 assert_equals(headers['origin'], `${get_host_info().ORIGIN}`); 80 delete headers['origin']; 81 } 82 83 async function query(token) { 84 const wt = new WebTransport(webtransport_url(`query.py?token=${token}`)); 85 try { 86 await wt.ready; 87 const streams = await wt.incomingUnidirectionalStreams; 88 const streams_reader = streams.getReader(); 89 const { value: readable } = await streams_reader.read(); 90 streams_reader.releaseLock(); 91 92 return await read_stream_as_json(readable); 93 } finally { 94 wt.close(); 95 } 96 } 97 98 async function readInto(reader, buffer) { 99 let offset = 0; 100 101 while (offset < buffer.byteLength) { 102 const {value: view, done} = await reader.read( 103 new Uint8Array(buffer, offset, buffer.byteLength - offset)); 104 buffer = view.buffer; 105 if (done) { 106 break; 107 } 108 offset += view.byteLength; 109 } 110 111 return buffer; 112 } 113 114 // Opens a new WebTransport connection. 115 async function openWebTransport(remoteContextHelper) { 116 const url = webtransport_url('custom-response.py?:status=200'); 117 await remoteContextHelper.executeScript((url) => { 118 window.testWebTransport = new WebTransport(url); 119 return window.testWebTransport.ready; 120 }, [url]); 121 } 122 123 // Opens a new WebTransport connection and then close it. 124 async function openThenCloseWebTransport(remoteContextHelper) { 125 const url = webtransport_url('custom-response.py?:status=200'); 126 await remoteContextHelper.executeScript((url) => { 127 window.testWebTransport = new WebTransport(url); 128 return window.testWebTransport.ready.then(async () => { 129 window.testWebTransport.close(); 130 await window.testWebTransport.closed; 131 }); 132 }, [url]); 133 }