Skip to content

Changelog

All notable changes to this project will be documented in this file.

The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.

Unreleased

  • Nothing (yet)

4.1.0 - 2026-03-07

Tip

This release includes some changes to the default behavior of ServeStatic for security hardening. If you are affected by any of these changes, please read the relevant sections in the documentation on allow_unsafe_symlinks.

Added

  • Added support for zstd compression on Python 3.14+.
  • Added support for the top-level servestatic module to run as a Django app.
  • Added Django system checks to test for common misconfigurations.
  • Added a new allow_unsafe_symlinks configuration option for WSGI/ASGI
  • Added a new SERVESTATIC_ALLOW_UNSAFE_SYMLINKS configuration option for Django.
  • Added jxl image support.

Changed

  • Improved event-loop handling for ASGI file iterator.
  • Installing servestatic as a Django app is now the suggested configuration. A warning will appear if it is not detected in INSTALLED_APPS when DEBUG is True.
  • servestatic.runserver_nostatic is no longer the recommended Django app installation path. This import path will be retained to ease WhiteNoise to ServeStatic migration, but now the documentation recommends to use the top-level servestatic module instead.
  • For security purposes, ServeStatic will no longer follow unsafe symlinks by default. If your symlinks point to files outside of your static root, it is highly recommended to copy them instead. This behavior can be disabled for trusted deployments using allow_unsafe_symlinks / SERVESTATIC_ALLOW_UNSAFE_SYMLINKS.

Fixed

  • Fixed a range-request edge case where the last byte could be requested but would not be served.

Security

  • Hardened autorefresh path matching to prevent potential path traversal or path clobbering.
  • Hardened static file resolution to block symlink breakout by default.

4.0.0 - 2026-03-05

Added

  • Added servestatic CLI command for creating manifests, hashing, and compressing for static files.

Changed

  • Minimum python version is now 3.10.
  • immutable_file_test now defaults to a regex matching the file name format generated by servestatic --hash (for example app.db8f2edc0c8a.js).

Deprecated

  • Calling the compression API via python -m servestatic.compress is now deprecated. Please use the servestatic --compress CLI instead.

Fixed

  • Fix race condition where ServeStatic could throw an exception when shutting down async file threads.

3.1.0 - 2025-06-10

Added

  • Added support for running ServeStatic in standalone WSGI/ASGI mode (without an app).

3.0.2 - 2025-06-03

Fixed

  • Fixed a bug where ServeStaticASGI was preventing compatibility with the lifespan protocol. All non-HTTP requests are now properly forwarded to the user's ASGI app.

3.0.1 - 2025-03-02

Fixed

  • Fixed compatibility between the two following Django settings: SERVESTATIC_KEEP_ONLY_HASHED_FILES and SERVESTATIC_USE_MANIFEST

3.0.0 - 2025-01-10

Changed

  • Drop Django 3.2 and 4.1 support.
  • Any errors from threads in the servestatic.compress command are now raised.
  • Compression code has been refactored to match upstream (WhiteNoise).

Fixed

  • Add asgiref to dependencies to fix import error.

2.1.1 - 2024-10-27

Fixed

  • Make sure WSGI SlicedFile is closed properly to prevent subtle bugs.

2.1.0 - 2024-10-02

Added

  • Support Python 3.13.

Changed

  • Query strings are now preserved during HTTP redirection.

2.0.1 - 2024-09-13

Fixed

  • Fix crash when running manage.py collectstatic when Django's settings.py:STATIC_ROOT is a Path object.

2.0.0 - 2024-09-12

Added

  • Django settings.py:SERVESTATIC_USE_MANIFEST will allow ServeStatic to use the Django manifest rather than scanning the filesystem.
    • When also using ServeStatic's CompressedManifestStaticFilesStorage backend, ServeStatic will no longer need to call os.stat.

Changed

  • Minimum python version is now 3.9.
  • Django setings.py:SERVESTATIC_USE_FINDERS will now discover files strictly using the finders API. Previously, ServeStatic would also scan settings.py:STATIC_ROOT for files not found by the finders API.
  • Async file reading is now done via threads rather than aiofiles due recent performance tests.
  • BaseServeStatic has been renamed to ServeStaticBase.
  • AsgiFileServer has been renamed to FileServerASGI.
  • Lots of internal refactoring to improve performance, code quality, and maintainability.

1.2.0 - 2024-08-30

Added

  • Verbose Django 404 error page when settings.py:DEBUG is True

Fixed

  • 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.

1.1.0 - 2024-08-27

Added

  • Files are now compressed within a thread pool to increase performance.

Fixed

  • Fix Django StreamingHttpResponse must consume synchronous iterators warning.
  • Fix Django bug where file paths could fail to be followed on Windows.

1.0.0 - 2024-05-08

Changed