Azure use python flask framework for function app
I tried different ways to integrate Azure Functions for Python with Flask framework. Finally, I did it success in my HttpTrigger function named TryFlask
via app.test_client()
.
Here is my sample code, as below.
import loggingimport azure.functions as funcfrom flask import Flask, requestapp = Flask(__name__)@app.route('/')def hello_world(): return 'Hello World!'@app.route('/hi')def hi(): return 'Hi World!'@app.route('/hello')@app.route('/hello/<name>', methods=['POST', 'GET'])def hello(name=None): return name != None and 'Hello, '+name or 'Hello, '+request.args.get('name')def main(req: func.HttpRequest) -> func.HttpResponse: logging.info('Python HTTP trigger function processed a request.') uri=req.params['uri'] with app.test_client() as c: doAction = { "GET": c.get(uri).data, "POST": c.post(uri).data } resp = doAction.get(req.method).decode() return func.HttpResponse(resp, mimetype='text/html')
For testing on local and Azure, to access the urls /
, '/hi' and /hello
via the url http(s)://<localhost:7071 or azurefunchost>/api/TryFlask
with query string ?uri=/
, ?uri=/hi
and ?uri=/hello/peter-pan
in browser, and to do the POST
method for the same url above with query string ?uri=/hello/peter-pan
, these are all work. Please see the results as the figures locally below, the same on cloud.
Note: In my solution, the url must have to be http(s)://<localhost:7071 or azurefunchost>/<routePrefix defined in host.json, default is api>/<function name>?uri=<uri defined in app.route, like / or /hi or /hello, even /hello/peter-pan?name=peter>
.
Flask app is just an WSGI application. WSGI is a rather simple interface (see http://ivory.idyll.org/articles/wsgi-intro/what-is-wsgi.html. So instead of using test_client() as middleware to connect to the Azure function environment, a proper wsgi wrapper implementation should be used, which calls the app=Flask() object.
There is a nice Azure Python wsgi wrapper implementation "azf-wsgi" available in https://github.com/vtbassmatt/azf-wsgi.
In order to use the azf-wsgi wrapper with Flask, I found it useful to use a middleware to rewrite the URL:s from /api/app to / so when developing, I don't need to know where my Flask app gets mounted. Additional benefit is that my main.py is just a normal Flask application, which I can run locally without using Azure functions environment (way faster).
My HttpTriggerApp/__init__.py of Azure function is attached. The myFlaskApp-folder is located under the HttpTriggerApp. Remember to use rlative import in the http-trigger as well as main.py (from . import myHelperFooBar).
For host.json and function.json, follow the azf-wsgi instructions.
import loggingimport azure.functions as func# note that the package is "azf-wsgi" but the import is "azf_wsgi"from azf_wsgi import AzureFunctionsWsgi# Import the Flask wsgi app (note relative import from the folder under the httpTrigger-folder.from .myFlaskAppFolder.main import app# rewrite URL:s to Azure function mount point (you can configure this in host.json and function.json)from werkzeug.middleware.dispatcher import DispatcherMiddlewareapp.config["APPLICATION_ROOT"] = "/api/app" # Flask app configuration so it knows correct endpoint urlsapplication = DispatcherMiddleware(None, { '/api/app': app,})# Wrap the Flask app as WSGI applicationdef main(req: func.HttpRequest, context: func.Context) -> func.HttpResponse: return AzureFunctionsWsgi(application).main(req, context)
Flask can be used now out of the box with Python Azure Functions -> see https://github.com/Azure/azure-functions-python-library/pull/45