Bug: Form() field does not handle list parameters
bdellegrazie opened this issue · 10 comments
I'm trying to parse a POST based Form that has a multi-valued string property.
However this doesn't appear to work?. It does work for the string parameter, but not for the list.
Minimal example:
from typing import Annotated
from aws_lambda_powertools.event_handler import APIGatewayHttpResolver
from aws_lambda_powertools.event_handler.openapi.params import Form
from aws_lambda_powertools.utilities.typing import LambdaContext
app = APIGatewayHttpResolver(
enable_validation=True,
)
@app.post("/example")
def example(
param: Annotated[
str,
Form(),
],
param_list: Annotated[
list[str],
Form(),
] = []
):
pass
def lambda_handler(event: dict, context: LambdaContext) -> dict:
return app.resolve(event, context)Tested by generating a dummy event to the lambda with body content like this:
import urlparse.parse
def test_example():
# Also tested with tuple form [("param_list", ["value1", "value2"])]
body = urlparse.parse.urlencode({
"param": "value",
"param_list": ["value1", "value2"]
}, doseq=True)
event = {
"headers": [
"accept": "application/json",
"content-type": "application/x-www-form-urlencoded"
],
...
"body": body
}
... rest of test elidedBut I always get response code of 422 like this:
{
"statusCode": 422,
"detail": [
{
"loc": [
"body","param_list"
],
"type": "list_type"
}
]
}Thanks!
Originally posted by @bdellegrazie in #7337
Thanks for opening your first issue here! We'll come back to you as soon as we can.
In the meantime, check out the #python channel on our Powertools for AWS Lambda Discord: Invite link
Hi @bdellegrazie – Thanks for bringing this up, this seems like an oversight in the implementation.
Hi @bdellegrazie, I'll take a look at this soon! If you have a solution, I'd appreciate it if you could send me a PR with the fix.
Thanks
Hi @leandrodamascena, sorry, I don't have a solution at present.
I've tried to find the issue but couldn't reproduce it. Do you have a minimal example?
In
is a test for this. I make a simple test local for an http event, but this works also.Hi @tonnico , thanks for the pointer to the test. I'll try again in case I made a mistake, I did mention that I might have been mistaken in the original thread.
Hi @tonnico, @leandrodamascena I think I've figured out what the bug is at least:
If a single value is parsed to an array parameter, it doesn't parse.
If multiple values are supplied, it works.
It looks like the parser is unable to accept a single value for an array.
I can confirm this issue.
parse_qs will always create lists, and here it will create a single item, when the list is only one item.
I have worked around this by using the following type in the form definition:
@app.post("/example")
def example(
param: Annotated[
str,
Form(),
],
param_list: Annotated[
None | str | list[str],
Form(),
] = None
):and checking the type in the resulting code. This works but adds unnecessary type checking in my code.
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 reopen the issue, or open a new issue referencing this one.
If you wish to keep having a conversation with other community members under this issue feel free to do so.