-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Support for Multi-Value Headers and Query String Parameters #741
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
Changes from all commits
27adafd
cbed252
b487fd4
1caeef1
0619e5c
3663ec7
7676bbd
4d27d89
10e2f95
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -346,21 +346,18 @@ def _construct_event(flask_request, port, binary_types): | |
| identity=identity, | ||
| path=endpoint) | ||
|
|
||
| event_headers = dict(flask_request.headers) | ||
| event_headers["X-Forwarded-Proto"] = flask_request.scheme | ||
| event_headers["X-Forwarded-Port"] = str(port) | ||
| headers_dict, multi_value_headers_dict = LocalApigwService._event_headers(flask_request, port) | ||
|
|
||
| # APIGW does not support duplicate query parameters. Flask gives query params as a list so | ||
| # we need to convert only grab the first item unless many were given, were we grab the last to be consistent | ||
| # with APIGW | ||
| query_string_dict = LocalApigwService._query_string_params(flask_request) | ||
| query_string_dict, multi_value_query_string_dict = LocalApigwService._query_string_params(flask_request) | ||
|
|
||
| event = ApiGatewayLambdaEvent(http_method=method, | ||
| body=request_data, | ||
| resource=endpoint, | ||
| request_context=context, | ||
| query_string_params=query_string_dict, | ||
| headers=event_headers, | ||
| multi_value_query_string_params=multi_value_query_string_dict, | ||
| headers=headers_dict, | ||
| multi_value_headers=multi_value_headers_dict, | ||
| path_parameters=flask_request.view_args, | ||
| path=flask_request.path, | ||
| is_base_64_encoded=is_base_64) | ||
|
|
@@ -379,12 +376,13 @@ def _query_string_params(flask_request): | |
| flask_request request | ||
| Request from Flask | ||
|
|
||
| Returns dict (str: str) | ||
| Returns dict (str: str), dict (str: list of str) | ||
| ------- | ||
| Empty dict if no query params where in the request otherwise returns a dictionary of key to value | ||
|
|
||
| """ | ||
| query_string_dict = {} | ||
| multi_value_query_string_dict = {} | ||
|
|
||
| # Flask returns an ImmutableMultiDict so convert to a dictionary that becomes | ||
| # a dict(str: list) then iterate over | ||
|
|
@@ -394,11 +392,46 @@ def _query_string_params(flask_request): | |
| # if the list is empty, default to empty string | ||
| if not query_string_value_length: | ||
| query_string_dict[query_string_key] = "" | ||
| multi_value_query_string_dict[query_string_key] = [""] | ||
| else: | ||
| # APIGW doesn't handle duplicate query string keys, picking the last one in the list | ||
| query_string_dict[query_string_key] = query_string_list[-1] | ||
| multi_value_query_string_dict[query_string_key] = query_string_list | ||
|
|
||
| return query_string_dict | ||
| return query_string_dict, multi_value_query_string_dict | ||
|
|
||
| @staticmethod | ||
| def _event_headers(flask_request, port): | ||
| """ | ||
| Constructs an APIGW equivalent headers dictionary | ||
|
|
||
| Parameters | ||
| ---------- | ||
| flask_request request | ||
| Request from Flask | ||
| int port | ||
| Forwarded Port | ||
|
|
||
| Returns dict (str: str), dict (str: list of str) | ||
| ------- | ||
| Returns a dictionary of key to list of strings | ||
|
|
||
| """ | ||
| headers_dict = {} | ||
| multi_value_headers_dict = {} | ||
|
|
||
| # Multi-value request headers is not really supported by Flask. | ||
medinarrior marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| # See https://github.com/pallets/flask/issues/850 | ||
| for header_key in flask_request.headers.keys(): | ||
|
||
| headers_dict[header_key] = flask_request.headers.get(header_key) | ||
| multi_value_headers_dict[header_key] = flask_request.headers.getlist(header_key) | ||
|
|
||
| headers_dict["X-Forwarded-Proto"] = flask_request.scheme | ||
| multi_value_headers_dict["X-Forwarded-Proto"] = [flask_request.scheme] | ||
|
|
||
| headers_dict["X-Forwarded-Port"] = str(port) | ||
| multi_value_headers_dict["X-Forwarded-Port"] = [str(port)] | ||
|
|
||
| return headers_dict, multi_value_headers_dict | ||
|
|
||
| @staticmethod | ||
| def _should_base64_encode(binary_types, request_mimetype): | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -132,7 +132,9 @@ def __init__(self, | |
| resource=None, | ||
| request_context=None, | ||
| query_string_params=None, | ||
| multi_value_query_string_params=None, | ||
| headers=None, | ||
| multi_value_headers=None, | ||
| path_parameters=None, | ||
| stage_variables=None, | ||
| path=None, | ||
|
|
@@ -145,7 +147,9 @@ def __init__(self, | |
| :param str resource: Resource for the reqeust | ||
| :param RequestContext request_context: RequestContext for the request | ||
| :param dict query_string_params: Query String parameters | ||
| :param dict multi_value_query_string_params: Multi-value Query String parameters | ||
| :param dict headers: dict of the request Headers | ||
| :param dict multi_value_headers: dict of the multi-value request Headers | ||
| :param dict path_parameters: Path Parameters | ||
| :param dict stage_variables: API Gateway Stage Variables | ||
| :param str path: Path of the request | ||
|
|
@@ -156,9 +160,16 @@ def __init__(self, | |
| query_string_params is not None: | ||
| raise TypeError("'query_string_params' must be of type dict or None") | ||
|
|
||
| if not isinstance(multi_value_query_string_params, dict) and \ | ||
| multi_value_query_string_params is not None: | ||
| raise TypeError("'multi_value_query_string_params' must be of type dict or None") | ||
|
|
||
| if not isinstance(headers, dict) and headers is not None: | ||
| raise TypeError("'headers' must be of type dict or None") | ||
|
|
||
| if not isinstance(multi_value_headers, dict) and multi_value_headers is not None: | ||
| raise TypeError("'multi_value_headers' must be of type dict or None") | ||
|
|
||
| if not isinstance(path_parameters, dict) and path_parameters is not None: | ||
| raise TypeError("'path_parameters' must be of type dict or None") | ||
|
|
||
|
|
@@ -170,7 +181,9 @@ def __init__(self, | |
| self.resource = resource | ||
| self.request_context = request_context | ||
| self.query_string_params = query_string_params | ||
| self.multi_value_query_string_params = multi_value_query_string_params | ||
| self.headers = headers | ||
| self.multi_value_headers = multi_value_headers | ||
| self.path_parameters = path_parameters | ||
| self.stage_variables = stage_variables | ||
| self.path = path | ||
|
|
@@ -191,7 +204,10 @@ def to_dict(self): | |
| "resource": self.resource, | ||
| "requestContext": request_context_dict, | ||
| "queryStringParameters": dict(self.query_string_params) if self.query_string_params else None, | ||
| "multiValueQueryStringParameters": dict(self.multi_value_query_string_params) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. do we need
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Probably because someone could mutate the public variable on the object after initializing? |
||
| if self.multi_value_query_string_params else None, | ||
| "headers": dict(self.headers) if self.headers else None, | ||
| "multiValueHeaders": dict(self.multi_value_headers) if self.multi_value_headers else None, | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. same here |
||
| "pathParameters": dict(self.path_parameters) if self.path_parameters else None, | ||
| "stageVariables": dict(self.stage_variables) if self.stage_variables else None, | ||
| "path": self.path, | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.