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
The comprehensive WSGI web application library.

Werkzeug werkzeug German noun: "tool". Etymology: werk ("work"), zeug ("stuff") Werkzeug is a comprehensive WSGI web application library. It began as

The Pallets Projects 6.2k Jan 01, 2023
Pyramid - A Python web framework

Pyramid Pyramid is a small, fast, down-to-earth, open source Python web framework. It makes real-world web application development and deployment more

Pylons Project 3.7k Dec 30, 2022
The web framework for inventors

Emmett is a full-stack Python web framework designed with simplicity in mind. The aim of Emmett is to be clearly understandable, easy to be learned an

Emmett 796 Dec 26, 2022
An easy-to-use high-performance asynchronous web framework.

中文 | English 一个易用的高性能异步 web 框架。 Index.py 文档 Index.py 实现了 ASGI3 接口,并使用 Radix Tree 进行路由查找。是最快的 Python web 框架之一。一切特性都服务于快速开发高性能的 Web 服务。 大量正确的类型注释 灵活且高效的

Index.py 264 Dec 31, 2022
A python application to log QSOs directly to QRZ.com from the command line

qrzlogger This script is a QRZ.com command line QSO logger. It does the following: asks the user for a call sign displays available call sign info pul

Michael Clemens 15 Jul 16, 2021
A familiar HTTP Service Framework for Python.

Responder: a familiar HTTP Service Framework for Python Powered by Starlette. That async declaration is optional. View documentation. This gets you a

Taoufik 3.6k Dec 27, 2022
Ape is a framework for Web3 Python applications and smart contracts, with advanced functionality for testing, deployment, and on-chain interactions.

Ape Framework Ape is a framework for Web3 Python applications and smart contracts, with advanced functionality for testing, deployment, and on-chain i

ApeWorX Ltd. 552 Dec 30, 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
A boilerplate Flask API for a Fullstack Project with some additional packages and configuration prebuilt. ⚙

Flask Boilerplate to quickly get started with production grade flask application with some additional packages and configuration prebuilt.

Yasser Tahiri 32 Dec 24, 2022
An easy-to-use high-performance asynchronous web framework.

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

Aber 264 Dec 31, 2022
Asynchronous HTTP client/server framework for asyncio and Python

Async http client/server framework Key Features Supports both client and server side of HTTP protocol. Supports both client and server Web-Sockets out

aio-libs 13.2k Jan 05, 2023
FastAPI framework, high performance, easy to learn, fast to code, ready for production

FastAPI framework, high performance, easy to learn, fast to code, ready for production Documentation: https://fastapi.tiangolo.com Source Code: https:

Sebastián Ramírez 53k Jan 02, 2023
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
Low code web framework for real world applications, in Python and Javascript

Full-stack web application framework that uses Python and MariaDB on the server side and a tightly integrated client side library.

Frappe 4.3k Dec 30, 2022
Mini Web Framework on MicroPython (Esp8266)

dupgee Dupgee is a mini web framework developed for micro-python(Tested on esp8266). Installation pip install dupgee Create Project dupgee create newp

ahmet kotan 38 Jul 25, 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
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
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
A framework that let's you compose websites in Python with ease!

Perry Perry = A framework that let's you compose websites in Python with ease! Perry works similar to Qt and Flutter, allowing you to create componen

Linkus 13 Oct 09, 2022
Quiz Web App with Flask and MongoDB as the Databases

quiz-app Quiz Web Application made with flask and mongodb as the Databases Before you run this application, change the inside MONGODB_URI ( in config.

gibran abdillah 7 Dec 14, 2022