Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: techjacker/flask-lambda
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: master
Choose a base ref
...
head repository: remedyhealth/flask-lambda
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: master
Choose a head ref
Can’t automatically merge. Don’t worry, you can still create the pull request.
  • 18 commits
  • 6 files changed
  • 5 contributors

Commits on Oct 16, 2018

  1. Copy the full SHA
    2421298 View commit details
  2. Copy the full SHA
    67ca48d View commit details
  3. Copy the full SHA
    c606508 View commit details
  4. Update README

    jochenvdv committed Oct 16, 2018
    Copy the full SHA
    845b6d5 View commit details
  5. Fix syntax in README

    jochenvdv committed Oct 16, 2018
    Copy the full SHA
    fb43695 View commit details
  6. Copy the full SHA
    af214f0 View commit details
  7. Fix typo in usage example

    jochenvdv committed Oct 16, 2018
    Copy the full SHA
    12fcae6 View commit details

Commits on Oct 17, 2018

  1. Copy the full SHA
    3fef8a5 View commit details
  2. Bump version to 0.1.1

    jochenvdv committed Oct 17, 2018
    Copy the full SHA
    2ab4afb View commit details

Commits on Nov 9, 2018

  1. Copy the full SHA
    e79a577 View commit details

Commits on Dec 20, 2018

  1. use proper logger message formatting

    The `event` object was not logged because of missing `%r`. The logging
    of unhandled exceptions didn't log the exception and, worse, would raise
    a TypeError "not all arguments converted during string formatting".
    francisATgwn committed Dec 20, 2018
    Copy the full SHA
    fc1bc0d View commit details

Commits on Jul 8, 2019

  1. Merge pull request #1 from GetWellNetwork/fix-logging

    use proper logger message formatting
    jochenvdv authored Jul 8, 2019
    Copy the full SHA
    1608d00 View commit details
  2. avoid keyerrors by using the get function on an object

    jente-peeraer-cloudway authored and Jochen Van de Velde committed Jul 8, 2019
    Copy the full SHA
    beff8a0 View commit details
  3. Merge pull request #2 from becloudway/hotfix/avoid-key-errors

    Hotfix: avoid key errors
    jochenvdv authored Jul 8, 2019
    Copy the full SHA
    caee16a View commit details
  4. Fix imports by refactoring package structure - version 0.1.4

    Jochen Van de Velde committed Jul 8, 2019
    Copy the full SHA
    3b4ee8f View commit details
  5. Copy the full SHA
    f4bc59d View commit details
  6. Release 0.1.5

    Jochen Van de Velde committed Jul 8, 2019
    Copy the full SHA
    12562da View commit details

Commits on Jan 22, 2024

  1. bytesIO fix

    arbee committed Jan 22, 2024
    Copy the full SHA
    17e0e62 View commit details
Showing with 108 additions and 54 deletions.
  1. +2 −0 .gitignore
  2. +51 −20 README.rst
  3. +37 −27 flask_lambda.py → flask_lambda/__init__.py
  4. +1 −0 flask_lambda/util/__init__.py
  5. +9 −0 flask_lambda/util/object_utils.py
  6. +8 −7 setup.py
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -87,3 +87,5 @@ ENV/

# Rope project settings
.ropeproject

.idea
71 changes: 51 additions & 20 deletions README.rst
Original file line number Diff line number Diff line change
@@ -1,26 +1,36 @@
flask-lambda-python3.6
============
flask-lambda-support
====================

**Python 3.6+ Only**
---------------
Write Flask applications that support being run in in AWS Lambda behind API Gateway.

For older versions of python use the original flask-lambda library which this code is adapted from:
https://github.com/sivel/flask-lambda
This project was forked from:
https://github.com/techjacker/flask-lambda

See this example flask project for how to use and deploy a flask app using this library:
https://github.com/techjacker/flask-lambda-example
Improvements:

* Expose original input event from AWS on Flask's request object
* Production-grade logging


Requirements
------------

* Python 3.6+
* Flask 0.10+


Installation
------------

pip install flask-lambda-python36
``pip install flask-lambda-support``


Usage
-----

Here is an example of what ``my_python_file.py`` would look like::
Here is an example of what a Flask app using this library would look like:

.. code-block:: python
from flask_lambda import FlaskLambda
@@ -29,17 +39,38 @@ Here is an example of what ``my_python_file.py`` would look like::
@app.route('/foo', methods=['GET', 'POST'])
def foo():
data = {
'form': request.form.copy(),
'args': request.args.copy(),
'json': request.json
}
return (
json.dumps(data, indent=4, sort_keys=True),
200,
{'Content-Type': 'application/json'}
)
data = {
'form': request.form.copy(),
'args': request.args.copy(),
'json': request.json
}
return (
json.dumps(data, indent=4, sort_keys=True),
200,
{'Content-Type': 'application/json'}
)
if __name__ == '__main__':
app.run(debug=True)
You can access the original input event and context on the Flask request context:

.. code-block:: python
from flask import request
assert request.aws_event['input']['httpMethod'] == 'POST'
assert request.aws_context.get_remaining_time_in_millis() == 10_000
Development
-----------

You can publish a new version to PyPI with the following commands:

