No keepAliveTimeout for HTTP server after answering a POST request synchronously
Nessuno ha ancora preso questa issue.
- Lingua principale
- JavaScript
- Stelle
- 122k
- Fork
- 37.3k
- Merge medio
- 4g 2h
- PR unite (30g)
- 283
Descrizione
- Version: v16.4.0
- Platform: Linux test01 4.19.0-13-amd64 # 1 SMP Debian 4.19.160-2 (2020-11-28) x86_64 GNU/Linux
- Subsystem: http
What steps will reproduce the bug?
When using the "normal" NodeJS "hello world" HTTP server example, which answers any request synchronously, and sending it a POST request with a body, server.keepAliveTimeout (default 5 sec) does not work. The HTTP connection remains open ("forever"?).
Complete Testcase
Here we test all 4 combinations of sync/async response and get/post request to a simple HTTP server, and expect a connection close from server after 1 sec - which works fine for all combinations except "synchronous response for a POST request". If the connection is still open, we try another request - to prove, the connection still works:
'use strict';
const http = require('http');
const net = require('net');
const server = http.createServer((req, res) => {
if (req.url === '/async') {
req.on('data', () => {});
req.on('end', () => {
res.end('test-body');
console.log('Server: Sent response asynchronously');
});
} else {
res.end('test-body');
console.log('Server: Sent response synchronously');
}
});
server.keepAliveTimeout = 1000;
server.listen(0, async () => {
await sendRequests('async', 'get');
await sendRequests('async', 'post');
await sendRequests('sync', 'get');
await sendRequests('sync', 'post'); // keepAliveTimeout does not work here!!
server.close();
});
async function sendRequests(type, method) {
console.log(`=== Testing ${type} response for method "${method}" and wait for keep-alive-close`);
return new Promise((resolve) => {
const client = new net.Socket();
let nextReqTimeout = null;
client.connect(server.address().port, '127.0.0.1', () => {
console.log('Client: Connected to server');
httpRequest();
nextReqTimeout = setTimeout(() => {
console.log('Client: ERROR: HTTP-Connection is still open - trying another request');
httpRequest();
nextReqTimeout = setTimeout(() => {
console.log('Client: ERROR: HTTP-Connection is still open - closing from client side now');
nextReqTimeout = null;
client.end();
}, server.keepAliveTimeout * 2);
}, server.keepAliveTimeout * 2);
});
client.on('data', function(data) {
console.log('Client: Got response data');
});
client.on('close', function() {
if (nextReqTimeout) {
console.log('Client: Server closed connection as expected');
clearTimeout(nextReqTimeout);
}
resolve();
});
function httpRequest() {
const rawRequests = {
'post': 'POST /' + type + ' HTTP/1.1\r\n' +
'Connection: keep-alive\r\n' +
'Content-Type: application/x-www-form-urlencoded\r\n' +
'Content-Length: 10\r\n' +
'\r\n' +
'Test=67890',
'get': 'GET /' + type + ' HTTP/1.1\r\n' +
'Connection: keep-alive\r\n' +
'\r\n'
};
console.log('Client: Sending request');
client.write(rawRequests[method]);
}
});
}
What is the expected behavior?
The keepAliveTimeout should also work after answering a POST request synchronously.
Possible cause
Maybe this is a race condition here:
- In
resOnFinishtheserver.keepAliveTimeoutis set on the socket, after sending the response - After that,
socketOnDatais called internally for the remaining POST body, which callsonParserExecuteCommon, which resets the socket timeout first - Normally
socketOnDatais called before sending the response, so in most cases it works as expected
Maybe there should be a swicth, to not reset the socket-timeout when socketOnData is called after the response was sent?
Guida per i contributori
Apri la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Direzione di ricerca
Esegui prima la riproduzione JavaScript fornita, quindi leggi in lib/_http_server.js le sezioni intorno a resOnFinish, socketOnData e onParserExecuteCommon. Traccia il modo in cui il corpo POST rimanente reimposta il timeout del socket dopo la risposta sincrona. Il lavoro è completato quando il caso POST sincrono viene chiuso dopo server.keepAliveTimeout come gli altri tre casi, con copertura di regressione per il comportamento segnalato.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Valutazione
- Stack tecnologico
- javascript
- Ambito
- api, backend
- Tipo di issue
- Bug
- Difficoltà
- 3/5
- Tempo stimato
- 1-2 giorni
- Stato di attività
- Attiva
- Chiarezza
- Specificata chiaramente
- Idoneità per principianti
- 68/100