def test_limited_stream_disconnection(): io = BytesIO(b"A bit of content") # disconnect detection on out of bytes stream = wsgi.LimitedStream(io, 255) with pytest.raises(ClientDisconnected): stream.read() # disconnect detection because file close io = BytesIO(b"x" * 255) io.close() stream = wsgi.LimitedStream(io, 255) with pytest.raises(ClientDisconnected): stream.read()
def test_limited_stream_disconnection(self): io = BytesIO(b'A bit of content') # disconnect detection on out of bytes stream = wsgi.LimitedStream(io, 255) with self.assert_raises(ClientDisconnected): stream.read() # disconnect detection because file close io = BytesIO(b'x' * 255) io.close() stream = wsgi.LimitedStream(io, 255) with self.assert_raises(ClientDisconnected): stream.read()
def handle_request(app, event, context): if u"multiValueHeaders" in event: headers = Headers(event["multiValueHeaders"]) else: headers = Headers(event["headers"]) strip_stage_path = os.environ.get("STRIP_STAGE_PATH", "").lower().strip() in [ "yes", "y", "true", "t", "1", ] if u"apigw.tencentcs.com" in headers.get(u"Host", u"") and not strip_stage_path: script_name = "/{}".format(event["requestContext"].get(u"stage", "")) else: script_name = "" path_info = event["path"] base_path = os.environ.get("API_GATEWAY_BASE_PATH") print(base_path) if base_path: script_name = "/" + base_path if path_info.startswith(script_name): path_info = path_info[len(script_name) :] or "/" if u"body" in event: body = event[u"body"] or "" else: body = "" if event.get("isBase64Encoded", False): body = base64.b64decode(body) if isinstance(body, string_types): body = to_bytes(body, charset="utf-8") environ = { "CONTENT_LENGTH": str(len(body)), "CONTENT_TYPE": headers.get(u"Content-Type", ""), "PATH_INFO": url_unquote(path_info), "QUERY_STRING": encode_query_string(event), "REMOTE_ADDR": event["requestContext"] .get(u"identity", {}) .get(u"sourceIp", ""), "REMOTE_USER": event["requestContext"] .get(u"authorizer", {}) .get(u"principalId", ""), "REQUEST_METHOD": event["httpMethod"], "SCRIPT_NAME": script_name, "SERVER_NAME": headers.get(u"Host", "Serverless"), "SERVER_PORT": headers.get(u"X-Forwarded-Port", "80"), "SERVER_PROTOCOL": "HTTP/1.1", "wsgi.errors": sys.stderr, "wsgi.input": BytesIO(body), "wsgi.multiprocess": False, "wsgi.multithread": False, "wsgi.run_once": False, "wsgi.url_scheme": headers.get(u"X-Forwarded-Proto", "http"), "wsgi.version": (1, 0), "serverless.authorizer": event["requestContext"].get(u"authorizer"), "serverless.event": event, "serverless.context": context, "API_GATEWAY_AUTHORIZER": event["requestContext"].get(u"authorizer"), "event": event, "context": context, } for key, value in environ.items(): if isinstance(value, string_types): environ[key] = wsgi_encoding_dance(value) for key, value in headers.items(): key = "HTTP_" + key.upper().replace("-", "_") if key not in ("HTTP_CONTENT_TYPE", "HTTP_CONTENT_LENGTH"): environ[key] = value response = Response.from_app(app, environ) returndict = {u"statusCode": response.status_code} if u"multiValueHeaders" in event: returndict["multiValueHeaders"] = group_headers(response.headers) else: returndict["headers"] = split_headers(response.headers) if event.get("requestContext").get("elb"): # If the request comes from ALB we need to add a status description returndict["statusDescription"] = u"%d %s" % ( response.status_code, HTTP_STATUS_CODES[response.status_code], ) if response.data: mimetype = response.mimetype or "text/plain" if ( mimetype.startswith("text/") or mimetype in TEXT_MIME_TYPES ) and not response.headers.get("Content-Encoding", ""): returndict["body"] = response.get_data(as_text=True) returndict["isBase64Encoded"] = False else: returndict["body"] = base64.b64encode(response.data).decode("utf-8") returndict["isBase64Encoded"] = True return returndict
def handle_request(app, event, context): if event.get("source") in ["aws.events", "serverless-plugin-warmup"]: return {} headers = Headers(event[u"headers"]) if u"amazonaws.com" in headers.get(u"Host", u""): script_name = "/{}".format(event[u"requestContext"].get(u"stage", "")) else: script_name = "" # If a user is using a custom domain on API Gateway, they may have a base # path in their URL. This allows us to strip it out via an optional # environment variable. path_info = event[u"path"] base_path = os.environ.get("API_GATEWAY_BASE_PATH", "") if base_path: script_name = "/" + base_path if path_info.startswith(script_name): path_info = path_info[len(script_name):] body = event[u"body"] or "" if event.get("isBase64Encoded", False): body = base64.b64decode(body) if isinstance(body, string_types): body = to_bytes(body, charset="utf-8") print(event) environ = { "CONTENT_LENGTH": str(len(body)), "CONTENT_TYPE": headers.get(u"Content-Type", ""), "PATH_INFO": path_info, "QUERY_STRING": url_encode(event.get(u"queryStringParameters") or {}), "REMOTE_ADDR": event[u"requestContext"].get(u"identity", {}).get(u"sourceIp", ""), "REMOTE_USER": event[u"requestContext"].get(u"authorizer", {}).get(u"principalId", ""), "REQUEST_METHOD": event[u"httpMethod"], "SCRIPT_NAME": script_name, "SERVER_NAME": headers.get(u"Host", "lambda"), "SERVER_PORT": headers.get(u"X-Forwarded-Port", "80"), "SERVER_PROTOCOL": "HTTP/1.1", "wsgi.errors": sys.stderr, "wsgi.input": BytesIO(body), "wsgi.multiprocess": False, "wsgi.multithread": False, "wsgi.run_once": False, "wsgi.url_scheme": headers.get(u"X-Forwarded-Proto", "http"), "wsgi.version": (1, 0), "serverless.authorizer": event[u"requestContext"].get(u"authorizer"), "serverless.event": event, "serverless.context": context, # TODO: Deprecate the following entries, as they do not comply with the WSGI # spec. For custom variables, the spec says: # # Finally, the environ dictionary may also contain server-defined variables. # These variables should be named using only lower-case letters, numbers, dots, # and underscores, and should be prefixed with a name that is unique to the # defining server or gateway. "API_GATEWAY_AUTHORIZER": event[u"requestContext"].get(u"authorizer"), "event": event, "context": context, } for key, value in environ.items(): if isinstance(value, string_types): environ[key] = wsgi_encoding_dance(value) for key, value in headers.items(): key = "HTTP_" + key.upper().replace("-", "_") if key not in ("HTTP_CONTENT_TYPE", "HTTP_CONTENT_LENGTH"): environ[key] = value response = Response.from_app(app, environ) returndict = { u"statusCode": response.status_code, u"headers": split_headers(response.headers), } if event.get("requestContext").get("elb"): # If the request comes from ALB we need to add a status description returndict["statusDescription"] = u"%d %s" % ( response.status_code, HTTP_STATUS_CODES[response.status_code], ) if response.data: mimetype = response.mimetype or "text/plain" if (mimetype.startswith("text/") or mimetype in TEXT_MIME_TYPES) and not response.headers.get( "Content-Encoding", ""): returndict["body"] = response.get_data(as_text=True) returndict["isBase64Encoded"] = False else: returndict["body"] = base64.b64encode( response.data).decode("utf-8") returndict["isBase64Encoded"] = True return returndict
def handler(event, context): headers = Headers(event[u'headers']) if headers.get(u'Host', u'').endswith(u'.amazonaws.com'): script_name = '/{}'.format(event[u'requestContext'].get(u'stage', '')) else: script_name = '' # If a user is using a custom domain on API Gateway, they may have a base # path in their URL. This allows us to strip it out via an optional # environment variable. path_info = event[u'path'] base_path = os.environ.get('API_GATEWAY_BASE_PATH', '') if base_path: script_name = '/' + base_path if path_info.startswith(script_name): path_info = path_info[len(script_name):] body = event[u'body'] or '' if event.get('isBase64Encoded', False): body = base64.b64decode(body) if isinstance(body, string_types): body = to_bytes(body) environ = { 'API_GATEWAY_AUTHORIZER': event[u'requestContext'].get(u'authorizer', None), 'CONTENT_LENGTH': str(len(body)), 'CONTENT_TYPE': headers.get(u'Content-Type', ''), 'PATH_INFO': path_info, 'QUERY_STRING': url_encode(event.get(u'queryStringParameters', None) or {}), 'REMOTE_ADDR': event[u'requestContext'].get(u'identity', {}).get(u'sourceIp', ''), 'REMOTE_USER': event[u'requestContext'].get(u'authorizer', {}).get(u'principalId', ''), 'REQUEST_METHOD': event[u'httpMethod'], 'SCRIPT_NAME': script_name, 'SERVER_NAME': headers.get(u'Host', 'lambda'), 'SERVER_PORT': headers.get(u'X-Forwarded-Port', '80'), 'SERVER_PROTOCOL': 'HTTP/1.1', 'event': event, 'context': context, 'wsgi.errors': sys.stderr, 'wsgi.input': BytesIO(body), 'wsgi.multiprocess': False, 'wsgi.multithread': False, 'wsgi.run_once': False, 'wsgi.url_scheme': headers.get(u'X-Forwarded-Proto', 'http'), 'wsgi.version': (1, 0), } for key, value in environ.items(): if isinstance(value, string_types): environ[key] = wsgi_encoding_dance(value) for key, value in headers.items(): key = 'HTTP_' + key.upper().replace('-', '_') if key not in ('HTTP_CONTENT_TYPE', 'HTTP_CONTENT_LENGTH'): environ[key] = value response = Response.from_app(wsgi_app, environ) # If there are multiple Set-Cookie headers, create case-mutated variations # in order to pass them through APIGW. This is a hack that's currently # needed. See: https://github.com/logandk/serverless-wsgi/issues/11 # Source: https://github.com/Miserlou/Zappa/blob/master/zappa/middleware.py new_headers = [x for x in response.headers if x[0] != 'Set-Cookie'] cookie_headers = [x for x in response.headers if x[0] == 'Set-Cookie'] if len(cookie_headers) > 1: for header, new_name in zip(cookie_headers, all_casings('Set-Cookie')): new_headers.append((new_name, header[1])) elif len(cookie_headers) == 1: new_headers.extend(cookie_headers) returndict = { u'statusCode': response.status_code, u'headers': dict(new_headers) } if response.data: mimetype = response.mimetype or 'text/plain' if ((mimetype.startswith('text/') or mimetype in TEXT_MIME_TYPES) and not response.headers.get('Content-Encoding', '')): returndict['body'] = response.get_data(as_text=True) else: returndict['body'] = base64.b64encode( response.data).decode('utf-8') returndict['isBase64Encoded'] = 'true' return returndict
def test_limiting(self): data = b'foo=Hello+World&bar=baz' req = Request.from_values( input_stream=BytesIO(data), content_length=len(data), content_type='application/x-www-form-urlencoded', method='POST') req.max_content_length = 400 strict_eq(req.form['foo'], u'Hello World') req = Request.from_values( input_stream=BytesIO(data), content_length=len(data), content_type='application/x-www-form-urlencoded', method='POST') req.max_form_memory_size = 7 pytest.raises(RequestEntityTooLarge, lambda: req.form['foo']) req = Request.from_values( input_stream=BytesIO(data), content_length=len(data), content_type='application/x-www-form-urlencoded', method='POST') req.max_form_memory_size = 400 strict_eq(req.form['foo'], u'Hello World') data = b'foo=Hello+World&bar=\xd6\xd0\xce\xc4' req = Request.from_values( input_stream=BytesIO(data), content_length=len(data), content_type='application/x-www-form-urlencoded; charset=GBK', method='POST') req.max_content_length = 400 strict_eq(req.form['bar'], u'中文') data = (b'--foo\r\nContent-Disposition: form-field; name=foo\r\n\r\n' b'Hello World\r\n' b'--foo\r\nContent-Disposition: form-field; name=bar\r\n\r\n' b'bar=baz\r\n--foo--') req = Request.from_values( input_stream=BytesIO(data), content_length=len(data), content_type='multipart/form-data; boundary=foo', method='POST') req.max_content_length = 4 pytest.raises(RequestEntityTooLarge, lambda: req.form['foo']) req = Request.from_values( input_stream=BytesIO(data), content_length=len(data), content_type='multipart/form-data; boundary=foo', method='POST') req.max_content_length = 400 strict_eq(req.form['foo'], u'Hello World') req = Request.from_values( input_stream=BytesIO(data), content_length=len(data), content_type='multipart/form-data; boundary=foo', method='POST') req.max_form_memory_size = 7 pytest.raises(RequestEntityTooLarge, lambda: req.form['foo']) req = Request.from_values( input_stream=BytesIO(data), content_length=len(data), content_type='multipart/form-data; boundary=foo', method='POST') req.max_form_memory_size = 400 strict_eq(req.form['foo'], u'Hello World')
def test_limited_stream(): class RaisingLimitedStream(wsgi.LimitedStream): def on_exhausted(self): raise BadRequest('input stream exhausted') io = BytesIO(b'123456') stream = RaisingLimitedStream(io, 3) strict_eq(stream.read(), b'123') pytest.raises(BadRequest, stream.read) io = BytesIO(b'123456') stream = RaisingLimitedStream(io, 3) strict_eq(stream.tell(), 0) strict_eq(stream.read(1), b'1') strict_eq(stream.tell(), 1) strict_eq(stream.read(1), b'2') strict_eq(stream.tell(), 2) strict_eq(stream.read(1), b'3') strict_eq(stream.tell(), 3) pytest.raises(BadRequest, stream.read) io = BytesIO(b'123456\nabcdefg') stream = wsgi.LimitedStream(io, 9) strict_eq(stream.readline(), b'123456\n') strict_eq(stream.readline(), b'ab') io = BytesIO(b'123456\nabcdefg') stream = wsgi.LimitedStream(io, 9) strict_eq(stream.readlines(), [b'123456\n', b'ab']) io = BytesIO(b'123456\nabcdefg') stream = wsgi.LimitedStream(io, 9) strict_eq(stream.readlines(2), [b'12']) strict_eq(stream.readlines(2), [b'34']) strict_eq(stream.readlines(), [b'56\n', b'ab']) io = BytesIO(b'123456\nabcdefg') stream = wsgi.LimitedStream(io, 9) strict_eq(stream.readline(100), b'123456\n') io = BytesIO(b'123456\nabcdefg') stream = wsgi.LimitedStream(io, 9) strict_eq(stream.readlines(100), [b'123456\n', b'ab']) io = BytesIO(b'123456') stream = wsgi.LimitedStream(io, 3) strict_eq(stream.read(1), b'1') strict_eq(stream.read(1), b'2') strict_eq(stream.read(), b'3') strict_eq(stream.read(), b'') io = BytesIO(b'123456') stream = wsgi.LimitedStream(io, 3) strict_eq(stream.read(-1), b'123') io = BytesIO(b'123456') stream = wsgi.LimitedStream(io, 0) strict_eq(stream.read(-1), b'') io = StringIO(u'123456') stream = wsgi.LimitedStream(io, 0) strict_eq(stream.read(-1), u'') io = StringIO(u'123\n456\n') stream = wsgi.LimitedStream(io, 8) strict_eq(list(stream), [u'123\n', u'456\n'])
def handler(event, context): if event.get("source") in ["aws.events", "serverless-plugin-warmup"]: return {} headers = Headers(event[u"headers"]) if u"amazonaws.com" in headers.get(u"Host", u""): script_name = "/{}".format(event[u"requestContext"].get(u"stage", "")) else: script_name = "" print(script_name) # If a user is using a custom domain on API Gateway, they may have a base # path in their URL. This allows us to strip it out via an optional # environment variable. path_info = event[u"path"] base_path = os.environ.get("API_GATEWAY_BASE_PATH", "") if base_path: script_name = "/" + base_path if path_info.startswith(script_name): path_info = path_info[len(script_name):] body = event[u"body"] or "" if event.get("isBase64Encoded", False): body = base64.b64decode(body) if isinstance(body, string_types): body = to_bytes(body, charset="utf-8") print(script_name) environ = { "API_GATEWAY_AUTHORIZER": event[u"requestContext"].get(u"authorizer"), "CONTENT_LENGTH": str(len(body)), "CONTENT_TYPE": headers.get(u"Content-Type", ""), "PATH_INFO": path_info, "QUERY_STRING": url_encode(event.get(u"queryStringParameters") or {}), "REMOTE_ADDR": event[u"requestContext"].get(u"identity", {}).get(u"sourceIp", ""), "REMOTE_USER": event[u"requestContext"].get(u"authorizer", {}).get(u"principalId", ""), "REQUEST_METHOD": event[u"httpMethod"], "SCRIPT_NAME": script_name, "SERVER_NAME": headers.get(u"Host", "lambda"), "SERVER_PORT": headers.get(u"X-Forwarded-Port", "80"), "SERVER_PROTOCOL": "HTTP/1.1", "event": event, "context": context, "wsgi.errors": sys.stderr, "wsgi.input": BytesIO(body), "wsgi.multiprocess": False, "wsgi.multithread": False, "wsgi.run_once": False, "wsgi.url_scheme": headers.get(u"X-Forwarded-Proto", "http"), "wsgi.version": (1, 0), } for key, value in environ.items(): if isinstance(value, string_types): environ[key] = wsgi_encoding_dance(value) for key, value in headers.items(): key = "HTTP_" + key.upper().replace("-", "_") if key not in ("HTTP_CONTENT_TYPE", "HTTP_CONTENT_LENGTH"): environ[key] = value print(environ) response = Response.from_app(wsgi_app, environ) print(response) # If there are multiple Set-Cookie headers, create case-mutated variations # in order to pass them through APIGW. This is a hack that's currently # needed. See: https://github.com/logandk/serverless-wsgi/issues/11 # Source: https://github.com/Miserlou/Zappa/blob/master/zappa/middleware.py new_headers = [x for x in response.headers if x[0] != "Set-Cookie"] cookie_headers = [x for x in response.headers if x[0] == "Set-Cookie"] if len(cookie_headers) > 1: for header, new_name in zip(cookie_headers, all_casings("Set-Cookie")): new_headers.append((new_name, header[1])) elif len(cookie_headers) == 1: new_headers.extend(cookie_headers) returndict = { u"statusCode": response.status_code, u"headers": dict(new_headers) } if response.data: mimetype = response.mimetype or "text/plain" if (mimetype.startswith("text/") or mimetype in TEXT_MIME_TYPES) and not response.headers.get( "Content-Encoding", ""): returndict["body"] = response.get_data(as_text=True) else: returndict["body"] = base64.b64encode( response.data).decode("utf-8") returndict["isBase64Encoded"] = "true" return returndict
def now_handler(event, context): payload = json.loads(event['body']) headers = Headers(payload.get('headers', {})) body = payload.get('body', '') if body != '': if payload.get('encoding') == 'base64': body = base64.b64decode(body) if isinstance(body, string_types): body = to_bytes(body, charset='utf-8') url = urlparse(unquote(payload['path'])) query = url.query path = url.path environ = { 'CONTENT_LENGTH': str(len(body)), 'CONTENT_TYPE': headers.get('content-type', ''), 'PATH_INFO': path, 'QUERY_STRING': query, 'REMOTE_ADDR': headers.get( 'x-forwarded-for', headers.get('x-real-ip', payload.get('true-client-ip', ''))), 'REQUEST_METHOD': payload['method'], 'SERVER_NAME': headers.get('host', 'lambda'), 'SERVER_PORT': headers.get('x-forwarded-port', '80'), 'SERVER_PROTOCOL': 'HTTP/1.1', 'event': event, 'context': context, 'wsgi.errors': sys.stderr, 'wsgi.input': BytesIO(body), 'wsgi.multiprocess': False, 'wsgi.multithread': False, 'wsgi.run_once': False, 'wsgi.url_scheme': headers.get('x-forwarded-proto', 'http'), 'wsgi.version': (1, 0), } for key, value in environ.items(): if isinstance(value, string_types) and key != 'QUERY_STRING': environ[key] = wsgi_encoding_dance(value) for key, value in headers.items(): key = 'HTTP_' + key.upper().replace('-', '_') if key not in ('HTTP_CONTENT_TYPE', 'HTTP_CONTENT_LENGTH'): environ[key] = value response = Response.from_app(__NOW_HANDLER_FILENAME.app, environ) return_dict = { 'statusCode': response.status_code, 'headers': dict(response.headers) } if response.data: return_dict['body'] = base64.b64encode( response.data).decode('utf-8') return_dict['encoding'] = 'base64' return return_dict
def test_limited_stream(): class RaisingLimitedStream(wsgi.LimitedStream): def on_exhausted(self): raise BadRequest("input stream exhausted") io = BytesIO(b"123456") stream = RaisingLimitedStream(io, 3) strict_eq(stream.read(), b"123") pytest.raises(BadRequest, stream.read) io = BytesIO(b"123456") stream = RaisingLimitedStream(io, 3) strict_eq(stream.tell(), 0) strict_eq(stream.read(1), b"1") strict_eq(stream.tell(), 1) strict_eq(stream.read(1), b"2") strict_eq(stream.tell(), 2) strict_eq(stream.read(1), b"3") strict_eq(stream.tell(), 3) pytest.raises(BadRequest, stream.read) io = BytesIO(b"123456\nabcdefg") stream = wsgi.LimitedStream(io, 9) strict_eq(stream.readline(), b"123456\n") strict_eq(stream.readline(), b"ab") io = BytesIO(b"123456\nabcdefg") stream = wsgi.LimitedStream(io, 9) strict_eq(stream.readlines(), [b"123456\n", b"ab"]) io = BytesIO(b"123456\nabcdefg") stream = wsgi.LimitedStream(io, 9) strict_eq(stream.readlines(2), [b"12"]) strict_eq(stream.readlines(2), [b"34"]) strict_eq(stream.readlines(), [b"56\n", b"ab"]) io = BytesIO(b"123456\nabcdefg") stream = wsgi.LimitedStream(io, 9) strict_eq(stream.readline(100), b"123456\n") io = BytesIO(b"123456\nabcdefg") stream = wsgi.LimitedStream(io, 9) strict_eq(stream.readlines(100), [b"123456\n", b"ab"]) io = BytesIO(b"123456") stream = wsgi.LimitedStream(io, 3) strict_eq(stream.read(1), b"1") strict_eq(stream.read(1), b"2") strict_eq(stream.read(), b"3") strict_eq(stream.read(), b"") io = BytesIO(b"123456") stream = wsgi.LimitedStream(io, 3) strict_eq(stream.read(-1), b"123") io = BytesIO(b"123456") stream = wsgi.LimitedStream(io, 0) strict_eq(stream.read(-1), b"") io = StringIO(u"123456") stream = wsgi.LimitedStream(io, 0) strict_eq(stream.read(-1), u"") io = StringIO(u"123\n456\n") stream = wsgi.LimitedStream(io, 8) strict_eq(list(stream), [u"123\n", u"456\n"])
:copyright: (c) 2014 by the Werkzeug Team, see AUTHORS for more details. :license: BSD, see LICENSE for more details. """ import re import string import inspect from weakref import WeakKeyDictionary from datetime import datetime, date from itertools import chain from werkzeug._compat import iter_bytes, text_type, BytesIO, int_to_byte, \ range_type, integer_types _logger = None _empty_stream = BytesIO() _signature_cache = WeakKeyDictionary() _epoch_ord = date(1970, 1, 1).toordinal() _cookie_params = set((b'expires', b'path', b'comment', b'max-age', b'secure', b'httponly', b'version')) _legal_cookie_chars = (string.ascii_letters + string.digits + u"/=!#$%&'*+-.^_`|~:").encode('ascii') _cookie_quoting_map = { b',': b'\\054', b';': b'\\073', b'"': b'\\"', b'\\': b'\\\\', }
def handle_payload_v2(app, event, context): headers = Headers(event[u"headers"]) script_name = get_script_name(headers, event.get("requestContext", {})) path_info = event[u"rawPath"] body = event.get("body", "") body = get_body_bytes(event, body) headers["Cookie"] = "; ".join(event.get("cookies", [])) environ = { "CONTENT_LENGTH": str(len(body)), "CONTENT_TYPE": headers.get(u"Content-Type", ""), "PATH_INFO": url_unquote(path_info), "QUERY_STRING": url_encode(event.get(u"queryStringParameters", {})), "REMOTE_ADDR": event.get("requestContext", {}).get(u"http", {}).get(u"sourceIp", ""), "REMOTE_USER": event.get("requestContext", {}).get(u"authorizer", {}).get(u"principalId", ""), "REQUEST_METHOD": event.get("requestContext", {}).get("http", {}).get("method", ""), "SCRIPT_NAME": script_name, "SERVER_NAME": headers.get(u"Host", "lambda"), "SERVER_PORT": headers.get(u"X-Forwarded-Port", "80"), "SERVER_PROTOCOL": "HTTP/1.1", "wsgi.errors": sys.stderr, "wsgi.input": BytesIO(body), "wsgi.multiprocess": False, "wsgi.multithread": False, "wsgi.run_once": False, "wsgi.url_scheme": headers.get(u"X-Forwarded-Proto", "http"), "wsgi.version": (1, 0), "serverless.authorizer": event.get("requestContext", {}).get(u"authorizer"), "serverless.event": event, "serverless.context": context, # TODO: Deprecate the following entries, as they do not comply with the WSGI # spec. For custom variables, the spec says: # # Finally, the environ dictionary may also contain server-defined variables. # These variables should be named using only lower-case letters, numbers, dots, # and underscores, and should be prefixed with a name that is unique to the # defining server or gateway. "API_GATEWAY_AUTHORIZER": event.get("requestContext", {}).get(u"authorizer"), "event": event, "context": context, } environ = setup_environ_items(environ, headers) response = Response.from_app(app, environ) returndict = generate_response(response, event) return returndict
def handle_payload_v1(app, event, context): if u"multiValueHeaders" in event: headers = Headers(event[u"multiValueHeaders"]) else: headers = Headers(event[u"headers"]) script_name = get_script_name(headers, event.get("requestContext", {})) # If a user is using a custom domain on API Gateway, they may have a base # path in their URL. This allows us to strip it out via an optional # environment variable. path_info = event[u"path"] base_path = os.environ.get("API_GATEWAY_BASE_PATH") if base_path: script_name = "/" + base_path if path_info.startswith(script_name): path_info = path_info[len(script_name):] body = event[u"body"] or "" body = get_body_bytes(event, body) environ = { "CONTENT_LENGTH": str(len(body)), "CONTENT_TYPE": headers.get(u"Content-Type", ""), "PATH_INFO": url_unquote(path_info), "QUERY_STRING": encode_query_string(event), "REMOTE_ADDR": event.get(u"requestContext", {}).get(u"identity", {}).get(u"sourceIp", ""), "REMOTE_USER": event.get(u"requestContext", {}).get(u"authorizer", {}).get(u"principalId", ""), "REQUEST_METHOD": event.get(u"httpMethod", {}), "SCRIPT_NAME": script_name, "SERVER_NAME": headers.get(u"Host", "lambda"), "SERVER_PORT": headers.get(u"X-Forwarded-Port", "80"), "SERVER_PROTOCOL": "HTTP/1.1", "wsgi.errors": sys.stderr, "wsgi.input": BytesIO(body), "wsgi.multiprocess": False, "wsgi.multithread": False, "wsgi.run_once": False, "wsgi.url_scheme": headers.get(u"X-Forwarded-Proto", "http"), "wsgi.version": (1, 0), "serverless.authorizer": event.get(u"requestContext", {}).get(u"authorizer"), "serverless.event": event, "serverless.context": context, # TODO: Deprecate the following entries, as they do not comply with the WSGI # spec. For custom variables, the spec says: # # Finally, the environ dictionary may also contain server-defined variables. # These variables should be named using only lower-case letters, numbers, dots, # and underscores, and should be prefixed with a name that is unique to the # defining server or gateway. "API_GATEWAY_AUTHORIZER": event.get(u"requestContext", {}).get(u"authorizer"), "event": event, "context": context, } environ = setup_environ_items(environ, headers) response = Response.from_app(app, environ) returndict = generate_response(response, event) return returndict