仅当在Node.js中发送响应时没有错误时才设置缓存头

时间:2019-06-14 06:48:43

标签: node.js http http-caching

我基本上是在这样做:

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')
    })
})
  • 出现错误时,我只返回一个空图像。但是在这种情况下,我不想设置缓存头,因为我不想缓存空白图像。
  • 因此,我尝试在发送响应后设置缓存头,但它们不会通过。
  • 如果在传递响应之前设置了缓存头,则在发生错误的情况下会缓存错误。

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

1 个答案:

答案 0 :(得分:1)

您无法按照自己尝试的方式去做。 http响应的顺序是发送http标头,然后开始发送响应正文。因此,如果您正在传递响应正文(就像您一样),则必须先发送标头。您无法开始发送响应正文,然后改变主意。他们已经发送了。

而且,在http库已经开始发送响应正文之后,您将无法发送标头。开始发送响应正文会写出与此响应一起的http标头的当前存储状态,然后开始编写响应。

据我所知,处理在发送http响应正文过程中发生的错误的唯一方法是过早关闭http连接。客户端将看到套接字关闭而看不到http响应的结尾,并且将了解到它收到了终止的未完成的响应。此时,您没有机会发送其他回复。该情况下的错误处理将需要在客户端进行,以便确定该怎么做。

另一种选择是在发送任何内容之前预取要发送给客户端的所有数据。这使您有最大的机会在开始发送http响应之前确定是否有任何原因会导致错误,然后您可以根据响应条件调整整个响应。如果您要这样做,显然您不能使用.pipe(res)之类的东西。取而代之的是,您必须将整个响应加载到内存中(或者如果要分批发送,则至少要加载一部分响应),并且只有在成功地对它进行了预检查和加载并准备好执行时,您开始发送响应。

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