Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WHITENOISE_STATIC_PREFIX still required if django app deployed on subpath #271

Open
w- opened this issue Jan 2, 2021 · 7 comments
Open

Comments

@w-
Copy link

w- commented Jan 2, 2021

The docs for WHITENOISE_STATIC_PREFIX currently say

Default: Path component of settings.STATIC_URL (with settings.FORCE_SCRIPT_NAME removed if set)
....
If your application is not running at the root of the domain and FORCE_SCRIPT_NAME is set then this value will be removed from the STATIC_URL path first to give the correct prefix.

I understand this to mean if in my settings.py I have

FORCE_SCRIPT_NAME = "/dev"
STATIC_URL = "{}/static/".format(FORCE_SCRIPT_NAME)

WHITENOISE_STATIC_PREFIX will automatically be /static/

However, this is not the case and i still need to explicitly set in my settings.py

WHITENOISE_STATIC_PREFIX = "/static/"

otherwise static files will not work.

Is this a bug, or am I misunderstanding something in the docs? I did see #164 which seems similar but different enough (no mention of FORCE_SCRIPT_NAME) where it explicitly mentions needing to do this, but that issue is from 2017 and seems to contradict the above documentation.

am using

  • whitenoise 5.2.0
  • zappa 0.52.0
  • django 3.1.4
@evansd
Copy link
Owner

evansd commented Jan 4, 2021

Your reading of the docs is correct so this does sound like a bug, but I'm struggling to understand what might be causing it.

Can you post a minimal reproducing example somewhere?

@manics
Copy link

manics commented Jan 4, 2021

I recently ran into something similar in https://github.com/ome/omero-web-docker. That's definitely not a minimal example, but I'm pretty sure it used to work, so if I get time I might be able to pin down the version where it broke.

@manics
Copy link

manics commented Jan 6, 2021

#259 is the problematic PR in my case, 5.1.0 works, 5.2.0 doesn't. I'm using Django 1.11 with something like

FORCE_SCRIPT_NAME = "/prefix"
STATIC_URL = "/prefix/static/"

The related issue #258 says

In Django 3.1 static urls are prefixed if there is a url path prefix specified by settings (FORCE_SCRIPT_NAME)
or
more likely, from the webserver.

I'm not familiar with Django 3, but could it be that get_script_prefix doesn't take FORCE_SCRIPT_NAME into account, so both cases need to be handled? E.g.

if settings.FORCE_SCRIPT_NAME:
    script_prefix = settings.FORCE_SCRIPT_NAME.rstrip("/")
else:
    script_prefix = get_script_prefix().rstrip("/")
...

@smith153
Copy link

I had a similar issue. I've not hosted django on apache before with mod_wsgi but figured I would try it out.

I had django mounted under '/d':

    WSGIDaemonProcess testnet.net python-home=/opt/python/cur python-path=/srv/www/testnet/ processes=2 threads=3
    WSGIProcessGroup testnet.net
    WSGIScriptAlias /d /srv/www/testnet/config/wsgi.py process-group=testnet.net

    <Directory /srv/www/testnet/config >
        <Files wsgi.py>
            Require all granted
        </Files>
    </Directory>

Which meant my static files weren't being served. I updated my config to STATIC_URL = "/d/static/", I could see in the html that the static files were prefixed right but django was giving 404 for each file. Setting FORCE_SCRIPT_NAME to many combinations of '/d', 'd', 'd/', etc nothing was working. This is what ended up working:

  #FORCE_SCRIPT_NAME = '/d'
  STATIC_URL = "/d/static/"
  WHITENOISE_STATIC_PREFIX = "/static/"

(yes FORCE_SCRIPT_NAME is commented out)

I checked and get_script_prefix() was returning '/d/'.

@bluespider42
Copy link

I had a similar issue which I solved by setting WHITENOISE_STATIC_PREFIX = "/static/" although I'm not sure why this worked.

@stewartadam
Copy link

stewartadam commented Sep 26, 2022

I believe this is still an issue, I've been experiencing incorrect pathing from static assets with whitenoise which I spent a bit of time debugging in TandoorRecipes/recipes#1878 and https://code.djangoproject.com/ticket/34028.

The root cause seems to be that recent Django versions cache the prefix and setting values based on their first access. Normally first access is a HTTP request so SCRIPT_NAME would be set on it and all is well... However, whitenoise attempts to access the configured STATIC_URL during middleware initialization, as you can see here:

recipes-web_recipes-1  |   File "/opt/recipes/recipes/wsgi.py", line 15, in <module>
recipes-web_recipes-1  |     _application = get_wsgi_application()
recipes-web_recipes-1  |   File "/opt/recipes/venv/lib/python3.10/site-packages/django/core/wsgi.py", line 13, in get_wsgi_application
recipes-web_recipes-1  |     return WSGIHandler()
recipes-web_recipes-1  |   File "/opt/recipes/venv/lib/python3.10/site-packages/django/core/handlers/wsgi.py", line 126, in __init__
recipes-web_recipes-1  |     self.load_middleware()
recipes-web_recipes-1  |   File "/opt/recipes/venv/lib/python3.10/site-packages/django/core/handlers/base.py", line 61, in load_middleware
recipes-web_recipes-1  |     mw_instance = middleware(adapted_handler)
recipes-web_recipes-1  |   File "/opt/recipes/venv/lib/python3.10/site-packages/whitenoise/middleware.py", line 47, in __init__
recipes-web_recipes-1  |     self.configure_from_settings(settings)
recipes-web_recipes-1  |   File "/opt/recipes/venv/lib/python3.10/site-packages/whitenoise/middleware.py", line 86, in configure_from_settings
recipes-web_recipes-1  |     self.static_prefix = urlparse(settings.STATIC_URL or "").path
recipes-web_recipes-1  |   File "/opt/recipes/venv/lib/python3.10/site-packages/django/conf/__init__.py", line 93, in __getattr__
recipes-web_recipes-1  |     val = self._add_script_prefix(val)
recipes-web_recipes-1  |   File "/opt/recipes/venv/lib/python3.10/site-packages/django/conf/__init__.py", line 144, in _add_script_prefix
recipes-web_recipes-1  |     traceback.print_stack()

Since this is during initialization and outside a HTTP request context, SCRIPT_NAME is absent and therefore the Django prefix gets incorrectly returned as '/' (i.e. STATIC_URL gets set to '/static/' and then remains that way). This causes all the asset URIs to be wrong when a real request comes in with SCRIPT_NAME header set.

In theory setting FORCE_SCRIPT_NAME should address this by short-circuiting SCRIPT_NAME and ensuring the Django prefix is set correct on whitenoise middleware initialization, but in my testing I didn't see that behavior. The prefix only gets set on the first HTTP request, so until then even with FORCE_SCRIPT_NAME set the prefix is still '/' according to Django - and that's what whitenoise sees. Note sure if thats a Django issue or if whitenoise needs to add an explicit check for FORCE_SCRIPT_NAME.

@tangjienan
Copy link

This issue still exists.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants