diff --git a/CHANGELOG.md b/CHANGELOG.md index fd9f9ff0..c7feb86c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -40,8 +40,9 @@ Using the following categories, list your changes in this order: ### Fixed -- Fix compatibility with third-party sync only middleware - - Django middleware now only runs in async mode to avoid clashing with Django's internal usage of `asgiref.AsyncToSync` +- Fix Django compatibility with third-party sync middleware + - ServeStatic Django middleware now only runs in async mode to avoid clashing with Django's internal usage of `asgiref.AsyncToSync` +- Respect Django `settings.py:FORCE_SCRIPT_NAME` configuration value ([Upstream PR](https://github.com/evansd/whitenoise/pull/486)) ## [1.1.0](https://github.com/Archmonger/ServeStatic/compare/1.0.0...1.1.0) - 2024-08-27 diff --git a/README.md b/README.md index a702066a..3e264e22 100644 --- a/README.md +++ b/README.md @@ -29,8 +29,8 @@ It's designed to work nicely with a CDN for high-traffic sites so you don't have `ServeStatic` automatically takes care of best-practices for you, for instance: -- Serving compressed content (gzip and Brotli formats, handling Accept-Encoding and Vary headers correctly) -- Setting far-future cache headers on content which won't change +- Serving compressed content (gzip and Brotli formats, handling Accept-Encoding and Vary headers correctly) +- Setting far-future cache headers on content which won't change Worried that serving static files with Python is horribly inefficient? Still think you should be using Amazon S3? Have a look at the FAQ below. @@ -58,4 +58,4 @@ None of this is rocket science, but it's fiddly and annoying and `ServeStatic` t --- -_This project is a fork of [WhiteNoise](https://github.com/evansd/whitenoise) for continued maintenience and feature updates._ +_This project is a fork of [WhiteNoise](https://github.com/evansd/whitenoise) for continued maintenance and feature updates._ diff --git a/docs/src/django-settings.md b/docs/src/django-settings.md index 74e5c822..3e707780 100644 --- a/docs/src/django-settings.md +++ b/docs/src/django-settings.md @@ -16,7 +16,7 @@ Don't use this for the bulk of your static files because you won't benefit from ## `SERVESTATIC_AUTOREFRESH` -**Default:** `settings.DEBUG` +**Default:** `settings.py:DEBUG` Recheck the filesystem to see if any files have changed before responding. This is designed to be used in development where it can be convenient to pick up changes to static files without restarting the server. For both performance and security reasons, this setting should not be used in production. @@ -24,7 +24,7 @@ Recheck the filesystem to see if any files have changed before responding. This ## `SERVESTATIC_USE_FINDERS` -**Default:** `settings.DEBUG` +**Default:** `settings.py:DEBUG` Instead of only picking up files collected into `STATIC_ROOT`, find and serve files in their original directories using Django's "finders" API. This is useful in development where it matches the behaviour of the old `runserver` command. It's also possible to use this setting in production, avoiding the need to run the `collectstatic` command during the build, so long as you do not wish to use any of the caching and compression features provided by the storage backends. @@ -32,7 +32,7 @@ Instead of only picking up files collected into `STATIC_ROOT`, find and serve fi ## `SERVESTATIC_MAX_AGE` -**Default:** `60 if not settings.DEBUG else 0` +**Default:** `60 if not settings.py:DEBUG else 0` Time (in seconds) for which browsers and proxies should cache **non-versioned** files. @@ -160,15 +160,15 @@ SERVESTATIC_IMMUTABLE_FILE_TEST = immutable_file_test ## `SERVESTATIC_STATIC_PREFIX` -**Default:** Path component of `settings.STATIC_URL` (with `settings.FORCE_SCRIPT_NAME` removed if set) +**Default:** `settings.py:STATIC_URL` The URL prefix under which static files will be served. -Usually this can be determined automatically by using the path component of `STATIC_URL`. So if `STATIC_URL` is `https://example.com/static/` then `SERVESTATIC_STATIC_PREFIX` will be `/static/`. +If this setting is unset, this value will automatically determined by analysing your `STATIC_URL` setting. For example, if `STATIC_URL = 'https://example.com/static/'` then `SERVESTATIC_STATIC_PREFIX` will be `/static/`. -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. +Note that `FORCE_SCRIPT_NAME` is also taken into account when automatically determining this value. For example, if `FORCE_SCRIPT_NAME = 'subdir/'` and `STATIC_URL = 'subdir/static/'` then `SERVESTATIC_STATIC_PREFIX` will be `/static/`. -If your deployment is more complicated than this (for instance, if you are using a CDN which is doing path rewriting) then you may need to configure this value directly. +If your deployment is more complicated than this (for instance, if you are using a CDN which is doing [path rewriting](https://blog.nginx.org/blog/creating-nginx-rewrite-rules)) then you may need to configure this value directly. --- diff --git a/src/servestatic/middleware.py b/src/servestatic/middleware.py index 66eca968..4bb790d9 100644 --- a/src/servestatic/middleware.py +++ b/src/servestatic/middleware.py @@ -16,7 +16,6 @@ from django.contrib.staticfiles import finders from django.contrib.staticfiles.storage import staticfiles_storage from django.http import FileResponse -from django.urls import get_script_prefix from servestatic.responders import MissingFileError @@ -144,10 +143,10 @@ def __init__(self, get_response, settings=settings): self.static_prefix = settings.SERVESTATIC_STATIC_PREFIX except AttributeError: self.static_prefix = urlparse(settings.STATIC_URL or "").path - script_prefix = get_script_prefix().rstrip("/") - if script_prefix: - if self.static_prefix.startswith(script_prefix): - self.static_prefix = self.static_prefix[len(script_prefix) :] + if settings.FORCE_SCRIPT_NAME: + script_name = settings.FORCE_SCRIPT_NAME.rstrip("/") + if self.static_prefix.startswith(script_name): + self.static_prefix = self.static_prefix[len(script_name) :] self.static_prefix = ensure_leading_trailing_slash(self.static_prefix) self.static_root = settings.STATIC_ROOT diff --git a/tests/test_django_whitenoise.py b/tests/test_django_whitenoise.py index 3dfa862f..b6854990 100644 --- a/tests/test_django_whitenoise.py +++ b/tests/test_django_whitenoise.py @@ -269,3 +269,12 @@ def test_error_message(server): ) assert "•" in response_content assert str(Path(__file__).parent / "test_files" / "static") in response_content + + +@override_settings(FORCE_SCRIPT_NAME="/subdir", STATIC_URL="static/") +def test_force_script_name(server, static_files, _collect_static): + url = storage.staticfiles_storage.url(static_files.js_path) + assert url.startswith("/subdir/static/") + response = server.get(url) + assert "/subdir" in response.url + assert response.content == static_files.js_content