Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bug: REST Event Handler doesn't handle some json parsing exceptions #3672

Closed
Dilski opened this issue Jan 25, 2024 · 5 comments · Fixed by #3677
Closed

Bug: REST Event Handler doesn't handle some json parsing exceptions #3672

Dilski opened this issue Jan 25, 2024 · 5 comments · Fixed by #3677
Assignees
Labels

Comments

@Dilski
Copy link

Dilski commented Jan 25, 2024

Expected Behaviour

This may or may not be a bug, but the REST API event handler payload validator does not gracefully handle empty bodies. I would expect an empty body to raise a 4xx (maybe a 422)

Current Behaviour

With the following setup, invoking the POST /todos endpoint with content-type: application/json but with an empty body will raise a TypeError and return a 500 error.

Code snippet

from typing import List, Optional

import requests
from pydantic import BaseModel, Field

from aws_lambda_powertools import Logger, Tracer
from aws_lambda_powertools.event_handler import APIGatewayRestResolver
from aws_lambda_powertools.logging import correlation_paths
from aws_lambda_powertools.utilities.typing import LambdaContext

tracer = Tracer()
logger = Logger()
app = APIGatewayRestResolver(enable_validation=True)  


class Todo(BaseModel):  
    userId: int
    id_: Optional[int] = Field(alias="id", default=None)
    title: str
    completed: bool


@app.post("/todos")
def create_todo(todo: Todo) -> str:  
    response = requests.post("https://jsonplaceholder.typicode.com/todos", json=todo.dict(by_alias=True))
    response.raise_for_status()

    return response.json()["id"]  


@logger.inject_lambda_context(correlation_id_path=correlation_paths.API_GATEWAY_HTTP)
@tracer.capture_lambda_handler
def lambda_handler(event: dict, context: LambdaContext) -> dict:
    return app.resolve(event, context)

Possible Solution

The validation middleware handles a json.JSONDecodeError exception, but json.loads will raise a TypeError if the request body is empty.

We could either:

  • Catch the TypeError and raise an appropriate response
  • Check for None in _get_body

Steps to Reproduce

Invoke the REST endpoint with an empty body.

Powertools for AWS Lambda (Python) version

latest

AWS Lambda function runtime

3.12

Packaging format used

PyPi

Debugging logs

No response

@Dilski Dilski added bug Something isn't working triage Pending triage from maintainers labels Jan 25, 2024
@leandrodamascena
Copy link
Contributor

Hi @Dilski! Thanks for opening this potential bug.

I'm working to reproduce this error and will update this issue as soon as I have an update.

@leandrodamascena leandrodamascena moved this from Triage to Working on it in Powertools for AWS Lambda (Python) Jan 25, 2024
@leandrodamascena leandrodamascena added event_handlers and removed triage Pending triage from maintainers labels Jan 25, 2024
@Dilski
Copy link
Author

Dilski commented Jan 25, 2024

@leandrodamascena just for extra info, we were doing this with a private API gateway and so tested with test invoke on the console

@leandrodamascena
Copy link
Contributor

@leandrodamascena just for extra info, we were doing this with a private API gateway and so tested with test invoke on the console

This was the missing piece of this puzzle! I could not reproduce this either in my local environment or on the Swagger/Public/Private endpoint. However, using the APIGW "Test" on the console I was able to reproduce it.

This is a very specific bug and thanks a lot for catching and reporting this. Testing your APIs thought AWS Console it will send to Lambda the exact string you added in the Headers section, and in this case the string is:

"headers": {
    "Content-Type": " application/json"
},
"multiValueHeaders": {
    "Content-Type": [
        " application/json"
    ]
},

If you see, there is a space before the application/json string and it fails in this line. It looks like the solution is to remove the spaces before checking the header, something like this if not content_type_value or content_type_value.strip().startswith("application/json"):. While we create a PullRequest and release a version to fix this, you can test using the header with no space between key and value: Content-Type:application/json.

We are planning to release a version on February 8th. Please let me know if it is enough for you to wait until then or need this fix immediately.

Thanks.

Copy link
Contributor

⚠️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 github-actions bot added the pending-release Fix or implementation already in dev waiting to be released label Jan 29, 2024
Copy link
Contributor

github-actions bot commented Feb 2, 2024

This is now released under 2.33.0 version!

@github-actions github-actions bot removed the pending-release Fix or implementation already in dev waiting to be released label Feb 2, 2024
@leandrodamascena leandrodamascena moved this from Coming soon to Shipped in Powertools for AWS Lambda (Python) Feb 6, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
Status: Shipped
2 participants