aws-powertools / powertools-lambda-python

A developer toolkit to implement Serverless best practices and increase developer velocity.
https://docs.powertools.aws.dev/lambda/python/latest/
MIT No Attribution
2.81k stars 389 forks source link

Bug: Validating POST body fails with BedrockAgentResolver #3902

Closed rubenfonseca closed 6 months ago

rubenfonseca commented 6 months ago

Discussed in https://github.com/aws-powertools/powertools-lambda-python/discussions/3893

Originally posted by **robk1234** March 6, 2024 What is the correct way to validate the POST body with BedrockAgent Resolver? I am getting a key error when I try with the following code: ```python from pydantic import EmailStr from typing_extensions import Annotated from aws_lambda_powertools import Logger, Tracer from aws_lambda_powertools.event_handler import BedrockAgentResolver from aws_lambda_powertools.event_handler.openapi.params import Body, Query from aws_lambda_powertools.utilities.typing import LambdaContext tracer = Tracer() logger = Logger() app = BedrockAgentResolver() @app.post('/email', description="Validate an Email via post body") def post_body_email(email: Annotated[EmailStr, Body(description="Email address to validate")], ) -> Annotated[bool, Body(description="returns true if I like the email")]: return True @app.get('/email', description="Validate email via get request") def get_email(email: Annotated[EmailStr, Query(description="Email address to validate")] )->Annotated[bool, Body(description="Returns True if I like the email")]: return True @logger.inject_lambda_context @tracer.capture_lambda_handler def lambda_handler(event: dict, context: LambdaContext): return app.resolve(event, context) if __name__ == "__main__": print(app.get_openapi_json_schema()) ``` The GET Request works fine: ```json { "sessionId": "123456789012345", "sessionAttributes": {}, "inputText": "Validate an email via get", "promptSessionAttributes": {}, "apiPath": "/email", "parameters": [ { "name": "email", "type": "string", "value": "johndoe@test.com" } ], "agent": { "name": "TimeAgent", "version": "DRAFT", "id": "XLHH72XNF2", "alias": "TSTALIASID" }, "httpMethod": "GET", "messageVersion": "1.0", "actionGroup": "SupportAssistant" } ``` Output is: ```bash ➜ test_lambda sam local invoke --event events/bedrock.json ApiFunction Invoking app.lambda_handler (python3.12) Local image is up-to-date Using local image: public.ecr.aws/lambda/python:3.12-rapid-x86_64. Mounting /Users/rklages/git/rob/test_lambda/.aws-sam/build/ApiFunction as /var/task:ro,delegated, inside runtime container START RequestId: b783d02d-bb17-449b-b7c8-3671475fac6b Version: $LATEST [WARNING] 2024-03-06T19:34:56.315Z 8bc618fb-4c0f-4847-9cb6-de8ddc744fb1 Subsegment ## lambda_handler discarded due to Lambda worker still initializing [WARNING] 2024-03-06T19:34:57.013Z 8bc618fb-4c0f-4847-9cb6-de8ddc744fb1 No subsegment to end. END RequestId: 8bc618fb-4c0f-4847-9cb6-de8ddc744fb1 REPORT RequestId: 8bc618fb-4c0f-4847-9cb6-de8ddc744fb1 Init Duration: 0.92 ms Duration: 6873.37 ms Billed Duration: 6874 ms Memory Size: 128 MB Max Memory Used: 128 MB {"messageVersion": "1.0", "response": {"actionGroup": "SupportAssistant", "apiPath": "/email", "httpMethod": "GET", "httpStatusCode": 200, "responseBody": {"application/json": {"body": "true"}}}} ``` With the POST payload: ```json { "sessionId": "123456789012345", "sessionAttributes": {}, "inputText": "Please validate email jobndoe@test.com via POST", "promptSessionAttributes": {}, "apiPath": "/email", "requestBody": { "application/json": { "properties": [ { "name": "email", "type": "string", "value": "johndoe@test.com" } ] } }, "agent": { "name": "TimeAgent", "version": "DRAFT", "id": "XLHH72XNF2", "alias": "TSTALIASID" }, "parameters": [], "httpMethod": "POST", "messageVersion": "1.0", "actionGroup": "SupportAssistant" } ``` I'm getting the following error: ```bash ➜ test_lambda sam local invoke --event events/bedrock_post.json ApiFunction Invoking app.lambda_handler (python3.12) Local image is up-to-date Using local image: public.ecr.aws/lambda/python:3.12-rapid-x86_64. Mounting /Users/rklages/git/rob/test_lambda/.aws-sam/build/ApiFunction as /var/task:ro,delegated, inside runtime container START RequestId: d785f329-b65b-4ef1-b55c-2c91e4adbd5d Version: $LATEST [WARNING] 2024-03-06T19:36:01.835Z 7d6e024a-be8d-495d-976f-c30fc60cf218 Subsegment ## lambda_handler discarded due to Lambda worker still initializing [WARNING] 2024-03-06T19:36:02.177Z 7d6e024a-be8d-495d-976f-c30fc60cf218 No subsegment to end. LAMBDA_WARNING: Unhandled exception. The most likely cause is an issue in the function code. However, in rare cases, a Lambda runtime update can cause unexpected function behavior. For functions using managed runtimes, runtime updates can be triggered by a function change, or can be applied automatically. To determine if the runtime has been updated, check the runtime version in the INIT_START log entry. If this error correlates with a change in the runtime version, you may be able to mitigate this error by temporarily rolling back to the previous runtime version. For more information, see https://docs.aws.amazon.com/lambda/latest/dg/runtimes-update.html [ERROR] KeyError: 'body' Traceback (most recent call last):   File "/var/task/aws_lambda_powertools/logging/logger.py", line 447, in decorate     return lambda_handler(event, context, *args, **kwargs)   File "/var/task/aws_lambda_powertools/tracing/tracer.py", line 313, in decorate     response = lambda_handler(event, context, **kwargs)   File "/var/task/app.py", line 34, in lambda_handler     return app.resolve(event, context)   File "/var/task/aws_lambda_powertools/event_handler/api_gateway.py", line 1815, in resolve     response = self._resolve().build(self.current_event, self._cors)   File "/var/task/aws_lambda_powertools/event_handler/api_gateway.py", line 1922, in _resolve     return self._call_route(route, route_keys) # pass fn args   File "/var/task/aws_lambda_powertools/event_handler/api_gateway.py", line 2000, in _call_route     route(router_middlewares=self._router_middlewares, app=self, route_arguments=route_arguments),   File "/var/task/aws_lambda_powertools/event_handler/api_gateway.py", line 400, in __call__     return self._middleware_stack(app)   File "/var/task/aws_lambda_powertools/event_handler/api_gateway.py", line 1291, in __call__     return self.current_middleware(app, self.next_middleware)   File "/var/task/aws_lambda_powertools/event_handler/middlewares/base.py", line 121, in __call__     return self.handler(app, next_middleware)   File "/var/task/aws_lambda_powertools/event_handler/middlewares/openapi_validation.py", line 105, in handler     received_body=self._get_body(app),   File "/var/task/aws_lambda_powertools/event_handler/middlewares/openapi_validation.py", line 230, in _get_body     return app.current_event.json_body   File "/var/lang/lib/python3.12/functools.py", line 995, in __get__     val = self.func(instance)   File "/var/task/aws_lambda_powertools/utilities/data_classes/common.py", line 153, in json_body     return self._json_deserializer(self.decoded_body)   File "/var/lang/lib/python3.12/functools.py", line 995, in __get__     val = self.func(instance)   File "/var/task/aws_lambda_powertools/utilities/data_classes/common.py", line 158, in decoded_body     body: str = self["body"]   File "/var/task/aws_lambda_powertools/utilities/data_classes/common.py", line 32, in __getitem__     return self._data[key] END RequestId: 7d6e024a-be8d-495d-976f-c30fc60cf218 REPORT RequestId: 7d6e024a-be8d-495d-976f-c30fc60cf218 Init Duration: 0.89 ms Duration: 6576.10 ms Billed Duration: 6577 ms Memory Size: 128 MB Max Memory Used: 128 MB {"errorMessage": "'body'", "errorType": "KeyError", "requestId": "7d6e024a-be8d-495d-976f-c30fc60cf218", "stackTrace": [" File \"/var/task/aws_lambda_powertools/logging/logger.py\", line 447, in decorate\n return lambda_handler(event, context, *args, **kwargs)\n", " File \"/var/task/aws_lambda_powertools/tracing/tracer.py\", line 313, in decorate\n response = lambda_handler(event, context, **kwargs)\n", " File \"/var/task/app.py\", line 34, in lambda_handler\n return app.resolve(event, context)\n", " File \"/var/task/aws_lambda_powertools/event_handler/api_gateway.py\", line 1815, in resolve\n response = self._resolve().build(self.current_event, self._cors)\n", " File \"/var/task/aws_lambda_powertools/event_handler/api_gateway.py\", line 1922, in _resolve\n return self._call_route(route, route_keys) # pass fn args\n", " File \"/var/task/aws_lambda_powertools/event_handler/api_gateway.py\", line 2000, in _call_route\n route(router_middlewares=self._router_middlewares, app=self, route_arguments=route_arguments),\n", " File \"/var/task/aws_lambda_powertools/event_handler/api_gateway.py\", line 400, in __call__\n return self._middleware_stack(app)\n", " File \"/var/task/aws_lambda_powertools/event_handler/api_gateway.py\", line 1291, in __call__\n return self.current_middleware(app, self.next_middleware)\n", " File \"/var/task/aws_lambda_powertools/event_handler/middlewares/base.py\", line 121, in __call__\n return self.handler(app, next_middleware)\n", " File \"/var/task/aws_lambda_powertools/event_handler/middlewares/openapi_validation.py\", line 105, in handler\n received_body=self._get_body(app),\n", " File \"/var/task/aws_lambda_powertools/event_handler/middlewares/openapi_validation.py\", line 230, in _get_body\n return app.current_event.json_body\n", " File \"/var/lang/lib/python3.12/functools.py\", line 995, in __get__\n val = self.func(instance)\n", " File \"/var/task/aws_lambda_powertools/utilities/data_classes/common.py\", line 153, in json_body\n return self._json_deserializer(self.decoded_body)\n", " File \"/var/lang/lib/python3.12/functools.py\", line 995, in __get__\n val = self.func(instance)\n", " File \"/var/task/aws_lambda_powertools/utilities/data_classes/common.py\", line 158, in decoded_body\n body: str = self[\"body\"]\n", " File \"/var/task/aws_lambda_powertools/utilities/data_classes/common.py\", line 32, in __getitem__\n return self._data[key]\n"]} ```
rubenfonseca commented 6 months ago

Thank you @robk1234 for reporting this. Working on a fix.

github-actions[bot] commented 6 months ago

⚠️COMMENT VISIBILITY WARNING⚠️

This issue is now closed. Please be mindful that future comments are hard for our team to see.

If you need more assistance, please either tag a team member or open a new issue that references this one.

If you wish to keep having a conversation with other community members under this issue feel free to do so.

github-actions[bot] commented 6 months ago

This is now released under 2.35.1 version!