Skip to content

Commit 16371fa

Browse files
šŸ— simplify magnum call function
extract scope and request body creation into a dedicated functions
1 parent 70f0750 commit 16371fa

File tree

1 file changed

+81
-76
lines changed

1 file changed

+81
-76
lines changed

ā€Žmangum/adapter.pyā€Ž

Lines changed: 81 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from dataclasses import dataclass, InitVar
77
from contextlib import ExitStack
88

9-
from mangum.types import ASGIApp
9+
from mangum.types import ASGIApp, Scope
1010
from mangum.protocols.lifespan import LifespanCycle
1111
from mangum.protocols.http import HTTPCycle
1212
from mangum.exceptions import ConfigurationError
@@ -91,89 +91,94 @@ def __call__(self, event: dict, context: "LambdaContext") -> dict:
9191
)
9292
stack.enter_context(lifespan_cycle)
9393

94-
request_context = event["requestContext"]
95-
96-
if event.get("multiValueHeaders"):
97-
headers = {
98-
k.lower(): ", ".join(v) if isinstance(v, list) else ""
99-
for k, v in event.get("multiValueHeaders", {}).items()
100-
}
101-
elif event.get("headers"):
102-
headers = {k.lower(): v for k, v in event.get("headers", {}).items()}
103-
else:
104-
headers = {}
105-
106-
# API Gateway v2
107-
if event.get("version") == "2.0":
108-
source_ip = request_context["http"]["sourceIp"]
109-
path = request_context["http"]["path"]
110-
http_method = request_context["http"]["method"]
111-
query_string = event.get("rawQueryString", "").encode()
112-
113-
if event.get("cookies"):
114-
headers["cookie"] = "; ".join(event.get("cookies", []))
115-
116-
# API Gateway v1 / ELB
117-
else:
118-
if "elb" in request_context:
119-
# NOTE: trust only the most right side value
120-
source_ip = headers.get("x-forwarded-for", "").split(", ")[-1]
121-
else:
122-
source_ip = request_context.get("identity", {}).get("sourceIp")
123-
124-
path = event["path"]
125-
http_method = event["httpMethod"]
126-
127-
if event.get("multiValueQueryStringParameters"):
128-
query_string = urllib.parse.urlencode(
129-
event.get("multiValueQueryStringParameters", {}), doseq=True
130-
).encode()
131-
elif event.get("queryStringParameters"):
132-
query_string = urllib.parse.urlencode(
133-
event.get("queryStringParameters", {})
134-
).encode()
135-
else:
136-
query_string = b""
137-
138-
server_name = headers.get("host", "mangum")
139-
if ":" not in server_name:
140-
server_port = headers.get("x-forwarded-port", 80)
141-
else:
142-
server_name, server_port = server_name.split(":") # pragma: no cover
143-
server = (server_name, int(server_port))
144-
client = (source_ip, 0)
145-
146-
if not path: # pragma: no cover
147-
path = "/"
148-
elif self.api_gateway_base_path:
149-
if path.startswith(self.api_gateway_base_path):
150-
path = path[len(self.api_gateway_base_path) :]
151-
152-
scope = {
153-
"type": "http",
154-
"http_version": "1.1",
155-
"method": http_method,
156-
"headers": [[k.encode(), v.encode()] for k, v in headers.items()],
157-
"path": urllib.parse.unquote(path),
158-
"raw_path": None,
159-
"root_path": "",
160-
"scheme": headers.get("x-forwarded-proto", "https"),
161-
"query_string": query_string,
162-
"server": server,
163-
"client": client,
164-
"asgi": {"version": "3.0"},
165-
"aws.event": event,
166-
"aws.context": context,
167-
}
168-
16994
is_binary = event.get("isBase64Encoded", False)
17095
initial_body = event.get("body") or b""
17196
if is_binary:
17297
initial_body = base64.b64decode(initial_body)
17398
elif not isinstance(initial_body, bytes):
17499
initial_body = initial_body.encode()
175100

101+
scope = self.event_to_asgi_scope(event)
102+
scope["aws.event"] = event
103+
scope["aws.context"] = context
176104
http_cycle = HTTPCycle(scope, text_mime_types=self.text_mime_types)
105+
177106
response = http_cycle(self.app, initial_body)
178107

179108
return response
109+
110+
def event_to_asgi_scope(self, event: dict) -> Scope:
111+
request_context = event["requestContext"]
112+
113+
if event.get("multiValueHeaders"):
114+
headers = {
115+
k.lower(): ", ".join(v) if isinstance(v, list) else ""
116+
for k, v in event.get("multiValueHeaders", {}).items()
117+
}
118+
elif event.get("headers"):
119+
headers = {k.lower(): v for k, v in event.get("headers", {}).items()}
120+
else:
121+
headers = {}
122+
123+
# API Gateway v2
124+
if event.get("version") == "2.0":
125+
source_ip = request_context["http"]["sourceIp"]
126+
path = request_context["http"]["path"]
127+
http_method = request_context["http"]["method"]
128+
query_string = event.get("rawQueryString", "").encode()
129+
130+
if event.get("cookies"):
131+
headers["cookie"] = "; ".join(event.get("cookies", []))
132+
133+
# API Gateway v1 / ELB
134+
else:
135+
if "elb" in request_context:
136+
# NOTE: trust only the most right side value
137+
source_ip = headers.get("x-forwarded-for", "").split(", ")[-1]
138+
else:
139+
source_ip = request_context.get("identity", {}).get("sourceIp")
140+
141+
path = event["path"]
142+
http_method = event["httpMethod"]
143+
144+
if event.get("multiValueQueryStringParameters"):
145+
query_string = urllib.parse.urlencode(
146+
event.get("multiValueQueryStringParameters", {}), doseq=True
147+
).encode()
148+
elif event.get("queryStringParameters"):
149+
query_string = urllib.parse.urlencode(
150+
event.get("queryStringParameters", {})
151+
).encode()
152+
else:
153+
query_string = b""
154+
155+
server_name = headers.get("host", "mangum")
156+
if ":" not in server_name:
157+
server_port = headers.get("x-forwarded-port", 80)
158+
else:
159+
server_name, server_port = server_name.split(":") # pragma: no cover
160+
server = (server_name, int(server_port))
161+
client = (source_ip, 0)
162+
163+
if not path: # pragma: no cover
164+
path = "/"
165+
elif self.api_gateway_base_path:
166+
if path.startswith(self.api_gateway_base_path):
167+
path = path[len(self.api_gateway_base_path) :]
168+
169+
scope = {
170+
"type": "http",
171+
"http_version": "1.1",
172+
"method": http_method,
173+
"headers": [[k.encode(), v.encode()] for k, v in headers.items()],
174+
"path": urllib.parse.unquote(path),
175+
"raw_path": None,
176+
"root_path": "",
177+
"scheme": headers.get("x-forwarded-proto", "https"),
178+
"query_string": query_string,
179+
"server": server,
180+
"client": client,
181+
"asgi": {"version": "3.0"},
182+
}
183+
184+
return scope

0 commit comments

Comments
Ā (0)
⚔