From 09ebb72d5212d11be4ca714a63c35a13aa297b8b Mon Sep 17 00:00:00 2001 From: CodeSchwert <2661899+CodeSchwert@users.noreply.github.com> Date: Sun, 21 Nov 2021 17:09:01 +1300 Subject: [PATCH 1/5] Add lambda test events. --- .gitignore | 1 + events/http_api_event.json | 38 +++++++++++++++++++++++ events/rest_api_event.json | 63 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 102 insertions(+) create mode 100644 events/http_api_event.json create mode 100644 events/rest_api_event.json diff --git a/.gitignore b/.gitignore index 7cd8924..62f4d6b 100644 --- a/.gitignore +++ b/.gitignore @@ -89,3 +89,4 @@ ENV/ .ropeproject .vscode/ +http_api_vs_rest_api/ diff --git a/events/http_api_event.json b/events/http_api_event.json new file mode 100644 index 0000000..03e58d1 --- /dev/null +++ b/events/http_api_event.json @@ -0,0 +1,38 @@ +{ + "version": "2.0", + "routeKey": "GET /", + "rawPath": "/templates/contracts", + "rawQueryString": "", + "cookies": [], + "headers": { + "Host": "localhost:5000", + "User-Agent": "insomnia/2021.6.0", + "Content-Type": "application/json", + "Authorization": "", + "Accept": "*/*", + "Content-Length": "16", + "X-Forwarded-Proto": "http", + "X-Forwarded-Port": "5000" + }, + "queryStringParameters": {}, + "requestContext": { + "accountId": "123456789012", + "apiId": "1234567890", + "http": { + "method": "GET", + "path": "/templates/contracts", + "protocol": "HTTP/1.1", + "sourceIp": "127.0.0.1", + "userAgent": "Custom User Agent String" + }, + "requestId": "4d160553-b400-4d10-8f14-5338b8936458", + "routeKey": "GET /", + "stage": null + }, + "body": "{\"foo\":\"bar\"}", + "pathParameters": { + "proxy": "templates/contracts" + }, + "stageVariables": null, + "isBase64Encoded": false +} \ No newline at end of file diff --git a/events/rest_api_event.json b/events/rest_api_event.json new file mode 100644 index 0000000..a429ac5 --- /dev/null +++ b/events/rest_api_event.json @@ -0,0 +1,63 @@ +{ + "body": "{\"message\": \"hello world\"}", + "resource": "/hello", + "path": "/hello", + "httpMethod": "GET", + "isBase64Encoded": false, + "queryStringParameters": { + "foo": "bar" + }, + "pathParameters": { + "proxy": "/path/to/resource" + }, + "stageVariables": { + "baz": "qux" + }, + "headers": { + "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8", + "Accept-Encoding": "gzip, deflate, sdch", + "Accept-Language": "en-US,en;q=0.8", + "Cache-Control": "max-age=0", + "CloudFront-Forwarded-Proto": "https", + "CloudFront-Is-Desktop-Viewer": "true", + "CloudFront-Is-Mobile-Viewer": "false", + "CloudFront-Is-SmartTV-Viewer": "false", + "CloudFront-Is-Tablet-Viewer": "false", + "CloudFront-Viewer-Country": "US", + "Host": "1234567890.execute-api.us-east-1.amazonaws.com", + "Upgrade-Insecure-Requests": "1", + "User-Agent": "Custom User Agent String", + "Via": "1.1 08f323deadbeefa7af34d5feb414ce27.cloudfront.net (CloudFront)", + "X-Amz-Cf-Id": "cDehVQoZnx43VYQb9j2-nvCh-9z396Uhbp027Y2JvkCPNLmGJHqlaA==", + "X-Forwarded-For": "127.0.0.1, 127.0.0.2", + "X-Forwarded-Port": "443", + "X-Forwarded-Proto": "https" + }, + "requestContext": { + "accountId": "123456789012", + "resourceId": "123456", + "stage": "prod", + "requestId": "c6af9ac6-7b61-11e6-9a41-93e8deadbeef", + "requestTime": "09/Apr/2015:12:34:56 +0000", + "requestTimeEpoch": 1428582896000, + "identity": { + "cognitoIdentityPoolId": null, + "accountId": null, + "cognitoIdentityId": null, + "caller": null, + "accessKey": null, + "sourceIp": "127.0.0.1", + "cognitoAuthenticationType": null, + "cognitoAuthenticationProvider": null, + "userArn": null, + "userAgent": "Custom User Agent String", + "user": null + }, + "path": "/prod/hello", + "resourcePath": "/hello", + "httpMethod": "POST", + "apiId": "1234567890", + "protocol": "HTTP/1.1" + } + } + \ No newline at end of file From 2a18758f846a8d83b4438c79ba588c5c51fafc0c Mon Sep 17 00:00:00 2001 From: CodeSchwert <2661899+CodeSchwert@users.noreply.github.com> Date: Sun, 21 Nov 2021 17:12:50 +1300 Subject: [PATCH 2/5] Update flask_lambda to work with AWS HTTP API gateways. --- flask_lambda.py | 145 +++++++++++++++++++++++++++++++----------------- 1 file changed, 93 insertions(+), 52 deletions(-) diff --git a/flask_lambda.py b/flask_lambda.py index 1a57560..13359ed 100644 --- a/flask_lambda.py +++ b/flask_lambda.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Copyright 2016 Matt Martz +# Copyright 2021 Nik Ho # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may @@ -15,65 +15,92 @@ # under the License. import sys - -try: - from urllib import urlencode -except ImportError: - from urllib.parse import urlencode - +import base64 +from urllib.parse import urlencode from flask import Flask - -try: - from cStringIO import StringIO -except ImportError: - try: - from StringIO import StringIO - except ImportError: - from io import StringIO - -from werkzeug.wrappers import BaseRequest - - -__version__ = '0.0.4' - - -def make_environ(event): - environ = {} - - for hdr_name, hdr_value in event['headers'].items(): - hdr_name = hdr_name.replace('-', '_').upper() - if hdr_name in ['CONTENT_TYPE', 'CONTENT_LENGTH']: - environ[hdr_name] = hdr_value - continue - - http_hdr_name = 'HTTP_%s' % hdr_name - environ[http_hdr_name] = hdr_value - +from io import StringIO +from werkzeug.wrappers import Request + + +__version__ = '1.0.0' + + +def make_wsgi_environ() -> dict: + """Default environs object.""" + return { + 'HTTP_HOST': '', + 'HTTP_X_FORWARDED_PORT': '', + 'HTTP_X_FORWARDED_PROTO': '', + 'SCRIPT_NAME': '', + 'wsgi.version': (1, 0), + 'wsgi.errors': sys.stderr, + 'wsgi.multithread': False, + 'wsgi.run_once': True, + 'wsgi.multiprocess': False + } + + +def make_v1_environ(event: dict, environ: dict): + """ + Create environ object from REST API Gateway event. + + Note: This function mutates the incoming eviron object. + """ qs = event['queryStringParameters'] - environ['REQUEST_METHOD'] = event['httpMethod'] environ['PATH_INFO'] = event['path'] environ['QUERY_STRING'] = urlencode(qs) if qs else '' environ['REMOTE_ADDR'] = event['requestContext']['identity']['sourceIp'] - environ['HOST'] = '%(HTTP_HOST)s:%(HTTP_X_FORWARDED_PORT)s' % environ - environ['SCRIPT_NAME'] = '' + environ['SERVER_PROTOCOL'] = event['requestContext']['protocol'] + + +def make_v2_environ(event: dict, environ: dict): + """ + Create environ object from HTTP API Gateway event. + + Note: This function mutates the incoming eviron object. + """ + qs = event['queryStringParameters'] + environ['REQUEST_METHOD'] = event['requestContext']['http']['method'] + environ['PATH_INFO'] = event['requestContext']['http']['path'] + environ['QUERY_STRING'] = urlencode(qs) if qs else '' + environ['REMOTE_ADDR'] = event['requestContext']['http']['sourceIp'] + environ['SERVER_PROTOCOL'] = event['requestContext']['http']['protocol'] - environ['SERVER_PORT'] = environ['HTTP_X_FORWARDED_PORT'] - environ['SERVER_PROTOCOL'] = 'HTTP/1.1' +def make_environ(event): + # get the standard base set of environ properties + environ = make_wsgi_environ() + + # set headers from event + if event['headers'] is not None: + for hdr_name, hdr_value in event['headers'].items(): + hdr_name = hdr_name.replace('-', '_').upper() + if hdr_name in ['CONTENT_TYPE', 'CONTENT_LENGTH']: + environ[hdr_name] = hdr_value + continue + # prefix HTTP to all other headers + http_hdr_name = 'HTTP_%s' % hdr_name + environ[http_hdr_name] = hdr_value + + # make environ specifically from REST or HTTP gateway events + # the properties of the event object is slightly different in both gateways + if event['version'] == '1.0': + make_v1_environ(event, environ) + else: + make_v2_environ(event, environ) + + # check if this is present in requests with no body environ['CONTENT_LENGTH'] = str( len(event['body']) if event['body'] else '' ) - + environ['SERVER_PORT'] = environ['HTTP_X_FORWARDED_PORT'] environ['wsgi.url_scheme'] = environ['HTTP_X_FORWARDED_PROTO'] environ['wsgi.input'] = StringIO(event['body'] or '') - 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) + # using werkzeug.wrappers.Request instead of BaseRequest + # as BaseRequest has a deprecation warning for next version + Request(environ) return environ @@ -88,23 +115,37 @@ def start_response(self, status, response_headers, exc_info=None): self.response_headers = dict(response_headers) -class FlaskLambda(Flask): +class FlaskAwsLambda(Flask): def __call__(self, event, context): - if 'httpMethod' not in event: + if 'version' not in event: # 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) + return super(FlaskAwsLambda, self).__call__(event, context) response = LambdaResponse() - body = next(self.wsgi_app( + # b''.join = fix for next stopIterator error + # https://github.com/sivel/flask-lambda/pull/10/files + body = b''.join(self.wsgi_app( make_environ(event), response.start_response )) - return { + lamdba_response = { 'statusCode': response.status, 'headers': response.response_headers, - 'body': body + 'body': body, + 'isBase64Encoded': False } + + content_type = response.response_headers['Content-Type'] + if 'text' not in content_type \ + and 'json' not in content_type \ + and 'xml' not in content_type \ + and 'javascript' not in content_type \ + and 'charset=' not in content_type: + lamdba_response['body'] = base64.b64encode(body).decode('utf-8') + lamdba_response['isBase64Encoded'] = True + + return lamdba_response From 038deb54ea52ca41e811e432acffd30522d350cb Mon Sep 17 00:00:00 2001 From: CodeSchwert <2661899+CodeSchwert@users.noreply.github.com> Date: Sun, 21 Nov 2021 17:13:03 +1300 Subject: [PATCH 3/5] Better README docs. --- README.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.rst b/README.rst index c439ebd..825009a 100644 --- a/README.rst +++ b/README.rst @@ -19,6 +19,8 @@ This module works pretty much just like Flask. This allows you to run and develo Here is an example of what ``my_python_file.py`` would look like:: + import json + from flask import request from flask_lambda import FlaskLambda app = FlaskLambda(__name__) From a0d0318bc90df3545e8043362696b4c0149549cb Mon Sep 17 00:00:00 2001 From: CodeSchwert <2661899+CodeSchwert@users.noreply.github.com> Date: Sun, 21 Nov 2021 17:17:52 +1300 Subject: [PATCH 4/5] Add pipfile and flask requirements. --- Pipfile | 12 ++++ Pipfile.lock | 136 ++++++++++++++++++++++++++++++++++++++++++ requirements.txt | 7 ++- test-requirements.txt | 7 --- 4 files changed, 154 insertions(+), 8 deletions(-) create mode 100644 Pipfile create mode 100644 Pipfile.lock delete mode 100644 test-requirements.txt diff --git a/Pipfile b/Pipfile new file mode 100644 index 0000000..9bb4d23 --- /dev/null +++ b/Pipfile @@ -0,0 +1,12 @@ +[[source]] +url = "https://pypi.org/simple" +verify_ssl = true +name = "pypi" + +[packages] +flask = "*" + +[dev-packages] + +[requires] +python_version = "3.9" diff --git a/Pipfile.lock b/Pipfile.lock new file mode 100644 index 0000000..a66d064 --- /dev/null +++ b/Pipfile.lock @@ -0,0 +1,136 @@ +{ + "_meta": { + "hash": { + "sha256": "f7f1cea682a03d85328caf2f88382c4380283d3892a9ba31b374784fb29536c4" + }, + "pipfile-spec": 6, + "requires": { + "python_version": "3.9" + }, + "sources": [ + { + "name": "pypi", + "url": "https://pypi.org/simple", + "verify_ssl": true + } + ] + }, + "default": { + "click": { + "hashes": [ + "sha256:353f466495adaeb40b6b5f592f9f91cb22372351c84caeb068132442a4518ef3", + "sha256:410e932b050f5eed773c4cda94de75971c89cdb3155a72a0831139a79e5ecb5b" + ], + "markers": "python_version >= '3.6'", + "version": "==8.0.3" + }, + "flask": { + "hashes": [ + "sha256:7b2fb8e934ddd50731893bdcdb00fc8c0315916f9fcd50d22c7cc1a95ab634e2", + "sha256:cb90f62f1d8e4dc4621f52106613488b5ba826b2e1e10a33eac92f723093ab6a" + ], + "index": "pypi", + "version": "==2.0.2" + }, + "itsdangerous": { + "hashes": [ + "sha256:5174094b9637652bdb841a3029700391451bd092ba3db90600dea710ba28e97c", + "sha256:9e724d68fc22902a1435351f84c3fb8623f303fffcc566a4cb952df8c572cff0" + ], + "markers": "python_version >= '3.6'", + "version": "==2.0.1" + }, + "jinja2": { + "hashes": [ + "sha256:077ce6014f7b40d03b47d1f1ca4b0fc8328a692bd284016f806ed0eaca390ad8", + "sha256:611bb273cd68f3b993fabdc4064fc858c5b47a973cb5aa7999ec1ba405c87cd7" + ], + "markers": "python_version >= '3.6'", + "version": "==3.0.3" + }, + "markupsafe": { + "hashes": [ + "sha256:01a9b8ea66f1658938f65b93a85ebe8bc016e6769611be228d797c9d998dd298", + "sha256:023cb26ec21ece8dc3907c0e8320058b2e0cb3c55cf9564da612bc325bed5e64", + "sha256:0446679737af14f45767963a1a9ef7620189912317d095f2d9ffa183a4d25d2b", + "sha256:04635854b943835a6ea959e948d19dcd311762c5c0c6e1f0e16ee57022669194", + "sha256:0717a7390a68be14b8c793ba258e075c6f4ca819f15edfc2a3a027c823718567", + "sha256:0955295dd5eec6cb6cc2fe1698f4c6d84af2e92de33fbcac4111913cd100a6ff", + "sha256:0d4b31cc67ab36e3392bbf3862cfbadac3db12bdd8b02a2731f509ed5b829724", + "sha256:10f82115e21dc0dfec9ab5c0223652f7197feb168c940f3ef61563fc2d6beb74", + "sha256:168cd0a3642de83558a5153c8bd34f175a9a6e7f6dc6384b9655d2697312a646", + "sha256:1d609f577dc6e1aa17d746f8bd3c31aa4d258f4070d61b2aa5c4166c1539de35", + "sha256:1f2ade76b9903f39aa442b4aadd2177decb66525062db244b35d71d0ee8599b6", + "sha256:20dca64a3ef2d6e4d5d615a3fd418ad3bde77a47ec8a23d984a12b5b4c74491a", + "sha256:2a7d351cbd8cfeb19ca00de495e224dea7e7d919659c2841bbb7f420ad03e2d6", + "sha256:2d7d807855b419fc2ed3e631034685db6079889a1f01d5d9dac950f764da3dad", + "sha256:2ef54abee730b502252bcdf31b10dacb0a416229b72c18b19e24a4509f273d26", + "sha256:36bc903cbb393720fad60fc28c10de6acf10dc6cc883f3e24ee4012371399a38", + "sha256:37205cac2a79194e3750b0af2a5720d95f786a55ce7df90c3af697bfa100eaac", + "sha256:3c112550557578c26af18a1ccc9e090bfe03832ae994343cfdacd287db6a6ae7", + "sha256:3dd007d54ee88b46be476e293f48c85048603f5f516008bee124ddd891398ed6", + "sha256:4296f2b1ce8c86a6aea78613c34bb1a672ea0e3de9c6ba08a960efe0b0a09047", + "sha256:47ab1e7b91c098ab893b828deafa1203de86d0bc6ab587b160f78fe6c4011f75", + "sha256:49e3ceeabbfb9d66c3aef5af3a60cc43b85c33df25ce03d0031a608b0a8b2e3f", + "sha256:4dc8f9fb58f7364b63fd9f85013b780ef83c11857ae79f2feda41e270468dd9b", + "sha256:4efca8f86c54b22348a5467704e3fec767b2db12fc39c6d963168ab1d3fc9135", + "sha256:53edb4da6925ad13c07b6d26c2a852bd81e364f95301c66e930ab2aef5b5ddd8", + "sha256:5855f8438a7d1d458206a2466bf82b0f104a3724bf96a1c781ab731e4201731a", + "sha256:594c67807fb16238b30c44bdf74f36c02cdf22d1c8cda91ef8a0ed8dabf5620a", + "sha256:5b6d930f030f8ed98e3e6c98ffa0652bdb82601e7a016ec2ab5d7ff23baa78d1", + "sha256:5bb28c636d87e840583ee3adeb78172efc47c8b26127267f54a9c0ec251d41a9", + "sha256:60bf42e36abfaf9aff1f50f52644b336d4f0a3fd6d8a60ca0d054ac9f713a864", + "sha256:611d1ad9a4288cf3e3c16014564df047fe08410e628f89805e475368bd304914", + "sha256:6300b8454aa6930a24b9618fbb54b5a68135092bc666f7b06901f897fa5c2fee", + "sha256:63f3268ba69ace99cab4e3e3b5840b03340efed0948ab8f78d2fd87ee5442a4f", + "sha256:6557b31b5e2c9ddf0de32a691f2312a32f77cd7681d8af66c2692efdbef84c18", + "sha256:693ce3f9e70a6cf7d2fb9e6c9d8b204b6b39897a2c4a1aa65728d5ac97dcc1d8", + "sha256:6a7fae0dd14cf60ad5ff42baa2e95727c3d81ded453457771d02b7d2b3f9c0c2", + "sha256:6c4ca60fa24e85fe25b912b01e62cb969d69a23a5d5867682dd3e80b5b02581d", + "sha256:6fcf051089389abe060c9cd7caa212c707e58153afa2c649f00346ce6d260f1b", + "sha256:7d91275b0245b1da4d4cfa07e0faedd5b0812efc15b702576d103293e252af1b", + "sha256:89c687013cb1cd489a0f0ac24febe8c7a666e6e221b783e53ac50ebf68e45d86", + "sha256:8d206346619592c6200148b01a2142798c989edcb9c896f9ac9722a99d4e77e6", + "sha256:905fec760bd2fa1388bb5b489ee8ee5f7291d692638ea5f67982d968366bef9f", + "sha256:97383d78eb34da7e1fa37dd273c20ad4320929af65d156e35a5e2d89566d9dfb", + "sha256:984d76483eb32f1bcb536dc27e4ad56bba4baa70be32fa87152832cdd9db0833", + "sha256:99df47edb6bda1249d3e80fdabb1dab8c08ef3975f69aed437cb69d0a5de1e28", + "sha256:9f02365d4e99430a12647f09b6cc8bab61a6564363f313126f775eb4f6ef798e", + "sha256:a30e67a65b53ea0a5e62fe23682cfe22712e01f453b95233b25502f7c61cb415", + "sha256:ab3ef638ace319fa26553db0624c4699e31a28bb2a835c5faca8f8acf6a5a902", + "sha256:aca6377c0cb8a8253e493c6b451565ac77e98c2951c45f913e0b52facdcff83f", + "sha256:add36cb2dbb8b736611303cd3bfcee00afd96471b09cda130da3581cbdc56a6d", + "sha256:b2f4bf27480f5e5e8ce285a8c8fd176c0b03e93dcc6646477d4630e83440c6a9", + "sha256:b7f2d075102dc8c794cbde1947378051c4e5180d52d276987b8d28a3bd58c17d", + "sha256:baa1a4e8f868845af802979fcdbf0bb11f94f1cb7ced4c4b8a351bb60d108145", + "sha256:be98f628055368795d818ebf93da628541e10b75b41c559fdf36d104c5787066", + "sha256:bf5d821ffabf0ef3533c39c518f3357b171a1651c1ff6827325e4489b0e46c3c", + "sha256:c47adbc92fc1bb2b3274c4b3a43ae0e4573d9fbff4f54cd484555edbf030baf1", + "sha256:cdfba22ea2f0029c9261a4bd07e830a8da012291fbe44dc794e488b6c9bb353a", + "sha256:d6c7ebd4e944c85e2c3421e612a7057a2f48d478d79e61800d81468a8d842207", + "sha256:d7f9850398e85aba693bb640262d3611788b1f29a79f0c93c565694658f4071f", + "sha256:d8446c54dc28c01e5a2dbac5a25f071f6653e6e40f3a8818e8b45d790fe6ef53", + "sha256:deb993cacb280823246a026e3b2d81c493c53de6acfd5e6bfe31ab3402bb37dd", + "sha256:e0f138900af21926a02425cf736db95be9f4af72ba1bb21453432a07f6082134", + "sha256:e9936f0b261d4df76ad22f8fee3ae83b60d7c3e871292cd42f40b81b70afae85", + "sha256:f0567c4dc99f264f49fe27da5f735f414c4e7e7dd850cfd8e69f0862d7c74ea9", + "sha256:f5653a225f31e113b152e56f154ccbe59eeb1c7487b39b9d9f9cdb58e6c79dc5", + "sha256:f826e31d18b516f653fe296d967d700fddad5901ae07c622bb3705955e1faa94", + "sha256:f8ba0e8349a38d3001fae7eadded3f6606f0da5d748ee53cc1dab1d6527b9509", + "sha256:f9081981fe268bd86831e5c75f7de206ef275defcb82bc70740ae6dc507aee51", + "sha256:fa130dd50c57d53368c9d59395cb5526eda596d3ffe36666cd81a44d56e48872" + ], + "markers": "python_version >= '3.6'", + "version": "==2.0.1" + }, + "werkzeug": { + "hashes": [ + "sha256:63d3dc1cf60e7b7e35e97fa9861f7397283b75d765afcaefd993d6046899de8f", + "sha256:aa2bb6fc8dee8d6c504c0ac1e7f5f7dc5810a9903e793b6f715a9f015bdadb9a" + ], + "markers": "python_version >= '3.6'", + "version": "==2.0.2" + } + }, + "develop": {} +} diff --git a/requirements.txt b/requirements.txt index 3a7e533..b019c33 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1,6 @@ -Flask>=0.10 +click==8.0.3 +Flask==2.0.2 +itsdangerous==2.0.1 +Jinja2==3.0.3 +MarkupSafe==2.0.1 +Werkzeug==2.0.2 diff --git a/test-requirements.txt b/test-requirements.txt deleted file mode 100644 index 2c8e765..0000000 --- a/test-requirements.txt +++ /dev/null @@ -1,7 +0,0 @@ -flake8==3.2.1 -flake8-import-order==0.11 -pep8==1.7.0 -pep8-naming==0.4.1 -pyflakes==1.3.0 -pycodestyle==2.2.0 -mccabe==0.5.2 From 4fa1244e7d710cf6d866b0296ec2f9738c491792 Mon Sep 17 00:00:00 2001 From: CodeSchwert <2661899+CodeSchwert@users.noreply.github.com> Date: Sun, 21 Nov 2021 17:26:48 +1300 Subject: [PATCH 5/5] Rename flask-lambda to flask-aws-lambda due to better support of API gateways. --- README.rst | 76 +++----------------------- flask_lambda.py => flask_aws_lambda.py | 0 setup.py | 17 +++--- 3 files changed, 18 insertions(+), 75 deletions(-) rename flask_lambda.py => flask_aws_lambda.py (100%) diff --git a/README.rst b/README.rst index 825009a..b7d2902 100644 --- a/README.rst +++ b/README.rst @@ -1,14 +1,14 @@ -flask-lambda +flask-aws-lambda ============ -Python module to make Flask compatible with AWS Lambda for creating RESTful applications. +Python module to make Flask compatible with AWS Lambda for creating RESTful applications. Compatible with both REST and HTTP API gateways. Installation ------------ :: - pip install flask-lambda + pip install flask-aws-lambda Usage ----- @@ -21,9 +21,10 @@ Here is an example of what ``my_python_file.py`` would look like:: import json from flask import request - from flask_lambda import FlaskLambda + from flask_aws_lambda import FlaskAwsLambda - app = FlaskLambda(__name__) + + app = FlaskAwsLambda(__name__) @app.route('/foo', methods=['GET', 'POST']) @@ -39,10 +40,10 @@ Here is an example of what ``my_python_file.py`` would look like:: {'Content-Type': 'application/json'} ) - if __name__ == '__main__': app.run(debug=True) + Flask-RESTful ------------- @@ -56,70 +57,11 @@ Configure your API Gateway with a ``{proxy+}`` resource with an ``ANY`` method. Deploying --------- -Consider using `python-mu `_. +Consider using `AWS Serverless Application Model (AWS SAM) `_. Lambda Test Event ----------------- -If you wish to use the "Test" functionality in Lambda for your function, you will need a "API Gateway AWS Proxy" event. Below is an event to test the above sample application:: - - { - "body": "{\"test\":\"body\"}", - "resource": "/{proxy+}", - "requestContext": { - "resourceId": "123456", - "apiId": "1234567890", - "resourcePath": "/{proxy+}", - "httpMethod": "POST", - "requestId": "c6af9ac6-7b61-11e6-9a41-93e8deadbeef", - "accountId": "123456789012", - "identity": { - "apiKey": null, - "userArn": null, - "cognitoAuthenticationType": null, - "caller": null, - "userAgent": "Custom User Agent String", - "user": null, - "cognitoIdentityPoolId": null, - "cognitoIdentityId": null, - "cognitoAuthenticationProvider": null, - "sourceIp": "127.0.0.1", - "accountId": null - }, - "stage": "prod" - }, - "queryStringParameters": { - "foo": "bar" - }, - "headers": { - "Via": "1.1 08f323deadbeefa7af34d5feb414ce27.cloudfront.net (CloudFront)", - "Accept-Language": "en-US,en;q=0.8", - "CloudFront-Is-Desktop-Viewer": "true", - "CloudFront-Is-SmartTV-Viewer": "false", - "CloudFront-Is-Mobile-Viewer": "false", - "X-Forwarded-For": "127.0.0.1, 127.0.0.2", - "CloudFront-Viewer-Country": "US", - "Accept": "application/json", - "Upgrade-Insecure-Requests": "1", - "X-Forwarded-Port": "443", - "Host": "1234567890.execute-api.us-east-1.amazonaws.com", - "X-Forwarded-Proto": "https", - "X-Amz-Cf-Id": "cDehVQoZnx43VYQb9j2-nvCh-9z396Uhbp027Y2JvkCPNLmGJHqlaA==", - "CloudFront-Is-Tablet-Viewer": "false", - "Cache-Control": "max-age=0", - "User-Agent": "Custom User Agent String", - "CloudFront-Forwarded-Proto": "https", - "Accept-Encoding": "gzip, deflate, sdch", - "Content-Type": "application/json" - }, - "pathParameters": { - "proxy": "foo" - }, - "httpMethod": "POST", - "stageVariables": { - "baz": "qux" - }, - "path": "/foo" - } +If you wish to use the "Test" functionality in Lambda for your function, you will need a "API Gateway AWS Proxy" event. Check the event JSON objects in the events folder. To update your test event, click "Actions" -> "Configure test event". diff --git a/flask_lambda.py b/flask_aws_lambda.py similarity index 100% rename from flask_lambda.py rename to flask_aws_lambda.py diff --git a/setup.py b/setup.py index 9c44fd5..9a881d2 100644 --- a/setup.py +++ b/setup.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- -# Copyright 2016 Matt Martz +# Copyright 2021 Nik Ho # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may @@ -63,17 +63,18 @@ def find_version(*file_paths): setup( - name='flask-lambda', - version=find_version('flask_lambda.py'), + name='flask-aws-lambda', + version=find_version('flask_aws_lambda.py'), description=('Python module to make Flask compatible with AWS Lambda for ' - 'creating RESTful applications'), + 'creating RESTful applications. Compatible with both REST ' + 'and HTTP API gateways.'), long_description=long_description, keywords='flask aws amazon lambda', - author='Matt Martz', - author_email='matt@sivel.net', - url='https://github.com/sivel/flask-lambda', + author='Nik Ho', + author_email='codeschwert@protonmail.com', + url='https://github.com/CodeSchwert/flask-aws-lambda', license='Apache License, Version 2.0', - py_modules=['flask_lambda'], + py_modules=['flask_aws_lambda'], install_requires=requirements, classifiers=[ 'Development Status :: 4 - Beta',