.. code-block:: bash
python3 setup.py sdist bdist_wheel
twine upload PATH_TO_WHL_FILE
[Refer to the official documentation on Python packaging for more information](https://packaging.python.org/tutorials/packaging-projects)
64 changes: 37 additions & 27 deletions flask_lambda.py → flask_lambda/__init__.py
Original file line number Diff line number Diff line change
@@ -23,23 +23,17 @@

from flask import Flask

try:
from cStringIO import StringIO
except ImportError:
try:
from StringIO import StringIO
except ImportError:
from io import StringIO
import io

from werkzeug.wrappers import BaseRequest
from flask import Request
from flask_lambda.util import get_nested


__version__ = '0.0.4'
__version__ = '0.1.2'


def make_environ(event):
def make_environ(event, context):
environ = {}
print('event', event)
# key might be there but set to None
headers = event.get('headers', {}) or {}
for hdr_name, hdr_value in headers.items():
@@ -51,40 +45,52 @@ def make_environ(event):
http_hdr_name = 'HTTP_{}'.format(hdr_name)
environ[http_hdr_name] = hdr_value

qs = event['queryStringParameters']
qs = event.get('queryStringParameters', '')

environ['REQUEST_METHOD'] = event['httpMethod']
environ['PATH_INFO'] = event['path']
environ['REQUEST_METHOD'] = event.get('httpMethod', '')
environ['PATH_INFO'] = event.get('path', '')
environ['QUERY_STRING'] = urlencode(qs) if qs else ''
environ['REMOTE_ADDR'] = event['requestContext']['identity']['sourceIp']
environ['REMOTE_ADDR'] = get_nested(event, '', 'requestContext', 'identity', 'sourceIp')
environ['HOST'] = '{}:{}'.format(
environ.get('HTTP_HOST', ''),
environ.get('HTTP_X_FORWARDED_PORT', ''),
)
environ['SCRIPT_NAME'] = ''
environ['SERVER_NAME'] = 'SERVER_NAME'

environ['SERVER_PORT'] = environ['HTTP_X_FORWARDED_PORT']
environ['SERVER_PORT'] = environ.get('HTTP_X_FORWARDED_PORT', '')
environ['SERVER_PROTOCOL'] = 'HTTP/1.1'

environ['CONTENT_LENGTH'] = str(
len(event['body']) if event['body'] else ''
len(event['body']) if 'body' in event and event['body'] else 0
)

environ['wsgi.url_scheme'] = environ['HTTP_X_FORWARDED_PROTO']
environ['wsgi.input'] = StringIO(event['body'] or '')
environ['wsgi.url_scheme'] = environ.get('HTTP_X_FORWARDED_PROTO', '')
environ['wsgi.input'] = io.BytesIO((event['body'] or '').encode())
environ['wsgi.version'] = (1, 0)
environ['wsgi.errors'] = sys.stderr
environ['wsgi.multithread'] = False
environ['wsgi.run_once'] = True
environ['wsgi.multiprocess'] = False

BaseRequest(environ)
# store AWS input event and context in WSGI environment
environ['aws.event'] = event
environ['aws.context'] = context

return environ


class LambdaResponse(object):
class LambdaRequest(Request):
@property
def aws_event(self):
return self.environ.get('aws.event')

@property
def aws_context(self):
return self.environ.get('aws.context')


class LambdaResponse:

def __init__(self):
self.status = None
@@ -96,21 +102,24 @@ def start_response(self, status, response_headers, exc_info=None):


class FlaskLambda(Flask):
request_class = LambdaRequest

def __call__(self, event, context):
try:
if 'httpMethod' not in event:
print('call as flask app')
self.logger.debug('Called as regular Flask app')
# In this "context" `event` is `environ` and
# `context` is `start_response`, meaning the request didn't
# occur via API Gateway and Lambda
return super(FlaskLambda, self).__call__(event, context)

print('call as aws lambda')
self.logger.debug('Called with AWS Lambda input event')
self.logger.debug('Event: %r', event)

response = LambdaResponse()

body = next(self.wsgi_app(
make_environ(event),
make_environ(event, context),
response.start_response
))

@@ -120,10 +129,11 @@ def __call__(self, event, context):
'body': body.decode('utf-8')
}

except Exception as e:
print('unexpected error', e)
except:
self.logger.exception('An unexpected exception occured')

return {
'statusCode': 500,
'headers': {},
'body': 'internal server error'
'body': 'Internal Server Error'
}
1 change: 1 addition & 0 deletions flask_lambda/util/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from flask_lambda.util.object_utils import get_nested
9 changes: 9 additions & 0 deletions flask_lambda/util/object_utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
def get_nested(o, default, *args):
if o is None:
return default
current = o
for arg in args:
if current is None or arg is None or current.get(arg, None) is None:
return default
current = current.get(arg, default)
return current
15 changes: 8 additions & 7 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
from setuptools import setup
from setuptools import setup, find_packages


with open('README.rst') as f:
long_description = f.read()

setup(
name='flask-lambda-python36',
version='0.1.0',
description=('Python3.6+ module to make Flask compatible with AWS Lambda'),
name='flask-lambda-support',
version='0.1.5',
description='Python 3.6+ module to make Flask compatible with AWS Lambda',
long_description=long_description,
keywords='flask aws amazon lambda',
author='Andrew Griffiths',
author_email='mail@andrewgriffithsonline.com',
url='https://github.com/techjacker/flask-lambda',
author='Jochen Van de Velde',
author_email='jochen.vandevelde@cloudway.be',
url='https://github.com/becloudway/flask-lambda',
license='Apache License, Version 2.0',
packages=find_packages(),
py_modules=['flask_lambda'],
install_requires=['Flask>=0.10'],
classifiers=[