Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

http2: respondWithFile() does not set headersSent to true #18862

Closed
trivikr opened this issue Feb 19, 2018 · 14 comments
Closed

http2: respondWithFile() does not set headersSent to true #18862

trivikr opened this issue Feb 19, 2018 · 14 comments
Labels
http2 Issues or PRs related to the http2 subsystem. invalid Issues and PRs that are invalid.

Comments

@trivikr
Copy link
Member

trivikr commented Feb 19, 2018

  • Version: v10.0.0-pre
  • Platform: N/A
  • Subsystem: http2

I came across this issue while writing unit tests for stream.respond() in PR #18861
The method respondWithFile() does not set state.flags, thus headersSent is still set to false:

respondWithFile(path, headers, options) {
if (this.destroyed || this.closed)
throw new errors.Error('ERR_HTTP2_INVALID_STREAM');
if (this.headersSent)
throw new errors.Error('ERR_HTTP2_HEADERS_SENT');
assertIsObject(options, 'options');
options = Object.assign({}, options);
if (options.offset !== undefined && typeof options.offset !== 'number')
throw new errors.TypeError('ERR_INVALID_OPT_VALUE',
'offset',
options.offset);
if (options.length !== undefined && typeof options.length !== 'number')
throw new errors.TypeError('ERR_INVALID_OPT_VALUE',
'length',
options.length);
if (options.statCheck !== undefined &&
typeof options.statCheck !== 'function') {
throw new errors.TypeError('ERR_INVALID_OPT_VALUE',
'statCheck',
options.statCheck);
}
let streamOptions = 0;
if (options.getTrailers !== undefined) {
if (typeof options.getTrailers !== 'function') {
throw new errors.TypeError('ERR_INVALID_OPT_VALUE',
'getTrailers',
options.getTrailers);
}
streamOptions |= STREAM_OPTION_GET_TRAILERS;
this[kState].getTrailers = options.getTrailers;
}
const session = this[kSession];
debug(`Http2Stream ${this[kID]} [Http2Session ` +
`${sessionName(session[kType])}]: initiating response`);
this[kUpdateTimer]();
headers = processHeaders(headers);
const statusCode = headers[HTTP2_HEADER_STATUS] |= 0;
// Payload/DATA frames are not permitted in these cases
if (statusCode === HTTP_STATUS_NO_CONTENT ||
statusCode === HTTP_STATUS_RESET_CONTENT ||
statusCode === HTTP_STATUS_NOT_MODIFIED) {
throw new errors.Error('ERR_HTTP2_PAYLOAD_FORBIDDEN', statusCode);
}
fs.open(path, 'r',
afterOpen.bind(this, session, options, headers, streamOptions));
}

This looks like a bug as both respond() and respondWithFD() set state.flags so that headersSent is set to true.

@hiroppy hiroppy added the http2 Issues or PRs related to the http2 subsystem. label Feb 19, 2018
@antoine-amara
Copy link
Contributor

If it's ok, I want to try to fix this issue, I reproduce the bug on my machine. It will be my first code contribution here after few contributions on documentation. But I think I can find it.

@trivikr
Copy link
Member Author

trivikr commented Feb 20, 2018

Sure @antoine-amara, I know the locations of the fixes, can guide you on how to fix it and which tests to update.
I'm waiting for response from HTTP2 team to find out whether this is actually a bug.

@antoine-amara
Copy link
Contributor

Ok thanks, I remain available to code a fix.

@joyeecheung
Copy link
Member

cc @nodejs/http2

@mcollina
Copy link
Member

This is indeed a bug. @antoine-amara Would you be able to send a PR?

@antoine-amara
Copy link
Contributor

Yes, I find the function to update, I write the code, tests and I will made a PR as soon as possible. Thanks 👍

@antoine-amara
Copy link
Contributor

Hello @trivikr @mcollina , I've got a fix but I don't know in which file I have to put my tests.

Can I post a PR and push the test later ?

@mcollina
Copy link
Member

@antoine-amara I think you can add an assertion to test/parallel/test-http2-respond-file.js.

antoine-amara added a commit to antoine-amara/node that referenced this issue Mar 1, 2018
When using respondWithFile or respondWithFD the headersSent flags was
never set to true. Fix it to set state.flags to
STREAM_FLAGS_HEADERS_SENT after processing headers into these methods.

Fixes: nodejs#18862
@antoine-amara
Copy link
Contributor

Hello @trivikr @mcollina , I complete tests but my modifications break test-http2-respond-file-304 and I don't find how to fix it. my branch is here. I can make a PR if is needed.

@mcollina
Copy link
Member

mcollina commented Mar 1, 2018

@antoine-amara open a PR and we will take a look!

@apapirovski
Copy link
Member

respondWithFile has to call multiple different async methods, unlike respondWithFD, which means that checking for headersSent in a sync manner is not possible. I do not see a bug here.

@mcollina
Copy link
Member

mcollina commented Mar 2, 2018

@apapirovski you are right! down the road respondWithFile will call processRespondWithFD https://github.com/nodejs/node/blob/master/lib/internal/http2/core.js#L1907 which in turn will flip the headerSent state.

Very likely #19070 can be closed then. I'm sorry @antoine-amara.

@antoine-amara
Copy link
Contributor

That's ok , I'm junior and I'm a beginner into the open source world. That's a good experience for me.

@apapirovski
Copy link
Member

This was resolved.

@apapirovski apapirovski added the invalid Issues and PRs that are invalid. label Apr 13, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
http2 Issues or PRs related to the http2 subsystem. invalid Issues and PRs that are invalid.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants