Less grepping and control-f-ing

List your Flask routes

ยท

2 min read

In codebases with lots of directories and subdirectories it can take a lot of "control-f-ing", "grepping", and "github searching" to find the code you want to change. Here is a method to list all the routes in your Flask app to aid in finding the endpoint and thus code you are searching for.

First, let's create a Flask app, app.py, with four varying endpoints which just return a number and a 200.

from flask import Flask
from flask import jsonify

app = Flask(__name__)

@app.route("/route_one")
def route_one():
    return jsonify({"path": "1"}), 200

@app.route("/route_two", methods=["GET"])
def route_two():
    return jsonify({"path": "2"}), 200


@app.route("/route_three", methods=["POST"])
def route_three():
    return jsonify({"path": "3"}), 200


@app.route("/route_four", methods=["PUT"])
def route_four():
    return jsonify({"path": "4"}), 200

Now, let's write a new route which returns all the routes defined in our file.

@app.route("/list_routes")
def list_routes():
    routes = []
    for route in app.url_map.iter_rules():
        routes.append({
            "rule": route.rule,
            "endpoint": route.endpoint,
            "methods": list(route.methods),
        })

    return jsonify(routes), 200

If I curl this route, I get:

[
  {
    "endpoint": "route_three", 
    "methods": [
      "OPTIONS", 
      "POST"
    ], 
    "rule": "/route_three"
  }, 
  {
    "endpoint": "list_routes", 
    "methods": [
      "OPTIONS", 
      "HEAD", 
      "GET"
    ], 
    "rule": "/list_routes"
  }, 
  {
    "endpoint": "route_four", 
    "methods": [
      "OPTIONS", 
      "PUT"
    ], 
    "rule": "/route_four"
  }, 
  {
    "endpoint": "route_one", 
    "methods": [
      "OPTIONS", 
      "HEAD", 
      "GET"
    ], 
    "rule": "/route_one"
  }, 
  {
    "endpoint": "route_two", 
    "methods": [
      "OPTIONS", 
      "HEAD", 
      "GET"
    ], 
    "rule": "/route_two"
  }, 
  {
    "endpoint": "static", 
    "methods": [
      "OPTIONS", 
      "HEAD", 
      "GET"
    ], 
    "rule": "/static/<path:filename>"
  }
]

I choose to return every endpoints rule, accepted methods, and endpoint. Notice that Flask automagically adds Options and Head to GET methods!

Let's say I am searching for route_two. I can just run:

curl localhost:8888/list_routes | grep -n "route_two"

And I get:

37:    "endpoint": "route_two", 
43:    "rule": "/route_two"

Nice!

Let's do a more realistic example with another file of routes added as a blueprint. First, I create a new file, page_two.py, which reads:

from flask import Blueprint, jsonify

page_two = Blueprint('page_two', import_name=__name__, url_prefix="/prefix")

@page_two.route("/route_five",  methods=["GET"])
def route_five():
    return jsonify({"path": "5"}), 200

To add this blueprint, I just add this line near the top of app.py:

from page_two import page_two
app.register_blueprint(page_two)

Now, I run curl localhost:8888/list_routes | grep -n "route_five" and I get:

3:    "endpoint": "page_two.route_five", 
9:    "rule": "/prefix/route_five"

In the endpoint definition, you can see the endpoint contains the name of the blueprint. To locate the file this route is in, I just go to app.py, find import line for page_two blueprint, and then the file the blueprint is defined in!

Happy coding! ๐Ÿ’ˆ

P.S. Here is the repo

ย