-
Notifications
You must be signed in to change notification settings - Fork 368
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
Flask API passed urlencoded ampersand in query string works on local but not through API Gateway via Zappa #1227
Comments
I believe that the url_unquote line in the Zappa codebase is causing the issue I'm seeing:
I noticed that the event being passed to the Lambda function had the correct query string info: so I did a quick python test:
Results:
AWS Results:
I'm not sure what the intent of that line is though (may cause other issues without that). |
I was about to create a similar ticket (it looks like we discovered and investigated in parallel), although mine was to do with '+' in url params, it's the same issue though, so I'll add my findings here, I tried ampersand and indeed it behaves the same way. I also think the problematic line is the unquote. I cloned the Zappa repository to a local directory and pip installed with -e in my virtualenv so that I could edit the library and upload a modified version to allow for debug/modifications when making requests to the version of my API in AWS. I modified to:
And also added this at L590 of handler.py
So let's send
This confuses my API (it's returning the request parameters as a response), and breaks the ampersand values as expected, it also treats '+' as ' '.
If I comment out
And the API returns:
If I call the local version of my Flask API, it seems Werkzeug is pretty unfussy about whether URL's are encoded or contain raw values for most characters (e.g. escaping '!' to '%21') , but of course '+' and '&' carry special meaning in a URL which Werkzeug needs to strictly honour. I don't know exactly what Werkzeug/Zappa expects (or what is in front of these when running the flask server in development mode), but after some playing with both local and lamda requests, it seems that it should be given the escaped version. I don't know if this will have wider implications for other wsgi receivers (e.g. Django)? |
I see the same behavior, the query string is decoded when it gets to my app and therefore parameters that contain characters like '&' cannot get properly parsed. Example URL: http://myapp.com?query=Jane%26John Expected query parameters
Actual query parameters
Like @atrojanowski mentioned above it seems to be because of url_unquote |
Ran into the same issue (with a %-encoded + in my case). The bug was itnroduced in 62a53ed. |
From zappa's point of view, it is only preparing the value for the "QUERY_STRING" key for the environ created for wsgi. In the current zappa implementation, with So given the example: URL: http://myapp.com/?query=Jane%26John&otherquery=B The lambda event is expected to contain:
And, as I understand, should be converted to the raw query string value for "QUERY_STRING" as:
However, as @atrojanowski mentioned, it was observed that the lambda event provides the unencoded string as the value in "queryStringParameters"/"multiValueQueryStringParameters". If that's assured, then it would be unexpected that we get an encoded value that would need to be "re-encoded" in order to preserve the "encoded" value. Unfortunately, I couldn't find any clear documentation on the content of the apigateway event values. In anycase, if assured that the "queryStringParameters"/"multiValueQueryStringParameters" are encoded, the suggestion in this issue appears to be correct, that we don't need the addtional |
I know this is an old zappa issue that you requested, but do you remember why you needed the QUERY_STRING to be unencoded? added in 62a53ed We supported this Miserlou/Zappa#2134 / #879 in version It appears that this testcase describes the desire of introducing 62a53ed#diff-6337f0a34289544e437f2604c7c78f4455c4e211183b8bf450df853e0cff9efbR2735-R2746 Where Without Now, there is a "safe" parameter we can pass to |
https://en.wikipedia.org/wiki/URL_encoding
Since "#" and "," are in the reserved character set they should be percent encoded. |
merged and released in 0.58.0 closing |
Context
Apologies if I've missed something simple. I'm trying to handle cases where some query parameters have an encoded ampersand (%26) in them. I can run the flask locally on my development machine and it works as expected but when I deploy via zappa to AWS using the API Gateway it seems the %26 is converted back to '&' and passed to the Lambda function so that when I try to use response.query_string or response.args the query parameter value is not passed correctly.
I have created a very simple flask example to show this behavior.
Expected Behavior
when a query string like
?test=M%26M
is passed to the API gateway url, I expectb'test=M%26M'
ImmutableMultiDict([('test', 'M&M')])
M&M
The expected behavior is the behavior I see when running my flask app via my local machine:
Actual Behavior
response.query_string is
b'test=M&M'
and response.args is{ "M": "", "test": "M" }
Here are some cloudfront logs:
Possible Fix
My only thought is that there is some API Gateway (and by extension, Zappa) setting to stop this from happening.
Steps to Reproduce
flaskdemo.py
,zappa_settings.json
, andpip freeze
in the Environment sectionzappa deploy test
https://xxxxxxxxx.execute-api.us-west-2.amazonaws.com/test/?test=M%26M
Your Environment
0.56.1
Mac Ventura 13.2.1 & Python 3.8.16
pip freeze
: (I created a new virtual env and only installed flask and zappa)zappa_settings.json
:The text was updated successfully, but these errors were encountered: