【问题标题】:Catch superagent request error before piping在管道之前捕获超级代理请求错误
【发布时间】:2018-02-01 00:59:51
【问题描述】:

我正在尝试将文件从服务 A 通过服务 B 传输到我的 Postman 客户端。服务 A 构建一个交付 CSV 文件,服务 B (nodejs) 必须通过管道传输到我的客户端。

经过大量研究,我成功地将文件传输到服务 B,然后传输到 Postman。现在我想处理丑陋的情况:如果请求令牌无效怎么办?如果找不到文件怎么办?

到目前为止,我发现零个文档或示例说明如何在使用 superagent 传递请求时成功处理错误。

这是我目前所拥有的

router.post("/csv", (req, res) => {
  download_csv(req.get("Authorization"), req.body.ids)
  .then((response) => {
    res.sendFile(path.resolve(response));
  })
  .catch((err) => {
    res.status(error.status).json(error.response.body);
  })   
});

function download_csv(token, ids) {
  const stream = fs.createWriteStream("filters.csv")
  let request = agent
    .post(`${profiles}/api/documents/csv`)
    .set("authorization", token)
    .send({
      ids: ids,
      action: DOWNLOAD_CSV_PROFILES
    })

  request.on("response", res => {
    // Maybe I can use abort to handle this thing, but can't figure out how!
    // if (res.status !== 200) request.abort()
    console.log(res.status)
  })

  request.on("abort", () => {
    console.log("aborted")
    return new Promise((resolve, reject) => {
      resolve("request aborted")
    })
  })

  request.pipe(stream)
  return streamToPromise(stream);
}

function streamToPromise(stream) {
  return new Promise((resolve, reject) => {
    stream.on("error", (err) => {
      console.log("error in error")
    })
    stream.on("finish", () => {
      console.log("File saved")
      resolve(stream.path);
    });
  });
}

此代码正确处理文件的创建。当我伪造令牌或拼错授权标头时,我会得到正确的 401 响应,但无论如何都会写入一个文件,其内容是身份验证错误。

无论如何都可以给我一个提示:

  • 真正捕获和管理失败时的请求
  • 在这种情况下,如何通过返回 express 上下文并仅返回失败的 express 请求来逃避管道?

非常感谢!

【问题讨论】:

    标签: node.js express pipeline superagent


    【解决方案1】:

    如果我理解正确,只需在 on('response') 中创建 fs 写入流并对结果进行小修复。

    function download_csv(token, ids) {
        return new Promise((resolve, reject) => {
          let request = agent
            .post(`${profiles}/api/documents/csv`)
            .set("authorization", token)
            .send({
              ids: ids,
              action: DOWNLOAD_CSV_PROFILES
            })
    
          request.on("response", res => {
            // Maybe I can use abort to handle this thing, but can't figure out how!
            if (res.status === 200) {
                res
                  .on("end", resolve)
                  .pipe(fs.createWriteStream("filters.csv"));
            } else {
              reject();
            }
          })
    
          request.on("abort", reject);
    
      });
    }
    

    我不确定您使用的“请求”是什么 - 但假设它实际上是请求 npm 模块会有所帮助。

    理想情况下,将文件上传到临时目录并在 promise 解决时将其移动,在拒绝时删除。这样就可以解决部分下载的问题。

    如果您想进行任何即时转换,请查看我的“scramjet”。有了 Promise,一切都会变得更简单。

    【讨论】:

    • 请求来自超级代理库。谢谢你的建议,我试试看!
    • 试了之后,我不认为它可以捕获套接字挂断错误(ECONNRESET)。
    • @Andy 你应该能够以某种方式访问​​底层套接字,除了如果库被合理地编写,还应该有 request.on("error") 事件来观看......
    • 我尝试使用request.on('error'),但它似乎不起作用。我遇到了非常令人困惑的行为,即 Node 在没有任何错误消息的情况下崩溃,即使我添加了未捕获的错误/拒绝处理程序......我只在使用 request.then 时看到了 ECONNRESET,而同一 URL 上没有流。
    • res.on('error', reject) in request.on("response", ...) 怎么样?
    猜你喜欢
    • 2018-08-05
    • 1970-01-01
    • 2013-12-10
    • 2010-12-05
    • 2012-07-21
    • 2012-07-04
    • 1970-01-01
    • 2021-07-03
    相关资源
    最近更新 更多