From f6e5621e7a85a49f0a762c08aecc5ca5bb03c8e5 Mon Sep 17 00:00:00 2001 From: sarahboyce Date: Tue, 4 Apr 2023 19:50:51 +0200 Subject: [PATCH 1/6] Revert change to use get_script_prefix --- docs/changelog.rst | 5 +++++ src/whitenoise/middleware.py | 9 ++++----- tests/test_django_whitenoise.py | 9 +++++++++ 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/docs/changelog.rst b/docs/changelog.rst index 7f64ddee..9d4058c4 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -4,6 +4,11 @@ Changelog * Changed documentation site URL from ``https://whitenoise.evans.io/`` to ``https://whitenoise.readthedocs.io/``. +6.5.0 (unreleased) +------------------ + +* Handle the Django setting ``FORCE_SCRIPT_NAME``. + 6.4.0 (2023-02-25) ------------------ diff --git a/src/whitenoise/middleware.py b/src/whitenoise/middleware.py index 3f5a8091..3cb5f499 100644 --- a/src/whitenoise/middleware.py +++ b/src/whitenoise/middleware.py @@ -8,7 +8,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 .base import WhiteNoise from .string_utils import ensure_leading_trailing_slash @@ -94,10 +93,10 @@ def __init__(self, get_response=None, settings=settings): self.static_prefix = settings.WHITENOISE_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 2654424f..c825733f 100644 --- a/tests/test_django_whitenoise.py +++ b/tests/test_django_whitenoise.py @@ -209,3 +209,12 @@ def test_relative_static_url(server, static_files, _collect_static): url = storage.staticfiles_storage.url(static_files.js_path) response = server.get(url) assert response.content == static_files.js_content + + +def test_force_script_name(server, static_files, _collect_static): + with override_settings( + FORCE_SCRIPT_NAME="/forced_script_name", STATIC_URL="static/" + ): + url = storage.staticfiles_storage.url(static_files.js_path) + response = server.get(url) + assert response.content == static_files.js_content From 45d8e08b3b5d21693086625c3c79fb5cc1e14be8 Mon Sep 17 00:00:00 2001 From: Archmonger <16909269+Archmonger@users.noreply.github.com> Date: Fri, 30 Aug 2024 01:37:40 -0700 Subject: [PATCH 2/6] better tests --- tests/test_django_whitenoise.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/test_django_whitenoise.py b/tests/test_django_whitenoise.py index 5dde8fd6..b6854990 100644 --- a/tests/test_django_whitenoise.py +++ b/tests/test_django_whitenoise.py @@ -271,10 +271,10 @@ def test_error_message(server): 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): - with override_settings( - FORCE_SCRIPT_NAME="/forced_script_name", STATIC_URL="static/" - ): - url = storage.staticfiles_storage.url(static_files.js_path) - response = server.get(url) - assert response.content == static_files.js_content + 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 From 489835bfa74f547845927ef2d45a91d4b2e119e0 Mon Sep 17 00:00:00 2001 From: Archmonger <16909269+Archmonger@users.noreply.github.com> Date: Fri, 30 Aug 2024 01:38:36 -0700 Subject: [PATCH 3/6] add changelog --- CHANGELOG.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) 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 From 5a26b5866024ca1b673829e2e6b4a3a6a94312b8 Mon Sep 17 00:00:00 2001 From: Archmonger <16909269+Archmonger@users.noreply.github.com> Date: Fri, 30 Aug 2024 01:41:37 -0700 Subject: [PATCH 4/6] fix spelling error in readme --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) 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._ From cac25dcecc166ad37fa0c268e9e43c97d0c448bc Mon Sep 17 00:00:00 2001 From: Archmonger <16909269+Archmonger@users.noreply.github.com> Date: Fri, 30 Aug 2024 02:16:31 -0700 Subject: [PATCH 5/6] new docs for static prefix --- docs/src/django-settings.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/src/django-settings.md b/docs/src/django-settings.md index 74e5c822..e75b818e 100644 --- a/docs/src/django-settings.md +++ b/docs/src/django-settings.md @@ -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. --- From 6b70b668e73e474db509c51f24757bc569446380 Mon Sep 17 00:00:00 2001 From: Archmonger <16909269+Archmonger@users.noreply.github.com> Date: Fri, 30 Aug 2024 02:18:11 -0700 Subject: [PATCH 6/6] consistency for settings.py callouts in docs --- docs/src/django-settings.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/src/django-settings.md b/docs/src/django-settings.md index e75b818e..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.