A lightweight framework for AWS Lambda for building Rest APIs.
Peyton is designed to be as small as possible, with no requirements outside of the standard python library. It allows developers to create and deploy serverless applications easily.
Currently Peyton supports v1.0 of the API Gateway Payload format and has been tested with both HTTP and REST APIs.
Peyton is being used in pre-production and is stable. However, the project is in it's pre-1.0 state and may change quickly. The author(s) will note breaking changes for releases, when necessary.
Peyton has no dependencies outside of the Python standard library.
Note: Pipenv is used for local development and CI only.
At this time Peyton only supports class based views, using HTTP verbs as method names. In practice class based views prove to be generally easy to reason about and encourage organization within a codebase.
At a minimum you must do three things to use Peyton:
- Instantiate the
Router
class - Define a new class that subclasses Peyton's
ViewClass
- Add the
register
decorator to the class, specifying the path to be used
Below is a simple example of an API definition with two views (routes).
from peyton.view import ViewBase
from peyton.response import Response
from peyton.request import Request
from peyton.router import Router
router = Router()
@router.register(path="/")
class Index(ViewBase):
def get(self) -> dict:
resp = Response(status_code=200, headers={}, body={"message": "received GET to index"},)
return resp.to_json()
def put(self) -> dict:
# Retrieve the body from the request
body = router.current_request.body
# Do something with the body
resp = Response(status_code=201, headers={}, body={"message": "received PUT to index"})
return resp.to_json()
def post(self) -> dict:
# Retrieve the body from the request
body = router.current_request.body
# Do something with the body
resp = Response(status_code=201, headers={}, body={"message": "received POST to index"})
return resp.to_json()
@router.register(path="/foo/{foo_id}/bar/{bar_id}")
class AllBars(ViewBase):
def get(self, foo_id, bar_id) -> dict:
resp = Response(status_code=200, headers={}, body={"foo_id": foo_id, "bar_id": bar_id, "message": "all bars by foo"},)
return resp.to_json()
def put(self, foo_id, bar_id) -> dict:
# Retrieve the body from the request
body = router.current_request.body
# Do something with the body
resp = Response(status_code=201, headers={}, body={"message": "received PUT to index"})
return resp.to_json()
def post(self, foo_id, bar_id) -> dict:
# Retrieve the body from the request
body = router.current_request.body
# Do something with the body
resp = Response(status_code=201, headers={}, body={"message": "received POST to index"})
return resp.to_json()
def lambda_handler(event, context):
request = Request(event)
return router.dispatch(request=request)
Performance is a top priority of this project. The total code package is designed to be as small as possible with no dependencies outside of the standard library. There will be continuous work being done to increase the speed of the code.
It is important to recognize when performing benchmarks when running APIs on lambda and observing the benchmarks below that using (or increasing) Provisioned Concurrency will reduce concurrent request times dramatically.
You can see benchmarks here
Peyton was inspired by Flask and Chalice. Please check out those great projects in addition to Peyton.