From 31b5de4ca762492d02f3d4829f21849c210e5102 Mon Sep 17 00:00:00 2001 From: monkut Date: Wed, 10 Aug 2022 15:06:57 +0900 Subject: [PATCH 01/12] :sparkles: Handle spaces in x-forwared-for (#1127) --- tests/tests.py | 87 ++++++++++++++++++++++++++++++++++++++++++++++++++ zappa/wsgi.py | 3 +- 2 files changed, 89 insertions(+), 1 deletion(-) diff --git a/tests/tests.py b/tests/tests.py index 831574606..96d8cb8c6 100644 --- a/tests/tests.py +++ b/tests/tests.py @@ -739,6 +739,93 @@ def test_wsgi_event(self): request = create_wsgi_request(event) + def test_wsgi_event__handle_space_in_xforwardedfor(self): + + ## This is a pre-proxy+ event + # event = { + # "body": "", + # "headers": { + # "Via": "1.1 e604e934e9195aaf3e36195adbcb3e18.cloudfront.net (CloudFront)", + # "Accept-Language": "en-US,en;q=0.5", + # "Accept-Encoding": "gzip", + # "CloudFront-Is-SmartTV-Viewer": "false", + # "CloudFront-Forwarded-Proto": "https", + # "X-Forwarded-For": "109.81.209.118, 216.137.58.43", + # "CloudFront-Viewer-Country": "CZ", + # "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", + # "X-Forwarded-Proto": "https", + # "X-Amz-Cf-Id": "LZeP_TZxBgkDt56slNUr_H9CHu1Us5cqhmRSswOh1_3dEGpks5uW-g==", + # "CloudFront-Is-Tablet-Viewer": "false", + # "X-Forwarded-Port": "443", + # "CloudFront-Is-Mobile-Viewer": "false", + # "CloudFront-Is-Desktop-Viewer": "true", + # "Content-Type": "application/json" + # }, + # "params": { + # "parameter_1": "asdf1", + # "parameter_2": "asdf2", + # }, + # "method": "POST", + # "query": { + # "dead": "beef" + # } + # } + + event = { + "body": None, + "resource": "/", + "requestContext": { + "resourceId": "6cqjw9qu0b", + "apiId": "9itr2lba55", + "resourcePath": "/", + "httpMethod": "GET", + "requestId": "c17cb1bf-867c-11e6-b938-ed697406e3b5", + "accountId": "724336686645", + "identity": { + "apiKey": None, + "userArn": None, + "cognitoAuthenticationType": None, + "caller": None, + "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:48.0) Gecko/20100101 Firefox/48.0", + "user": None, + "cognitoIdentityPoolId": None, + "cognitoIdentityId": None, + "cognitoAuthenticationProvider": None, + "sourceIp": "50.191.225.98", + "accountId": None, + }, + "stage": "devorr", + }, + "queryStringParameters": None, + "httpMethod": "GET", + "pathParameters": None, + "headers": { + "Via": "1.1 6801928d54163af944bf854db8d5520e.cloudfront.net (CloudFront)", + "Accept-Language": "en-US,en;q=0.5", + "Accept-Encoding": "gzip, deflate, br", + "CloudFront-Is-SmartTV-Viewer": "false", + "CloudFront-Forwarded-Proto": "https", + "X-Forwarded-For": "50.191.225.98 , 204.246.168.101", + "CloudFront-Viewer-Country": "US", + "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", + "Upgrade-Insecure-Requests": "1", + "Host": "9itr2lba55.execute-api.us-east-1.amazonaws.com", + "X-Forwarded-Proto": "https", + "X-Amz-Cf-Id": "qgNdqKT0_3RMttu5KjUdnvHI3OKm1BWF8mGD2lX8_rVrJQhhp-MLDw==", + "CloudFront-Is-Tablet-Viewer": "false", + "X-Forwarded-Port": "443", + "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:48.0) Gecko/20100101 Firefox/48.0", + "CloudFront-Is-Mobile-Viewer": "false", + "CloudFront-Is-Desktop-Viewer": "true", + }, + "stageVariables": None, + "path": "/", + } + expected = "50.191.225.98" + request = create_wsgi_request(event) + actual = request["REMOTE_ADDR"] + self.assertEqual(actual, expected) + def test_wsgi_path_info_unquoted(self): event = { "body": {}, diff --git a/zappa/wsgi.py b/zappa/wsgi.py index d2300bc3b..c33988aa4 100644 --- a/zappa/wsgi.py +++ b/zappa/wsgi.py @@ -100,7 +100,8 @@ def create_wsgi_request( if "," in x_forwarded_for: # The last one is the cloudfront proxy ip. The second to last is the real client ip. # Everything else is user supplied and untrustworthy. - remote_addr = x_forwarded_for.split(", ")[-2] + addresses = [addr.strip() for addr in x_forwarded_for.split(",")] + remote_addr = addresses[-2] # get client ip else: remote_addr = x_forwarded_for or "127.0.0.1" From 53e9d9cd022bb6005de1f4399b1785eb1c532b6d Mon Sep 17 00:00:00 2001 From: monkut Date: Fri, 12 Aug 2022 11:39:49 +0900 Subject: [PATCH 02/12] :fire: remove `six` (no longer needed as 2.x is no longer supported) --- Pipfile | 1 - tests/tests.py | 31 ------------------------------- zappa/wsgi.py | 8 ++++---- 3 files changed, 4 insertions(+), 36 deletions(-) diff --git a/Pipfile b/Pipfile index 0b6cf396f..28839f094 100644 --- a/Pipfile +++ b/Pipfile @@ -35,7 +35,6 @@ python-slugify = "*" PyYAML = "*" # previous versions don't work with urllib3 1.24 requests = ">=2.20.0" -six = "*" toml = "*" tqdm = "*" troposphere = ">=3.0" diff --git a/tests/tests.py b/tests/tests.py index 96d8cb8c6..8ffa81e4e 100644 --- a/tests/tests.py +++ b/tests/tests.py @@ -740,37 +740,6 @@ def test_wsgi_event(self): request = create_wsgi_request(event) def test_wsgi_event__handle_space_in_xforwardedfor(self): - - ## This is a pre-proxy+ event - # event = { - # "body": "", - # "headers": { - # "Via": "1.1 e604e934e9195aaf3e36195adbcb3e18.cloudfront.net (CloudFront)", - # "Accept-Language": "en-US,en;q=0.5", - # "Accept-Encoding": "gzip", - # "CloudFront-Is-SmartTV-Viewer": "false", - # "CloudFront-Forwarded-Proto": "https", - # "X-Forwarded-For": "109.81.209.118, 216.137.58.43", - # "CloudFront-Viewer-Country": "CZ", - # "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", - # "X-Forwarded-Proto": "https", - # "X-Amz-Cf-Id": "LZeP_TZxBgkDt56slNUr_H9CHu1Us5cqhmRSswOh1_3dEGpks5uW-g==", - # "CloudFront-Is-Tablet-Viewer": "false", - # "X-Forwarded-Port": "443", - # "CloudFront-Is-Mobile-Viewer": "false", - # "CloudFront-Is-Desktop-Viewer": "true", - # "Content-Type": "application/json" - # }, - # "params": { - # "parameter_1": "asdf1", - # "parameter_2": "asdf2", - # }, - # "method": "POST", - # "query": { - # "dead": "beef" - # } - # } - event = { "body": None, "resource": "/", diff --git a/zappa/wsgi.py b/zappa/wsgi.py index c33988aa4..e8c21a8f5 100644 --- a/zappa/wsgi.py +++ b/zappa/wsgi.py @@ -1,9 +1,9 @@ import base64 import logging import sys +from io import BytesIO from urllib.parse import urlencode -import six from requestlogger import ApacheFormatter from werkzeug import urls @@ -77,12 +77,12 @@ def create_wsgi_request( body = base64.b64decode(encoded_body) else: body = event_info["body"] - if isinstance(body, six.string_types): + if isinstance(body, str): body = body.encode("utf-8") else: body = event_info["body"] - if isinstance(body, six.string_types): + if isinstance(body, str): body = body.encode("utf-8") # Make header names canonical, e.g. content-type => Content-Type @@ -129,7 +129,7 @@ def create_wsgi_request( environ["CONTENT_TYPE"] = headers["Content-Type"] # This must be Bytes or None - environ["wsgi.input"] = six.BytesIO(body) + environ["wsgi.input"] = BytesIO(body) if body: environ["CONTENT_LENGTH"] = str(len(body)) else: From 678202e0e4618e540bf069a3a3fd410e67240ba8 Mon Sep 17 00:00:00 2001 From: monkut Date: Fri, 12 Aug 2022 13:25:36 +0900 Subject: [PATCH 03/12] :white_check_mark: add testcase for SUPPORTED_VERSION check to increase code coverage. --- tests/tests.py | 10 ++++++++++ tests/utils.py | 6 ++++++ 2 files changed, 16 insertions(+) diff --git a/tests/tests.py b/tests/tests.py index 8ffa81e4e..681694a7d 100644 --- a/tests/tests.py +++ b/tests/tests.py @@ -57,6 +57,8 @@ ) from zappa.wsgi import common_log, create_wsgi_request +from .utils import get_invalid_sys_versioninfo + def random_string(length): return "".join(random.choice(string.printable) for _ in range(length)) @@ -2721,6 +2723,14 @@ def test_delete_lambda_concurrency(self, client): FunctionName="abc", ) + @mock.patch("sys.version_info", new_callable=get_invalid_sys_versioninfo) + def test_unsupported_version_error(self, m): + import sys + from importlib import reload + with self.assertRaises(RuntimeError): + import zappa + reload(zappa) + if __name__ == "__main__": unittest.main() diff --git a/tests/utils.py b/tests/utils.py index 91e588cc4..923109b21 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -1,6 +1,7 @@ import functools import os from contextlib import contextmanager +from collections import namedtuple import boto3 import placebo @@ -72,3 +73,8 @@ def stub_open(*args, **kwargs): with patch("__builtin__.open", stub_open): yield mock_open, mock_file + + +def get_invalid_sys_versioninfo() -> tuple: + invalid_versioninfo = namedtuple("version_info", ["major", "minor", "micro", "releaselevel", "serial"]) + return invalid_versioninfo(3, 6, 1, "final", 0) From 8bda3cee437632015e903764760f28740a243411 Mon Sep 17 00:00:00 2001 From: monkut Date: Fri, 12 Aug 2022 13:26:09 +0900 Subject: [PATCH 04/12] :art: run black/isort --- tests/tests.py | 2 ++ tests/utils.py | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/tests.py b/tests/tests.py index 681694a7d..902382379 100644 --- a/tests/tests.py +++ b/tests/tests.py @@ -2727,8 +2727,10 @@ def test_delete_lambda_concurrency(self, client): def test_unsupported_version_error(self, m): import sys from importlib import reload + with self.assertRaises(RuntimeError): import zappa + reload(zappa) diff --git a/tests/utils.py b/tests/utils.py index 923109b21..0ca85b668 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -1,7 +1,7 @@ import functools import os -from contextlib import contextmanager from collections import namedtuple +from contextlib import contextmanager import boto3 import placebo From 96958afa05662aeb0a50317d252b01f21bf61e73 Mon Sep 17 00:00:00 2001 From: monkut Date: Fri, 12 Aug 2022 18:11:09 +0900 Subject: [PATCH 05/12] :wrench: rename function for clarity --- tests/tests.py | 4 ++-- tests/utils.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/tests.py b/tests/tests.py index 902382379..fcdf3ef5f 100644 --- a/tests/tests.py +++ b/tests/tests.py @@ -57,7 +57,7 @@ ) from zappa.wsgi import common_log, create_wsgi_request -from .utils import get_invalid_sys_versioninfo +from .utils import get_unsupported_sys_versioninfo def random_string(length): @@ -2723,7 +2723,7 @@ def test_delete_lambda_concurrency(self, client): FunctionName="abc", ) - @mock.patch("sys.version_info", new_callable=get_invalid_sys_versioninfo) + @mock.patch("sys.version_info", new_callable=get_unsupported_sys_versioninfo) def test_unsupported_version_error(self, m): import sys from importlib import reload diff --git a/tests/utils.py b/tests/utils.py index 0ca85b668..d40119cc4 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -75,6 +75,6 @@ def stub_open(*args, **kwargs): yield mock_open, mock_file -def get_invalid_sys_versioninfo() -> tuple: +def get_unsupported_sys_versioninfo() -> tuple: invalid_versioninfo = namedtuple("version_info", ["major", "minor", "micro", "releaselevel", "serial"]) return invalid_versioninfo(3, 6, 1, "final", 0) From 71d5b04562831fddb2aa4aa539f7488b39b12a2f Mon Sep 17 00:00:00 2001 From: monkut Date: Fri, 12 Aug 2022 18:11:59 +0900 Subject: [PATCH 06/12] :fire: remove unnecessary import --- tests/tests.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/tests.py b/tests/tests.py index fcdf3ef5f..adde57118 100644 --- a/tests/tests.py +++ b/tests/tests.py @@ -2725,7 +2725,6 @@ def test_delete_lambda_concurrency(self, client): @mock.patch("sys.version_info", new_callable=get_unsupported_sys_versioninfo) def test_unsupported_version_error(self, m): - import sys from importlib import reload with self.assertRaises(RuntimeError): From 5869e47255bf0f1046d83a4f78d4817d2867a9ce Mon Sep 17 00:00:00 2001 From: monkut Date: Fri, 12 Aug 2022 18:12:23 +0900 Subject: [PATCH 07/12] :wrench: change name of unused mock instance --- tests/tests.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/tests.py b/tests/tests.py index adde57118..292a65006 100644 --- a/tests/tests.py +++ b/tests/tests.py @@ -2724,7 +2724,7 @@ def test_delete_lambda_concurrency(self, client): ) @mock.patch("sys.version_info", new_callable=get_unsupported_sys_versioninfo) - def test_unsupported_version_error(self, m): + def test_unsupported_version_error(self, *_): from importlib import reload with self.assertRaises(RuntimeError): From 62a53ed92445eaa3ab444df5bf98488562147cb8 Mon Sep 17 00:00:00 2001 From: monkut Date: Fri, 12 Aug 2022 18:45:01 +0900 Subject: [PATCH 08/12] :sparkles: (#879) Fix url decoding for query string --- tests/tests.py | 13 +++++++++++++ zappa/wsgi.py | 1 + 2 files changed, 14 insertions(+) diff --git a/tests/tests.py b/tests/tests.py index 292a65006..64d80c1c0 100644 --- a/tests/tests.py +++ b/tests/tests.py @@ -2732,6 +2732,19 @@ def test_unsupported_version_error(self, *_): reload(zappa) + def test_wsgi_query_string_unquoted(self): + event = { + "body": {}, + "headers": {}, + "pathParameters": {}, + "path": "/path/path1", + "httpMethod": "GET", + "queryStringParameters": {"a": "A,B", "b": "C#D"}, + "requestContext": {}, + } + request = create_wsgi_request(event) + self.assertEqual(request["QUERY_STRING"], "a=A,B&b=C#D") + if __name__ == "__main__": unittest.main() diff --git a/zappa/wsgi.py b/zappa/wsgi.py index e8c21a8f5..3325cd0bc 100644 --- a/zappa/wsgi.py +++ b/zappa/wsgi.py @@ -45,6 +45,7 @@ def create_wsgi_request( else: query = event_info.get("queryStringParameters", {}) query_string = urlencode(query) if query else "" + query_string = urls.url_unquote(query_string) if context_header_mappings: for key, value in context_header_mappings.items(): From bafaba1b63f770e83250eca7adafa7f97765c592 Mon Sep 17 00:00:00 2001 From: monkut Date: Fri, 12 Aug 2022 19:16:59 +0900 Subject: [PATCH 09/12] :wrench: change docstring type multi-line comment to standard multiline comment :sparkles: handle case where "requestContext" is not provided by the event. > Systems calling the Lambda (other than API Gateway) may not provide the field requestContext in the event. :white_check_mark: add testcases --- tests/tests.py | 83 ++++++++++++++++++++++++++++++++++++++++++++++++++ zappa/wsgi.py | 44 +++++++++++++------------- 2 files changed, 105 insertions(+), 22 deletions(-) diff --git a/tests/tests.py b/tests/tests.py index 64d80c1c0..284da7306 100644 --- a/tests/tests.py +++ b/tests/tests.py @@ -1009,6 +1009,89 @@ def test_wsgi_without_body(self): response_tuple = collections.namedtuple("Response", ["status_code", "content"]) response = response_tuple(200, "hello") + def test_wsgi_without_requestcontext(self): + event = { + "body": None, + "resource": "/", + "queryStringParameters": None, + "pathParameters": None, + "headers": { + "Via": "1.1 38205a04d96d60185e88658d3185ccee.cloudfront.net (CloudFront)", + "Accept-Language": "en-US,en;q=0.5", + "Accept-Encoding": "gzip, deflate, br", + "CloudFront-Is-SmartTV-Viewer": "false", + "CloudFront-Forwarded-Proto": "https", + "X-Forwarded-For": "71.231.27.57, 104.246.180.51", + "CloudFront-Viewer-Country": "US", + "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", + "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:45.0) Gecko/20100101 Firefox/45.0", + "Host": "xo2z7zafjh.execute-api.us-east-1.amazonaws.com", + "X-Forwarded-Proto": "https", + "Cookie": "zappa=AQ4", + "CloudFront-Is-Tablet-Viewer": "false", + "X-Forwarded-Port": "443", + "Referer": "https://xo8z7zafjh.execute-api.us-east-1.amazonaws.com/former/post", + "CloudFront-Is-Mobile-Viewer": "false", + "X-Amz-Cf-Id": "31zxcUcVyUxBOMk320yh5NOhihn5knqrlYQYpGGyOngKKwJb0J0BAQ==", + "CloudFront-Is-Desktop-Viewer": "true", + }, + "stageVariables": None, + "path": "/", + "isBase64Encoded": True, + } + environ = create_wsgi_request(event, trailing_slash=False) + self.assertTrue(environ) + + def test_wsgi_with_authorizer(self): + expected_remote_user = "remote-user" + authorizer = { + "principalId": expected_remote_user, + } + event = { + "body": None, + "resource": "/", + "requestContext": { + "resourceId": "6cqjw9qu0b", + "apiId": "9itr2lba55", + "resourcePath": "/", + "httpMethod": "POST", + "requestId": "c17cb1bf-867c-11e6-b938-ed697406e3b5", + "accountId": "724336686645", + "authorizer": authorizer, + "stage": "devorr", + }, + "queryStringParameters": None, + "httpMethod": "POST", + "pathParameters": None, + "headers": { + "Via": "1.1 38205a04d96d60185e88658d3185ccee.cloudfront.net (CloudFront)", + "Accept-Language": "en-US,en;q=0.5", + "Accept-Encoding": "gzip, deflate, br", + "CloudFront-Is-SmartTV-Viewer": "false", + "CloudFront-Forwarded-Proto": "https", + "X-Forwarded-For": "71.231.27.57, 104.246.180.51", + "CloudFront-Viewer-Country": "US", + "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", + "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:45.0) Gecko/20100101 Firefox/45.0", + "Host": "xo2z7zafjh.execute-api.us-east-1.amazonaws.com", + "X-Forwarded-Proto": "https", + "Cookie": "zappa=AQ4", + "CloudFront-Is-Tablet-Viewer": "false", + "X-Forwarded-Port": "443", + "Referer": "https://xo8z7zafjh.execute-api.us-east-1.amazonaws.com/former/post", + "CloudFront-Is-Mobile-Viewer": "false", + "X-Amz-Cf-Id": "31zxcUcVyUxBOMk320yh5NOhihn5knqrlYQYpGGyOngKKwJb0J0BAQ==", + "CloudFront-Is-Desktop-Viewer": "true", + }, + "stageVariables": None, + "path": "/", + "isBase64Encoded": True, + } + + environ = create_wsgi_request(event, trailing_slash=False) + self.assertEqual(environ["REMOTE_USER"], expected_remote_user) + self.assertDictEqual(environ["API_GATEWAY_AUTHORIZER"], authorizer) + def test_wsgi_from_apigateway_testbutton(self): """ API Gateway resources have a "test bolt" button on methods. diff --git a/zappa/wsgi.py b/zappa/wsgi.py index 3325cd0bc..3878a8554 100644 --- a/zappa/wsgi.py +++ b/zappa/wsgi.py @@ -25,20 +25,19 @@ def create_wsgi_request( Given some event_info via API Gateway, create and return a valid WSGI request environ. """ - method = event_info["httpMethod"] + method = event_info.get("httpMethod", None) headers = merge_headers(event_info) or {} # Allow for the AGW console 'Test' button to work (Pull #735) - """ - API Gateway and ALB both started allowing for multi-value querystring - params in Nov. 2018. If there aren't multi-value params present, then - it acts identically to 'queryStringParameters', so we can use it as a - drop-in replacement. - - The one caveat here is that ALB will only include _one_ of - queryStringParameters _or_ multiValueQueryStringParameters, which means - we have to check for the existence of one and then fall back to the - other. - """ + # API Gateway and ALB both started allowing for multi-value querystring + # params in Nov. 2018. If there aren't multi-value params present, then + # it acts identically to 'queryStringParameters', so we can use it as a + # drop-in replacement. + # + # The one caveat here is that ALB will only include _one_ of + # queryStringParameters _or_ multiValueQueryStringParameters, which means + # we have to check for the existence of one and then fall back to the + # other. + if "multiValueQueryStringParameters" in event_info: query = event_info["multiValueQueryStringParameters"] query_string = urlencode(query, doseq=True) if query else "" @@ -60,13 +59,6 @@ def create_wsgi_request( if header_val is not None: headers[key] = header_val - # Extract remote user from context if Authorizer is enabled - remote_user = None - if event_info["requestContext"].get("authorizer"): - remote_user = event_info["requestContext"]["authorizer"].get("principalId") - elif event_info["requestContext"].get("identity"): - remote_user = event_info["requestContext"]["identity"].get("userArn") - # Related: https://github.com/Miserlou/Zappa/issues/677 # https://github.com/Miserlou/Zappa/issues/683 # https://github.com/Miserlou/Zappa/issues/696 @@ -124,6 +116,17 @@ def create_wsgi_request( "wsgi.run_once": False, } + # Systems calling the Lambda (other than API Gateway) may not provide the field requestContext + # Extract remote_user, authorizer if Authorizer is enabled + remote_user = None + if "requestContext" in event_info: + authorizer = event_info["requestContext"].get("authorizer", None) + if authorizer: + remote_user = authorizer.get("principalId") + environ["API_GATEWAY_AUTHORIZER"] = authorizer + elif event_info["requestContext"].get("identity"): + remote_user = event_info["requestContext"]["identity"].get("userArn") + # Input processing if method in ["POST", "PUT", "PATCH", "DELETE"]: if "Content-Type" in headers: @@ -150,9 +153,6 @@ def create_wsgi_request( if remote_user: environ["REMOTE_USER"] = remote_user - if event_info["requestContext"].get("authorizer"): - environ["API_GATEWAY_AUTHORIZER"] = event_info["requestContext"]["authorizer"] - return environ From bef77fcb5b5b7858ff102c63751aafc9018a6735 Mon Sep 17 00:00:00 2001 From: monkut Date: Tue, 27 Sep 2022 09:32:39 +0900 Subject: [PATCH 10/12] :fire: remove duplicate comment --- zappa/wsgi.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zappa/wsgi.py b/zappa/wsgi.py index 3878a8554..3b0729c36 100644 --- a/zappa/wsgi.py +++ b/zappa/wsgi.py @@ -94,7 +94,7 @@ def create_wsgi_request( # The last one is the cloudfront proxy ip. The second to last is the real client ip. # Everything else is user supplied and untrustworthy. addresses = [addr.strip() for addr in x_forwarded_for.split(",")] - remote_addr = addresses[-2] # get client ip + remote_addr = addresses[-2] else: remote_addr = x_forwarded_for or "127.0.0.1" From bff61ef83a148d07be401061a5476fc7bc37ece9 Mon Sep 17 00:00:00 2001 From: monkut Date: Tue, 27 Sep 2022 09:33:52 +0900 Subject: [PATCH 11/12] :pencil: add docstring to util function, `get_unsupported_sys_versioninfo()` --- tests/utils.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/utils.py b/tests/utils.py index d40119cc4..db48b0db5 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -76,5 +76,6 @@ def stub_open(*args, **kwargs): def get_unsupported_sys_versioninfo() -> tuple: + """Mock used to test the python unsupported version testcase""" invalid_versioninfo = namedtuple("version_info", ["major", "minor", "micro", "releaselevel", "serial"]) return invalid_versioninfo(3, 6, 1, "final", 0) From e78cd9c58c177928332545fad036b19bfe845a79 Mon Sep 17 00:00:00 2001 From: monkut Date: Thu, 6 Oct 2022 16:16:06 +0900 Subject: [PATCH 12/12] :fire: remove double-underscore --- tests/tests.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/tests.py b/tests/tests.py index df1e8cd51..589211684 100644 --- a/tests/tests.py +++ b/tests/tests.py @@ -763,7 +763,7 @@ def test_wsgi_event(self): request = create_wsgi_request(event) - def test_wsgi_event__handle_space_in_xforwardedfor(self): + def test_wsgi_event_handle_space_in_xforwardedfor(self): event = { "body": None, "resource": "/",