【问题标题】:Send custom error message, with serverless-http (express)使用 serverless-http (express) 发送自定义错误消息
【发布时间】:2019-10-19 03:31:43
【问题描述】:

我需要从我的 express 应用程序中发送 JSON 格式的自定义错误消息,并使用 serverless-http 在 lambda 函数中提供服务

如果我弄错了,请纠正我,但据我了解,我们需要使用 LAMBA_PROXY APIG 集成才能发送直接从 lambda 函数定义的自定义错误消息。

这是我迄今为止尝试过的:

res.status(400).json({ message: 'email already taken' });

serverless.yml

functions:
  auth:
    handler: src/express/auth/index.handler
    name: ${self:service}-auth-${env:STAGE}
    # warmup: true
    integration: lambda-proxy
    memorySize: 128
    timeout: 15
    events:
        - http:
            path: /auth/
            method: ANY
            cors: true
        - http:
            path: /auth/{any+}
            method: ANY
            cors: true

这是 API 返回的内容(状态码为 400)

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <title>Error</title>
    </head>
    <body>
        <pre>Bad Request</pre>
    </body>
</html>

关于如何以 JSON 格式发送自定义响应的任何线索?

更新: 经过更多测试,我发现调用next(error) 并没有到达最后一个错误处理程序


const register = async (req, res, next) {
  try {
    await verifyEmail(req.body.email);
    const user = await Users.register(req.body);
    const token = sign(user.attrs, {});
    res.json({ token, user });
  } catch (e) {
    next(e);
  }
};

const generalError = async (err, req, res, next) => {
  // doesn't reach this part! :(
  console.log('generalError handler', JSON.stringify(err));
  res.status(errorOut.status).json(errorOut);
};

ApiRouter.post('/register', register);
app.use('/auth', ApiRouter);
app.use(generalError);

【问题讨论】:

    标签: express lambda aws-api-gateway serverless-framework serverless


    【解决方案1】:

    (我刚刚回答了一个非常相似的问题here

    是的,这在 Express 文档中的 Error Handling 下进行了解释。

    Express 带有一个内置的错误处理程序,可以处理应用程序中可能遇到的任何错误。这个默认的错误处理中间件函数被添加到中间件函数栈的末尾。

    如果您将错误传递给next(),并且您没有在自定义错误处理程序中处理它,它将由内置错误处理程序处理;错误将通过堆栈跟踪写入客户端。堆栈跟踪不包含在生产环境中。

    要覆盖此处理程序,请参阅 Express 文档中标题为 Writing error handlers 的部分。

    它解释了:

    以与其他中间件函数相同的方式定义错误处理中间件函数,除了错误处理函数有四个参数而不是三个:(err, req, res, next)。例如:

    app.use(function (err, req, res, next) {
      console.error(err.stack)
      res.status(500).send('Something broke!')
    })
    

    在其他 app.use() 和路由调用之后,您最后定义错误处理中间件

    所以在你的情况下,如果你想用 400 和一些 JSON 来响应,你可能会写这样的东西:

    const serverless = require('serverless-http');
    const express = require('express');
    const app = express();
    
    // Your middleware and other routes here
    app.use(/* register your middleware as normal */);
    
    // Finally, your custom error handler
    app.use(function customErrorHandler(err, req, res, next) {
       res.status(400).json({ message: 'email already taken' });
    });
    
    module.exports.handler = serverless(app);
    

    【讨论】:

    • 嘿@romellem,感谢您的回答!很抱歉没有发布更多细节,但我已经这样实现了。所以我有`ApiRouter.post('/register', Controller.register); app.use(/auth, ApiRouter); /* 错误处理 */ app.use(ErrorController.error404); app.use(ErrorController.generalError); ` 我刚刚发现它没有到达最后一个错误处理程序。我会更新问题
    • 我已经更新了这个问题。您可以在最下方查看更新
    • 听起来 Lambda 正在覆盖 Express 的一些默认功能。你必须做一些矿石研究。我发现了这个问题 - stackoverflow.com/a/46697547/864233 - 这可能会给你更多的线索。
    • 是的! lambda 有一些可疑之处,即没有调用后备中间件。也许在包装上,或其他东西上。我尝试了 NODE_ENV=production 和 development,结果相同。现在我很想直接从catch 块调用错误中间件!
    猜你喜欢
    • 2017-11-19
    • 1970-01-01
    • 1970-01-01
    • 2010-11-09
    • 2018-12-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-17
    相关资源
    最近更新 更多