Koa的`ctx.status`没有被发送到客户端
这是我的简单路线:
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; });
这里是我的客户代码:
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? } }
一切正常,当我发送一个适当的文件名,但为什么响应状态代码总是404
即使我在我的服务器代码中设置为500
错误? 可能是因为我的代码到达ctx.response.body = ...
时发送的响应已经完成了,在这种情况下.on('error')
的代码没有做任何事情吗?
任何帮助,将不胜感激。
查看Koa代码 ,它对ENOENT
(这是文件不存在时引发的错误)具有特定的处理:
// ENOENT support if ('ENOENT' == err.code) err.status = 404;
从我所看到的,你不能改变Koa将发回的状态码(公平地说,发送404不存在的文件是合理的)。
然而,有一个很快的黑客:因为Koa显式地检查匹配ENOENT
err.code
,如果你改变了这个代码,你可以诱骗Koa返回另一个状态码:
file.on('error', err => { err.code = 'ENOEXIST'; // a made-up code err.status = 500; });
或者,您可以先检查(使用fs.exists()
, fs.access()
或fs.stat()
)在创build读取stream之前查看文件是否存在。
我想你需要尝试这样的事情:
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; }); });