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

http: don't write error to socket #34465

Closed
wants to merge 5 commits into from

Conversation

ronag
Copy link
Member

@ronag ronag commented Jul 21, 2020

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.

Checklist
  • make -j4 test (UNIX), or vcbuild test (Windows) passes
  • tests and/or benchmarks are included
  • documentation is changed or added
  • commit message follows commit guidelines

@ronag ronag added the http Issues or PRs related to the http subsystem. label Jul 21, 2020
@ronag ronag requested review from jasnell and addaleax July 21, 2020 18:54
@ronag
Copy link
Member Author

ronag commented Jul 21, 2020

Maybe a bit too strict but figuring out whether it's actually safe to write to the socket or not is non trivial.

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.
@ronag ronag force-pushed the http-error-write branch from 81b3062 to 6657553 Compare July 21, 2020 18:56
Copy link
Member

@lpinca lpinca left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's best effort, I don't think we should change this.

@nodejs-github-bot
Copy link
Collaborator

@ronag
Copy link
Member Author

ronag commented Jul 21, 2020

It's best effort, I don't think we should change this.

Why? It can corrupt responses without the client being able to detect it?

@lpinca
Copy link
Member

lpinca commented Jul 21, 2020

What is the advantage in removing the response? It's a single chunk which is written in a single write with no other pending writes.

@ronag
Copy link
Member Author

ronag commented Jul 21, 2020

It's a single chunk which is written in a single write with no other pending writes.

I haven't followed the code fully but I believe e.g. bad response could be written after the http headers are written and be parsed as part of the http response body.

In the case of 'upgrade' (websocket) and 'connect' I'm not sure what actually happens.

@ronag
Copy link
Member Author

ronag commented Jul 21, 2020

@nodejs/http

@lpinca
Copy link
Member

lpinca commented Jul 21, 2020

On upgrade the parser is freed and the socketOnError listener removed. And if the client writes an invalid upgrade request a 400 response if expected.

@ronag
Copy link
Member Author

ronag commented Jul 21, 2020

On upgrade the parser is freed and the socketOnError listener removed. And if the client writes an invalid upgrade request a 400 response if expected.

Cool. That leaves the after headers are written scenario.

@dougwilson
Copy link
Member

I don't have specific opinion to add to this PR, but just wanted to link the original PR #15324 that added the first response writing if any of the conversation from that thread helps here.

@lpinca
Copy link
Member

lpinca commented Jul 21, 2020

Cool. That leaves the after headers are written scenario.

I do not remember any bug report opened for this scenario. Do you mean something like this?

  • Part of the response is written when the request is in progress.
  • The request triggers a 'clientError'.

@ronag
Copy link
Member Author

ronag commented Jul 21, 2020

Ok. Changed to only write if nothing else has been written to the socket.

@ronag
Copy link
Member Author

ronag commented Jul 21, 2020

Cool. That leaves the after headers are written scenario.

I do not remember any bug report opened for this scenario.

There is non as far as I know.

Do you mean something like this?

  • Part of the response is written when the request is in progress.
  • The request triggers a 'clientError'.

The socket emits 'error' at any point after the headers has been written and the body has not yet completed writing. Writes can still succeed after 'error' is emitted.

@lpinca
Copy link
Member

lpinca commented Jul 21, 2020

Looks better now.

@nodejs-github-bot
Copy link
Collaborator

@nodejs-github-bot
Copy link
Collaborator

Copy link
Member

@mcollina mcollina left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

@wa-Nadoo
Copy link

I think the 'clientError' event documentation should be updated too https://nodejs.org/api/http.html#http_event_clienterror

@ronag
Copy link
Member Author

ronag commented Jul 21, 2020

@wa-Nadoo PTAL

@ronag
Copy link
Member Author

ronag commented Jul 25, 2020

Landed in e8d7fed

@ronag ronag closed this Jul 25, 2020
ronag added a commit that referenced this pull request Jul 25, 2020
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 <luigipinca@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
@MylesBorins
Copy link
Contributor

This change is breaking a test on v14.x

=== release test-http-1.0 ===
Path: parallel/test-http-1.0
assert.js:103
  throw new AssertionError(obj);
  ^

AssertionError [ERR_ASSERTION]: Expected values to be strictly equal:
+ actual - expected

+ ''
- 'HTTP/1.1 200 OK\r\n' +
-   'Content-Type: text/plain\r\n' +
-   'Connection: close\r\n' +
-   'Transfer-Encoding: chunked\r\n' +
-   '\r\n' +
-   '7\r\n' +
-   'Hello, \r\n' +
-   '6\r\n' +
-   'world!\r\n' +
-   '0\r\n' +
-   '\r\n'
    at response_validator (/Users/mylesborins/code/node/v14.x/test/parallel/test-http-1.0.js:158:12)
    at Socket.<anonymous> (/Users/mylesborins/code/node/v14.x/test/parallel/test-http-1.0.js:54:7)
    at Socket.<anonymous> (/Users/mylesborins/code/node/v14.x/test/common/index.js:363:15)
    at Socket.emit (events.js:326:22)
    at endReadableNT (_stream_readable.js:1244:12)
    at processTicksAndRejections (internal/process/task_queues.js:80:21) {
  generatedMessage: true,
  code: 'ERR_ASSERTION',
  actual: '',
  expected: 'HTTP/1.1 200 OK\r\n' +
    'Content-Type: text/plain\r\n' +
    'Connection: close\r\n' +
    'Transfer-Encoding: chunked\r\n' +
    '\r\n' +
    '7\r\n' +
    'Hello, \r\n' +
    '6\r\n' +
    'world!\r\n' +
    '0\r\n' +
    '\r\n',
  operator: 'strictEqual'
}

Any idea what's going on? Should this be backported?

MylesBorins pushed a commit that referenced this pull request Jul 27, 2020
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 <luigipinca@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
@ruyadorno ruyadorno mentioned this pull request Jul 28, 2020
addaleax pushed a commit that referenced this pull request Sep 22, 2020
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 <luigipinca@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
addaleax pushed a commit that referenced this pull request Sep 22, 2020
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 <luigipinca@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
@codebytere codebytere mentioned this pull request Sep 28, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
http Issues or PRs related to the http subsystem.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants