http.Server is not able to handle RST packets and emits clientError
- Version: v12.16.1 (but I've also experienced this with latest master)
- Platform: macOS 10.15.4 - Darwin ** 19.4.0 Darwin Kernel Version 19.4.0: Wed Mar 4 22:28:40 PST 2020; root:xnu-6153.101.6~15/RELEASE_X86_64 x86_64
- Subsystem: http and/or net
What steps will reproduce the bug?
- Start the following node.js application:
'use strict';
const { createServer } = require('http');
const server = createServer((req, res) => {
res.writeHead(200, {'Content-Length': 2}).end('OK');
})
server.on('clientError', (err, socket) => {
console.log('CLIENT ERROR');
socket.end('HTTP/1.1 400 Bad Request\r\n\r\n');
});
server.listen(8331);
- Start a haproxy instance with the following configuration:
global
log stdout format raw local1
maxconn 4096
defaults
log global
mode http
option httplog
option dontlognull
option forwardfor
retries 3
option redispatch
maxconn 2000
timeout connect 5000
timeout client 50000
timeout server 50000
frontend proxy
bind 0.0.0.0:8330
default_backend fastify
backend fastify
server local 127.0.0.1:8331
-
Make several (usually two or three within the same terminal in the timespan of few seconds is enought) HTTP requests to the haproxy endpoint (
http://127.0.0.1:8330/check
) -
Note that random
CLIENT ERROR
logs will be shown on the Node.js server output, which is a indication thatclientError
is emitted. Note that the client side of the connection (in this case haproxy) has already received the 200 response, so the clientError handler data is never actually received. -
(optional) If you run tcpdump on port 8331 (the Node.js one) you will see that Node is not sending FIN and neither haproxy. Moreover at some point haproxy sends RST and this cause Node.js to emit the clientError.
How often does it reproduce? Is there a required condition?
As said above, triggering multiple request in short timeframe is enough.
Another way is to add option http-server-close
to haproxy to force a Connection: close
. This will emit the error on each request.
What is the expected behavior?
Node.js should correctly handle connection terminated via RST (probably ignoring them) without emitting an error.
What do you see instead?
Node.js emits a clientError when receiving a RST packet.