pythonroutesflask

Add a prefix to all Flask routes


I have a prefix that I want to add to every route. Right now I add a constant to the route at every definition. Is there a way to do this automatically?

PREFIX = "/abc/123"

@app.route(PREFIX + "/")
def index_page():
  return "This is a website about burritos"

@app.route(PREFIX + "/about")
def about_page():
  return "This is a website about burritos"

Solution

  • The answer depends on how you are serving this application.

    Sub-mounted inside of another WSGI container

    Assuming that you are going to run this application inside of a WSGI container (mod_wsgi, uwsgi, gunicorn, etc); you need to actually mount, at that prefix the application as a sub-part of that WSGI container (anything that speaks WSGI will do) and to set your APPLICATION_ROOT config value to your prefix:

    app.config["APPLICATION_ROOT"] = "/abc/123"
    
    @app.route("/")
    def index():
        return "The URL for this page is {}".format(url_for("index"))
    
    # Will return "The URL for this page is /abc/123/"
    

    Setting the APPLICATION_ROOT config value simply limit Flask's session cookie to that URL prefix. Everything else will be automatically handled for you by Flask and Werkzeug's excellent WSGI handling capabilities.

    An example of properly sub-mounting your app

    If you are not sure what the first paragraph means, take a look at this example application with Flask mounted inside of it:

    from flask import Flask, url_for
    from werkzeug.serving import run_simple
    from werkzeug.middleware.dispatcher import DispatcherMiddleware
     
    app = Flask(__name__)
    app.config['APPLICATION_ROOT'] = '/abc/123'
     
    @app.route('/')
    def index():
        return 'The URL for this page is {}'.format(url_for('index'))
    
    def simple(env, resp):
        resp(b'200 OK', [(b'Content-Type', b'text/plain')])
        return [b'Hello WSGI World']
    
    app.wsgi_app = DispatcherMiddleware(simple, {'/abc/123': app.wsgi_app})
    
    if __name__ == '__main__':
        app.run('localhost', 5000)
    

    Proxying requests to the app

    If, on the other hand, you will be running your Flask application at the root of its WSGI container and proxying requests to it (for example, if it's being FastCGI'd to, or if nginx is proxy_pass-ing requests for a sub-endpoint to your stand-alone uwsgi / gevent server then you can either: