No keepAliveTimeout for HTTP server after answering a POST request synchronously
Nadie ha tomado este issue todavía.
- Lenguaje dominante
- JavaScript
- Estrellas
- 122k
- Forks
- 37.3k
- Merge medio
- 4 d 2 h
- PR fusionados (30 d)
- 283
Descripción
- 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?
Guía de contribución
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Línea de trabajo
Ejecuta primero la reproducción de JavaScript proporcionada y después lee en lib/_http_server.js alrededor de resOnFinish, socketOnData y onParserExecuteCommon. Sigue cómo el cuerpo POST restante restablece el tiempo de espera del socket después de la respuesta síncrona. Se considera terminado cuando el caso POST síncrono se cierra después de server.keepAliveTimeout, igual que los otros tres casos, con cobertura de regresión para el comportamiento notificado.
Escrito por el modelo de indexación a partir del texto del issue.
Evaluación
- Stack tecnológico
- javascript
- Área
- api, backend
- Tipo de issue
- Error
- Dificultad
- 3/5
- Tiempo estimado
- 1-2 días
- Estado de actividad
- Activo
- Claridad
- Bien especificado
- Aptitud para principiantes
- 68/100