Skip to content

Commit cdb33b8

Browse files
committed
Revert "http2: refactor error handling"
This reverts commit 4ca8ff2. That commit was landed without a green CI and is failing on Windows.
1 parent 99c478e commit cdb33b8

9 files changed

+33
-328
lines changed

doc/api/http2.md

+4-35
Original file line numberDiff line numberDiff line change
@@ -1118,8 +1118,6 @@ added: v8.4.0
11181118
* `headers` {[Headers Object][]}
11191119
* `options` {Object}
11201120
* `statCheck` {Function}
1121-
* `onError` {Function} Callback function invoked in the case of an
1122-
Error before send
11231121
* `getTrailers` {Function} Callback function invoked to collect trailer
11241122
headers.
11251123
* `offset` {number} The offset position at which to begin reading
@@ -1148,16 +1146,6 @@ server.on('stream', (stream) => {
11481146
function statCheck(stat, headers) {
11491147
headers['last-modified'] = stat.mtime.toUTCString();
11501148
}
1151-
1152-
function onError(err) {
1153-
if (err.code === 'ENOENT') {
1154-
stream.respond({ ':status': 404 });
1155-
} else {
1156-
stream.respond({ ':status': 500 });
1157-
}
1158-
stream.end();
1159-
}
1160-
11611149
stream.respondWithFile('/some/file',
11621150
{ 'content-type': 'text/plain' },
11631151
{ statCheck });
@@ -1190,10 +1178,6 @@ The `offset` and `length` options may be used to limit the response to a
11901178
specific range subset. This can be used, for instance, to support HTTP Range
11911179
requests.
11921180

1193-
The `options.onError` function may also be used to handle all the errors
1194-
that could happen before the delivery of the file is initiated. The
1195-
default behavior is to destroy the stream.
1196-
11971181
When set, the `options.getTrailers()` function is called immediately after
11981182
queuing the last chunk of payload data to be sent. The callback is passed a
11991183
single object (with a `null` prototype) that the listener may used to specify
@@ -1224,19 +1208,6 @@ added: v8.4.0
12241208

12251209
* Extends: {net.Server}
12261210

1227-
In `Http2Server`, there is no `'clientError'` event as there is in
1228-
HTTP1. However, there are `'socketError'`, `'sessionError'`, and
1229-
`'streamError'`, for error happened on the socket, session or stream
1230-
respectively.
1231-
1232-
#### Event: 'socketError'
1233-
<!-- YAML
1234-
added: v8.4.0
1235-
-->
1236-
1237-
The `'socketError'` event is emitted when a `'socketError'` event is emitted by
1238-
an `Http2Session` associated with the server.
1239-
12401211
#### Event: 'sessionError'
12411212
<!-- YAML
12421213
added: v8.4.0
@@ -1246,15 +1217,13 @@ The `'sessionError'` event is emitted when an `'error'` event is emitted by
12461217
an `Http2Session` object. If no listener is registered for this event, an
12471218
`'error'` event is emitted.
12481219

1249-
#### Event: 'streamError'
1220+
#### Event: 'socketError'
12501221
<!-- YAML
1251-
added: REPLACEME
1222+
added: v8.4.0
12521223
-->
12531224

1254-
* `socket` {http2.ServerHttp2Stream}
1255-
1256-
If an `ServerHttp2Stream` emits an `'error'` event, it will be forwarded here.
1257-
The stream will already be destroyed when this event is triggered.
1225+
The `'socketError'` event is emitted when a `'socketError'` event is emitted by
1226+
an `Http2Session` associated with the server.
12581227

12591228
#### Event: 'stream'
12601229
<!-- YAML

lib/http2.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ const {
1515
createSecureServer,
1616
connect,
1717
Http2ServerRequest,
18-
Http2ServerResponse
18+
Http2ServerResponse,
1919
} = require('internal/http2/core');
2020

2121
module.exports = {
@@ -27,5 +27,5 @@ module.exports = {
2727
createSecureServer,
2828
connect,
2929
Http2ServerResponse,
30-
Http2ServerRequest
30+
Http2ServerRequest,
3131
};

lib/internal/http2/compat.js

+9-7
Original file line numberDiff line numberDiff line change
@@ -58,13 +58,8 @@ function onStreamEnd() {
5858
}
5959

6060
function onStreamError(error) {
61-
// this is purposefully left blank
62-
//
63-
// errors in compatibility mode are
64-
// not forwarded to the request
65-
// and response objects. However,
66-
// they are forwarded to 'clientError'
67-
// on the server by Http2Stream
61+
const request = this[kRequest];
62+
request.emit('error', error);
6863
}
6964

7065
function onRequestPause() {
@@ -87,6 +82,11 @@ function onStreamResponseDrain() {
8782
response.emit('drain');
8883
}
8984

85+
function onStreamResponseError(error) {
86+
const response = this[kResponse];
87+
response.emit('error', error);
88+
}
89+
9090
function onStreamClosedRequest() {
9191
const req = this[kRequest];
9292
req.push(null);
@@ -271,7 +271,9 @@ class Http2ServerResponse extends Stream {
271271
stream[kResponse] = this;
272272
this.writable = true;
273273
stream.on('drain', onStreamResponseDrain);
274+
stream.on('error', onStreamResponseError);
274275
stream.on('close', onStreamClosedResponse);
276+
stream.on('aborted', onAborted.bind(this));
275277
const onfinish = this[kFinish].bind(this);
276278
stream.on('streamClosed', onfinish);
277279
stream.on('finish', onfinish);

lib/internal/http2/core.js

+6-37
Original file line numberDiff line numberDiff line change
@@ -1506,13 +1506,6 @@ class Http2Stream extends Duplex {
15061506
this.once('ready', this._destroy.bind(this, err, callback));
15071507
return;
15081508
}
1509-
1510-
const server = session[kServer];
1511-
1512-
if (err && server) {
1513-
server.emit('streamError', err, this);
1514-
}
1515-
15161509
process.nextTick(() => {
15171510
debug(`[${sessionName(session[kType])}] destroying stream ${this[kID]}`);
15181511

@@ -1536,8 +1529,9 @@ class Http2Stream extends Duplex {
15361529
// All done
15371530
const rst = this[kState].rst;
15381531
const code = rst ? this[kState].rstCode : NGHTTP2_NO_ERROR;
1539-
if (!err && code !== NGHTTP2_NO_ERROR) {
1540-
err = new errors.Error('ERR_HTTP2_STREAM_ERROR', code);
1532+
if (code !== NGHTTP2_NO_ERROR) {
1533+
const err = new errors.Error('ERR_HTTP2_STREAM_ERROR', code);
1534+
process.nextTick(() => this.emit('error', err));
15411535
}
15421536
process.nextTick(emit.bind(this, 'streamClosed', code));
15431537
debug(`[${sessionName(session[kType])}] stream ${this[kID]} destroyed`);
@@ -1640,24 +1634,13 @@ function doSendFileFD(session, options, fd, headers, getTrailers, err, stat) {
16401634
abort(this);
16411635
return;
16421636
}
1643-
const onError = options.onError;
1644-
16451637
if (err) {
1646-
if (onError) {
1647-
onError(err);
1648-
} else {
1649-
this.destroy(err);
1650-
}
1638+
process.nextTick(() => this.emit('error', err));
16511639
return;
16521640
}
1653-
16541641
if (!stat.isFile()) {
16551642
err = new errors.Error('ERR_HTTP2_SEND_FILE');
1656-
if (onError) {
1657-
onError(err);
1658-
} else {
1659-
this.destroy(err);
1660-
}
1643+
process.nextTick(() => this.emit('error', err));
16611644
return;
16621645
}
16631646

@@ -1694,17 +1677,12 @@ function doSendFileFD(session, options, fd, headers, getTrailers, err, stat) {
16941677

16951678
function afterOpen(session, options, headers, getTrailers, err, fd) {
16961679
const state = this[kState];
1697-
const onError = options.onError;
16981680
if (this.destroyed || session.destroyed) {
16991681
abort(this);
17001682
return;
17011683
}
17021684
if (err) {
1703-
if (onError) {
1704-
onError(err);
1705-
} else {
1706-
this.destroy(err);
1707-
}
1685+
process.nextTick(() => this.emit('error', err));
17081686
return;
17091687
}
17101688
state.fd = fd;
@@ -1713,20 +1691,13 @@ function afterOpen(session, options, headers, getTrailers, err, fd) {
17131691
doSendFileFD.bind(this, session, options, fd, headers, getTrailers));
17141692
}
17151693

1716-
function streamOnError(err) {
1717-
// we swallow the error for parity with HTTP1
1718-
// all the errors that ends here are not critical for the project
1719-
debug('ServerHttp2Stream errored, avoiding uncaughtException', err);
1720-
}
1721-
17221694

17231695
class ServerHttp2Stream extends Http2Stream {
17241696
constructor(session, id, options, headers) {
17251697
super(session, options);
17261698
this[kInit](id);
17271699
this[kProtocol] = headers[HTTP2_HEADER_SCHEME];
17281700
this[kAuthority] = headers[HTTP2_HEADER_AUTHORITY];
1729-
this.on('error', streamOnError);
17301701
debug(`[${sessionName(session[kType])}] created serverhttp2stream`);
17311702
}
17321703

@@ -2585,8 +2556,6 @@ module.exports = {
25852556
createServer,
25862557
createSecureServer,
25872558
connect,
2588-
Http2Session,
2589-
Http2Stream,
25902559
Http2ServerRequest,
25912560
Http2ServerResponse
25922561
};

test/parallel/test-http2-client-stream-destroy-before-connect.js

+12-5
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,18 @@ server.on('listening', common.mustCall(() => {
3636
req.destroy(err);
3737

3838
req.on('error', common.mustCall((err) => {
39-
common.expectsError({
40-
type: Error,
41-
message: 'test'
42-
})(err);
43-
}));
39+
const fn = err.code === 'ERR_HTTP2_STREAM_ERROR' ?
40+
common.expectsError({
41+
code: 'ERR_HTTP2_STREAM_ERROR',
42+
type: Error,
43+
message: 'Stream closed with error code 2'
44+
}) :
45+
common.expectsError({
46+
type: Error,
47+
message: 'test'
48+
});
49+
fn(err);
50+
}, 2));
4451

4552
req.on('streamClosed', common.mustCall((code) => {
4653
assert.strictEqual(req.rstCode, NGHTTP2_INTERNAL_ERROR);

test/parallel/test-http2-compat-errors.js

-52
This file was deleted.

test/parallel/test-http2-respond-file-404.js

-47
This file was deleted.

0 commit comments

Comments
 (0)