【问题标题】:HTTP/2 compatibility API, how to handle itHTTP/2 兼容 API,如何处理
【发布时间】:2022-01-16 14:21:09
【问题描述】:

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

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

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 文档很糟糕......似乎他们的每一点文档都必须以悬念结束......

【问题讨论】:

    标签: node.js https http2 alpn


    【解决方案1】:

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

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

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

    • 对于 HTTP/1x 请求,只会调用兼容性请求处理程序
    • 对于 HTTP/2 请求,both 兼容性和 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 的其他人有用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-05-12
      • 2020-11-21
      • 2020-11-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多