From 57b78100694667aa0dbe738c30257fbbfbea19b6 Mon Sep 17 00:00:00 2001 From: scheianu Date: Fri, 11 Sep 2026 13:18:29 +0300 Subject: [PATCH] Fix 404 on the header logo caused by an encoded query string base.html passed the cache-busting query string INSIDE the filename argument: url_for('static', filename='uploads/header_logo.png?v=1') Flask percent-encodes the '?' to '%3F', producing a request for a file literally named "header_logo.png%3Fv=1", which does not exist. Every authenticated page therefore logged: GET /static/uploads/header_logo.png%3Fv=1 404 The logo silently stayed hidden too, because the element carries onerror="this.style.display='none'". Changes: - base.html / login.html: append "?v=..." OUTSIDE url_for(), matching what admin/customize_logos.html already did correctly. - Inject logo_version from a context processor instead of hardcoding it. It is derived from the newest logo's mtime, so uploading a new logo in Admin -> Customize Logos is reflected immediately. The previous value was a literal 1, which defeated cache-busting entirely; login.html used range(1, 999999) | random, which changed on every request and made the logo uncacheable. Verified: /, /content/ and /players/ now render /static/uploads/header_logo.png?v= (HTTP 200), and no %3F requests appear in the logs. --- app/app.py | 20 ++++++++++++++++++++ app/templates/auth/login.html | 2 +- app/templates/base.html | 2 +- 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/app/app.py b/app/app.py index 27e31a6..52e95ea 100644 --- a/app/app.py +++ b/app/app.py @@ -191,9 +191,29 @@ def register_context_processors(app): @app.context_processor def inject_config(): """Inject configuration variables into all templates""" + # Cache-busting token for the uploadable logos. + # + # Must be appended OUTSIDE url_for(): passing 'logo.png?v=1' as the + # filename makes Flask percent-encode the '?' into '%3F', which asks + # for a file literally named "logo.png%3Fv=1" and 404s. + # + # Derived from the newest logo's mtime so that uploading a new logo in + # Admin → Customize Logos is picked up immediately, rather than reusing + # a hardcoded value the browser has already cached. + logo_version = 1 + for _logo_name in ('header_logo.png', 'login_logo.png'): + try: + _mtime = int(os.path.getmtime( + os.path.join(app.config['UPLOAD_FOLDER'], _logo_name))) + logo_version = max(logo_version, _mtime) + except OSError: + # Logo not uploaded yet — keep the current token. + pass + return { 'server_version': app.config['SERVER_VERSION'], 'build_date': app.config['BUILD_DATE'], + 'logo_version': logo_version, 'logo_exists': os.path.exists( os.path.join(app.root_path, app.config['UPLOAD_FOLDERLOGO'], 'logo.png') ) diff --git a/app/templates/auth/login.html b/app/templates/auth/login.html index 5d4a88d..ff9fcb0 100644 --- a/app/templates/auth/login.html +++ b/app/templates/auth/login.html @@ -181,7 +181,7 @@