Examples

HTTP handlers

Skipping the CORS headers default and configuring it.

>>> from pprint import pprint

>>> from lambda_handlers.handlers import http_handler
>>> from lambda_handlers.response import cors

>>> @http_handler(
...     cors=cors(origin='localhost', credentials=False),
... )
... def handler(event, context):
...     return event['body']

>>> payload = {'body': '{"answer": 42}'}    
>>> response = handler(payload, None)
>>> pprint(response)
{'body': '{"answer": 42}',
 'headers': {'Access-Control-Allow-Origin': 'localhost',
             'Content-Type': 'application/json'},
 'statusCode': 200}

Using jsonschema to validate a User model as input.

>>> from pprint import pprint
>>> from typing import Any, Dict, List, Tuple, Union

>>> import jsonschema

>>> from lambda_handlers.handlers import http_handler
>>> from lambda_handlers.errors import EventValidationError

>>> class SchemaValidator:
...    """A payload validator that uses jsonschema schemas."""
...
...    @classmethod
...    def validate(cls, instance, schema: Dict[str, Any]):
...        """Raise EventValidationError (if any error) from validating `instance` against `schema`."""
...        validator = jsonschema.Draft7Validator(schema)
...        errors = list(validator.iter_errors(instance))
...        if errors:
...            field_errors = sorted(validator.iter_errors(instance), key=lambda error: error.path)
...            raise EventValidationError(field_errors)
...
...    @staticmethod
...    def format_errors(errors: List[Dict[str, Any]]) -> List[Dict[str, Any]]:
...        """Re-format the errors from JSONSchema."""
...        path_errors: Dict[str, List[str]] = defaultdict(list)
...        for error in errors:
...            path_errors[error.path.pop()].append(error.message)
...        return [{path: messages} for path, messages in path_errors.items()]

>>> user_schema: Dict[str, Any] = {
...     'type': 'object',
...     'properties': {
...         'user_id': {'type': 'number'},
...     },
... }

>>> @http_handler()
... def handler(event, context):
...     user = event['body']
...     SchemaValidator.validate(user, user_schema)
...     return user

>>> payload = {'body': '{"user_id": 42}'}    
>>> response = handler(payload, None)
>>> pprint(response)
{'body': '{"user_id": 42}',
 'headers': {'Access-Control-Allow-Credentials': True,
             'Access-Control-Allow-Origin': '*',
             'Content-Type': 'application/json'},
 'statusCode': 200}

Using Marshmallow to validate a User model as input body and response body.

>>> from pprint import pprint
>>> from typing import Any, Dict, List, Tuple, Union

>>> from marshmallow import Schema, fields, ValidationError

>>> from lambda_handlers.handlers import http_handler
>>> from lambda_handlers.errors import EventValidationError

>>> class SchemaValidator:
...     """A data validator that uses Marshmallow schemas."""
... 
...     @classmethod
...     def validate(cls, instance: Any, schema: Schema) -> Any:
...         """Return the data or raise EventValidationError if any error from validating `instance` against `schema`."""
...         try:
...             return schema.load(instance)
...         except ValidationError as error:
...             raise EventValidationError(error.messages)

>>> class UserSchema(Schema):
...     user_id = fields.Integer(required=True)

>>> @http_handler()
... def handler(event, context):
...     user = event['body']
...     SchemaValidator.validate(user, UserSchema())
...     return user

>>> payload = {'body': '{"user_id": 42}'}    
>>> response = handler(payload, None)
>>> pprint(response)
{'body': '{"user_id": 42}',
 'headers': {'Access-Control-Allow-Credentials': True,
             'Access-Control-Allow-Origin': '*',
             'Content-Type': 'application/json'},
 'statusCode': 200}

>>> payload = {'body': '{"user_id": "marvin"}'}    
>>> response = handler(payload, None)
>>> pprint(response)
{'body': '{"errors": {"user_id": ["Not a valid integer."]}}',
 'headers': {'Access-Control-Allow-Credentials': True,
             'Access-Control-Allow-Origin': '*',
             'Content-Type': 'application/json'},
 'statusCode': 400}