Flask like web framework for AWS Lambda

Overview

lambdarest logo

lambdarest

Build Status Latest Version PyPI - Downloads Python Support Examples tested with pytest-readme

Python routing mini-framework for AWS Lambda with optional JSON-schema validation.

⚠️ A user study is currently happening here, and your opinion makes the day! Thanks for participating! 😊

Features

  • lambda_handler function constructor with built-in dispatcher
  • Decorator to register functions to handle HTTP methods
  • Optional JSON-schema input validation using same decorator

Support the development ❤️

You can support the development by:

  1. Contributing code

  2. Buying the maintainer a coffee

  3. Buying some Lambdarest swag

    like this mug for example:

    lambdarest mug

External articles / tutorials

Other articles? add them here

Installation

Install the package from PyPI using pip:

$ pip install lambdarest

Getting Started

This module helps you to handle different HTTP methods in your AWS Lambda.

from lambdarest import lambda_handler

@lambda_handler.handle("get")
def my_own_get(event):
    return {"this": "will be json dumped"}

##### TEST #####

input_event = {
    "body": '{}',
    "httpMethod": "GET",
    "resource": "/"
}
result = lambda_handler(event=input_event)
assert result == {"body": '{"this": "will be json dumped"}', "statusCode": 200, "headers":{}}

Documentation

See docs for documentation and examples covering amongst:

Anormal unittest behaviour with lambda_handler singleton

Because of python unittests leaky test-cases it seems like you shall beware of this issue when using the singleton lambda_handler in a multiple test-case scenario.

Tests

This package uses Poetry to install requirements and run tests.

Use the following commands to install requirements and run test-suite:

$ poetry install
$ poetry run task test

For more info see Contributing...

Changelog

See HISTORY.md

Contributors

Thanks for contributing!

@sphaugh, @amacks, @jacksgt, @mkreg, @aphexer, @nabrosimoff, @elviejokike, @eduardomourar, @devgrok, @AlbertoTrindade, @paddie, @svdgraaf, @simongarnier, @martinbuberl, @adamelmore, @sloev

Wanna contribute?

And by the way, we have a Code Of Friendlyhood!

