You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Save repro.mjs in the same directory as the cert and key, run node repro.mjs
import{once}from'node:events';import{readFileSync}from'node:fs';importhttp2from'node:http2';import{Readable}from'node:stream';const{HTTP2_HEADER_AUTHORITY,HTTP2_HEADER_METHOD,HTTP2_HEADER_PATH,HTTP2_HEADER_SCHEME,HTTP2_METHOD_POST,}=http2.constants;constbaseH2URL=newURL('https://localhost:3443');constcwd=process.cwd();constcert=readFileSync(`${cwd}/localhost.cert`);constkey=readFileSync(`${cwd}/localhost.key`);consth2server=http2.createSecureServer({ cert, key },(req,res)=>{console.log(req.url);req.pipe(res);});awaitonce(h2server.listen(baseH2URL.port),'listening');console.log('h2::server listening on',h2server.address());constclient=http2.connect(baseH2URL,{rejectUnauthorized: false});client.on('error',(err)=>console.error(err));constreq=client.request({[HTTP2_HEADER_AUTHORITY]: baseH2URL.host,[HTTP2_HEADER_METHOD]: HTTP2_METHOD_POST,[HTTP2_HEADER_PATH]: `${baseH2URL.pathname}${baseH2URL.search}`,[HTTP2_HEADER_SCHEME]: baseH2URL.protocol.replace(/\p{Punctuation}/gu,''),});req.on('end',()=>console.log('response::ended'));// never get called <---|req.on('error',(err)=>console.error(err));req.on('data',(chunk)=>console.info(chunk));req.on('response',async(headers)=>{console.log(`response::status ${headers[':status']}`);constbody=[];forawait(constchunkofreq){console.info('before::chunk');body.push(chunk);console.log(chunk);console.info('after::chunk');}console.log(Buffer.concat(body).toString());// not reachable <---|});constbody=newBlob(['bits']);Readable.from(body.stream()).pipe(req);// Readable.fromWeb(body.stream()).pipe(req); // issue persists with both methods <---|console.log('h2::brrrr!');
Check logs 🪵 and get surprised 😯
How often does it reproduce? Is there a required condition?
Always reproduces 😮💨
What is the expected behavior? Why is that the expected behavior?
The connection should close 📪 after the data transfer is complete 🏁
What do you see instead?
Connection hangs for an infinite ♾️ amount of time
Additional information
The issue only affects the node:http2 module, and does not appear in the node:http module
Initially identified in -> rekwest package 📦 tests 🧪
Solution to resolve the issue has been found 🔍 in shape 🗿 and form 💎 of async generator wrapper:
import{once}from'node:events';import{readFileSync}from'node:fs';importhttp2from'node:http2';import{Readable}from'node:stream';const{HTTP2_HEADER_AUTHORITY,HTTP2_HEADER_METHOD,HTTP2_HEADER_PATH,HTTP2_HEADER_SCHEME,HTTP2_METHOD_POST,}=http2.constants;constbaseH2URL=newURL('https://localhost:3443');constcwd=process.cwd();constcert=readFileSync(`${cwd}/localhost.cert`);constkey=readFileSync(`${cwd}/localhost.key`);consth2server=http2.createSecureServer({ cert, key },(req,res)=>{console.log(req.url);req.pipe(res);});awaitonce(h2server.listen(baseH2URL.port),'listening');console.log('h2::server listening on',h2server.address());constclient=http2.connect(baseH2URL,{rejectUnauthorized: false});client.on('error',(err)=>console.error(err));constreq=client.request({[HTTP2_HEADER_AUTHORITY]: baseH2URL.host,[HTTP2_HEADER_METHOD]: HTTP2_METHOD_POST,[HTTP2_HEADER_PATH]: `${baseH2URL.pathname}${baseH2URL.search}`,[HTTP2_HEADER_SCHEME]: baseH2URL.protocol.replace(/\p{Punctuation}/gu,''),});req.on('end',()=>console.log('response::ended'));// get called <---|req.on('error',(err)=>console.error(err));req.on('data',(chunk)=>console.info(chunk));req.on('response',async(headers)=>{console.log(`response::status ${headers[':status']}`);constbody=[];forawait(constchunkofreq){console.info('before::chunk');body.push(chunk);console.log(chunk);console.info('after::chunk');}console.log(Buffer.concat(body).toString());// reachable <---|});constbody=newBlob(['bits']);asyncfunction*tap(value){yield*value.stream();}Readable.from(tap(body)).pipe(req);// Readable.fromWeb(tap(body)).pipe(req); // works with both methods <---|console.log('h2::brrrr!');
Version
v20.4.0
Platform
Microsoft Windows NT 10.0.22621.0 x64
Subsystem
No response
What steps will reproduce the bug?
Run following scripts:
openssl req -days 365 -keyout localhost.key -newkey ec -nodes -pkeyopt ec_paramgen_curve:prime256v1 -subj //SKIP=1/CN=localhost -out localhost.cert -x509
repro.mjs
in the same directory as the cert and key, runnode repro.mjs
How often does it reproduce? Is there a required condition?
Always reproduces 😮💨
What is the expected behavior? Why is that the expected behavior?
The connection should close 📪 after the data transfer is complete 🏁
What do you see instead?
Connection hangs for an infinite ♾️ amount of time
Additional information
The issue only affects the
node:http2
module, and does not appear in thenode:http
moduleInitially identified in -> rekwest package 📦 tests 🧪
The text was updated successfully, but these errors were encountered: