0

虽然最初我决定创建一个仅 HTTP/2 的服务器,但我发现兼容性 API 是一个不错的选择,可以支持不支持或不支持 HTTP/2 的客户端(fetchreact-native?)。

但是,我很难理解如何处理 HTTP/1x 处理程序上的传入请求,即报告req.httpVersion === "2.0"ALPN negotiation section以下代码是文档中的摘录nodejs

function onRequest(req, res) {
  // Detects if it is a HTTPS request or HTTP/2
  const { socket: { alpnProtocol } } = req.httpVersion === '2.0' ?
    req.stream.session : req;

  // HERE: OK, say we have  req.httpVersion === '2.0'
  // Now, what?

  res.writeHead(200, { 'content-type': 'application/json' });
  res.end(JSON.stringify({
    alpnProtocol,
    httpVersion: req.httpVersion
  }));
}

首先,我不明白上面的代码应该做什么。就像,我知道它做了什么,但它没有什么特别的——似乎只是通用的 HTTP/1x 请求处理程序,它发送一些 JSON,仅此而已。我错过了什么吗?

除此之外:

  • 一旦 HTTP/1x 处理程序报告req.httpVersion = "2.0",我该怎么办?
    它也会由 HTTP/2 处理程序 ( server.on("stream", ()=>{ ... })) 处理,所以我应该在 HTTP/1x 处理程序中忽略它吗?
  • 如果它不会由 HTTP/2 处理程序自动处理,我可以而且应该手动将请求转发给 HTTP/2 处理程序吗?
function http2handler(stream, headers){ ... }

function http1xhandler(req, res) {
  if (req.httpVersion === "2.0") {
    // handle as HTTP/2
    return http2handler(req.stream, req.headers);
  }

  // handle as HTTP/1x ...
}

const server = createSecureServer(
  { cert, key, allowHTTP1: true },
  http1xhandler
).listen(4443);

server.on("stream", http2handler);
  • 如果以上都不是,示例中的响应 JSON 是否在向客户端指示它应该切换到 HTTP/2 方面发挥作用?如果是这样,客户究竟应该怎么做?

抱歉,如果这可能是一个愚蠢的问题,nodejs 文档很糟糕......似乎他们的每一点文档都必须以悬念结束......

4

1 回答 1

0

在摆弄了一些代码并阅读了更多的文章和答案之后,我想我终于明白了发生了什么。但是,如果我在这里说的任何内容有误,我将不胜感激。

HTTP/2 兼容性 API 为HTTP/1x 和 HTTP/2 请求提供了一个通用的请求处理程序。如ALPN 协商文档所示,开发人员应限制对公共 HTTP/1x API 的响应 - 直到识别出 HTTP/2 请求。您可以检查req.httpVersion以识别这些,并根据需要分支您的代码。

如果您同时指定兼容性请求处理程序(回调函数 on createSecureServer)和on("stream", ...)事件处理程序(仅限 HTTP/2),则服务器行为是:

  • 对于 HTTP/1x 请求,只会调用兼容性请求处理程序
  • 对于 HTTP/2 请求,兼容性和请求处理程序on("stream", ...)将被调用 -但只有一个处理程序应该响应请求。如果您尝试响应来自两个处理程序的请求,您将获得:
    Error [ERR_HTTP2_HEADERS_SENT]: Response has already been initiated.

我选择处理这些的方式是创建独立HTTP/1xHTTP/2处理程序,每个处理自己的蛋糕。兼容性处理程序应忽略 HTTP/2 请求。在代码中:

function http1xhandler(req, res) {
  if (req.httpVersion === "2.0") {
    // Ignore HTTP/2 requests, will be handled by the on("stream", ...) event handler
    // Or, you can answer the HTTP/2 request here, using HTTP/2 features as well
    return;
  }

  // Handle HTTP/1x request
  res.writeHead(200, { 'content-type': 'text/plain' });
  res.end("Hello HTTP/1x!");
}

const server = createSecureServer(
  { cert, key, allowHTTP1: true },
  http1xhandler
).listen(4443);

// Do not use the following if you are handling
// HTTP/2 in the HTTP/1x compatibility callback

function http2handler(stream, headers){
  stream.respond({
      'content-type': 'text/plain; charset=utf-8',
      ':status': 200
    });
  stream.end("Hello HTTP/2!");
}

server.on("stream", http2handler);

希望这对研究这些 API 的其他人有用。

于 2021-12-13T14:05:17.747 回答