diff --git a/README.md b/README.md index 1f7e074..5ff38fe 100644 --- a/README.md +++ b/README.md @@ -4,10 +4,12 @@ OpenFaaS Python Flask Templates The Python Flask templates that make use of the incubator project [of-watchdog](https://github.com/openfaas-incubator/of-watchdog). Templates available in this repository: + - python27-flask - python3-flask - python3-flask-debian - python3-flask-armhf + - python3-http - python3-http-debian - python3-http-armhf @@ -15,44 +17,124 @@ Templates available in this repository: Notes: - To build and deploy a function for Raspberry Pi or ARMv7 in general, use the language templates ending in *-armhf* +## Picking your template + +The templates named `python*-flask*` are designed as a drop-in replacement for the classic `python3` template, but using the more efficient of-watchdog. The move to use flask as an underlying framework allows for greater control over the HTTP request and response. + +Those templates named `python*-http*` are designed to offer full control over the HTTP request and response. Flask is used as an underlying framework. + +The `witness` HTTP server is used along with Flask for all templates. + +Are you referencing pip modules which require a native build toolchain? It's advisable to use the template with a `-debian` suffix in this case. The Debian images are larger, however they are usually more efficient for use with modules like `numpy` and `pandas`. + ## Downloading the templates + +Using template pull: + +```bash +faas template pull https://github.com/openfaas-incubator/python-flask-template ``` -$ faas template pull https://github.com/openfaas-incubator/python-flask-template + +Using template store: + +```bash +faas template store pull python3-flask ``` -# Using the python27-flask/python3-flask templates +# Using the python3-flask template + Create a new function + ``` -$ faas new --lang python27-flask +export OPENFAAS_PREFIX=alexellis2 +export FN="tester" +faas new --lang python3-flask $FN ``` + Build, push, and deploy + ``` -$ faas up -f .yml +faas up -f $FN.yml ``` + Test the new function + ``` -$ echo -n content | faas invoke +echo -n content | faas invoke $FN +``` + +## Example of returning a string + +```python +def handle(req): + """handle a request to the function + Args: + req (str): request body + """ + + return "Hi" + str(req) +``` + +## Example of returning a custom HTTP code + +```python +def handle(req): + return "request accepted", 201 +``` + +## Example of returning a custom HTTP code and content-type + +```python +def handle(req): + return "request accepted", 201, {"Content-Type":"binary/octet-stream"} +``` + +## Example of accepting raw bytes in the request + +Update stack.yml: + +```yaml + environment: + RAW_BODY: True +``` + +> Note: the value for `RAW_BODY` is case-sensitive. + +```python +def handle(req): + """handle a request to the function + Args: + req (str): request body + """ + + # req is bytes, so an input of "hello" returns i.e. b'hello' + return string(req) ``` # Using the python3-http templates + Create a new function + ``` -$ faas new --lang python3-http +export OPENFAAS_PREFIX=alexellis2 +export FN="tester" +faas new --lang python3-http $FN ``` + Build, push, and deploy + ``` -$ faas up -f .yml -``` -Set your OpenFaaS gateway URL. For example: -``` -$ OPENFAAS_URL=http://127.0.0.1:8080 +faas up -f $FN.yml ``` + Test the new function + ``` -$ curl -i $OPENFAAS_URL/function/ +echo -n content | faas invoke $FN ``` ## Event and Context Data + The function handler is passed two arguments, *event* and *context*. *event* contains data about the request, including: @@ -66,12 +148,15 @@ The function handler is passed two arguments, *event* and *context*. - hostname ## Response Bodies + By default, the template will automatically attempt to set the correct Content-Type header for you based on the type of response. For example, returning a dict object type will automatically attach the header `Content-Type: application/json` and returning a string type will automatically attach the `Content-Type: text/html, charset=utf-8` for you. ## Example usage + ### Custom status codes and response bodies + Successful response status code and JSON response body ```python def handle(event, context): diff --git a/template/python3-flask-armhf/index.py b/template/python3-flask-armhf/index.py index 9c45794..35fa6a8 100644 --- a/template/python3-flask-armhf/index.py +++ b/template/python3-flask-armhf/index.py @@ -4,9 +4,14 @@ from flask import Flask, request from function import handler from waitress import serve +import os app = Flask(__name__) +# distutils.util.strtobool() can throw an exception +def is_true(val): + return len(val) > 0 and val.lower() == "true" or val == "1" + @app.before_request def fix_transfer_encoding(): """ @@ -22,7 +27,14 @@ def fix_transfer_encoding(): @app.route("/", defaults={"path": ""}, methods=["POST", "GET"]) @app.route("/", methods=["POST", "GET"]) def main_route(path): - ret = handler.handle(request.get_data()) + raw_body = os.getenv("RAW_BODY") + + as_text = True + + if is_true(raw_body): + as_text = False + + ret = handler.handle(request.get_data(as_text=as_text)) return ret if __name__ == '__main__': diff --git a/template/python3-flask-debian/index.py b/template/python3-flask-debian/index.py index 9c45794..35fa6a8 100644 --- a/template/python3-flask-debian/index.py +++ b/template/python3-flask-debian/index.py @@ -4,9 +4,14 @@ from flask import Flask, request from function import handler from waitress import serve +import os app = Flask(__name__) +# distutils.util.strtobool() can throw an exception +def is_true(val): + return len(val) > 0 and val.lower() == "true" or val == "1" + @app.before_request def fix_transfer_encoding(): """ @@ -22,7 +27,14 @@ def fix_transfer_encoding(): @app.route("/", defaults={"path": ""}, methods=["POST", "GET"]) @app.route("/", methods=["POST", "GET"]) def main_route(path): - ret = handler.handle(request.get_data()) + raw_body = os.getenv("RAW_BODY") + + as_text = True + + if is_true(raw_body): + as_text = False + + ret = handler.handle(request.get_data(as_text=as_text)) return ret if __name__ == '__main__': diff --git a/template/python3-flask/index.py b/template/python3-flask/index.py index 9c45794..35fa6a8 100644 --- a/template/python3-flask/index.py +++ b/template/python3-flask/index.py @@ -4,9 +4,14 @@ from flask import Flask, request from function import handler from waitress import serve +import os app = Flask(__name__) +# distutils.util.strtobool() can throw an exception +def is_true(val): + return len(val) > 0 and val.lower() == "true" or val == "1" + @app.before_request def fix_transfer_encoding(): """ @@ -22,7 +27,14 @@ def fix_transfer_encoding(): @app.route("/", defaults={"path": ""}, methods=["POST", "GET"]) @app.route("/", methods=["POST", "GET"]) def main_route(path): - ret = handler.handle(request.get_data()) + raw_body = os.getenv("RAW_BODY") + + as_text = True + + if is_true(raw_body): + as_text = False + + ret = handler.handle(request.get_data(as_text=as_text)) return ret if __name__ == '__main__':