Python 使用API网关处理AWS Lambda错误
我在Lambda函数中有Python 使用API网关处理AWS Lambda错误,python,amazon-web-services,aws-lambda,aws-api-gateway,aws-step-functions,Python,Amazon Web Services,Aws Lambda,Aws Api Gateway,Aws Step Functions,我在Lambda函数中有类BadRequest(异常):pass 我想提出BadRequest(“无效的请求参数”),并让API返回一个状态代码为400、正文为{“message”:“无效的请求参数”}(或等效内容)的响应 但是,简单地这样做会返回一个状态代码为200(哦,不!)和body的响应 { “errorMessage”:“无效的请求参数”, “errorType”:“BadRequest”, “stackTrace”: } 在网上搜索之后,我似乎有3个选择: (一) 2) 使用集成响
类BadRequest(异常):pass
我想提出BadRequest(“无效的请求参数”)
,并让API返回一个状态代码为400、正文为{“message”:“无效的请求参数”}
(或等效内容)的响应
但是,简单地这样做会返回一个状态代码为200(哦,不!)和body的响应
{
“errorMessage”:“无效的请求参数”,
“errorType”:“BadRequest”,
“stackTrace”:
}
在网上搜索之后,我似乎有3个选择:
(一)
2) 使用集成响应和方法响应将错误解析为更好的响应。我希望正则表达式[BadRequest]..
并在抛出异常时插入前缀(在我看来不是很优雅)
3) 用于创建API的有状态表示。这似乎有点乏味,因为我需要学习ASL,而且我不认识任何聋人。-
-.-
我应该进入哪个兔子洞?为什么?您应该捕获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"
}
public类LambdaFunctionHandler实现RequestHandler{
@凌驾
公共字符串handleRequest(字符串输入,上下文){
Map errorPayload=newhashmap();
errorPayload.put(“errorType”、“BadRequest”);
errorPayload.put(“httpStatus”,400);
errorPayload.put(“requestId”,context.getAwsRequestId());
errorPayload.put(“消息”,“无效请求参数”+stackstace);
字符串消息=新的ObjectMapper().writeValueAsString(errorPayload);
抛出新的运行时异常(消息);
}
}
然后使用选项2映射错误代码。
整合响应:
选择模式:“%BadRequest”。*
方法应答:500
映射模板:
#set($errorMessageObj=$util.parseJson($input.path('$.errorMessage')))
{
“类型”:“$errorMessageObj.errorType”,
“消息”:“$errorMessageObj.message”,
“请求id”:“$errorMessageObj.requestId”
}
这是AWS Step函数的完美用例。您需要设置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函数输出的任何内容
希望这有帮助 使使用Lambda和API网关实现restapi变得非常简单,包括将引发的异常转换为响应。对于您的特定情况,您会提出如下异常:
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")
在GitHub上有一个完整的REST API使用Chalice和Lambda以及API网关的工作示例:。三年后,我将回到这个问题上来,描述我今天如何解决这个问题。我使用部署lambda函数和API网关 我使用一个装饰器捕捉异常并返回有效负载。例如,这里有一个成功的请求、一个预期的异常和一个意外的异常
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很容易返回适当的错误消息和错误。我在这个
handle_exceptions
实现中有非常基本的日志记录,但是您可以通过f.\uuuu name_uuu
获得非常详细的消息,以了解Lambda函数出错的原因以及异常的来源。所有这些错误管理都对API用户完全隐藏。对chalice和step函数了解不多。我建议对该lambda使用集成响应和方法响应。它是为处理这类问题而构建的功能,我在任何地方都使用它来根据某些触发器格式化我的响应。走这条路线的主要原因是AWS支持解决AWS服务的这个问题。因此,对于您或将来接管此项目的人来说,管理开销更少。另外,这并不难学,然后你也可以为传入的数据编写json语法文档。在这种情况下,如何避免200/回溯响应?另请参阅以下博文:[Amazon API Gateway和AWS Lambda中的错误处理模式]()
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.")