5
5
import traceback
6
6
import warnings
7
7
import zlib
8
+ from abc import ABC , abstractmethod
8
9
from enum import Enum
9
10
from functools import partial
10
11
from http import HTTPStatus
24
25
25
26
from aws_lambda_powertools .event_handler import content_types
26
27
from aws_lambda_powertools .event_handler .exceptions import NotFoundError , ServiceError
27
- from aws_lambda_powertools .event_handler .router import BaseRouter , Router
28
28
from aws_lambda_powertools .shared .cookies import Cookie
29
29
from aws_lambda_powertools .shared .functions import powertools_dev_is_set
30
30
from aws_lambda_powertools .shared .json_encoder import Encoder
35
35
LambdaFunctionUrlEvent ,
36
36
)
37
37
from aws_lambda_powertools .utilities .data_classes .common import BaseProxyEvent
38
+ from aws_lambda_powertools .utilities .typing import LambdaContext
38
39
39
40
logger = logging .getLogger (__name__ )
40
41
@@ -252,6 +253,165 @@ def build(self, event: BaseProxyEvent, cors: Optional[CORSConfig] = None) -> Dic
252
253
}
253
254
254
255
256
+ class BaseRouter (ABC ):
257
+ current_event : BaseProxyEvent
258
+ lambda_context : LambdaContext
259
+ context : dict
260
+
261
+ @abstractmethod
262
+ def route (
263
+ self ,
264
+ rule : str ,
265
+ method : Any ,
266
+ cors : Optional [bool ] = None ,
267
+ compress : bool = False ,
268
+ cache_control : Optional [str ] = None ,
269
+ ):
270
+ raise NotImplementedError ()
271
+
272
+ def get (self , rule : str , cors : Optional [bool ] = None , compress : bool = False , cache_control : Optional [str ] = None ):
273
+ """Get route decorator with GET `method`
274
+
275
+ Examples
276
+ --------
277
+ Simple example with a custom lambda handler using the Tracer capture_lambda_handler decorator
278
+
279
+ ```python
280
+ from aws_lambda_powertools import Tracer
281
+ from aws_lambda_powertools.event_handler import APIGatewayRestResolver
282
+
283
+ tracer = Tracer()
284
+ app = APIGatewayRestResolver()
285
+
286
+ @app.get("/get-call")
287
+ def simple_get():
288
+ return {"message": "Foo"}
289
+
290
+ @tracer.capture_lambda_handler
291
+ def lambda_handler(event, context):
292
+ return app.resolve(event, context)
293
+ ```
294
+ """
295
+ return self .route (rule , "GET" , cors , compress , cache_control )
296
+
297
+ def post (self , rule : str , cors : Optional [bool ] = None , compress : bool = False , cache_control : Optional [str ] = None ):
298
+ """Post route decorator with POST `method`
299
+
300
+ Examples
301
+ --------
302
+ Simple example with a custom lambda handler using the Tracer capture_lambda_handler decorator
303
+
304
+ ```python
305
+ from aws_lambda_powertools import Tracer
306
+ from aws_lambda_powertools.event_handler import APIGatewayRestResolver
307
+
308
+ tracer = Tracer()
309
+ app = APIGatewayRestResolver()
310
+
311
+ @app.post("/post-call")
312
+ def simple_post():
313
+ post_data: dict = app.current_event.json_body
314
+ return {"message": post_data["value"]}
315
+
316
+ @tracer.capture_lambda_handler
317
+ def lambda_handler(event, context):
318
+ return app.resolve(event, context)
319
+ ```
320
+ """
321
+ return self .route (rule , "POST" , cors , compress , cache_control )
322
+
323
+ def put (self , rule : str , cors : Optional [bool ] = None , compress : bool = False , cache_control : Optional [str ] = None ):
324
+ """Put route decorator with PUT `method`
325
+
326
+ Examples
327
+ --------
328
+ Simple example with a custom lambda handler using the Tracer capture_lambda_handler decorator
329
+
330
+ ```python
331
+ from aws_lambda_powertools import Tracer
332
+ from aws_lambda_powertools.event_handler import APIGatewayRestResolver
333
+
334
+ tracer = Tracer()
335
+ app = APIGatewayRestResolver()
336
+
337
+ @app.put("/put-call")
338
+ def simple_put():
339
+ put_data: dict = app.current_event.json_body
340
+ return {"message": put_data["value"]}
341
+
342
+ @tracer.capture_lambda_handler
343
+ def lambda_handler(event, context):
344
+ return app.resolve(event, context)
345
+ ```
346
+ """
347
+ return self .route (rule , "PUT" , cors , compress , cache_control )
348
+
349
+ def delete (
350
+ self , rule : str , cors : Optional [bool ] = None , compress : bool = False , cache_control : Optional [str ] = None
351
+ ):
352
+ """Delete route decorator with DELETE `method`
353
+
354
+ Examples
355
+ --------
356
+ Simple example with a custom lambda handler using the Tracer capture_lambda_handler decorator
357
+
358
+ ```python
359
+ from aws_lambda_powertools import Tracer
360
+ from aws_lambda_powertools.event_handler import APIGatewayRestResolver
361
+
362
+ tracer = Tracer()
363
+ app = APIGatewayRestResolver()
364
+
365
+ @app.delete("/delete-call")
366
+ def simple_delete():
367
+ return {"message": "deleted"}
368
+
369
+ @tracer.capture_lambda_handler
370
+ def lambda_handler(event, context):
371
+ return app.resolve(event, context)
372
+ ```
373
+ """
374
+ return self .route (rule , "DELETE" , cors , compress , cache_control )
375
+
376
+ def patch (
377
+ self , rule : str , cors : Optional [bool ] = None , compress : bool = False , cache_control : Optional [str ] = None
378
+ ):
379
+ """Patch route decorator with PATCH `method`
380
+
381
+ Examples
382
+ --------
383
+ Simple example with a custom lambda handler using the Tracer capture_lambda_handler decorator
384
+
385
+ ```python
386
+ from aws_lambda_powertools import Tracer
387
+ from aws_lambda_powertools.event_handler import APIGatewayRestResolver
388
+
389
+ tracer = Tracer()
390
+ app = APIGatewayRestResolver()
391
+
392
+ @app.patch("/patch-call")
393
+ def simple_patch():
394
+ patch_data: dict = app.current_event.json_body
395
+ patch_data["value"] = patched
396
+
397
+ return {"message": patch_data}
398
+
399
+ @tracer.capture_lambda_handler
400
+ def lambda_handler(event, context):
401
+ return app.resolve(event, context)
402
+ ```
403
+ """
404
+ return self .route (rule , "PATCH" , cors , compress , cache_control )
405
+
406
+ def append_context (self , ** additional_context ):
407
+ """Append key=value data as routing context"""
408
+ self .context .update (** additional_context )
409
+
410
+ def clear_context (self ):
411
+ """Resets routing context"""
412
+ self .context .clear ()
413
+
414
+
255
415
class ApiGatewayResolver (BaseRouter ):
256
416
"""API Gateway and ALB proxy resolver
257
417
@@ -595,7 +755,7 @@ def include_router(self, router: "Router", prefix: Optional[str] = None) -> None
595
755
596
756
Parameters
597
757
----------
598
- router : aws_lambda_powertools.event_handler.router. Router
758
+ router : aws_lambda_powertools.event_handler.Router
599
759
The Router containing a list of routes to be registered after the existing routes
600
760
prefix : str, optional
601
761
An optional prefix to be added to the originally defined rule
@@ -618,6 +778,31 @@ def include_router(self, router: "Router", prefix: Optional[str] = None) -> None
618
778
self .route (* route )(func )
619
779
620
780
781
+ class Router (BaseRouter ):
782
+ """Router helper class to allow splitting ApiGatewayResolver into multiple files"""
783
+
784
+ def __init__ (self ):
785
+ self ._routes : Dict [tuple , Callable ] = {}
786
+ self .api_resolver : Optional [BaseRouter ] = None
787
+ self .context = {} # early init as customers might add context before event resolution
788
+
789
+ def route (
790
+ self ,
791
+ rule : str ,
792
+ method : Union [str , Union [List [str ], Tuple [str ]]],
793
+ cors : Optional [bool ] = None ,
794
+ compress : bool = False ,
795
+ cache_control : Optional [str ] = None ,
796
+ ):
797
+ def register_route (func : Callable ):
798
+ # Convert methods to tuple. It needs to be hashable as its part of the self._routes dict key
799
+ methods = (method ,) if isinstance (method , str ) else tuple (method )
800
+ self ._routes [(rule , methods , cors , compress , cache_control )] = func
801
+ return func
802
+
803
+ return register_route
804
+
805
+
621
806
class APIGatewayRestResolver (ApiGatewayResolver ):
622
807
current_event : APIGatewayProxyEvent
623
808
0 commit comments