仅当在 Node.js 中发送响应没有错误时,如何设置缓存 headers

How to set cache headers only if there isn't an error in sending the response in Node.js

我基本上是这样做的:

app.get('/:id.:ext', (req, res) => {
  const remote = bucket.file(`images/${req.params.id}.${req.params.ext}`)
  // if (isProd)
  //   res.set('Cache-Control', 'public, max-age=604800')
  remote.createReadStream({ validation: false })
    .on('error', error => {
      console.log(error)
      res.send(`data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7`)
    })
    .pipe(res)
    .on('end', () => {
      res.set('Cache-Control', 'public, max-age=86400')
    })
})

想知道如何解决这个问题。

你不能按照你想做的方式做你想做的事。 http 响应的顺序是发送 http headers,然后开始发送响应 body。因此,如果您要发送响应 body(就像您一样),您必须先发送 headers。您不能先发送响应 body,然后再改变主意 headers。他们已经被发送了。

并且,在 http 库已经开始发送响应 body 之后,您无法发送 headers。开始发送响应 body 写出与此响应一起使用的 http headers 当前存储的状态,然后开始写入响应。

据我所知,处理在发送 http 响应 body 过程中发生的错误的唯一方法是过早地关闭 http 连接。客户端将在没有看到 http 响应结束的情况下看到套接字关闭,并且将理解它得到了一个终止的、未完成的响应。此时您没有机会发送另一个回复。这种情况下的错误处理需要 client-side 才能决定要做什么。

另一种选择是在发送任何内容之前预取要发送给客户端的所有数据。这使您有最大的机会在开始发送 http 响应之前确定是否有任何内容会导致错误,然后您可以制作整个响应以匹配您的错误条件。如果你要这样做,你显然不能使用 .pipe(res) 之类的东西。相反,您必须将整个响应加载到内存中(或者至少是响应的一部分,如果您要分块发送)并且只有在成功 pre-flighted 并加载并准备好时开始发送回复了吗。

此外,另一种避免缓存错误图像的方法是对错误图像 URL 执行 301(临时重定向)而不是 return 将其作为对原始请求的响应。然后,当浏览器加载重定向 URL 并获取图像时,它不会将其缓存为原始 URL.