Module aws_lambda_powertools.middleware_factory
Utilities to enhance middlewares
Expand source code
""" Utilities to enhance middlewares """
from .factory import lambda_handler_decorator
__all__ = ["lambda_handler_decorator"]
Sub-modules
aws_lambda_powertools.middleware_factory.exceptions
aws_lambda_powertools.middleware_factory.factory
Functions
def lambda_handler_decorator(decorator: Optional[Callable] = None, trace_execution: Optional[bool] = None) ‑> Callable
-
Decorator factory for decorating Lambda handlers.
You can use lambda_handler_decorator to create your own middlewares, where your function signature follows:
fn(handler, event, context)
Custom keyword arguments are also supported e.g.
fn(handler, event, context, option=value)
Middlewares created by this factory supports tracing to help you quickly troubleshoot any overhead that custom middlewares may cause - They will appear as custom subsegments.
Non-key value params are not supported e.g.
fn(handler, event, context, option)
Environment Variables
POWERTOOLS_TRACE_MIDDLEWARES : str uses
Tracer
to create sub-segments per middleware (e.g."true", "True", "TRUE"
)Parameters
decorator
:Callable
- Middleware to be wrapped by this factory
trace_execution
:bool
-
Flag to explicitly enable trace execution for middlewares.
Env POWERTOOLS_TRACE_MIDDLEWARES="true"
Example
Create a middleware no params
from aws_lambda_powertools.middleware_factory import lambda_handler_decorator @lambda_handler_decorator def log_response(handler, event, context): any_code_to_execute_before_lambda_handler() response = handler(event, context) any_code_to_execute_after_lambda_handler() print(f"Lambda handler response: {response}") @log_response def lambda_handler(event, context): return True
Create a middleware with params
from aws_lambda_powertools.middleware_factory import lambda_handler_decorator @lambda_handler_decorator def obfuscate_sensitive_data(handler, event, context, fields=None): # Obfuscate email before calling Lambda handler if fields: for field in fields: field = event.get(field, "") event[field] = obfuscate_pii(field) response = handler(event, context) print(f"Lambda handler response: {response}") @obfuscate_sensitive_data(fields=["email"]) def lambda_handler(event, context): return True
Trace execution of custom middleware
from aws_lambda_powertools import Tracer from aws_lambda_powertools.middleware_factory import lambda_handler_decorator tracer = Tracer(service="payment") # or via env var ... @lambda_handler_decorator(trace_execution=True) def log_response(handler, event, context): ... @tracer.capture_lambda_handler @log_response def lambda_handler(event, context): return True
Limitations
- Async middlewares not supported
- Classes, class methods middlewares not supported
Raises
MiddlewareInvalidArgumentError
- When middleware receives non keyword=arguments
Expand source code
def lambda_handler_decorator(decorator: Optional[Callable] = None, trace_execution: Optional[bool] = None) -> Callable: """Decorator factory for decorating Lambda handlers. You can use lambda_handler_decorator to create your own middlewares, where your function signature follows: `fn(handler, event, context)` Custom keyword arguments are also supported e.g. `fn(handler, event, context, option=value)` Middlewares created by this factory supports tracing to help you quickly troubleshoot any overhead that custom middlewares may cause - They will appear as custom subsegments. **Non-key value params are not supported** e.g. `fn(handler, event, context, option)` Environment variables --------------------- POWERTOOLS_TRACE_MIDDLEWARES : str uses `aws_lambda_powertools.tracing.Tracer` to create sub-segments per middleware (e.g. `"true", "True", "TRUE"`) Parameters ---------- decorator: Callable Middleware to be wrapped by this factory trace_execution: bool Flag to explicitly enable trace execution for middlewares.\n `Env POWERTOOLS_TRACE_MIDDLEWARES="true"` Example ------- **Create a middleware no params** from aws_lambda_powertools.middleware_factory import lambda_handler_decorator @lambda_handler_decorator def log_response(handler, event, context): any_code_to_execute_before_lambda_handler() response = handler(event, context) any_code_to_execute_after_lambda_handler() print(f"Lambda handler response: {response}") @log_response def lambda_handler(event, context): return True **Create a middleware with params** from aws_lambda_powertools.middleware_factory import lambda_handler_decorator @lambda_handler_decorator def obfuscate_sensitive_data(handler, event, context, fields=None): # Obfuscate email before calling Lambda handler if fields: for field in fields: field = event.get(field, "") event[field] = obfuscate_pii(field) response = handler(event, context) print(f"Lambda handler response: {response}") @obfuscate_sensitive_data(fields=["email"]) def lambda_handler(event, context): return True **Trace execution of custom middleware** from aws_lambda_powertools import Tracer from aws_lambda_powertools.middleware_factory import lambda_handler_decorator tracer = Tracer(service="payment") # or via env var ... @lambda_handler_decorator(trace_execution=True) def log_response(handler, event, context): ... @tracer.capture_lambda_handler @log_response def lambda_handler(event, context): return True Limitations ----------- * Async middlewares not supported * Classes, class methods middlewares not supported Raises ------ MiddlewareInvalidArgumentError When middleware receives non keyword=arguments """ if decorator is None: return functools.partial(lambda_handler_decorator, trace_execution=trace_execution) trace_execution = resolve_truthy_env_var_choice( env=os.getenv(constants.MIDDLEWARE_FACTORY_TRACE_ENV, "false"), choice=trace_execution, ) @functools.wraps(decorator) def final_decorator(func: Optional[Callable] = None, **kwargs: Any): # If called with kwargs return new func with kwargs if func is None: return functools.partial(final_decorator, **kwargs) if not inspect.isfunction(func): # @custom_middleware(True) vs @custom_middleware(log_event=True) raise MiddlewareInvalidArgumentError( f"Only keyword arguments is supported for middlewares: {decorator.__qualname__} received {func}", # type: ignore # noqa: E501 ) @functools.wraps(func) def wrapper(event, context, **handler_kwargs): try: middleware = functools.partial(decorator, func, event, context, **kwargs, **handler_kwargs) if trace_execution: tracer = Tracer(auto_patch=False) with tracer.provider.in_subsegment(name=f"## {decorator.__qualname__}"): response = middleware() else: response = middleware() return response except Exception: logger.exception(f"Caught exception in {decorator.__qualname__}") raise return wrapper return final_decorator