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