Forums

Flask catch all does not work as expected

In my app, I have implemented a catch all mechanism in flask backend according to the sample code in http://flask.pocoo.org/snippets/57/

The idea is to handle all routing by my frontend code (vue router, if that is relevant). I have several other routes in my flask code, but they should only be called by ajax calls.

Unfortunately, it does not work as I expected. Either I am doing something wrong, or I do not understand the catch all mechanism. This is what I have in my flask code currently:

@app.route('/', defaults={'path': ''})
@app.route('/<path:path>')
def catch_all(path):
    return render_template("index.html")

@app.route("/test", methods=['GET'])
def get_def():
    return jsonify(tst="dummy")

Now, if I enter https://weisswurst.pythonanywhere.com/test, I would expect the flask catch all code to render my index.html file, so my frontend router can handle it (it should route to a customized 404 page). But instead I get a page showing {"tst":"dummy"}, so apparently the /test route was triggered by entering the url manually.

What am I doing wrong?

According to the Flask docs

Flask uses the Werkzeug routing system which was designed to automatically order routes by complexity. This means that you can declare routes in arbitrary order and they will still work as expected. This is a requirement if you want to properly implement decorator based routing since decorators could be fired in undefined order when the application is split into multiple modules.

I must admit, though, that I've found it hard to pin down exactly what "complexity" means in that sentence! However, I think it's to do with how specific a route is, which would mean that your catch-all is less "complex" than your static route for /test/.

Ok, but what exactly should I do to really implement this "catch all" mechanism?

remove your /test route?

Sure, but that one was just for testing. As I said in my op, I have several other routes in my flask code, but they should only be called by ajax calls.

how does a web server differentiate what is ajax and what is not? (it can't)

In the meantime, I have understood that that is the case yes.

I have just been misled by all the sites which talk about this "catch all" mechanism. It is obvious though that there is no "catch all", just a "catch everything else".

From my (maybe naive) point of view, this seems just a missing feature in the flask/werkzeug routing system. It would be so nice if I could just define my own route priority.

Anyway, case closed.