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; }); });