【问题标题】:Ways of failing http request after 200 response header sent发送 200 响应标头后 http 请求失败的方法
【发布时间】:2019-06-28 07:56:35
【问题描述】:

简而言之:

考虑一个长期响应的情况,当有大量数据要发送时。然后服务器需要在完成所有数据的生成之前将数据传回给客户端。如果我是对的,这需要在一开始就发送 http 标头。但是,如果在流式传输数据期间出现异常,将其传达给客户端的最佳方式是什么?理想情况下,我希望浏览器中的XMLHttpRequest 因非 200 响应代码或类似代码而失败。我在服务器上使用 nodejs express。

详细问题:

我需要将大量数据流式传输到浏览器中,大约 700Mb。我需要在生成数据时将数据流式传输到客户端,而不是在服务器上缓冲它,否则服务器将耗尽内存。

这是我在浏览器端使用的代码。

return new Promise((resolve, reject) => {
  const xhr = new XMLHttpRequest();
  xhr.open('GET', this.getDownloadLink(), true);
  xhr.setRequestHeader('authorization', this.getAuthToken());
  xhr.responseType = 'blob';
  xhr.onload = () => {
    if (xhr.status === 200) {
      saveAsFile(xhr.response);
      resolve();
    }
    else {
      reject(xhr.response);
    }
  };
  xhr.onerror = () => {
    reject(xhr.response);
  };
  xhr.send();
});

我使用 XHR 是因为我需要设置授权标头。浏览器可以在保存文件之前保留 700Mb,可能是因为它将 blob 存储在磁盘上,这不是阻止程序。

所以我开始传输,不知道它会以成功结束。那么如果数据生成在中间失败,我如何从服务器向客户端传达错误? 我希望在服务器出现故障时拒绝上述承诺。

这是我在服务器上使用的部分代码:

response.status(200);
db.stream
.on('data', data => response.write())
.on('error', error => {
  // this does not work as intended
  response.status(500);
  response.end(error.message);
})

如您所见,它在发送标头后对数据进行管道传输。

【问题讨论】:

    标签: node.js http express websocket xmlhttprequest


    【解决方案1】:

    有一种在响应结束时发送“标头”的方法。他们被称为Trailers

    您可以使用 nodejs Response object 发送它们。

    【讨论】:

      【解决方案2】:

      标头已发送,仅此而已,没有转折点。客户端不会一次收到整个 700mb 的 http 响应,它会一块一块地接收。如果我们以明文形式读取 http 响应,则它的第一部分将是元数据(状态等)和逐行的标题。这就是为什么在你已经发送了 200 之后无法发送 500 状态的原因。不是因为 Node.js 或 express 不允许,而是因为 http 作为通信协议不允许它。 我可以看到您正在使用 http 来传输这么多数据,因为您的业务逻辑需要一个标头。我建议你看看 socket.io。它允许您从查询字符串中获取一些有用的信息/数据,您可以将您正在使用标头的数据作为查询参数放在其中,并通过 socket.io 节点 api 访问它!执行任何身份验证或相关内容非常方便。 希望对你有所帮助!

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-07-18
        • 2019-05-09
        • 2014-12-18
        • 2017-08-25
        • 1970-01-01
        • 1970-01-01
        • 2011-10-19
        • 1970-01-01
        相关资源
        最近更新 更多