I am doing this essentially:
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')
})
})
Wondering how to get around this.
You can't do what you're trying to do the way you're trying to do it. The sequence of an http response is to send the http headers, then start sending the respond body. So if you're piping a response body (like you are), you HAVE to send the headers first. You can't start sending the response body, then changing your mind about the headers. They've already been sent.
And, you can't send headers after the http library has already starting sending the respond body. Starting to send the response body writes out the currently stored state of the http headers that go with this response and then starts writing the response.
As best I know, the only way to deal with an error that occurs in the middle of sending the http response body is to close the http connection prematurely. The client will see the socket close without seeing the end of the http response and will understand that it got a terminated, unfinished response. You don't get a chance to send another response at that point. Error handling for that case will need to be client-side in order to decide what to do.
Another option is to prefetch all the data you want to send to the client BEFORE you send anything. This allows you the most chances to determine if anything is going to cause an error before you've started sending the http response and then you can craft the entire response to match your error condition. You obviously can't use something like .pipe(res)
if you're going to do that. Instead, you've have to load the entire response into memory (or at least a chunk of the response if you're going to send it in chunks) and only when that has been successfully pre-flighted and loaded and ready to go do you start sending the response.
Also, another way to avoid getting an error image cached is to do a 301 (temporary redirect) to the error image URL rather than return it as the response to the original request. Then, when the browser loads that redirected URL and gets the image, it will not cache it as the original URL.