使用 API 网关处理 AWS Lambda 错误
Handling AWS Lambda errors with API Gateway
我的 Lambda 函数中有 class BadRequest(Exception): pass
。
我想要 raise BadRequest("Invalid request params")
并让 API return 状态码为 400 和正文的响应 { "message": "Invalid request params" }
(或等效)。
只是这样做,但是 return 是一个状态代码为 200(哦不!)和正文的响应
{
"errorMessage": "Invalid request params",
"errorType": "BadRequest",
"stackTrace": <my application code that the user shouldnt see>
}
网上搜索了一下,好像有3种选择:
1) chalice
2) 使用集成响应和方法响应将该错误解析为更好的响应。我会像 [BadRequest].*
这样的正则表达式,并在抛出异常时插入一个前缀(IMO 不是很优雅)。
3) 使用 Step Functions 创建 API 的状态表示。这似乎有点乏味,因为我需要学习美国手语而且我不认识任何聋人。 -.-
我应该去哪个兔子洞,为什么?
您应该在 Lambda 中捕获异常并抛出自定义异常,如下所示。
public class LambdaFunctionHandler implements RequestHandler<String, String> {
@Override
public String handleRequest(String input, Context context) {
Map<String, Object> errorPayload = new HashMap();
errorPayload.put("errorType", "BadRequest");
errorPayload.put("httpStatus", 400);
errorPayload.put("requestId", context.getAwsRequestId());
errorPayload.put("message", "Invalid request params " + stackstace);
String message = new ObjectMapper().writeValueAsString(errorPayload);
throw new RuntimeException(message);
}
}
And then use Option 2 to map the error code .
Integration response:
Selection pattern: “.*"BadRequest".*”
Method response: 500
Mapping template:
#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))
{
"type" : "$errorMessageObj.errorType",
"message" : "$errorMessageObj.message",
"request-id" : "$errorMessageObj.requestId"
}
这是 AWS Step Functions 的完美用例。您需要设置 API 网关以直接调用您将创建的状态机。
这是上述状态机的 ASL:
{
"Comment": "A state machine that executes my lambda function and catches the bad error.",
"StartAt": "MyLambda",
"States": {
"MyLambda": {
"Type": "Task",
"Resource": "arn:aws:lambda:REGION:ACCOUNT_ID:function:FUNCTION_NAME",
"Catch": [
{
"ErrorEquals": ["BadError"],
"Next": "BadErrorFallback"
}
],
"End": true
},
"BadErrorFallback": {
"Type": "Pass",
"Result": "Put here whatever is the result that you want to return.",
"End": true
}
}
}
这将做的是 运行 您提供的 lambda 函数。如果 lambda 函数抛出 BadError,那么它将输出 BadErrorFallback 状态的结果。否则它将输出 lambda 函数输出的任何内容。
希望对您有所帮助!
Chalice 使用 Lambda 和 API 网关实现 REST APIs 非常简单,包括将引发的异常转换为响应。对于您的特定情况,您会引发这样的异常:
import chalice
app = chalice.Chalice(app_name='your-app')
app.debug = True # Includes stack trace in response. Set to False for production.
@app.route('/api', methods=['GET'])
def your_api():
raise chalice.BadRequestError("Your error message")
有一个 REST API 的完整工作示例,它使用带有 Lambda 的 Chalice 和 GitHub 上的 API 网关:aws-doc-sdk-examples。
3 年后我 return 回答这个问题来描述我今天如何解决这个问题。我使用 Serverless Framework 来部署我的 lambda 函数和一个 API 网关。
我使用了一个装饰器来捕获异常并且 return 是一个有效负载。比如这里是一个成功的请求,一个预期的异常,一个意外的异常。
def my_successful_request(event, context):
return {
"statusCode": 200,
"body": json.dumps({"success": True})
}
def handle_exceptions(f):
def deco(*args, **kwargs):
try:
return f(*args, **kwargs)
except BadRequest as e:
print(e)
return {"statusCode": 400, "body": json.dumps({"message": str(e)})}
except Exception as e:
print(e)
return {"statusCode": 500, "body": json.dumps({"message": "unexpected error"})}
return deco
@handle_exceptions
def my_expected_error_request(event, context):
raise BadRequest("This function raises a BadRequest with a 400 status code that should be sent to the user. The end user can read this text.")
@handle_exceptions
def my_unexpected_error_request(event, context):
raise Exception("Uh oh. I didn't expect this. A 500 error with an obfuscated message is raised. The end user cannot read this text.")
这种模式使得 API 到 return 适当的错误消息和 status code. I have very rudimentary logging in this handle_exceptions
implementation but you can get really detailed messages with f.__name__
to know what Lambda function erred and the traceback module 理解异常的来源变得非常容易。 API 用户完全隐藏了所有这些错误管理。
我的 Lambda 函数中有 class BadRequest(Exception): pass
。
我想要 raise BadRequest("Invalid request params")
并让 API return 状态码为 400 和正文的响应 { "message": "Invalid request params" }
(或等效)。
只是这样做,但是 return 是一个状态代码为 200(哦不!)和正文的响应
{
"errorMessage": "Invalid request params",
"errorType": "BadRequest",
"stackTrace": <my application code that the user shouldnt see>
}
网上搜索了一下,好像有3种选择:
1) chalice
2) 使用集成响应和方法响应将该错误解析为更好的响应。我会像 [BadRequest].*
这样的正则表达式,并在抛出异常时插入一个前缀(IMO 不是很优雅)。
3) 使用 Step Functions 创建 API 的状态表示。这似乎有点乏味,因为我需要学习美国手语而且我不认识任何聋人。 -.-
我应该去哪个兔子洞,为什么?
您应该在 Lambda 中捕获异常并抛出自定义异常,如下所示。
public class LambdaFunctionHandler implements RequestHandler<String, String> {
@Override
public String handleRequest(String input, Context context) {
Map<String, Object> errorPayload = new HashMap();
errorPayload.put("errorType", "BadRequest");
errorPayload.put("httpStatus", 400);
errorPayload.put("requestId", context.getAwsRequestId());
errorPayload.put("message", "Invalid request params " + stackstace);
String message = new ObjectMapper().writeValueAsString(errorPayload);
throw new RuntimeException(message);
}
}
And then use Option 2 to map the error code .
Integration response:
Selection pattern: “.*"BadRequest".*”
Method response: 500
Mapping template:
#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))
{
"type" : "$errorMessageObj.errorType",
"message" : "$errorMessageObj.message",
"request-id" : "$errorMessageObj.requestId"
}
这是 AWS Step Functions 的完美用例。您需要设置 API 网关以直接调用您将创建的状态机。
这是上述状态机的 ASL:
{
"Comment": "A state machine that executes my lambda function and catches the bad error.",
"StartAt": "MyLambda",
"States": {
"MyLambda": {
"Type": "Task",
"Resource": "arn:aws:lambda:REGION:ACCOUNT_ID:function:FUNCTION_NAME",
"Catch": [
{
"ErrorEquals": ["BadError"],
"Next": "BadErrorFallback"
}
],
"End": true
},
"BadErrorFallback": {
"Type": "Pass",
"Result": "Put here whatever is the result that you want to return.",
"End": true
}
}
}
这将做的是 运行 您提供的 lambda 函数。如果 lambda 函数抛出 BadError,那么它将输出 BadErrorFallback 状态的结果。否则它将输出 lambda 函数输出的任何内容。
希望对您有所帮助!
Chalice 使用 Lambda 和 API 网关实现 REST APIs 非常简单,包括将引发的异常转换为响应。对于您的特定情况,您会引发这样的异常:
import chalice
app = chalice.Chalice(app_name='your-app')
app.debug = True # Includes stack trace in response. Set to False for production.
@app.route('/api', methods=['GET'])
def your_api():
raise chalice.BadRequestError("Your error message")
有一个 REST API 的完整工作示例,它使用带有 Lambda 的 Chalice 和 GitHub 上的 API 网关:aws-doc-sdk-examples。
3 年后我 return 回答这个问题来描述我今天如何解决这个问题。我使用 Serverless Framework 来部署我的 lambda 函数和一个 API 网关。
我使用了一个装饰器来捕获异常并且 return 是一个有效负载。比如这里是一个成功的请求,一个预期的异常,一个意外的异常。
def my_successful_request(event, context):
return {
"statusCode": 200,
"body": json.dumps({"success": True})
}
def handle_exceptions(f):
def deco(*args, **kwargs):
try:
return f(*args, **kwargs)
except BadRequest as e:
print(e)
return {"statusCode": 400, "body": json.dumps({"message": str(e)})}
except Exception as e:
print(e)
return {"statusCode": 500, "body": json.dumps({"message": "unexpected error"})}
return deco
@handle_exceptions
def my_expected_error_request(event, context):
raise BadRequest("This function raises a BadRequest with a 400 status code that should be sent to the user. The end user can read this text.")
@handle_exceptions
def my_unexpected_error_request(event, context):
raise Exception("Uh oh. I didn't expect this. A 500 error with an obfuscated message is raised. The end user cannot read this text.")
这种模式使得 API 到 return 适当的错误消息和 status code. I have very rudimentary logging in this handle_exceptions
implementation but you can get really detailed messages with f.__name__
to know what Lambda function erred and the traceback module 理解异常的来源变得非常容易。 API 用户完全隐藏了所有这些错误管理。