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
Cses2humio - CrowdStrike Falcon Event Stream to Humio

CrowdStrike Falcon Event Stream to Humio This project intend to provide a simple

Trifork.Security 6 Aug 02, 2022
An easy-to-use high-performance asynchronous web framework.

An easy-to-use high-performance asynchronous web framework.

Aber 264 Dec 31, 2022
Loan qualifier app - Loan Qualifier Application Built With Python

Loan Qualifier Application This program is designed to automate the discovery pr

Phil Hills 1 Jan 04, 2022
Chisel is a light-weight Python WSGI application framework built for creating well-documented, schema-validated JSON web APIs

chisel Chisel is a light-weight Python WSGI application framework built for creating well-documented, schema-validated JSON web APIs. Here are its fea

Craig Hobbs 2 Dec 02, 2021
An effective, simple, and async security library for the Sanic framework.

Sanic Security An effective, simple, and async security library for the Sanic framework. Table of Contents About the Project Getting Started Prerequis

Sunset Dev 72 Nov 30, 2022
Web framework based on type hint。

Hint API 中文 | English 基于 Type hint 的 Web 框架 hintapi 文档 hintapi 实现了 WSGI 接口,并使用 Radix Tree 进行路由查找。是最快的 Python web 框架之一。一切特性都服务于快速开发高性能的 Web 服务。 大量正确的类型

Aber 19 Dec 02, 2022
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
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
🔥 Fire up your API with this flamethrower

🔥 Fire up your API. Documentation: https://flama.perdy.io Flama Flama aims to bring a layer on top of Starlette to provide an easy to learn and fast

José Antonio Perdiguero 216 Dec 26, 2022
Restful API framework wrapped around MongoEngine

Flask-MongoRest A Restful API framework wrapped around MongoEngine. Setup from flask import Flask from flask_mongoengine import MongoEngine from flask

Close 525 Jan 01, 2023
The Web framework for perfectionists with deadlines.

Django Django is a high-level Python Web framework that encourages rapid development and clean, pragmatic design. Thanks for checking it out. All docu

Django 67.9k Dec 29, 2022
An abstract and extensible framework in python for building client SDKs and CLI tools for a RESTful API.

django-rest-client An abstract and extensible framework in python for building client SDKs and CLI tools for a RESTful API. Suitable for APIs made wit

Certego 4 Aug 25, 2022
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
Asita is a web application framework for python based on express-js framework.

Asita is a web application framework for python. It is designed to be easy to use and be more easy for javascript users to use python frameworks because it is based on express-js framework.

Mattéo 4 Nov 16, 2021
A Simple Kivy Greeting App

SimpleGreetingApp A Simple Kivy Greeting App This is a very simple GUI App that receives a name text input from the user and returns a "Hello" greetin

Mariya 40 Dec 02, 2022
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
Pyrin is an application framework built on top of Flask micro-framework to make life easier for developers who want to develop an enterprise application using Flask

Pyrin A rich, fast, performant and easy to use application framework to build apps using Flask on top of it. Pyrin is an application framework built o

Mohamad Nobakht 10 Jan 25, 2022
🦍 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
Microservice example with Python, Faust-Streaming and Kafka (Redpanda)

Microservices Orchestration with Python, Faust-Streaming and Kafka (Redpanda) Example project for PythonBenin meetup. It demonstrates how to use Faust

Lé 3 Jun 13, 2022
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 do

Flashbots 293 Dec 31, 2022