pallets / flask

The Python micro framework for building web applications.
https://flask.palletsprojects.com
BSD 3-Clause "New" or "Revised" License
67.87k stars 16.2k forks source link

"catch-all" endpoint doesn't work with `static_url_path="/"` #5527

Closed DRMPN closed 3 months ago

DRMPN commented 3 months ago

Catch all endpoint for SPA from docs doesn't work with static_url_path="/" or static_url_path=""

Context

I'm using Flask to serve React SPA with client-side routing. Flask worked perfectly, until I added images and decided to serve it from static/ folder.

Expected:

I can serve images from static/ folder. I can reload a non-root page and Flask won't respond with 404 Not Found.

Current:

I can navigate to /path or /path1/path2 and etc. with no problems, but when I reload any non-root page the Flask gives me 404 Not Found and the catch-all route didn't trigger.

Example:

folder structure

.
├── __init__.py
└── main/
    ├── static/
    │   ├── image1.jpg
    │   ├── image2.jpg
    │   ├── index.html
    │   └── main.js
    ├── __init__.py
    └── routes.py

./__init__.py

def create_app(config_class=Config) -> Flask:
  app = Flask(__name__)
  from .main import bp as main_bp
  app.register_blueprint(main_bp)
  return app

./main/__init__.py

from flask import Blueprint

bp = Blueprint("main", __name__, static_folder="static", static_url_path="/")

from .main import routes

./main/routes.py

from .main import bp

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

Error message

<!doctype html>
<html lang=en>
<title>404 Not Found</title>
<h1>Not Found</h1>
<p>The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again.</p>

Environment:

davidism commented 3 months ago

The static route is a catch-all path, it matches all paths below it. You need a prefix like /static to distinguish it if you have another top-level catch-all path.