@@ -206,7 +206,7 @@ def __init__(
206
206
cors : bool ,
207
207
compress : bool ,
208
208
cache_control : Optional [str ],
209
- middlewares : Optional [List [Callable [..., Any ]]],
209
+ middlewares : Optional [List [Callable [..., Response ]]],
210
210
):
211
211
"""
212
212
@@ -225,9 +225,8 @@ def __init__(
225
225
Whether or not to enable gzip compression for this route
226
226
cache_control: Optional[str]
227
227
The cache control header value, example "max-age=3600"
228
- middlewares: Optional[List[Callable[..., Any]]]
229
- The list of route middlewares. These are called in the order they are
230
- provided.
228
+ middlewares: Optional[List[Callable[..., Response]]]
229
+ The list of route middlewares to be called in order.
231
230
"""
232
231
self .method = method .upper ()
233
232
self .rule = rule
@@ -238,9 +237,7 @@ def __init__(
238
237
self .cache_control = cache_control
239
238
self .middlewares = middlewares or []
240
239
241
- """
242
- _middleware_stack_built is used to ensure the middleware stack is only built once.
243
- """
240
+ # _middleware_stack_built is used to ensure the middleware stack is only built once.
244
241
self ._middleware_stack_built = False
245
242
246
243
def __call__ (
@@ -258,7 +255,7 @@ def __call__(
258
255
----------
259
256
router_middlewares: List[Callable]
260
257
The list of Router Middlewares (assigned to ALL routes)
261
- app: Callable
258
+ app: "ApiGatewayResolver"
262
259
The ApiGatewayResolver instance to pass into the middleware stack
263
260
route_arguments: Dict[str, str]
264
261
The route arguments to pass to the app function (extracted from the Api Gateway
@@ -267,13 +264,11 @@ def __call__(
267
264
Returns
268
265
-------
269
266
Union[Dict, Tuple, Response]
270
- Returns an API Response object in ALL cases, excepting when the original API route
271
- handler is called which may also return a Dict or Tuple response .
267
+ API Response object in ALL cases, except when the original API route
268
+ handler is called which may also return a Dict, Tuple, or Response .
272
269
"""
273
270
274
- # Check self._middleware_stack_built to ensure the middleware stack is only built once.
275
- # This will save CPU time when an API route is processed multiple times.
276
- #
271
+ # Save CPU cycles by building middleware stack once
277
272
if not self ._middleware_stack_built :
278
273
self ._build_middleware_stack (router_middlewares = router_middlewares )
279
274
@@ -312,14 +307,16 @@ def _build_middleware_stack(self, router_middlewares: List[Callable[..., Any]])
312
307
middleware handlers is applied in the order of being added to the handler.
313
308
"""
314
309
all_middlewares = router_middlewares + self .middlewares
310
+ logger .debug (f"Building middleware stack: { all_middlewares } " )
315
311
316
312
# IMPORTANT:
317
313
# this must be the last middleware in the stack (tech debt for backward
318
- # compatability purposes)
314
+ # compatibility purposes)
319
315
#
320
- # This adapter will call the registered API passing only the expected route arguments extracted from the path
316
+ # This adapter will:
317
+ # 1. Call the registered API passing only the expected route arguments extracted from the path
321
318
# and not the middleware.
322
- # This adapter will adapt the response type of the route handler (Union[Dict, Tuple, Response])
319
+ # 2. Adapt the response type of the route handler (Union[Dict, Tuple, Response])
323
320
# and normalise into a Response object so middleware will always have a constant signature
324
321
all_middlewares .append (_registered_api_adapter )
325
322
@@ -450,31 +447,42 @@ def route(
450
447
451
448
def use (self , middlewares : List [Callable [..., Response ]]) -> None :
452
449
"""
453
- Add a list of middlewares to the global router middleware list
450
+ Add one or more global middlewares that run before/after route specific middleware.
454
451
455
- These middlewares will be called in insertion order and
456
- before any middleware registered at the route level.
452
+ NOTE: Middlewares are called in insertion order.
453
+
454
+ Parameters
455
+ ----------
456
+ middlewares: List[Callable[..., Response]]
457
+ List of global middlewares to be used
458
+
459
+ Examples
460
+ --------
457
461
458
- Example
459
- -------
460
462
Add middlewares to be used for every request processed by the Router.
461
463
462
- ```
463
- my_custom_middleware = new CustomMiddleware()
464
+ ```python
465
+ from aws_lambda_powertools import Logger
466
+ from aws_lambda_powertools.event_handler import APIGatewayRestResolver, Response
467
+ from aws_lambda_powertools.event_handler.middlewares import NextMiddleware
464
468
465
- app.use([my_custom_middleware])
469
+ logger = Logger()
470
+ app = APIGatewayRestResolver()
466
471
467
- ```
472
+ def log_request_response(app: APIGatewayRestResolver, next_middleware: NextMiddleware) -> Response:
473
+ logger.info("Incoming request", path=app.current_event.path, request=app.current_event.raw_event)
468
474
469
- Parameters
470
- ----------
471
- middlewares - List of middlewares to be used
475
+ result = next_middleware(app)
476
+ logger.info("Response received", response=result.__dict__)
472
477
473
- Returns
474
- -------
475
- None
478
+ return result
476
479
480
+ app.use(middlewares=[log_request_response])
477
481
482
+
483
+ def lambda_handler(event, context):
484
+ return app.resolve(event, context)
485
+ ```
478
486
"""
479
487
self ._router_middlewares = self ._router_middlewares + middlewares
480
488
@@ -646,14 +654,14 @@ def lambda_handler(event, context):
646
654
def _push_processed_stack_frame (self , frame : str ):
647
655
"""
648
656
Add Current Middleware to the Middleware Stack Frames
649
- The stack frames will be used when excpetions are thrown and Powertools
657
+ The stack frames will be used when exceptions are thrown and Powertools
650
658
debug is enabled by developers.
651
659
"""
652
660
self .processed_stack_frames .append (frame )
653
661
654
662
def _reset_processed_stack (self ):
655
663
"""Reset the Processed Stack Frames"""
656
- self .processed_stack_frames = []
664
+ self .processed_stack_frames . clear ()
657
665
658
666
def append_context (self , ** additional_context ):
659
667
"""Append key=value data as routing context"""
@@ -832,6 +840,7 @@ def __init__(
832
840
self ._debug = self ._has_debug (debug )
833
841
self ._strip_prefixes = strip_prefixes
834
842
self .context : Dict = {} # early init as customers might add context before event resolution
843
+ self .processed_stack_frames = []
835
844
836
845
# Allow for a custom serializer or a concise json serialization
837
846
self ._serializer = serializer or partial (json .dumps , separators = ("," , ":" ), cls = Encoder )
@@ -1005,8 +1014,7 @@ def _resolve(self) -> ResponseBuilder:
1005
1014
if match_results :
1006
1015
logger .debug ("Found a registered route. Calling function" )
1007
1016
# Add matched Route reference into the Resolver context
1008
- self .append_context (_route = route )
1009
- self .append_context (_path = path )
1017
+ self .append_context (_route = route , _path = path )
1010
1018
1011
1019
return self ._call_route (route , match_results .groupdict ()) # pass fn args
1012
1020
0 commit comments