6

I saw that Azure now supports Python (preview) in the function apps. I have a existing Flask app and was wondering if it's possible to deploy that one as a function app without major changes?

I have read through the Azure tutorials that uses Python in function apps (https://learn.microsoft.com/en-us/azure/azure-functions/functions-reference-python), however not with the flask framework...

Has anyone any experience with it?

wasp256
  • 5,943
  • 12
  • 72
  • 119

3 Answers3

13

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 logging
import azure.functions as func
from flask import Flask, request

app = 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.

enter image description here

enter image description here

enter image description here

enter image description here

enter image description here

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>.

Peter Pan
  • 23,476
  • 4
  • 25
  • 43
  • This one works ok for simple cases, but does not work with JSON payload for POST requests! The main()-wrapper is incomplete. – Tmu Oct 29 '19 at 13:58
  • @Peter Pan I have a question related to this post. Do you have a minute? I am happy to post new question if needed. Cheers – wwnde Jan 15 '21 at 02:35
  • @PeterPan can you please help me to answer the following question- https://stackoverflow.com/questions/68121920/azure-function-apps-integration-of-flask-framework-with-azure-functions – Stark Jun 24 '21 at 19:43
9

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 logging
import 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 DispatcherMiddleware
app.config["APPLICATION_ROOT"] = "/api/app"     # Flask app configuration so it knows correct endpoint urls
application = DispatcherMiddleware(None, {
    '/api/app': app,
})

# Wrap the Flask app as WSGI application
def main(req: func.HttpRequest, context: func.Context) -> func.HttpResponse:
    return AzureFunctionsWsgi(application).main(req, context)
Tmu
  • 271
  • 3
  • 4
8

Flask can be used now out of the box with Python Azure Functions -> see https://github.com/Azure/azure-functions-python-library/pull/45

quervernetzt
  • 10,311
  • 6
  • 32
  • 51