3 Star 0 Fork 0

mirrors_LF-Engineering / serverless-wsgi

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
wsgi_handler_test.py 37.64 KB
一键复制 编辑 原始数据 按行查看 历史
Logan Raarup 提交于 2021-12-08 19:07 . Make tests pass on macOS
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import builtins
import importlib
import json
import os
import pytest
import sys
from werkzeug.datastructures import MultiDict
from werkzeug.wrappers import Request, Response
from werkzeug.urls import url_encode
# Reference to open() before monkeypatching
original_open = open
# This workaround is needed for coverage.py to pick up the wsgi handler module
try:
import wsgi_handler # noqa: F401
except: # noqa: E722
pass
class MockApp:
def __init__(self):
self.cookie_count = 3
self.response_mimetype = "text/plain"
self.status_code = 200
def __call__(self, environ, start_response):
self.last_environ = environ
response = Response("Hello World ☃!", mimetype=self.response_mimetype)
cookies = [
("CUSTOMER", "WILE_E_COYOTE"),
("PART_NUMBER", "ROCKET_LAUNCHER_0002"),
("LOT_NUMBER", "42"),
]
for cookie in cookies[: self.cookie_count]:
response.set_cookie(cookie[0], cookie[1])
print("application debug #1", file=environ["wsgi.errors"])
response.status_code = self.status_code
return response(environ, start_response)
class MockFile:
def __init__(self):
self.contents = None
def __enter__(self):
return self
def __exit__(self, *args):
pass
def read(self):
return self.contents
def write(self, data):
self.contents = data
class MockFileManager:
def __init__(self):
self.files = {}
def open(self, name, mode="r", buffering=-1, **options):
if name not in self.files:
if mode.startswith("r"): # pragma: no cover
return original_open(name, mode, buffering, **options)
else:
self.files[name] = MockFile()
return self.files[name]
@pytest.fixture
def mock_app(monkeypatch):
mock_app = MockApp()
def mock_importlib(module):
class MockObject:
pass
app = MockObject()
app.app = mock_app
app.app.module = module
return app
monkeypatch.setattr(importlib, "import_module", mock_importlib)
return mock_app
@pytest.fixture
def mock_app_with_import_error(monkeypatch):
def mock_importlib(module):
raise ImportError("No module named {}".format(module))
monkeypatch.setattr(importlib, "import_module", mock_importlib)
@pytest.fixture
def mock_wsgi_app_file(monkeypatch):
monkeypatch.setattr(os.path, "abspath", lambda x: "/tmp")
manager = MockFileManager()
with manager.open("/tmp/.serverless-wsgi", "w") as f:
f.write(json.dumps({"app": "app.app"}))
monkeypatch.setattr(builtins, "open", manager.open)
@pytest.fixture
def mock_subdir_wsgi_app_file(monkeypatch):
monkeypatch.setattr(os.path, "abspath", lambda x: "/tmp")
manager = MockFileManager()
with manager.open("/tmp/.serverless-wsgi", "w") as f:
f.write(json.dumps({"app": "subdir/app.app"}))
monkeypatch.setattr(builtins, "open", manager.open)
@pytest.fixture
def mock_text_mime_wsgi_app_file(monkeypatch):
monkeypatch.setattr(os.path, "abspath", lambda x: "/tmp")
manager = MockFileManager()
with manager.open("/tmp/.serverless-wsgi", "w") as f:
f.write(
json.dumps(
{"app": "app.app", "text_mime_types": ["application/custom+json"]}
)
)
monkeypatch.setattr(builtins, "open", manager.open)
@pytest.fixture
def event_v1():
return {
"body": None,
"headers": {
"Accept": "*/*",
"Accept-Encoding": "gzip, deflate",
"CloudFront-Forwarded-Proto": "https",
"CloudFront-Is-Desktop-Viewer": "true",
"CloudFront-Is-Mobile-Viewer": "false",
"CloudFront-Is-SmartTV-Viewer": "false",
"CloudFront-Is-Tablet-Viewer": "false",
"CloudFront-Viewer-Country": "DK",
"Cookie": "CUSTOMER=WILE_E_COYOTE; PART_NUMBER=ROCKET_LAUNCHER_0001",
"Host": "3z6kd9fbb1.execute-api.us-east-1.amazonaws.com",
"Postman-Token": "778a706e-d6b0-48d5-94dd-9e98c22f12fe",
"User-Agent": "PostmanRuntime/3.0.11-hotfix.2",
"Via": "1.1 b8fa.cloudfront.net (CloudFront)",
"X-Amz-Cf-Id": "jx0Bvz9rm--Mz3wAj4i46FdOQQK3RHF4H0moJjBsQ==",
"X-Amzn-Trace-Id": "Root=1-58d534a5-1e7cffe644b086304dce7a1e",
"X-Forwarded-For": "76.20.166.147, 205.251.218.72",
"X-Forwarded-Port": "443",
"X-Forwarded-Proto": "https",
"cache-control": "no-cache",
},
"httpMethod": "GET",
"isBase64Encoded": False,
"path": "/some/path",
"pathParameters": {"proxy": "some/path"},
"queryStringParameters": {"param1": "value1", "param2": "value2"},
"requestContext": {
"accountId": "16794",
"apiId": "3z6kd9fbb1",
"httpMethod": "GET",
"identity": {
"accessKey": None,
"accountId": None,
"apiKey": None,
"caller": None,
"cognitoAuthenticationProvider": None,
"cognitoAuthenticationType": None,
"cognitoIdentityId": None,
"cognitoIdentityPoolId": None,
"sourceIp": "76.20.166.147",
"user": None,
"userAgent": "PostmanRuntime/3.0.11-hotfix.2",
"userArn": None,
},
"authorizer": {"principalId": "wile_e_coyote"},
"requestId": "ad2db740-10a2-11e7-8ced-35048084babb",
"resourceId": "r4kza9",
"resourcePath": "/{proxy+}",
"stage": "dev",
},
"resource": "/{proxy+}",
"stageVariables": None,
}
@pytest.fixture
def elb_event():
return {
"requestContext": {
"elb": {
"targetGroupArn": "arn:aws:elasticloadbalancing:us-east-1:12345:targetgroup/xxxx/5e43816d76759862"
}
},
"httpMethod": "GET",
"path": "/cats",
"queryStringParameters": {},
"headers": {
"accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8",
"accept-encoding": "gzip, deflate",
"accept-language": "en-US,en;q=0.9,da;q=0.8",
"cache-control": "max-age=0",
"connection": "keep-alive",
"host": "xxxx-203391234.us-east-1.elb.amazonaws.com",
"upgrade-insecure-requests": "1",
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36",
"x-amzn-trace-id": "Root=1-5f05949b-77e2b0f9434e2acbf5ad8ce8",
"x-forwarded-for": "95.181.37.218",
"x-forwarded-port": "80",
"x-forwarded-proto": "http",
},
"body": "",
"isBase64Encoded": False,
}
@pytest.fixture # noqa: F811
def wsgi_handler(): # noqa: F811
if "wsgi_handler" in sys.modules:
del sys.modules["wsgi_handler"]
import wsgi_handler
return wsgi_handler
def test_handler(mock_wsgi_app_file, mock_app, event_v1, capsys, wsgi_handler):
response = wsgi_handler.handler(event_v1, {"memory_limit_in_mb": "128"})
assert response == {
"body": "Hello World ☃!",
"headers": {
"set-cookie": "CUSTOMER=WILE_E_COYOTE; Path=/",
"Content-Length": "16",
"Content-Type": "text/plain; charset=utf-8",
"sEt-cookie": "LOT_NUMBER=42; Path=/",
"Set-cookie": "PART_NUMBER=ROCKET_LAUNCHER_0002; Path=/",
},
"statusCode": 200,
"isBase64Encoded": False,
}
assert wsgi_handler.wsgi_app.last_environ == {
"CONTENT_LENGTH": "0",
"CONTENT_TYPE": "",
"HTTP_ACCEPT": "*/*",
"HTTP_ACCEPT_ENCODING": "gzip, deflate",
"HTTP_CACHE_CONTROL": "no-cache",
"HTTP_CLOUDFRONT_FORWARDED_PROTO": "https",
"HTTP_CLOUDFRONT_IS_DESKTOP_VIEWER": "true",
"HTTP_CLOUDFRONT_IS_MOBILE_VIEWER": "false",
"HTTP_CLOUDFRONT_IS_SMARTTV_VIEWER": "false",
"HTTP_CLOUDFRONT_IS_TABLET_VIEWER": "false",
"HTTP_CLOUDFRONT_VIEWER_COUNTRY": "DK",
"HTTP_COOKIE": "CUSTOMER=WILE_E_COYOTE; PART_NUMBER=ROCKET_LAUNCHER_0001",
"HTTP_HOST": "3z6kd9fbb1.execute-api.us-east-1.amazonaws.com",
"HTTP_POSTMAN_TOKEN": "778a706e-d6b0-48d5-94dd-9e98c22f12fe",
"HTTP_USER_AGENT": "PostmanRuntime/3.0.11-hotfix.2",
"HTTP_VIA": "1.1 b8fa.cloudfront.net (CloudFront)",
"HTTP_X_AMZN_TRACE_ID": "Root=1-58d534a5-1e7cffe644b086304dce7a1e",
"HTTP_X_AMZ_CF_ID": "jx0Bvz9rm--Mz3wAj4i46FdOQQK3RHF4H0moJjBsQ==",
"HTTP_X_FORWARDED_FOR": "76.20.166.147, 205.251.218.72",
"HTTP_X_FORWARDED_PORT": "443",
"HTTP_X_FORWARDED_PROTO": "https",
"PATH_INFO": "/some/path",
"QUERY_STRING": url_encode(event_v1["queryStringParameters"]),
"REMOTE_ADDR": "76.20.166.147",
"REMOTE_USER": "wile_e_coyote",
"REQUEST_METHOD": "GET",
"SCRIPT_NAME": "/dev",
"SERVER_NAME": "3z6kd9fbb1.execute-api.us-east-1.amazonaws.com",
"SERVER_PORT": "443",
"SERVER_PROTOCOL": "HTTP/1.1",
"wsgi.errors": wsgi_handler.wsgi_app.last_environ["wsgi.errors"],
"wsgi.input": wsgi_handler.wsgi_app.last_environ["wsgi.input"],
"wsgi.multiprocess": False,
"wsgi.multithread": False,
"wsgi.run_once": False,
"wsgi.url_scheme": "https",
"wsgi.version": (1, 0),
"serverless.authorizer": {"principalId": "wile_e_coyote"},
"serverless.context": {"memory_limit_in_mb": "128"},
"serverless.event": event_v1,
}
out, err = capsys.readouterr()
assert out == ""
assert err == "application debug #1\n"
def test_handler_multivalue(
mock_wsgi_app_file, mock_app, event_v1, capsys, wsgi_handler
):
event_v1["multiValueQueryStringParameters"] = {
"param1": ["value1"],
"param2": ["value2", "value3"],
}
# Convert regular headers request to multiValueHeaders
multi_headers = {}
for key, value in event_v1["headers"].items():
if key not in multi_headers:
multi_headers[key] = []
multi_headers[key].append(value)
event_v1["multiValueHeaders"] = multi_headers
response = wsgi_handler.handler(event_v1, {"memory_limit_in_mb": "128"})
query_string = wsgi_handler.wsgi_app.last_environ["QUERY_STRING"]
assert query_string == url_encode(
MultiDict(
(i, k)
for i, j in event_v1["multiValueQueryStringParameters"].items()
for k in j
)
)
assert response == {
"body": "Hello World ☃!",
"multiValueHeaders": {
"Content-Length": ["16"],
"Content-Type": ["text/plain; charset=utf-8"],
"Set-Cookie": [
"CUSTOMER=WILE_E_COYOTE; Path=/",
"PART_NUMBER=ROCKET_LAUNCHER_0002; Path=/",
"LOT_NUMBER=42; Path=/",
],
},
"statusCode": 200,
"isBase64Encoded": False,
}
def test_handler_china(mock_wsgi_app_file, mock_app, event_v1, capsys, wsgi_handler):
event_v1["headers"]["Host"] = "x.amazonaws.com.cn"
wsgi_handler.handler(event_v1, {"memory_limit_in_mb": "128"})
assert wsgi_handler.wsgi_app.last_environ["SCRIPT_NAME"] == "/dev"
def test_handler_single_cookie(mock_wsgi_app_file, mock_app, event_v1, wsgi_handler):
wsgi_handler.wsgi_app.cookie_count = 1
response = wsgi_handler.handler(event_v1, {})
assert response == {
"body": "Hello World ☃!",
"headers": {
"Set-Cookie": "CUSTOMER=WILE_E_COYOTE; Path=/",
"Content-Length": "16",
"Content-Type": "text/plain; charset=utf-8",
},
"statusCode": 200,
"isBase64Encoded": False,
}
def test_handler_no_cookie(mock_wsgi_app_file, mock_app, event_v1, wsgi_handler):
wsgi_handler.wsgi_app.cookie_count = 0
response = wsgi_handler.handler(event_v1, {})
assert response == {
"body": "Hello World ☃!",
"headers": {
"Content-Length": "16",
"Content-Type": "text/plain; charset=utf-8",
},
"statusCode": 200,
"isBase64Encoded": False,
}
def test_handler_schedule(mock_wsgi_app_file, mock_app, event_v1, wsgi_handler):
event_v1 = {"source": "aws.events"}
response = wsgi_handler.handler(event_v1, {})
assert response == {}
def test_handler_warmup_plugin(
mock_wsgi_app_file, mock_app, event_v1, wsgi_handler, capsys
):
event_v1 = {"source": "serverless-plugin-warmup"}
response = wsgi_handler.handler(event_v1, {})
assert response == {}
out, err = capsys.readouterr()
assert out == "Lambda warming event received, skipping handler\n"
assert err == ""
def test_handler_custom_domain(mock_wsgi_app_file, mock_app, event_v1, wsgi_handler):
event_v1["headers"]["Host"] = "custom.domain.com"
wsgi_handler.handler(event_v1, {})
assert wsgi_handler.wsgi_app.last_environ == {
"CONTENT_LENGTH": "0",
"CONTENT_TYPE": "",
"HTTP_ACCEPT": "*/*",
"HTTP_ACCEPT_ENCODING": "gzip, deflate",
"HTTP_CACHE_CONTROL": "no-cache",
"HTTP_CLOUDFRONT_FORWARDED_PROTO": "https",
"HTTP_CLOUDFRONT_IS_DESKTOP_VIEWER": "true",
"HTTP_CLOUDFRONT_IS_MOBILE_VIEWER": "false",
"HTTP_CLOUDFRONT_IS_SMARTTV_VIEWER": "false",
"HTTP_CLOUDFRONT_IS_TABLET_VIEWER": "false",
"HTTP_CLOUDFRONT_VIEWER_COUNTRY": "DK",
"HTTP_COOKIE": "CUSTOMER=WILE_E_COYOTE; PART_NUMBER=ROCKET_LAUNCHER_0001",
"HTTP_HOST": "custom.domain.com",
"HTTP_POSTMAN_TOKEN": "778a706e-d6b0-48d5-94dd-9e98c22f12fe",
"HTTP_USER_AGENT": "PostmanRuntime/3.0.11-hotfix.2",
"HTTP_VIA": "1.1 b8fa.cloudfront.net (CloudFront)",
"HTTP_X_AMZN_TRACE_ID": "Root=1-58d534a5-1e7cffe644b086304dce7a1e",
"HTTP_X_AMZ_CF_ID": "jx0Bvz9rm--Mz3wAj4i46FdOQQK3RHF4H0moJjBsQ==",
"HTTP_X_FORWARDED_FOR": "76.20.166.147, 205.251.218.72",
"HTTP_X_FORWARDED_PORT": "443",
"HTTP_X_FORWARDED_PROTO": "https",
"PATH_INFO": "/some/path",
"QUERY_STRING": url_encode(event_v1["queryStringParameters"]),
"REMOTE_ADDR": "76.20.166.147",
"REMOTE_USER": "wile_e_coyote",
"REQUEST_METHOD": "GET",
"SCRIPT_NAME": "",
"SERVER_NAME": "custom.domain.com",
"SERVER_PORT": "443",
"SERVER_PROTOCOL": "HTTP/1.1",
"wsgi.errors": wsgi_handler.wsgi_app.last_environ["wsgi.errors"],
"wsgi.input": wsgi_handler.wsgi_app.last_environ["wsgi.input"],
"wsgi.multiprocess": False,
"wsgi.multithread": False,
"wsgi.run_once": False,
"wsgi.url_scheme": "https",
"wsgi.version": (1, 0),
"serverless.authorizer": {"principalId": "wile_e_coyote"},
"serverless.context": {},
"serverless.event": event_v1,
}
def test_handler_api_gateway_base_path(
mock_wsgi_app_file, mock_app, event_v1, wsgi_handler
):
event_v1["headers"]["Host"] = "custom.domain.com"
event_v1["path"] = "/prod/some/path"
try:
os.environ["API_GATEWAY_BASE_PATH"] = "prod"
wsgi_handler.handler(event_v1, {})
finally:
del os.environ["API_GATEWAY_BASE_PATH"]
assert wsgi_handler.wsgi_app.last_environ == {
"CONTENT_LENGTH": "0",
"CONTENT_TYPE": "",
"HTTP_ACCEPT": "*/*",
"HTTP_ACCEPT_ENCODING": "gzip, deflate",
"HTTP_CACHE_CONTROL": "no-cache",
"HTTP_CLOUDFRONT_FORWARDED_PROTO": "https",
"HTTP_CLOUDFRONT_IS_DESKTOP_VIEWER": "true",
"HTTP_CLOUDFRONT_IS_MOBILE_VIEWER": "false",
"HTTP_CLOUDFRONT_IS_SMARTTV_VIEWER": "false",
"HTTP_CLOUDFRONT_IS_TABLET_VIEWER": "false",
"HTTP_CLOUDFRONT_VIEWER_COUNTRY": "DK",
"HTTP_COOKIE": "CUSTOMER=WILE_E_COYOTE; PART_NUMBER=ROCKET_LAUNCHER_0001",
"HTTP_HOST": "custom.domain.com",
"HTTP_POSTMAN_TOKEN": "778a706e-d6b0-48d5-94dd-9e98c22f12fe",
"HTTP_USER_AGENT": "PostmanRuntime/3.0.11-hotfix.2",
"HTTP_VIA": "1.1 b8fa.cloudfront.net (CloudFront)",
"HTTP_X_AMZN_TRACE_ID": "Root=1-58d534a5-1e7cffe644b086304dce7a1e",
"HTTP_X_AMZ_CF_ID": "jx0Bvz9rm--Mz3wAj4i46FdOQQK3RHF4H0moJjBsQ==",
"HTTP_X_FORWARDED_FOR": "76.20.166.147, 205.251.218.72",
"HTTP_X_FORWARDED_PORT": "443",
"HTTP_X_FORWARDED_PROTO": "https",
"PATH_INFO": "/some/path",
"QUERY_STRING": url_encode(event_v1["queryStringParameters"]),
"REMOTE_ADDR": "76.20.166.147",
"REMOTE_USER": "wile_e_coyote",
"REQUEST_METHOD": "GET",
"SCRIPT_NAME": "/prod",
"SERVER_NAME": "custom.domain.com",
"SERVER_PORT": "443",
"SERVER_PROTOCOL": "HTTP/1.1",
"wsgi.errors": wsgi_handler.wsgi_app.last_environ["wsgi.errors"],
"wsgi.input": wsgi_handler.wsgi_app.last_environ["wsgi.input"],
"wsgi.multiprocess": False,
"wsgi.multithread": False,
"wsgi.run_once": False,
"wsgi.url_scheme": "https",
"wsgi.version": (1, 0),
"serverless.authorizer": {"principalId": "wile_e_coyote"},
"serverless.context": {},
"serverless.event": event_v1,
}
def test_handler_strip_stage_path(mock_wsgi_app_file, mock_app, event_v1, wsgi_handler):
try:
os.environ["STRIP_STAGE_PATH"] = "True"
wsgi_handler.handler(event_v1, {})
finally:
del os.environ["STRIP_STAGE_PATH"]
assert wsgi_handler.wsgi_app.last_environ["SCRIPT_NAME"] == ""
def test_handler_base64(mock_wsgi_app_file, mock_app, event_v1, wsgi_handler):
wsgi_handler.wsgi_app.cookie_count = 1
wsgi_handler.wsgi_app.response_mimetype = "image/jpeg"
response = wsgi_handler.handler(event_v1, {})
assert response == {
"body": "SGVsbG8gV29ybGQg4piDIQ==",
"headers": {
"Set-Cookie": "CUSTOMER=WILE_E_COYOTE; Path=/",
"Content-Length": "16",
"Content-Type": "image/jpeg",
},
"statusCode": 200,
"isBase64Encoded": True,
}
def test_handler_plain(mock_wsgi_app_file, mock_app, event_v1, wsgi_handler):
wsgi_handler.wsgi_app.cookie_count = 1
plain_mimetypes = [
"application/vnd.api+json",
"application/javascript; charset=utf-8",
"image/svg+xml; charset=utf-8",
]
for mimetype in plain_mimetypes:
wsgi_handler.wsgi_app.response_mimetype = mimetype
response = wsgi_handler.handler(event_v1, {})
assert response == {
"body": "Hello World ☃!",
"headers": {
"Set-Cookie": "CUSTOMER=WILE_E_COYOTE; Path=/",
"Content-Length": "16",
"Content-Type": mimetype,
},
"statusCode": 200,
"isBase64Encoded": False,
}
def test_handler_base64_request(mock_wsgi_app_file, mock_app, event_v1, wsgi_handler):
event_v1["body"] = "SGVsbG8gd29ybGQ="
event_v1["headers"]["Content-Type"] = "text/plain"
event_v1["isBase64Encoded"] = True
event_v1["httpMethod"] = "PUT"
wsgi_handler.handler(event_v1, {})
environ = wsgi_handler.wsgi_app.last_environ
assert environ["CONTENT_TYPE"] == "text/plain"
assert environ["CONTENT_LENGTH"] == "11"
assert environ["REQUEST_METHOD"] == "PUT"
assert environ["wsgi.input"].getvalue().decode() == "Hello world"
def test_non_package_subdir_app(mock_subdir_wsgi_app_file, mock_app, wsgi_handler):
assert wsgi_handler.wsgi_app.module == "app"
def test_handler_binary_request_body(
mock_wsgi_app_file, mock_app, event_v1, wsgi_handler
):
event_v1["body"] = (
"LS0tLS0tV2ViS2l0Rm9ybUJvdW5kYXJ5VTRDZE5CRWVLQWxIaGRRcQ0KQ29udGVu"
"dC1EaXNwb3NpdGlvbjogZm9ybS1kYXRhOyBuYW1lPSJ3YXQiDQoNCmhleW9vb3Bw"
"cHBwDQotLS0tLS1XZWJLaXRGb3JtQm91bmRhcnlVNENkTkJFZUtBbEhoZFFxDQpD"
"b250ZW50LURpc3Bvc2l0aW9uOiBmb3JtLWRhdGE7IG5hbWU9ImZpbGVUb1VwbG9h"
"ZCI7IGZpbGVuYW1lPSJGRjREMDAtMC44LnBuZyINCkNvbnRlbnQtVHlwZTogaW1h"
"Z2UvcG5nDQoNColQTkcNChoKAAAADUlIRFIAAAABAAAAAQEDAAAAJdtWygAAAANQ"
"TFRF/00AXDU4fwAAAAF0Uk5TzNI0Vv0AAAAKSURBVHicY2IAAAAGAAM2N3yoAAAA"
"AElFTkSuQmCCDQotLS0tLS1XZWJLaXRGb3JtQm91bmRhcnlVNENkTkJFZUtBbEho"
"ZFFxDQpDb250ZW50LURpc3Bvc2l0aW9uOiBmb3JtLWRhdGE7IG5hbWU9InN1Ym1p"
"dCINCg0KVXBsb2FkIEltYWdlDQotLS0tLS1XZWJLaXRGb3JtQm91bmRhcnlVNENk"
"TkJFZUtBbEhoZFFxLS0NCg=="
)
event_v1["headers"][
"Content-Type"
] = "multipart/form-data; boundary=----WebKitFormBoundaryU4CdNBEeKAlHhdQq"
event_v1["isBase64Encoded"] = True
event_v1["httpMethod"] = "POST"
wsgi_handler.handler(event_v1, {})
environ = wsgi_handler.wsgi_app.last_environ
assert environ["CONTENT_LENGTH"] == "496"
assert Request(environ).form["submit"] == "Upload Image"
def test_handler_request_body_undecodable_with_latin1(
mock_wsgi_app_file, mock_app, event_v1, wsgi_handler
):
event_v1["body"] = (
"------WebKitFormBoundary3vA72kRLuq9D3NdL\r\n"
u'Content-Disposition: form-data; name="text"\r\n\r\n'
"テスト 테스트 测试\r\n"
"------WebKitFormBoundary3vA72kRLuq9D3NdL--"
)
event_v1["headers"][
"Content-Type"
] = "multipart/form-data; boundary=----WebKitFormBoundary3vA72kRLuq9D3NdL"
event_v1["httpMethod"] = "POST"
wsgi_handler.handler(event_v1, {})
environ = wsgi_handler.wsgi_app.last_environ
assert Request(environ).form["text"] == "テスト 테스트 测试"
def test_handler_custom_text_mime_types(
mock_text_mime_wsgi_app_file, mock_app, event_v1, wsgi_handler
):
wsgi_handler.wsgi_app.cookie_count = 1
wsgi_handler.wsgi_app.response_mimetype = "application/custom+json"
response = wsgi_handler.handler(event_v1, {})
assert response == {
"body": "Hello World ☃!",
"headers": {
"Set-Cookie": "CUSTOMER=WILE_E_COYOTE; Path=/",
"Content-Length": "16",
"Content-Type": "application/custom+json",
},
"statusCode": 200,
"isBase64Encoded": False,
}
def test_handler_alb(mock_wsgi_app_file, mock_app, wsgi_handler, elb_event):
response = wsgi_handler.handler(elb_event, {})
assert response == {
"body": "Hello World ☃!",
"headers": {
"set-cookie": "CUSTOMER=WILE_E_COYOTE; Path=/",
"Content-Length": "16",
"Content-Type": "text/plain; charset=utf-8",
"sEt-cookie": "LOT_NUMBER=42; Path=/",
"Set-cookie": "PART_NUMBER=ROCKET_LAUNCHER_0002; Path=/",
},
"statusDescription": "200 OK",
"statusCode": 200,
"isBase64Encoded": False,
}
def test_alb_query_params(mock_wsgi_app_file, mock_app, wsgi_handler, elb_event):
elb_event["queryStringParameters"] = {"test": "test%20test"}
response = wsgi_handler.handler(elb_event, {})
query_string = wsgi_handler.wsgi_app.last_environ["QUERY_STRING"]
assert query_string == "test=test+test"
assert response == {
"body": "Hello World ☃!",
"headers": {
"set-cookie": "CUSTOMER=WILE_E_COYOTE; Path=/",
"Content-Length": "16",
"Content-Type": "text/plain; charset=utf-8",
"sEt-cookie": "LOT_NUMBER=42; Path=/",
"Set-cookie": "PART_NUMBER=ROCKET_LAUNCHER_0002; Path=/",
},
"statusDescription": "200 OK",
"statusCode": 200,
"isBase64Encoded": False,
}
def test_alb_multi_query_params(mock_wsgi_app_file, mock_app, wsgi_handler, elb_event):
del elb_event["queryStringParameters"]
elb_event["multiValueQueryStringParameters"] = {
"%E6%B8%AC%E8%A9%A6": ["%E3%83%86%E3%82%B9%E3%83%88", "test"],
"test": "test%20test",
}
response = wsgi_handler.handler(elb_event, {})
query_string = wsgi_handler.wsgi_app.last_environ["QUERY_STRING"]
assert query_string == url_encode({"測試": ["テスト", "test"], "test": "test test"})
assert response == {
"body": "Hello World ☃!",
"headers": {
"set-cookie": "CUSTOMER=WILE_E_COYOTE; Path=/",
"Content-Length": "16",
"Content-Type": "text/plain; charset=utf-8",
"sEt-cookie": "LOT_NUMBER=42; Path=/",
"Set-cookie": "PART_NUMBER=ROCKET_LAUNCHER_0002; Path=/",
},
"statusDescription": "200 OK",
"statusCode": 200,
"isBase64Encoded": False,
}
def test_command_exec(mock_wsgi_app_file, mock_app, wsgi_handler):
response = wsgi_handler.handler(
{"_serverless-wsgi": {"command": "exec", "data": "print(1+4)"}}, {}
)
assert response[0] == 0
assert response[1] == "5\n"
response = wsgi_handler.handler(
{"_serverless-wsgi": {"command": "exec", "data": "invalid code"}}, {}
)
assert response[0] == 1
assert "Traceback (most recent call last):" in response[1]
assert "SyntaxError: invalid syntax" in response[1]
def test_command_command(mock_wsgi_app_file, mock_app, wsgi_handler):
response = wsgi_handler.handler(
{"_serverless-wsgi": {"command": "command", "data": 'echo "hello world"'}}, {}
)
assert response[0] == 0
assert response[1] == "hello world\n"
response = wsgi_handler.handler(
{
"_serverless-wsgi": {
"command": "command",
"data": "ls non-existing-filename",
}
},
{},
)
assert response[0] > 0
assert "No such file or directory" in response[1]
def test_command_manage(mock_wsgi_app_file, mock_app, wsgi_handler):
class MockObject:
pass
class MockDjango:
def call_command(*args):
print("Called with: {}".format(", ".join(args[1:])))
sys.modules["django"] = MockObject()
sys.modules["django.core"] = MockObject()
sys.modules["django.core"].management = MockDjango()
response = wsgi_handler.handler(
{"_serverless-wsgi": {"command": "manage", "data": "check --list-tags"}}, {}
)
assert response[0] == 0
assert response[1] == "Called with: check, --list-tags\n"
def test_command_flask(mock_wsgi_app_file, mock_app, wsgi_handler):
class MockObject:
def __init__(self, **kwargs):
for k, v in kwargs.items():
self.__dict__[k] = v
class MockFlaskGroup:
def __init__(self, create_app):
assert create_app() == mock_app
def main(ctx, args, standalone_mode):
assert not standalone_mode
print("Called with: {}".format(", ".join(args)))
sys.modules["flask"] = MockObject()
sys.modules["flask.cli"] = MockObject(FlaskGroup=MockFlaskGroup)
response = wsgi_handler.handler(
{"_serverless-wsgi": {"command": "flask", "data": "custom command"}}, {}
)
assert response[0] == 0
assert response[1] == "Called with: custom, command\n"
def test_command_unknown(mock_wsgi_app_file, mock_app, wsgi_handler):
response = wsgi_handler.handler(
{"_serverless-wsgi": {"command": "unknown", "data": 'echo "hello world"'}}, {}
)
assert response[0] == 1
assert "Traceback (most recent call last):" in response[1]
assert "Exception: Unknown command: unknown" in response[1]
def test_app_import_error(mock_wsgi_app_file, mock_app_with_import_error, event_v1):
with pytest.raises(Exception, match="Unable to import app.app"):
if "wsgi_handler" in sys.modules:
del sys.modules["wsgi_handler"]
import wsgi_handler # noqa: F401
def test_handler_with_encoded_characters_in_path(
mock_wsgi_app_file, mock_app, event_v1, capsys, wsgi_handler
):
event_v1["path"] = "/city/new%20york"
wsgi_handler.handler(event_v1, {"memory_limit_in_mb": "128"})
assert wsgi_handler.wsgi_app.last_environ["PATH_INFO"] == "/city/new york"
@pytest.fixture
def event_v2():
return {
"version": "2.0",
"routeKey": "GET /some/path",
"rawPath": "/some/path",
"rawQueryString": "param1=value1&param2=value2&param2=value3",
"cookies": ["CUSTOMER=WILE_E_COYOTE", "PART_NUMBER=ROCKET_LAUNCHER_0001"],
"headers": {
"Accept": "*/*",
"Accept-Encoding": "gzip, deflate",
"CloudFront-Forwarded-Proto": "https",
"CloudFront-Is-Desktop-Viewer": "true",
"CloudFront-Is-Mobile-Viewer": "false",
"CloudFront-Is-SmartTV-Viewer": "false",
"CloudFront-Is-Tablet-Viewer": "false",
"CloudFront-Viewer-Country": "DK",
"Host": "3z6kd9fbb1.execute-api.us-east-1.amazonaws.com",
"Postman-Token": "778a706e-d6b0-48d5-94dd-9e98c22f12fe",
"User-Agent": "PostmanRuntime/3.0.11-hotfix.2",
"Via": "1.1 b8fa.cloudfront.net (CloudFront)",
"X-Amz-Cf-Id": "jx0Bvz9rm--Mz3wAj4i46FdOQQK3RHF4H0moJjBsQ==",
"X-Amzn-Trace-Id": "Root=1-58d534a5-1e7cffe644b086304dce7a1e",
"X-Forwarded-For": "76.20.166.147, 205.251.218.72",
"X-Forwarded-Port": "443",
"X-Forwarded-Proto": "https",
"cache-control": "no-cache",
},
"queryStringParameters": {"param1": "value1", "param2": "value2,value3"},
"requestContext": {
"accountId": "16794",
"apiId": "3z6kd9fbb1",
"authorizer": {"principalId": "wile_e_coyote"},
"domainName": "id.execute-api.us-east-1.amazonaws.com",
"domainPrefix": "id",
"http": {
"method": "GET",
"path": "/some/path",
"protocol": "HTTP/1.1",
"sourceIp": "76.20.166.147",
"userAgent": "agent",
},
"requestId": "ad2db740-10a2-11e7-8ced-35048084babb",
"stage": "dev",
"routeKey": "$default",
"time": "12/Mar/2020:19:03:58 +0000",
"timeEpoch": 1583348638390,
},
"pathParameters": {"proxy": "some/path"},
"isBase64Encoded": False,
"stageVariables": None,
}
def test_handler_v2(mock_wsgi_app_file, mock_app, event_v2, capsys, wsgi_handler):
response = wsgi_handler.handler(event_v2, {"memory_limit_in_mb": "128"})
assert response == {
"body": "Hello World ☃!",
"headers": {
"set-cookie": "CUSTOMER=WILE_E_COYOTE; Path=/",
"Content-Length": "16",
"Content-Type": "text/plain; charset=utf-8",
"sEt-cookie": "LOT_NUMBER=42; Path=/",
"Set-cookie": "PART_NUMBER=ROCKET_LAUNCHER_0002; Path=/",
},
"statusCode": 200,
"isBase64Encoded": False,
}
assert wsgi_handler.wsgi_app.last_environ == {
"CONTENT_LENGTH": "0",
"CONTENT_TYPE": "",
"HTTP_ACCEPT": "*/*",
"HTTP_ACCEPT_ENCODING": "gzip, deflate",
"HTTP_CACHE_CONTROL": "no-cache",
"HTTP_CLOUDFRONT_FORWARDED_PROTO": "https",
"HTTP_CLOUDFRONT_IS_DESKTOP_VIEWER": "true",
"HTTP_CLOUDFRONT_IS_MOBILE_VIEWER": "false",
"HTTP_CLOUDFRONT_IS_SMARTTV_VIEWER": "false",
"HTTP_CLOUDFRONT_IS_TABLET_VIEWER": "false",
"HTTP_CLOUDFRONT_VIEWER_COUNTRY": "DK",
"HTTP_COOKIE": "CUSTOMER=WILE_E_COYOTE; PART_NUMBER=ROCKET_LAUNCHER_0001",
"HTTP_HOST": "3z6kd9fbb1.execute-api.us-east-1.amazonaws.com",
"HTTP_POSTMAN_TOKEN": "778a706e-d6b0-48d5-94dd-9e98c22f12fe",
"HTTP_USER_AGENT": "PostmanRuntime/3.0.11-hotfix.2",
"HTTP_VIA": "1.1 b8fa.cloudfront.net (CloudFront)",
"HTTP_X_AMZN_TRACE_ID": "Root=1-58d534a5-1e7cffe644b086304dce7a1e",
"HTTP_X_AMZ_CF_ID": "jx0Bvz9rm--Mz3wAj4i46FdOQQK3RHF4H0moJjBsQ==",
"HTTP_X_FORWARDED_FOR": "76.20.166.147, 205.251.218.72",
"HTTP_X_FORWARDED_PORT": "443",
"HTTP_X_FORWARDED_PROTO": "https",
"PATH_INFO": "/some/path",
"QUERY_STRING": "param1=value1&param2=value2&param2=value3",
"REMOTE_ADDR": "76.20.166.147",
"REMOTE_USER": "wile_e_coyote",
"REQUEST_METHOD": "GET",
"SCRIPT_NAME": "/dev",
"SERVER_NAME": "3z6kd9fbb1.execute-api.us-east-1.amazonaws.com",
"SERVER_PORT": "443",
"SERVER_PROTOCOL": "HTTP/1.1",
"wsgi.errors": wsgi_handler.wsgi_app.last_environ["wsgi.errors"],
"wsgi.input": wsgi_handler.wsgi_app.last_environ["wsgi.input"],
"wsgi.multiprocess": False,
"wsgi.multithread": False,
"wsgi.run_once": False,
"wsgi.url_scheme": "https",
"wsgi.version": (1, 0),
"serverless.authorizer": {"principalId": "wile_e_coyote"},
"serverless.context": {"memory_limit_in_mb": "128"},
"serverless.event": event_v2,
}
out, err = capsys.readouterr()
assert out == ""
assert err == "application debug #1\n"
def test_handler_with_encoded_characters_in_path_v2(
mock_wsgi_app_file, mock_app, event_v2, capsys, wsgi_handler
):
event_v2["rawPath"] = "/city/new%20york"
wsgi_handler.handler(event_v2, {"memory_limit_in_mb": "128"})
assert wsgi_handler.wsgi_app.last_environ["PATH_INFO"] == "/city/new york"
@pytest.fixture
def event_lambda_integration():
return {
"body": {},
"method": "GET",
"principalId": "testuser",
"stage": "dev",
"cognitoPoolClaims": {"sub": ""},
"enhancedAuthContext": {
"principalId": "testuser",
"integrationLatency": "1031",
"contextTest": "123",
},
"headers": {
"Accept": "*/*",
"Authorization": "Bearer f14a720d62e1d1295d9",
"CloudFront-Forwarded-Proto": "https",
"CloudFront-Is-Desktop-Viewer": "true",
"CloudFront-Is-Mobile-Viewer": "false",
"CloudFront-Is-SmartTV-Viewer": "false",
"CloudFront-Is-Tablet-Viewer": "false",
"CloudFront-Viewer-Country": "FI",
"Host": "k3k8rkx1mf.execute-api.us-east-1.amazonaws.com",
"User-Agent": "curl/7.68.0",
"Via": "2.0 3bf180720d62e0d1295d99086d103efb.cloudfront.net (CloudFront)",
"X-Amz-Cf-Id": "9Z6K736EDx_vlsij1PA-ZVxIPPi-vAIMaLNOvJ2FrbpvGMisAISY8Q==",
"X-Amzn-Trace-Id": "Root=1-5055b7d3-751afb497f81bab2759b6e7b",
"X-Forwarded-For": "83.23.10.243, 130.166.149.164",
"X-Forwarded-Port": "443",
"X-Forwarded-Proto": "https",
},
"query": {"q": "test"},
"path": {"p": "path2"},
"identity": {
"cognitoIdentityPoolId": "",
"accountId": "",
"cognitoIdentityId": "",
"caller": "",
"sourceIp": "83.23.100.243",
"principalOrgId": "",
"accessKey": "",
"cognitoAuthenticationType": "",
"cognitoAuthenticationProvider": "",
"userArn": "",
"userAgent": "curl/7.68.0",
"user": "",
},
"stageVariables": {},
"requestPath": "/some/{p}",
}
def test_handler_lambda(
mock_wsgi_app_file, mock_app, event_lambda_integration, capsys, wsgi_handler
):
response = wsgi_handler.handler(
event_lambda_integration, {"memory_limit_in_mb": "128"}
)
assert response == {
"body": "Hello World ☃!",
"headers": {
"set-cookie": "CUSTOMER=WILE_E_COYOTE; Path=/",
"Content-Length": "16",
"Content-Type": "text/plain; charset=utf-8",
"sEt-cookie": "LOT_NUMBER=42; Path=/",
"Set-cookie": "PART_NUMBER=ROCKET_LAUNCHER_0002; Path=/",
},
"statusCode": 200,
"isBase64Encoded": False,
}
assert wsgi_handler.wsgi_app.last_environ == {
"CONTENT_LENGTH": "0",
"CONTENT_TYPE": "",
"HTTP_ACCEPT": "*/*",
"HTTP_AUTHORIZATION": "Bearer f14a720d62e1d1295d9",
"HTTP_CLOUDFRONT_FORWARDED_PROTO": "https",
"HTTP_CLOUDFRONT_IS_DESKTOP_VIEWER": "true",
"HTTP_CLOUDFRONT_IS_MOBILE_VIEWER": "false",
"HTTP_CLOUDFRONT_IS_SMARTTV_VIEWER": "false",
"HTTP_CLOUDFRONT_IS_TABLET_VIEWER": "false",
"HTTP_CLOUDFRONT_VIEWER_COUNTRY": "FI",
"HTTP_HOST": "k3k8rkx1mf.execute-api.us-east-1.amazonaws.com",
"HTTP_USER_AGENT": "curl/7.68.0",
"HTTP_VIA": "2.0 3bf180720d62e0d1295d99086d103efb.cloudfront.net (CloudFront)",
"HTTP_X_AMZN_TRACE_ID": "Root=1-5055b7d3-751afb497f81bab2759b6e7b",
"HTTP_X_AMZ_CF_ID": "9Z6K736EDx_vlsij1PA-ZVxIPPi-vAIMaLNOvJ2FrbpvGMisAISY8Q==",
"HTTP_X_FORWARDED_FOR": "83.23.10.243, 130.166.149.164",
"HTTP_X_FORWARDED_PORT": "443",
"HTTP_X_FORWARDED_PROTO": "https",
"PATH_INFO": "/some/path2",
"QUERY_STRING": "q=test",
"REMOTE_ADDR": "83.23.100.243",
"REMOTE_USER": "testuser",
"REQUEST_METHOD": "GET",
"SCRIPT_NAME": "/dev",
"SERVER_NAME": "k3k8rkx1mf.execute-api.us-east-1.amazonaws.com",
"SERVER_PORT": "443",
"SERVER_PROTOCOL": "HTTP/1.1",
"wsgi.errors": wsgi_handler.wsgi_app.last_environ["wsgi.errors"],
"wsgi.input": wsgi_handler.wsgi_app.last_environ["wsgi.input"],
"wsgi.multiprocess": False,
"wsgi.multithread": False,
"wsgi.run_once": False,
"wsgi.url_scheme": "https",
"wsgi.version": (1, 0),
"serverless.authorizer": {
"principalId": "testuser",
"integrationLatency": "1031",
"contextTest": "123",
},
"serverless.context": {"memory_limit_in_mb": "128"},
"serverless.event": event_lambda_integration,
}
out, err = capsys.readouterr()
assert out == ""
assert err == "application debug #1\n"
def test_handler_lambda_error(
mock_wsgi_app_file, mock_app, event_lambda_integration, capsys, wsgi_handler
):
mock_app.status_code = 400
with pytest.raises(Exception, match='"statusCode": 400'):
wsgi_handler.handler(event_lambda_integration, {"memory_limit_in_mb": "128"})
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/mirrors_LF-Engineering/serverless-wsgi.git
git@gitee.com:mirrors_LF-Engineering/serverless-wsgi.git
mirrors_LF-Engineering
serverless-wsgi
serverless-wsgi
master

搜索帮助

344bd9b3 5694891 D2dac590 5694891