Here is my simple route:
router.post('/getFile', async (ctx) => {
const fileName = `${ctx.request.body.file}.pdf`;
const file = fs.createReadStream(fileName); // This file might not exist.
file.on('error', (err) => {
ctx.response.status = 500; // This status code doesn't make it to client when there's an error.
});
ctx.response.type = 'application/pdf';
ctx.response.body = file;
});
And here is my client code:
async function main() {
const request = {
method: 'POST',
body: JSON.stringify({ file: 'bad-file-name' }),
headers: {
'Content-Type': 'application/json',
'Accept': 'application/pdf'
}
};
const response = await fetch('/getFile', request);
if (!response.ok) {
console.log(response.status); // This is always 404 when I give a bad file name, even though I set it to 500 above. Why?
}
}
Everything is fine when I send a proper file name, but why is the response status code always 404 even though I set it to 500 in my server code during error? Could it be that the response is already finished sending by the time my code reaches ctx.response.body = ... in which case the code in the .on('error') isn't doing anything?
Any help would be appreciated.
I think you need try something like this:
router.post('/getFile', async (ctx) => {
const fileName = `${ctx.request.body.file}.pdf`;
const file = fs.createReadStream(fileName); // This file might not exist.
file.on('error', (err) => {
ctx.response.status = 500; // This status code doesn't make it to client when there's an error.
});
file.on('close', () => {
ctx.response.type = 'application/pdf';
ctx.response.body = file;
});
});
Looking at the Koa code, it has specific handling for ENOENT (which is the error that gets thrown when a file doesn't exist):
// ENOENT support
if ('ENOENT' == err.code) err.status = 404;
From what I can see, you can't change which status code Koa will send back (and, to be fair, sending back a 404 for non-existent files does make sense).
However, there's a quick hack: because Koa explicitly checks for err.code matching ENOENT, if you change that code, you can trick Koa into returning another status code:
file.on('error', err => {
err.code = 'ENOEXIST'; // a made-up code
err.status = 500;
});
Alternatively, you can first check (using fs.exists(), fs.access() or fs.stat()) to see if the file exists before creating the read stream.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With