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
// server.jsconsthttp2=require('http2');const{ readFileSync }=require('fs');// Create an HTTP/2 serverconstserver=http2.createSecureServer({key: readFileSync('localhost-privkey.pem'),cert: readFileSync('localhost-cert.pem'),sessionTimeout: 10,});consttimer=10000;// Handle new connectionsserver.on('stream',(stream,headers)=>{constpath=headers[':path'];console.log(`Request received for ${path} on stream ${stream.id}`);stream.respond({'content-type': 'text/html',':status': 200});stream.write(`<h1>Hello from stream ${stream.id}</h1>`);});server.on('session',(session)=>{console.log('New session established');constinterval=setInterval(()=>{if(session.closed||session.destroyed){clearInterval(interval);}},500);session.on('close',()=>{clearInterval(interval);});});constPORT=8443;server.listen(PORT,()=>{console.log(`Server started on port ${PORT}`);console.log(`Server will send GOAWAY after ${timer/1000} seconds`);});setTimeout(()=>{server.close(()=>console.log('__________SERVER CLOSED__________'));console.log('__________SERVER CLOSE IS FIRED___________');},timer);
client.js
consthttp2=require('http2');letclient=null;letrequestCount=0;letreceivedGoaway=false;// Create connectionfunctionconnect(){receivedGoaway=false;client=http2.connect('https://localhost:8443',{rejectUnauthorized: false});client.on('error',err=>console.error('Connection error:',err));client.on('close',()=>console.log('Connection closed'));client.on('goaway',()=>{console.log('GOAWAY received');receivedGoaway=true;// Reconnect after goawaysetTimeout(()=>{connect();sendRequest();},1000);});}// Send a single requestfunctionsendRequest(){// Skip if connection got GOAWAYif(receivedGoaway)return;requestCount++;console.log(`Opening Stream/Request #${requestCount}`);// Create requestconstreq=client.request({':path': `/req-${requestCount}`,':method': 'POST'});// Simple handlersreq.on('response',headers=>console.log(`Response: ${headers[':status']}`));req.on('data',chunk=>console.log(`Data: ${chunk.toString().trim()}`));req.on('end',()=>console.log(`Stream #${requestCount} complete`));req.on('error',err=>console.error(`Stream error:`,err.message));// Write and endreq.write(`Data for request ${requestCount}`);req.end(`Final data for ${requestCount}`);if(!receivedGoaway){setTimeout(sendRequest,1000);}}// Start clientconnect();sendRequest();
Keep all of the above file(server.js, client.js, localhost-privkey.pem, localhost-cert.pem) in same folder.
Run
node server.js
Run below script with 10s of running server.js
node client.js
server.close is fired after 10s of server start and if it do not find any active request it automatically closes this is why client need to start within 10s of starting server
How often does it reproduce? Is there a required condition?
This reproduce always when server have fired close call but it have active client connections.
What is the expected behavior? Why is that the expected behavior?
According to the Node.js documentation:
server.close()
stops the server from accepting new connections and closes all connections connected to this server which are not sending a request or waiting for a response.
The server should:
Stop accepting new connections (currently works)
Close all existing HTTP/2 sessions gracefully by sending GOAWAY frames (not working)
Allow in-flight requests to complete (currently works)
Prevent new streams (requests) on existing connections (not working)
Terminate cleanly after all active streams finish (not working)
The server should not wait for client to close instead server should close connection once it have processes all active stream/request.
What do you see instead?
Currently:
The server stops accepting new connections
But existing connections remain open indefinitely
New streams (requests) can be initiated on existing connections
The server's close callback may never be called if clients maintain open connections
Start of server shutdown can starve indefinitely, leading to processes that cannot terminate cleanly and causing resource leaks
Additional information
As per http2 docs, if there is need of connection close, server should send goaway frame and ensure gracefull session close by processing all active request(or stream) and discarding any new request.
Refer paragraph 5 of http2 link
The text was updated successfully, but these errors were encountered:
I have attached a PR which ensure that server will stop accepting any request and it will close automatically once it is done processing all active request.
pandeykushagra51
changed the title
http2 server wait to close infinitely
http2 server wait infinitely to close
Mar 25, 2025
Version
v23.1.0
Platform
Subsystem
http2
What steps will reproduce the bug?
Create an HTTP/2 server and call
while there are active client connections.
server.js
client.js
localhost-privkey.pem
localhost-cert.pem
Steps to reproduce:
server.close is fired after 10s of server start and if it do not find any active request it automatically closes this is why client need to start within 10s of starting server
How often does it reproduce? Is there a required condition?
This reproduce always when server have fired close call but it have active client connections.
What is the expected behavior? Why is that the expected behavior?
According to the Node.js documentation:
server.close()
The server should:
The server should not wait for client to close instead server should close connection once it have processes all active stream/request.
What do you see instead?
Currently:
Additional information
As per http2 docs, if there is need of connection close, server should send goaway frame and ensure gracefull session close by processing all active request(or stream) and discarding any new request.
Refer paragraph 5 of http2 link
The text was updated successfully, but these errors were encountered: