镜像站点 · 本页由第三方 GitHub 只读镜像提供,非 GitHub 官方站点,不接受任何登录或凭据输入。前往 github.com
Skip to content

HTTP2: Calling res.end after res.writeHead(204) cause an error #21740

Description

@RidgeA
  • Version: v10.6.0
  • Platform: Linux localhost.localdomain 4.17.3-200.fc28.x86_64 deps: update openssl to 1.0.1j #1 SMP Tue Jun 26 14:17:07 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux (Fedora 28)
  • Subsystem: http2

Hi!

I'm playing around with http2 module and server push and faced with a strange error.

Invoking of res.end() method after res.writeHeader(204) causes error:

internal/http2/compat.js:377
  this.sendTrailers(this[kResponse][kTrailers]);
                                   ^

TypeError: Cannot read property 'Symbol(trailers)' of undefined
    at ServerHttp2Stream.onStreamTrailersReady (internal/http2/compat.js:377:36)
    at ServerHttp2Stream.emit (events.js:182:13)
    at Http2Stream.onStreamTrailers [as ontrailers] (internal/http2/core.js:311:15)

Code to reproduce:

"use strict";

const http2 = require('http2');
const fs = require('fs');
const cert = {
  key: fs.readFileSync('./cert/key.pem'),
  cert: fs.readFileSync('./cert/cert.pem')
};
const html =
`
<!doctype html>
<head>
    <title>HTTP/2 Test</title>
    <link rel="stylesheet" href="/styles.css" type="text/css">
    <script src="/bundle.js" async></script>
</head>
<body>
<h1>Hello</h1>
</body>
</html>
`;

http2.createSecureServer(cert, (req, res) => {

  const {url} = req;

  if (['/index.html', '/'].includes(url)) {
    res.writeHead(200, {'content-type':'text/html'});
    res.end(html);
  } else {
    res.writeHead(204);
    res.end();
  }

}).listen(8443, err => {
  if (!err) {
    console.log(`Server started at ${8443}.`)
  }
});

After digging into the issue, I found out that if we set 204, 205 and 304 status codes the stream are closed automatically - see https://github.com/nodejs/node/blob/master/lib/internal/http2/core.js#L2266 and https://github.com/nodejs/node/blob/master/lib/internal/http2/core.js#L2281

Calling of req.end method after that causes an error (see above).

According to the documentation req.end() MUST be called for each request: https://nodejs.org/api/http2.html#http2_response_end_data_encoding_callback
but it is impossible due to closing the stream caused by calling writeHeader method.

I believe, in order to keep backward compatibility with http/https modules, the res.end method shouldn't throw an error in such case.

Activity

  1. changed the title [-]Http2: Calling `res.end` after `res.writeHead(204)` cause an error.[/-] [+]HTTP2: Calling `res.end` after `res.writeHead(204)` cause an error.[/+] on Jul 10, 2018
  2. changed the title [-]HTTP2: Calling `res.end` after `res.writeHead(204)` cause an error.[/-] [+]HTTP2: Calling `res.end` after `res.writeHead(204)` cause an error[/+] on Jul 10, 2018
  3. added
    http2Issues and PRs related to the http2 subsystem.
    on Jul 10, 2018
  4. addaleax commented on Jul 10, 2018

    @addaleax
    Member

    @nodejs/http2

  5. RidgeA commented on Jul 11, 2018

    @RidgeA
    ContributorAuthor

    PR to fix this issue - #21764

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    http2Issues and PRs related to the http2 subsystem.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions