Koa 的 `ctx.status` 没有发送给客户端
Koa's `ctx.status` not getting sent to client
这是我的简单路线:
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')
中的代码什么也没做?
如有任何帮助,我们将不胜感激。
查看at the Koa code,它对ENOENT
有特定的处理(这是当文件不存在时抛出的错误):
// ENOENT support
if ('ENOENT' == err.code) err.status = 404;
据我所知,您无法更改 Koa 将发回的状态码(而且,公平地说,对于不存在的文件发回 404 确实有道理)。
但是,有一个快速破解方法:因为 Koa 显式检查 err.code
匹配 ENOENT
,如果您更改该代码,您可以欺骗 Koa 返回另一个状态代码:
file.on('error', err => {
err.code = 'ENOEXIST'; // a made-up code
err.status = 500;
});
或者,您可以先检查(使用 fs.exists()
、fs.access()
或 fs.stat()
)以查看文件是否存在,然后再创建读取流。
我认为你需要尝试这样的事情:
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;
});
});
这是我的简单路线:
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')
中的代码什么也没做?
如有任何帮助,我们将不胜感激。
查看at the Koa code,它对ENOENT
有特定的处理(这是当文件不存在时抛出的错误):
// ENOENT support
if ('ENOENT' == err.code) err.status = 404;
据我所知,您无法更改 Koa 将发回的状态码(而且,公平地说,对于不存在的文件发回 404 确实有道理)。
但是,有一个快速破解方法:因为 Koa 显式检查 err.code
匹配 ENOENT
,如果您更改该代码,您可以欺骗 Koa 返回另一个状态代码:
file.on('error', err => {
err.code = 'ENOEXIST'; // a made-up code
err.status = 500;
});
或者,您可以先检查(使用 fs.exists()
、fs.access()
或 fs.stat()
)以查看文件是否存在,然后再创建读取流。
我认为你需要尝试这样的事情:
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;
});
});