PSA: Routing Redirect Behavior
- From:
- Armin Ronacher
- Date:
- 2011-06-29 @ 16:56
Hi,
One of the design principles of the Werkzeug routing system which is
used by Flask is that URLs shall be unique. A lot of the
implementation's complexity can be tracked down to the enforcement of
uniqueness of the URLs.
For instance if you provide a URL specification like this:
@app.route('/', defaults={'page': 1})
@app.route('/page/<int:page>')
def show_list(page):
...
It has the effect that if you go to 'http://example.com/' you will
trigger that view for page=1. That's obvious. But what happens if you
go to 'http://example.com/page/1'? In that case Werkzeug will notify
the framework (in this case Flask) that it has a better URL and will
request a redirect to 'http://example.com/'.
As a result of this we strongly recommend against URL specifications
that are not unique like this:
@app.route('/foo/')
@app.route('/foo/index.html')
def render_foo():
...
While it will currently work, we never intended that this code will work
with the default redirecting active. We will probably provide a way
with Werkzeug 0.7 to make one of them the canonical way.
Right now the correct way to express this intention is this:
@app.route('/foo/')
@app.route('/foo/index.html', redirect_to='foo/')
def render_foo():
...
However that still does not tell the URL builder which of the ones is
preferred. With 0.7 we will probably provide an alias setting:
@app.route('/foo/')
@app.route('/foo/index.html', alias=True)
def render_foo():
...
If you noticed infinite redirects with Flask 0.7: upgrade to Flask 0.7.1
which we just pushed out. Changes in the blueprint code surfaced a bug
in the Werkzeug routing system regarding this redirection code and we
added a tiny workaround to fix this problem for the time being.
Why didn't we catch that problem? The newly introduced blueprint code
was defaulting the 'defaults' parameter to '{}' instead of None. It's
supposed to do the same, but unfortunately it's currently not and we did
not have a test case that covered that edge case. The testsuite in
Flask has been expanded for this case and the Werkzeug 0.7 release will
overhaul the general routing system to make it less error prone.
In case you want to help out: if you share your URL map with us we can
ensure that we cover every case in the current routing behavior:
http://paste.pocoo.org/show/423644/
Regards,
Armin