Comments
  • Support of resource path {placeholders} in the middle

    Support of resource path {placeholders} in the middle

    I made a resource path preparing before routing.

    The issue was found when I tried to implement lambda for working with URL /bay/{bay_id}/status. The router was not able to find a correct handler.

    I made preparing of the path before routing. Now, the resource path is being filled by path parameters before the routing, but if the parameters list is incorrect, the code still returns code 404.

    opened by nabrosimoff 12
  • Make Api Gateway custom domain work (with basepath)

    Make Api Gateway custom domain work (with basepath)

    When APIGW is setup with a custom domain. The path to the call will include the basepath (if setup). To fix this, we need to check for the resource path which will contain the actual path without the basepath.

    This fixes #31

    opened by svdgraaf 12
  • Fixed issue where using path parameters but no custom domain breaks

    Fixed issue where using path parameters but no custom domain breaks

    I just redeployed an api to api gateway without a custom domain, but with path parameters in the url. This broke the parsing. I think this was an edge cased that I missed last time.

    This change fixes this issue. It checks if both path and resource are set. If so, it checks if they are the same. If so, it uses resource, if not. It uses path, which will contain all the values for the path parameters.

    opened by svdgraaf 11
  • [Question/BUG] Query Parameters converted to float

    [Question/BUG] Query Parameters converted to float

    issue / feature request

    I Would like to understand the rationale of converting any query parameter that is a series of digits to floats. I am building an API that relies on Account ID's being based which are digits, these are needed in string form and python-lambdarest uses the float() function to convert all strings that are numeric, without the ability to override this behaviour from what i can tell.

    Is there a reason for this - HTTP is a string based protocol afaik, hence converting to float seems somewhat arbitrary and if needed something that could be done in business logic vs the underlying library which is parsing the API Gateway JSON payload.

    Thanks!

    opened by andyfase 9
  • Use workzeug for route parsing

    Use workzeug for route parsing

    TL/DR: This PR makes paths like /foo/bar/<int:id>/ work.

    I needed path parameter support for my api, I noticed that Workzeug (from Flask) solved that issue already, and here we are.

    • I added a dependency on workzeug
    • I added the mapper for mapping the function calls
    • I added a short description in the readme
    opened by svdgraaf 7
  • minimally process standard lambda (dict) responses

    minimally process standard lambda (dict) responses

    Personally, I'd prefer to be able to return a normal lambda response from my handlers and not have to introduce a library-specific output format:

    @lambda_handler.handle("get", path="/")
    def index(event: dict) -> dict:
    	return {
    		"statusCode": 302,
    		"headers": {
    			"Location": "https://example.com"
    		}
    	}
    

    This allows the library to be used solely for its routing capabilities which is desirable to those that aren't interested in any output massaging.

    opened by adamelmore 6
  • Using functools wraps on inner function

    Using functools wraps on inner function

    This fixes the same issues from PR #51 , but it also works for python 2.7.

    I run into problems when trying to document the code that contained @lambda_handler and it was not possible because the wrapper function was not marked as decorator.

    opened by eduardomourar 6
  • Options for configuring CORS and preflight requests

    Options for configuring CORS and preflight requests

    Is CORS handling within the scope of this project?

    I'd like to configure CORS when I call create_lambda_handler. Maybe it would be sufficient to add a headers kwarg for my use case?

    @sloev

    opened by furrycatherder 5
  • [BUG] multiValueHeaders not being sent back (ALB)

    [BUG] multiValueHeaders not being sent back (ALB)

    It looks like ALB needs support for multiValueHeaders as part of the return JSON for things like Content-Type, headers does not seem to be properly passed through the ALB. I added a multiValueHeader element by copying and modifying headers in the to_json and inner_lambda_handler and it seems to work as expected and the ALB properly interprets. I can submit a PR, but I cannot vouch for the quality of the code, however it does seem to work

    diff --git a/lambdarest/__init__.py b/lambdarest/__init__.py
    index d8cd80f..8079e97 100755
    --- a/lambdarest/__init__.py
    +++ b/lambdarest/__init__.py
    @@ -22,10 +22,11 @@ class Response(object):
         if no headers are specified, empty dict is returned
         """
     
    -    def __init__(self, body=None, status_code=None, headers=None):
    +    def __init__(self, body=None, status_code=None, headers=None, multiValueHeaders=None):
             self.body = body
             self.status_code = status_code
             self.headers = headers
    +        self.multiValueHeaders = multiValueHeaders
             self.status_code_description = None
             self.isBase64_encoded = False
     
    @@ -42,8 +43,12 @@ class Response(object):
                 if do_json_dumps
                 else self.body,
                 "statusCode": status_code,
    -            "headers": self.headers or {},
             }
    +        ## handle multiValueHeaders if defined, default to headers
    +        if (self.multiValueHeaders == None) :
    +            response["headers"] = self.headers or {}
    +        else:
    +            response["multiValueHeaders"] = self.multiValueHeaders
             # if body is None, remove the key
             if response.get("body") == None:
                 response.pop("body")
    @@ -235,21 +240,22 @@ def create_lambda_handler(
                                 raise ValueError("Response tuple has more than 3 items")
     
                             # Unpack the tuple, missing items will be defaulted
    -                        body, status_code, headers = response + (None,) * (
    -                            3 - response_len
    +                        body, status_code, headers, multiValueHeaders = response + (None,) * (
    +                            4 - response_len
                             )
     
                         elif isinstance(response, dict) and all(
    -                        key in ["body", "statusCode", "headers"]
    +                        key in ["body", "statusCode", "headers", "multiValueHeaders"]
                             for key in response.keys()
                         ):
                             body = response.get("body")
                             status_code = response.get("statusCode") or status_code
                             headers = response.get("headers") or headers
    +                        multiValueHeaders = response.get("multiValueHeaders") or multiValueHeaders
     
                         else:  # if response is string, int, etc.
                             body = response
    -                    response = Response(body, status_code, headers)
    +                    response = Response(body, status_code, headers, multiValueHeaders)
                     return response.to_json(
                         encoder=json_encoder,
                         application_load_balancer=application_load_balancer,
    
    
    opened by amacks 5
  • Trouble installing with pip

    Trouble installing with pip

    When running the install command "pip install lambdarest" I get an error

    ERROR: Command errored out with exit status 1: command: /backend/api_lambda/bin/python3 -c 'import sys, setuptools, tokenize; sys.argv[0] = '"'"'/private/var/folders/65/jpxwzrxj68xb7lp74c2_yf8hrp6vql/T/pip-install-wor4aeh7/lambdarest/setup.py'"'"'; file='"'"'/private/var/folders/65/jpxwzrxj68xb7lp74c2_yf8hrp6vql/T/pip-install-wor4aeh7/lambdarest/setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(file);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, file, '"'"'exec'"'"'))' egg_info --egg-base /private/var/folders/65/jpxwzrxj68xb7lp74c2_yf8hrp6vql/T/pip-install-wor4aeh7/lambdarest/pip-egg-info cwd: /private/var/folders/65/jpxwzrxj68xb7lp74c2_yf8hrp6vql/T/pip-install-wor4aeh7/lambdarest/ Complete output (5 lines): Traceback (most recent call last): File "", line 1, in File "/private/var/folders/65/jpxwzrxj68xb7lp74c2_yf8hrp6vql/T/pip-install-wor4aeh7/lambdarest/setup.py", line 9, in history = open("HISTORY.md").read() FileNotFoundError: [Errno 2] No such file or directory: 'HISTORY.md' ---------------------------------------- ERROR: Command errored out with exit status 1: python setup.py egg_info Check the logs for full command output.

    Is there an issue with the setup.py script? Is this a known issue?

    opened by zchesty 5
  • Briefly mention in README how to setup api-gateway for Lambdarest lambda

    Briefly mention in README how to setup api-gateway for Lambdarest lambda

    Hi @svdgraaf, Can you maybe briefly write an update to the readme mentioning how to setup the api-gateway for using Lambdarest. I haven't been using lambdarest in production in over a year so i am a bit rusty. Thanks for your contributions!

    help wanted 
    opened by sloev 5
  • [ENHANCEMENT] Support Lambda Function URLs

    [ENHANCEMENT] Support Lambda Function URLs

    I've been using lambdarest for years and tried the latest version with Lambda Function URLs, which will not work without a bit of work (notably, the field names in the event are slightly different than what the code expects). I recognize this project is currently unmaintained, but wanted to introduce this enhancement as a notice to other users should they consider trying this themselves.

    Sample event from Lambda Function URL request

    {
      "version": "2.0",
      "routeKey": "$default",
      "rawPath": "/my/path",
      "rawQueryString": "parameter1=value1&parameter1=value2&parameter2=value",
      "cookies": [
        "cookie1",
        "cookie2"
      ],
      "headers": {
        "header1": "value1",
        "header2": "value1,value2"
      },
      "queryStringParameters": {
        "parameter1": "value1,value2",
        "parameter2": "value"
      },
      "requestContext": {
        "accountId": "123456789012",
        "apiId": "<urlid>",
        "authentication": null,
        "authorizer": {
            "iam": {
                    "accessKey": "AKIA...",
                    "accountId": "111122223333",
                    "callerId": "AIDA...",
                    "cognitoIdentity": null,
                    "principalOrgId": null,
                    "userArn": "arn:aws:iam::111122223333:user/example-user",
                    "userId": "AIDA..."
            }
        },
        "domainName": "<url-id>.lambda-url.us-west-2.on.aws",
        "domainPrefix": "<url-id>",
        "http": {
          "method": "POST",
          "path": "/my/path",
          "protocol": "HTTP/1.1",
          "sourceIp": "123.123.123.123",
          "userAgent": "agent"
        },
        "requestId": "id",
        "routeKey": "$default",
        "stage": "$default",
        "time": "12/Mar/2020:19:03:58 +0000",
        "timeEpoch": 1583348638390
      },
      "body": "Hello from client!",
      "pathParameters": null,
      "isBase64Encoded": false,
      "stageVariables": null
    }
    
    help wanted Pay maintainer to give a damn 😅 
    opened by gswalden 1
Releases(untagged-080ed2ae2bbff1b043aa)
Owner
sloev / Johannes Valbjørn
I like to write software and then give it away for free. Walking the thin line between silly and useful.
sloev / Johannes Valbjørn
TinyAPI - 🔹 A fast & easy and lightweight WSGI Framework for Python

TinyAPI - 🔹 A fast & easy and lightweight WSGI Framework for Python

xArty 3 Apr 08, 2022
A PC remote controller for YouTube and Twitch

Lazynite Lazynite is a PC remote controller for YouTube and Twitch on Telegram. Features Volume control; Browser fullscreen / video fullscreen; PC shu

Alessio Celentano 46 Nov 12, 2022
Swagger/OpenAPI First framework for Python on top of Flask with automatic endpoint validation & OAuth2 support

Connexion Connexion is a framework that automagically handles HTTP requests based on OpenAPI Specification (formerly known as Swagger Spec) of your AP

Zalando SE 4.2k Jan 07, 2023
Web APIs for Django. 🎸

Django REST framework Awesome web-browsable Web APIs. Full documentation for the project is available at https://www.django-rest-framework.org/. Fundi

Encode 24.7k Jan 03, 2023
The source code to the Midnight project

MidnightSniper Started: 24/08/2021 Ended: 24/10/2021 What? This is the source code to a project developed to snipe minecraft names Why release? The ad

Kami 2 Dec 03, 2021
JustPy is an object-oriented, component based, high-level Python Web Framework

JustPy Docs and Tutorials Introduction JustPy is an object-oriented, component based, high-level Python Web Framework that requires no front-en

927 Jan 08, 2023
A simple todo app using flask and sqlachemy

TODO app This is a simple TODO app made using Flask. Packages used: DoodleCSS Special thanks to Chris McCormick (@mccrmx) :) Flask Flask-SQLAlchemy Fl

Lenin 1 Dec 26, 2021
CherryPy is a pythonic, object-oriented HTTP framework. https://docs.cherrypy.org/

Welcome to the GitHub repository of CherryPy! CherryPy is a pythonic, object-oriented HTTP framework. It allows building web applications in much the

CherryPy 1.6k Dec 29, 2022
The no-nonsense, minimalist REST and app backend framework for Python developers, with a focus on reliability, correctness, and performance at scale.

The Falcon Web Framework Falcon is a reliable, high-performance Python web framework for building large-scale app backends and microservices. It encou

Falconry 9k Jan 01, 2023
Web3.py plugin for using Flashbots' bundle APIs

This library works by injecting a new module in the Web3.py instance, which allows submitting "bundles" of transactions directly to miners. This is done by also creating a middleware which captures c

Georgios Konstantopoulos 294 Jan 04, 2023
The lightning-fast ASGI server. ?

The lightning-fast ASGI server. Documentation: https://www.uvicorn.org Community: https://discuss.encode.io/c/uvicorn Requirements: Python 3.6+ (For P

Encode 6k Jan 03, 2023
Light, Flexible and Extensible ASGI API framework

Starlite Starlite is a light, opinionated and flexible ASGI API framework built on top of pydantic and Starlette. Check out the Starlite documentation

Na'aman Hirschfeld 1.6k Jan 09, 2023
🦍 The Cloud-Native API Gateway

Kong or Kong API Gateway is a cloud-native, platform-agnostic, scalable API Gateway distinguished for its high performance and extensibility via plugi

Kong 33.8k Jan 09, 2023
bottle.py is a fast and simple micro-framework for python web-applications.

Bottle: Python Web Framework Bottle is a fast, simple and lightweight WSGI micro web-framework for Python. It is distributed as a single file module a

Bottle Micro Web Framework 7.8k Dec 31, 2022
Web-frameworks-benchmark

Web-frameworks-benchmark

Nickolay Samedov 4 May 13, 2021
A microservice written in Python detecting nudity in images/videos

py-nudec py-nudec (python nude detector) is a microservice, which scans all the images and videos from the multipart/form-data request payload and sen

Michael Grigoryan 8 Jul 09, 2022
A very simple asynchronous wrapper that allows you to get access to the Oracle database in asyncio programs.

cx_Oracle_async A very simple asynchronous wrapper that allows you to get access to the Oracle database in asyncio programs. Easy to use , buy may not

36 Dec 21, 2022
A shopping list and kitchen inventory management app.

Flask React Project This is the backend for the Flask React project. Getting started Clone this repository (only this branch) git clone https://github

11 Jun 03, 2022
The Python micro framework for building web applications.

Flask Flask is a lightweight WSGI web application framework. It is designed to make getting started quick and easy, with the ability to scale up to co

The Pallets Projects 61.5k Jan 06, 2023
Developer centric, performant and extensible Python ASGI framework

Introduction xpresso is an ASGI web framework built on top of Starlette, Pydantic and di, with heavy inspiration from FastAPI. Some of the standout fe

Adrian Garcia Badaracco 119 Dec 27, 2022