Add a prefix to all Flask routes
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:
- Use a Blueprint, as Miguel points out in his answer.
- or use the
DispatcherMiddleware
fromwerkzeug
(or thePrefixMiddleware
from su27's answer) to sub-mount your application in the stand-alone WSGI server you're using. (See An example of properly sub-mounting your app above for the code to use).
How to set an api prefix in a flask application?
You have to set the SCRIPT_NAME
env var with your prefix.
Please note, this is a WSGI server feature, and thus the Flask development server ignores it.
Read more at https://dlukes.github.io/flask-wsgi-url-prefix.html
How can I add a prefix to all routes with the Flask REST JSON module?
Reading the discussions on Github do the following:
# Create blueprint
api_bp = Blueprint('API', __name__, url_prefix='/api')
# Create Api instance only passing the blueprint
api = Api(blueprint=api_bp)
# register routes
api.route(PostList, 'post_list', '/posts')
api.route(PostDetail, 'post_detail', '/posts/<int:id>')
# initialize Api instance to App
api.init_app(app)
Don't forget that the view names will change. i.e view 'post_list'
becomes 'API.post_list'
so you have to adjust your schemes, but not your route declarations. This is also discussed in the linked Github discussion.
Add route prefix to Flask application running behing Gunicorn
If you are doing app composition, then you can use the DispatcherMiddleware
trick you referenced. However, it sounds like you are trying to have a single service that is subpath mounted, but doesn't serve anything out of the "higher" paths at all.
There are several different ways to do this.
Replace
Flask.url_map._rules
with awerkzeug.routing.Submount
rule factory:from werkzeug.routing import SubPath
app = Flask(__name__)
# register blueprints and extensions
# load config, etc.
app.url_map._rules = SubPath(app.config['APPLICATION_ROOT'], app.url_map._rules)Replace
Flask.url_rule_class
:from werkzeug.routing import Rule
app.url_rule_class = lambda path, **options: Rule(PREFIX + path, **options)Replace
add_url_rule
, as you suggest in your question.
Related Topics
How to Generate Dynamic (Parameterized) Unit Tests in Python
Dynamically Evaluate an Expression from a Formula in Pandas
When to Use and When Not to Use Python 3.5 'Await'
CSV in Python Adding an Extra Carriage Return, on Windows
How to Print the Full Numpy Array, Without Truncation
What Is the Python Equivalent for a Case/Switch Statement
What Do *Args and **Kwargs Mean
Getting a List of Values from a List of Dicts
What Are the Risks of Running 'Sudo Pip'
What Should I Do with "Unexpected Indent" in Python
Why Can't I Use a List as a Dict Key in Python
Importing Orange Returns "Importerror: No Module Named Orange"