Skip to content

Commit 73cfd9b

Browse files
(feat): introduce specialized routers for typing (#1824)
Co-authored-by: Leandro Damascena <[email protected]>
1 parent 693fb63 commit 73cfd9b

File tree

4 files changed

+142
-0
lines changed

4 files changed

+142
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
from aws_lambda_powertools.event_handler.api_gateway import Router
2+
from aws_lambda_powertools.utilities.data_classes import (
3+
ALBEvent,
4+
APIGatewayProxyEvent,
5+
APIGatewayProxyEventV2,
6+
LambdaFunctionUrlEvent,
7+
)
8+
9+
10+
class APIGatewayRouter(Router):
11+
"""Specialized Router class that exposes current_event as an APIGatewayProxyEvent"""
12+
13+
current_event: APIGatewayProxyEvent
14+
15+
16+
class APIGatewayHttpRouter(Router):
17+
"""Specialized Router class that exposes current_event as an APIGatewayProxyEventV2"""
18+
19+
current_event: APIGatewayProxyEventV2
20+
21+
22+
class LambdaFunctionUrlRouter(Router):
23+
"""Specialized Router class that exposes current_event as a LambdaFunctionUrlEvent"""
24+
25+
current_event: LambdaFunctionUrlEvent
26+
27+
28+
class ALBRouter(Router):
29+
"""Specialized Router class that exposes current_event as an ALBEvent"""
30+
31+
current_event: ALBEvent

docs/core/event_handler/api_gateway.md

+15
Original file line numberDiff line numberDiff line change
@@ -459,6 +459,21 @@ When necessary, you can set a prefix when including a router object. This means
459459
--8<-- "examples/event_handler_rest/src/split_route_prefix_module.py"
460460
```
461461

462+
#### Specialized router types
463+
464+
You can use specialized router classes according to the type of event that you are resolving. This way you'll get type hints from your IDE as you access the `current_event` property.
465+
466+
| Router | Resolver | `current_event` type |
467+
|-------------------------|---------------------------|------------------------|
468+
| APIGatewayRouter | APIGatewayRestResolver | APIGatewayProxyEvent |
469+
| APIGatewayHttpRouter | APIGatewayHttpResolver | APIGatewayProxyEventV2 |
470+
| ALBRouter | ALBResolver | ALBEvent |
471+
| LambdaFunctionUrlRouter | LambdaFunctionUrlResolver | LambdaFunctionUrlEvent |
472+
473+
```python hl_lines="1 5 9"
474+
--8<-- "examples/event_handler_rest/src/split_route_specialized_router.py"
475+
```
476+
462477
#### Sharing contextual data
463478

464479
You can use `append_context` when you want to share data between your App and Router instances. Any data you share will be available via the `context` dictionary available in your App or Router context.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
from aws_lambda_powertools.event_handler import APIGatewayRestResolver
2+
from aws_lambda_powertools.event_handler.router import APIGatewayRouter
3+
4+
app = APIGatewayRestResolver()
5+
router = APIGatewayRouter()
6+
7+
8+
@router.get("/me")
9+
def get_self():
10+
# router.current_event is a APIGatewayProxyEvent
11+
account_id = router.current_event.request_context.account_id
12+
13+
return {"account_id": account_id}
14+
15+
16+
app.include_router(router)
17+
18+
19+
def lambda_handler(event, context):
20+
return app.resolve(event, context)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
from aws_lambda_powertools.event_handler import (
2+
ALBResolver,
3+
APIGatewayHttpResolver,
4+
APIGatewayRestResolver,
5+
LambdaFunctionUrlResolver,
6+
Response,
7+
)
8+
from aws_lambda_powertools.event_handler.router import (
9+
ALBRouter,
10+
APIGatewayHttpRouter,
11+
APIGatewayRouter,
12+
LambdaFunctionUrlRouter,
13+
)
14+
from aws_lambda_powertools.utilities.data_classes import (
15+
ALBEvent,
16+
APIGatewayProxyEvent,
17+
APIGatewayProxyEventV2,
18+
LambdaFunctionUrlEvent,
19+
)
20+
from tests.functional.utils import load_event
21+
22+
23+
def test_alb_router_event_type():
24+
app = ALBResolver()
25+
router = ALBRouter()
26+
27+
@router.route(rule="/lambda", method=["GET"])
28+
def foo():
29+
assert type(router.current_event) is ALBEvent
30+
return Response(status_code=200, body="routed")
31+
32+
app.include_router(router)
33+
result = app(load_event("albEvent.json"), {})
34+
assert result["body"] == "routed"
35+
36+
37+
def test_apigateway_router_event_type():
38+
app = APIGatewayRestResolver()
39+
router = APIGatewayRouter()
40+
41+
@router.route(rule="/my/path", method=["GET"])
42+
def foo():
43+
assert type(router.current_event) is APIGatewayProxyEvent
44+
return Response(status_code=200, body="routed")
45+
46+
app.include_router(router)
47+
result = app(load_event("apiGatewayProxyEvent.json"), {})
48+
assert result["body"] == "routed"
49+
50+
51+
def test_apigatewayhttp_router_event_type():
52+
app = APIGatewayHttpResolver()
53+
router = APIGatewayHttpRouter()
54+
55+
@router.route(rule="/my/path", method=["POST"])
56+
def foo():
57+
assert type(router.current_event) is APIGatewayProxyEventV2
58+
return Response(status_code=200, body="routed")
59+
60+
app.include_router(router)
61+
result = app(load_event("apiGatewayProxyV2Event.json"), {})
62+
assert result["body"] == "routed"
63+
64+
65+
def test_lambda_function_url_router_event_type():
66+
app = LambdaFunctionUrlResolver()
67+
router = LambdaFunctionUrlRouter()
68+
69+
@router.route(rule="/", method=["GET"])
70+
def foo():
71+
assert type(router.current_event) is LambdaFunctionUrlEvent
72+
return Response(status_code=200, body="routed")
73+
74+
app.include_router(router)
75+
result = app(load_event("lambdaFunctionUrlEvent.json"), {})
76+
assert result["body"] == "routed"

0 commit comments

Comments
 (0)