The following conditions cause an error event on http2stream, even though http2stream received all data and RST_STREAM from a client.
http2stream is not destroyed(does not consume all data)
- goaway frame is not received
- socket error happens
http2stream received all data and RST_STREAM
Socket error without goaway frame causes a http2session.destroy(err).
|
function socketOnError(error) { |
|
const session = this[kSession]; |
|
if (session !== undefined) { |
|
// We can ignore ECONNRESET after GOAWAY was received as there's nothing |
|
// we can do and the other side is fully within its rights to do so. |
|
if (error.code === 'ECONNRESET' && session[kState].goawayCode !== null) |
|
return session.destroy(); |
|
debugSessionObj(this, 'socket error [%s]', error.message); |
|
session.destroy(error); |
|
} |
|
} |
http2session.destroy(err) propagate error to http2stream.destroy(err).
|
destroy(error = NGHTTP2_NO_ERROR, code) { |
|
if (this.destroyed) |
|
return; |
|
debugSessionObj(this, 'destroying'); |
|
|
|
if (typeof error === 'number') { |
|
code = error; |
|
error = |
|
code !== NGHTTP2_NO_ERROR ? |
|
new ERR_HTTP2_SESSION_ERROR(code) : undefined; |
|
} |
|
if (code === undefined && error != null) |
|
code = NGHTTP2_INTERNAL_ERROR; |
|
|
|
const state = this[kState]; |
|
state.flags |= SESSION_FLAGS_DESTROYED; |
|
state.destroyCode = code; |
|
|
|
// Clear timeout and remove timeout listeners |
|
this.setTimeout(0); |
|
this.removeAllListeners('timeout'); |
|
|
|
// Destroy any pending and open streams |
|
const cancel = new ERR_HTTP2_STREAM_CANCEL(error); |
|
state.pendingStreams.forEach((stream) => stream.destroy(cancel)); |
|
state.streams.forEach((stream) => stream.destroy(error)); |
I thought that http2stream got RST_STREAM means that there is no error about processing data. So, I thought if http2stream is closed by RST_STREAM, connection error should not cause http2stream error.
The codes to reproduce.
'use strict';
const common = require('../common');
const fixtures = require('../common/fixtures');
const http2 = require('http2');
const fs = require('fs');
const net = require('net');
const tmpdir = require('../common/tmpdir');
tmpdir.refresh();
const loc = fixtures.path('person-large.jpg');
const server = http2.createServer();
let session_;
server.on('session', (session)=>{
session_ = session;
});
server.on('stream', common.mustCall((stream) => {
let sum = 0;
stream.pause();
const slowRead = ()=>{
setTimeout(()=>{
const data = stream.read(stream._readableState.highWaterMark/10);
sum += data ? data.length: 0;
console.log('read:' + sum + ' soc:' + socket.bytesWritten + ' closed:' + stream.closed + ' destroyed:' + stream.destroyed);
if(stream.closed){ // Got RST_STREAM and stream was closed but all data isn't processed.
socket.destroy(); // destroy connection without goaway frame.
try{
session_.ping(()=>{}); // activate read.
}catch(err){
console.log(err);
}
}
slowRead();
}, 10)
};
slowRead();
stream.respond();
stream.end();
stream.on('error', (err)=>{
// Stream allready closed, but error event happens.
console.log(err);
});
}));
let socket;
server.listen(0, common.mustCall(() => {
const options = {
createConnection: (authority, options) => {
socket = net.connect(server.address().port, 'localhost');
return socket;
}
}
const client = http2.connect(`http://localhost:${server.address().port}`, options);
const req = client.request({ ':method': 'POST' });
req.on('response', common.mustCall());
req.resume();
const str = fs.createReadStream(loc);
str.on('end', common.mustCall());
str.pipe(req);
}));
The following conditions cause an error event on
http2stream, even thoughhttp2streamreceived all data and RST_STREAM from a client.http2streamis not destroyed(does not consume all data)http2streamreceived all data and RST_STREAMSocket error without goaway frame causes a
http2session.destroy(err).node/lib/internal/http2/core.js
Lines 2678 to 2688 in 81bc7b3
http2session.destroy(err)propagate error tohttp2stream.destroy(err).node/lib/internal/http2/core.js
Lines 1298 to 1323 in 81bc7b3
I thought that
http2streamgot RST_STREAM means that there is no error about processing data. So, I thought ifhttp2streamis closed by RST_STREAM, connection error should not causehttp2streamerror.The codes to reproduce.