After upgrading Wagtail and supporting packages, I'm having a strange problem where all the static assets (CSS, JS, fonts, etc..) return a 404 error when logged into the Wagtail admin, ie. the sessionid is valid and set in the browser. However, the are accessible when not logged in (no sessionid cookie). This is true for the public facing site as well as /admin
The site is running:
- Django==4.1.8
- wagtail==4.2.2
- whitenoise==6.4.0
- Python==3.11.2
- hosted via heroku.
Both production and dev (currently locally) are set using STATICFILES_STORAGE = whitenoise.storage.CompressedManifestStaticFilesStorage
and STATIC_URL = "static/"
. Migrations and collectstatic
have also been run.
I've tested this a couple of ways:
Using curl
No Cookie:
curl -I http://127.0.0.1:8000/static/wagtailadmin/js/vendor.610e8c3f47d9.js
HTTP/1.1 200 OK
Date: Mon, 01 May 2023 06:11:55 GMT
Server: WSGIServer/0.2 CPython/3.11.2
Content-Type: text/javascript; charset="utf-8"
Cache-Control: max-age=315360000, public, immutable
Access-Control-Allow-Origin: *
Vary: Accept-Encoding, Cookie
Last-Modified: Mon, 01 May 2023 03:59:51 GMT
ETag: "644f3937-41103"
Content-Length: 266499
X-Content-Type-Options: nosniff
Referrer-Policy: same-origin
Cross-Origin-Opener-Policy: same-origin
X-Frame-Options: DENY
With Cookie:
curl -I http://127.0.0.1:8000/static/wagtailadmin/js/vendor.610e8c3f47d9.js -H "Cookie: csrftoken=fPp7Oq2lR90jkilUiPDRHTOPTsu2lMZm;sessionid=his9jbjahqa3j86hjueeop0lno8pb4a9"
HTTP/1.1 404 Not Found
Date: Mon, 01 May 2023 06:15:53 GMT
Server: WSGIServer/0.2 CPython/3.11.2
Content-Type: text/html; charset=utf-8
Content-Length: 2761
Vary: Cookie
Invalid sessionid:
à la sessionid=thisisnotvalid
returns assets fine
Setting full URL for STATIC_URL
This is where it gets interesting. If I set STATIC_URL = "http://127.0.0.1:8000/static/"
and log in via http://localhost:8000
everything works perfectly. If I set STATIC_URL = "http://localhost:8000/static/"
no dice! It's the same if I swap them. Apparently STATIC_URL
and WAGTAILADMIN_BASE_URL
cannot be the same.
In production I don't really have the option (or don't want) to serve the assets from a separate domain. I'd expect it to just work as it did formally.
Debug setting
DEBUG=True:
Setting STATIC_URL
works with static/
but not when it's the same as the accessing domain and works when set to an alternate.
DEBUG=False:
Works as described above. static/
and matching domains don't work. An alternate does.
Relevent bits of configs
base.py:
STATICFILES_FINDERS = [
"django.contrib.staticfiles.finders.FileSystemFinder",
"django.contrib.staticfiles.finders.AppDirectoriesFinder",
]
STATICFILES_DIRS = [
os.path.join(PROJECT_DIR, "static"),
]
STATIC_ROOT = os.path.join(BASE_DIR, "staticfiles")
dev.py:
STATICFILES_STORAGE = "whitenoise.storage.CompressedManifestStaticFilesStorage"
STATIC_URL = "http://127.0.0.1:8000/static/"
production.py:
STATICFILES_STORAGE = "whitenoise.storage.CompressedManifestStaticFilesStorage"
STATIC_URL = "https://www.domainredacted.com/static/" # Formally just "static/"
It's quite late and perhaps I missed something while upgrading but I can't seem to find it. Any help is greatly appreciated.
App & Middleware:
INSTALLED_APPS = [
......
"generic_chooser",
"django_extensions",
"storages", # For S3 Storage
"wagtail_2fa",
"django_otp",
"django_otp.plugins.otp_totp",
"captcha",
"wagtailcaptcha",
"wagtail.contrib.modeladmin",
"wagtail.contrib.forms",
"wagtail.contrib.redirects",
"wagtail.contrib.settings",
"wagtail.contrib.routable_page",
"wagtailmetadata",
"wagtail.embeds",
"wagtail.sites",
"wagtail.users",
"wagtail.snippets",
"wagtail.documents",
"wagtail.images",
"wagtail.search",
"wagtail.admin",
"wagtail",
"wagtail.contrib.search_promotions",
"wagtail.contrib.table_block",
"modelcluster",
"taggit",
"django.contrib.sitemaps",
"django.contrib.admin",
"django.contrib.auth",
"django.contrib.contenttypes",
"django.contrib.sessions",
"django.contrib.messages",
"whitenoise.runserver_nostatic",
"django.contrib.staticfiles",
]
MIDDLEWARE = [
"django.contrib.sessions.middleware.SessionMiddleware",
"django.middleware.common.CommonMiddleware",
"django.middleware.csrf.CsrfViewMiddleware",
"django.contrib.auth.middleware.AuthenticationMiddleware",
"wagtail_2fa.middleware.VerifyUserMiddleware",
"django.contrib.messages.middleware.MessageMiddleware",
"django.middleware.clickjacking.XFrameOptionsMiddleware",
"django.middleware.security.SecurityMiddleware",
"whitenoise.middleware.WhiteNoiseMiddleware",
"wagtail.contrib.redirects.middleware.RedirectMiddleware",
]