【问题标题】:Koa's `ctx.status` not getting sent to clientKoa 的`ctx.status` 没有被发送到客户端
【发布时间】:2017-10-17 17:58:14
【问题描述】:

这是我的简单路线:

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') 中的代码没有做任何事情?

任何帮助将不胜感激。

【问题讨论】:

    标签: javascript node.js http fetch koa


    【解决方案1】:

    我认为你需要尝试这样的事情:

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

    【讨论】:

      【解决方案2】:

      查看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())以查看文件是否存在。

      【讨论】:

      • 哦,糟糕,我认为接受答案会给你带来赏金。现在给你。
      猜你喜欢
      • 2018-01-30
      • 2021-06-04
      • 1970-01-01
      • 2017-08-17
      • 2013-03-14
      • 2016-01-09
      • 1970-01-01
      • 2011-08-15
      • 1970-01-01
      相关资源
      最近更新 更多