Pyverless
Developing complex APIs within AWS lambdas can be somewhat of a messy task. Lambdas are independent functions that have to work together in order to create a full-blown app, like atoms to a complex organism.
In order to define the infrastructure you may use a framework like Serverless, but you may find yourself copying and pasting blobs of code within your handler functions, namely for authentication, data validation, error handling and response creation to name a few.
Enter Pyverless
Pyverless is a mini-framework with a bunch of utilities that aims to help you create APIs using AWS Lambdas fast and in a consistent way. Pyverless provides the following.
- Class-Based Handlers
- Serializers
- Authentication handling
- JWT and cryptography
- Exceptions
- Configuration
- Warmup handling
Bring more consistency and development speed to your lambda-based APIs!
Class-Based Handlers
Class based handlers (CBH) use the approach of Django's Class-Based Views to provide code reuse, consistency and generally abstract simple and common tasks. The aim of class-based handlers is to suit a wide range of applications by providing generic Handler classes and mixins.
Within AWS Lambda, a handler is a function that takes an event and a context and returns a response.
Generic CBH are based off the following base handler
BaseHandler
This class provides the as_handler()
method that returns a handler function (taking event
and context
as arguments).
Usage:
class MyHandler(BaseHandler):
pass
_myHandler = MyHandler.as_handler()
There is a set of generic CBHs to handle basic CRUD operations within an API:
CreateHandler
Handler that reads the request body and creates the object with each (key, value) pair as a parameter for the constructor.
The model
attribute must be set on the handler and the create_object
method can be overwritten.
Usage:
class UserCreateHandler(CreateHandler):
model = MyUserClass
required_body_keys = ['email', 'password']
RetrieveHandler
Handler that returns a serialized Object.
The model
attribute must be set and id
must be present on the pathParameters.
The user must overwrite either the serializer
attribute or the serialize
method.
Usage:
class UserRetrieveHandler(RetrieveHandler):
model = MyUserClass
serializer = serialize_user
UpdateHandler
Handler that sets self.object and for each (key, value) pair of the body
sets self.object.key = value.
The model
attribute must be set and id
must be present on the pathParameters.
Returns the serialized node and sets the HTTP status code to 200
Usage:
class UserUpdateHandler(UpdateHandler):
model = MyUserClass
required_body_keys = ['title', 'body']
serializer = serialize_user
DeleteHandler
Handler that sets self.object, calls its delete() method and sets the HTTP status code to 204.
The model
attribute must be set and id
must be present on the pathParameters.
The user can also overwrite the get_queryset
method to limit the search.
Usage:
class UserDeleteHandler(DeleteHandler):
model = MyUserClass
ListHandler
Handler that returns a list of serialized nodes and sets the HTTP status code to 200.
The model
attribute must be set and the user must overwrite either the serializer
attribute
or the serialize
method.
class UserListHandler(ListHandler):
model = MyUserClass
serializer = user_serializer
def get_queryset(self):
return only_some_users
Mixins
There are also a set of mixins available:
RequestBodyMixin
This mixin provides the get_body()
method which is in charge of gathering the request body dictionary. Define required_body_keys
and optinal_body_keys
as follows. Within the handler, you can access the body via self.body
or by calling get_body()
class MyHandler(RequestBodyMixin, BaseHandler):
required_body_keys = ['name', 'email']
optinal_body_keys = ['phone']
_myHandler = MyHandler.as_handler()
AuthorizationMixin
This mixin provides the get_user()
method in charge of getting the user out of an authenticated API call.
Within the handler, you can access the body via self.user
or by calling get_user()
. The user will be a object
of the class specified on pyverless settings as USER_MODEL
.
RequestBodyMixin
This mixin provides the get_object()
method in charge of gathering a particular object,
you can access the object via self.object
.
The id
of the object will be taken from the pathParameters and
the user must set the model
attribute on the handler.
ListMixin
This mixin provides the get_queryset()
method in charge of getting a list of objects,
you can access the list via self.queryset
. The user must set the model
attribute
and either the serializer
attribute or serialize()
method on the handler.
S3FileMixin
This mixin provides the get_file()
and get_message_part()
methods in charge of
reading an event from aws S3, you can access the file via self.file
.
The file will be a dict()
with the following keys: bucket, owner, file_name, size.
Warning: Only tested with objectCreated!!!!
SQSMessagesMixin
This mixin provides the get_messages()
method in charge of reading an SQS event from aws.
You can access the list of messages via self.messages
.
Each message will be a dict()
with the following keys: attributes, text_message, queue_source, region.
Serializers
TODO