# pylambdarest
[![CI/CD Status](https://github.com/MarwanDebbiche/pylambdarest/workflows/CI%2FCD/badge.svg?branch=master)](https://github.com/MarwanDebbiche/pylambdarest/actions?query=branch:master)
[![Coverage Status](https://coveralls.io/repos/github/MarwanDebbiche/pylambdarest/badge.svg?branch=master)](https://coveralls.io/github/MarwanDebbiche/pylambdarest?branch=master)
[![Latest Version](https://img.shields.io/pypi/v/pylambdarest.svg?color=blue)](https://pypi.python.org/pypi/pylambdarest)
[![PyPI - Downloads](https://img.shields.io/pypi/dm/pylambdarest?label=pypi%20downloads)](https://pypi.org/project/pylambdarest/)
![License](https://img.shields.io/github/license/MarwanDebbiche/pylambdarest)
pylambdarest is a lightweight opinionated framework for building REST API using [AWS Lambda](https://aws.amazon.com/lambda/) and [API Gateway](https://aws.amazon.com/api-gateway/).
## Motivation
Why another framework ?
When using API Gateway and python Lambda functions, the most common pattern is to have a unique Lambda function triggered by a proxy API Gateway resource. The Lambda then uses a framework like [Flask](https://flask.palletsprojects.com/en/1.1.x/) to do all the routing. In an API Gateway + Lambda context, I feel like **the routing should be handled by API Gateway itself**, then forwarding the request to specific Lambda functions for each resource or endpoint.
## Features
- No routing. Yes, this is a feature. Routing should be handled by API Gateway.
- API Gateway event parsing (including request body and path parameters).
- Cleaner syntax.
- Optional body schema and query parameters validation.
## Installation
Install the package from PyPI using pip:
```
$ pip install pylambdarest
```
pylambdarest should also be included in the deployment package of your Lambda functions.
## Getting started
pylambdarest provides a `@route` decorator to parse the API Gateway event into a `Request` object available in the handler function as an argument. It also formats the handler's output to the expected Lambda + API Gateway format seamlessly.
Turning this:
```python
import json
def handler(event, context):
body = json.loads(event["body"])
query_params = event["queryStringParameters"]
path_params = event["pathParameters"]
return {
"statusCode": 200,
"body": json.dumps({
"message": f"Hello from AWS Lambda {body['name']}!!"
})
}
```
Into this:
```python
from pylambdarest import route
@route()
def handler(request):
body = request.json
query_params = request.query_params
path_params = request.path_params
return 200, {"message": f"Hello from AWS Lambda {body['name']}!!"}
```
You can still access the original `event` and `context` arguments from the handler:
```python
from pylambdarest import route
@route()
def handler(request, event, context):
print(event)
body = request.json
return 200, {"message": f"Hello from AWS Lambda {body['name']}!!"}
```
<br/>
Path parameters defined in API Gateway can also be accessed directly as function argument:
<br/>
![api-gateway-path-params](https://raw.githubusercontent.com/MarwanDebbiche/pylambdarest/master/images/api-gateway-path-params.png)
```python
from pylambdarest import route
@route()
def get_user(user_id):
print(user_id)
# get user from db
user = {"id": user_id, "name": "John Doe"}
return 200, user
```
## Schema Validation
pylambdarest optionally provides schema validation using [jsonschema](https://github.com/Julian/jsonschema):
```python
from pylambdarest import route
user_schema = {
"type": "object",
"properties": {
"name": {"type": "string"}
},
"required": ["name"],
"additionalProperties": False
}
@route(body_schema=user_schema)
def create_user(request):
# If the request's body does not
# satisfy the user_schema,
# a 400 will be returned
# Create user here
return 201
query_params_schema = {
"type": "object",
"properties": {
# Only string types are allowed for query parameters.
# Types casting should be done in the handler.
"page": {"type": "string"}
},
"additionalProperties": False
}
@route(query_params_schema=query_params_schema)
def get_users(request):
page = int(request.query_params.get("page", 1))
# request users in db
users = [
{"userId": i}
for i in range((page - 1) * 50, page * 50)
]
return 200, users
```
## Example
You can look at the [sample](https://github.com/MarwanDebbiche/pylambdarest/tree/master/sample) for a minimal pylambdarest API.
In this sample, we use the [serverless](https://www.serverless.com/) framework to declare the API Gateway -> Lambda routing
The packaging of the Lambda functions is done using the [serverless-python-requirements](https://github.com/UnitedIncome/serverless-python-requirements) plugin.
Raw data
{
"_id": null,
"home_page": "https://github.com/MarwanDebbiche/pylambdarest",
"name": "pylambdarest",
"maintainer": "",
"docs_url": null,
"requires_python": ">=3.7.2,<4.0.0",
"maintainer_email": "",
"keywords": "aws-lambda,serverless,api-gateway,rest-api",
"author": "Marwan Debbiche (Macbook Pro)",
"author_email": "marwan.debbiche@gmail.com",
"download_url": "https://files.pythonhosted.org/packages/c1/5b/2ebd216e671a48e72b9c6255996cfb661fa288e5cdd7b70bd85c91ee6cad/pylambdarest-0.2.1.tar.gz",
"platform": null,
"description": "# pylambdarest\n\n[![CI/CD Status](https://github.com/MarwanDebbiche/pylambdarest/workflows/CI%2FCD/badge.svg?branch=master)](https://github.com/MarwanDebbiche/pylambdarest/actions?query=branch:master)\n[![Coverage Status](https://coveralls.io/repos/github/MarwanDebbiche/pylambdarest/badge.svg?branch=master)](https://coveralls.io/github/MarwanDebbiche/pylambdarest?branch=master)\n[![Latest Version](https://img.shields.io/pypi/v/pylambdarest.svg?color=blue)](https://pypi.python.org/pypi/pylambdarest)\n[![PyPI - Downloads](https://img.shields.io/pypi/dm/pylambdarest?label=pypi%20downloads)](https://pypi.org/project/pylambdarest/)\n![License](https://img.shields.io/github/license/MarwanDebbiche/pylambdarest)\n\npylambdarest is a lightweight opinionated framework for building REST API using [AWS Lambda](https://aws.amazon.com/lambda/) and [API Gateway](https://aws.amazon.com/api-gateway/).\n\n## Motivation\n\nWhy another framework ?\n\nWhen using API Gateway and python Lambda functions, the most common pattern is to have a unique Lambda function triggered by a proxy API Gateway resource. The Lambda then uses a framework like [Flask](https://flask.palletsprojects.com/en/1.1.x/) to do all the routing. In an API Gateway + Lambda context, I feel like **the routing should be handled by API Gateway itself**, then forwarding the request to specific Lambda functions for each resource or endpoint.\n\n## Features\n\n- No routing. Yes, this is a feature. Routing should be handled by API Gateway.\n- API Gateway event parsing (including request body and path parameters).\n- Cleaner syntax.\n- Optional body schema and query parameters validation.\n\n## Installation\n\nInstall the package from PyPI using pip:\n\n```\n$ pip install pylambdarest\n```\n\npylambdarest should also be included in the deployment package of your Lambda functions.\n\n## Getting started\n\npylambdarest provides a `@route` decorator to parse the API Gateway event into a `Request` object available in the handler function as an argument. It also formats the handler's output to the expected Lambda + API Gateway format seamlessly.\n\nTurning this:\n\n```python\nimport json\n\ndef handler(event, context):\n body = json.loads(event[\"body\"])\n query_params = event[\"queryStringParameters\"]\n path_params = event[\"pathParameters\"]\n\n return {\n \"statusCode\": 200,\n \"body\": json.dumps({\n \"message\": f\"Hello from AWS Lambda {body['name']}!!\"\n })\n }\n\n```\n\nInto this:\n\n```python\nfrom pylambdarest import route\n\n@route()\ndef handler(request):\n body = request.json\n query_params = request.query_params\n path_params = request.path_params\n\n return 200, {\"message\": f\"Hello from AWS Lambda {body['name']}!!\"}\n```\n\nYou can still access the original `event` and `context` arguments from the handler:\n\n```python\nfrom pylambdarest import route\n\n@route()\ndef handler(request, event, context):\n print(event)\n body = request.json\n\n return 200, {\"message\": f\"Hello from AWS Lambda {body['name']}!!\"}\n```\n\n<br/>\n\nPath parameters defined in API Gateway can also be accessed directly as function argument:\n\n<br/>\n\n![api-gateway-path-params](https://raw.githubusercontent.com/MarwanDebbiche/pylambdarest/master/images/api-gateway-path-params.png)\n\n```python\nfrom pylambdarest import route\n\n@route()\ndef get_user(user_id):\n print(user_id)\n\n # get user from db\n user = {\"id\": user_id, \"name\": \"John Doe\"}\n\n return 200, user\n```\n\n## Schema Validation\n\npylambdarest optionally provides schema validation using [jsonschema](https://github.com/Julian/jsonschema):\n\n```python\nfrom pylambdarest import route\n\nuser_schema = {\n \"type\": \"object\",\n \"properties\": {\n \"name\": {\"type\": \"string\"}\n },\n \"required\": [\"name\"],\n \"additionalProperties\": False\n}\n\n@route(body_schema=user_schema)\ndef create_user(request):\n # If the request's body does not\n # satisfy the user_schema,\n # a 400 will be returned\n\n # Create user here\n\n return 201\n\n\nquery_params_schema = {\n \"type\": \"object\",\n \"properties\": {\n # Only string types are allowed for query parameters.\n # Types casting should be done in the handler.\n \"page\": {\"type\": \"string\"}\n },\n \"additionalProperties\": False\n}\n\n@route(query_params_schema=query_params_schema)\ndef get_users(request):\n page = int(request.query_params.get(\"page\", 1))\n\n # request users in db\n users = [\n {\"userId\": i}\n for i in range((page - 1) * 50, page * 50)\n ]\n\n return 200, users\n```\n\n## Example\n\nYou can look at the [sample](https://github.com/MarwanDebbiche/pylambdarest/tree/master/sample) for a minimal pylambdarest API.\n\nIn this sample, we use the [serverless](https://www.serverless.com/) framework to declare the API Gateway -> Lambda routing\n\nThe packaging of the Lambda functions is done using the [serverless-python-requirements](https://github.com/UnitedIncome/serverless-python-requirements) plugin.\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "Lightweight framework for building REST API using AWS Lambda + API Gateway",
"version": "0.2.1",
"project_urls": {
"Documentation": "https://pylambdarest.readthedocs.io",
"Homepage": "https://github.com/MarwanDebbiche/pylambdarest",
"Repository": "https://github.com/MarwanDebbiche/pylambdarest"
},
"split_keywords": [
"aws-lambda",
"serverless",
"api-gateway",
"rest-api"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "69cf35d37623512490945681ad87af5dd994bb1da339582ab3d7b86295b7c1fc",
"md5": "f68b4a4bb29fde6e2081c632f5958dad",
"sha256": "44acfad5d240ec5b7dbf84e8ca03a1b81e4bc7d52c4f8529e5296fbdab5ace9e"
},
"downloads": -1,
"filename": "pylambdarest-0.2.1-py3-none-any.whl",
"has_sig": false,
"md5_digest": "f68b4a4bb29fde6e2081c632f5958dad",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.7.2,<4.0.0",
"size": 6799,
"upload_time": "2022-10-31T17:07:13",
"upload_time_iso_8601": "2022-10-31T17:07:13.998165Z",
"url": "https://files.pythonhosted.org/packages/69/cf/35d37623512490945681ad87af5dd994bb1da339582ab3d7b86295b7c1fc/pylambdarest-0.2.1-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "c15b2ebd216e671a48e72b9c6255996cfb661fa288e5cdd7b70bd85c91ee6cad",
"md5": "f8bfe2826d5d077eb522e13657102bb4",
"sha256": "1057a77eb7d669a625b0092cbd03f6a317757965e9739164b18bed0606ec144f"
},
"downloads": -1,
"filename": "pylambdarest-0.2.1.tar.gz",
"has_sig": false,
"md5_digest": "f8bfe2826d5d077eb522e13657102bb4",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.7.2,<4.0.0",
"size": 6545,
"upload_time": "2022-10-31T17:07:15",
"upload_time_iso_8601": "2022-10-31T17:07:15.989490Z",
"url": "https://files.pythonhosted.org/packages/c1/5b/2ebd216e671a48e72b9c6255996cfb661fa288e5cdd7b70bd85c91ee6cad/pylambdarest-0.2.1.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2022-10-31 17:07:15",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "MarwanDebbiche",
"github_project": "pylambdarest",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "pylambdarest"
}