Skip to content

Commit e8d7fed

Browse files
committed
http: don't write error to socket
The state of the connection is unknown at this point and writing to it can corrupt client state before it is aware of an error. PR-URL: #34465 Reviewed-By: Luigi Pinca <[email protected]> Reviewed-By: Matteo Collina <[email protected]> Reviewed-By: James M Snell <[email protected]>
1 parent de19224 commit e8d7fed

File tree

3 files changed

+34
-3
lines changed

3 files changed

+34
-3
lines changed

doc/api/http.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -1074,8 +1074,8 @@ type other than {net.Socket}.
10741074

10751075
Default behavior is to try close the socket with a HTTP '400 Bad Request',
10761076
or a HTTP '431 Request Header Fields Too Large' in the case of a
1077-
[`HPE_HEADER_OVERFLOW`][] error. If the socket is not writable it is
1078-
immediately destroyed.
1077+
[`HPE_HEADER_OVERFLOW`][] error. If the socket is not writable or has already
1078+
written data it is immediately destroyed.
10791079

10801080
`socket` is the [`net.Socket`][] object that the error originated from.
10811081

lib/_http_server.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -618,7 +618,7 @@ function socketOnError(e) {
618618
this.on('error', noop);
619619

620620
if (!this.server.emit('clientError', e, this)) {
621-
if (this.writable) {
621+
if (this.writable && this.bytesWritten === 0) {
622622
const response = e.code === 'HPE_HEADER_OVERFLOW' ?
623623
requestHeaderFieldsTooLargeResponse : badRequestResponse;
624624
this.write(response);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
'use strict';
2+
const { mustCall } = require('../common');
3+
const assert = require('assert');
4+
const { createServer } = require('http');
5+
const { createConnection } = require('net');
6+
7+
const server = createServer();
8+
9+
server.on('request', mustCall((req, res) => {
10+
res.write('asd', () => {
11+
res.socket.emit('error', new Error('kaboom'));
12+
});
13+
}));
14+
15+
server.listen(0, mustCall(() => {
16+
const c = createConnection(server.address().port);
17+
let received = '';
18+
19+
c.on('connect', mustCall(() => {
20+
c.write('GET /blah HTTP/1.1\r\n\r\n');
21+
}));
22+
c.on('data', mustCall((data) => {
23+
received += data.toString();
24+
}));
25+
c.on('end', mustCall(() => {
26+
// Should not include anything else after asd.
27+
assert.strictEqual(received.indexOf('asd\r\n'), received.length - 5);
28+
c.end();
29+
}));
30+
c.on('close', mustCall(() => server.close()));
31+
}));

0 commit comments

Comments
 (0)