mirror of
https://github.com/frappe/gunicorn.git
synced 2026-07-02 10:41:30 +08:00
252 lines
11 KiB
Markdown
252 lines
11 KiB
Markdown
<span id="news"></span>
|
||
# Changelog
|
||
|
||
## 25.0.1 - 2026-02-02
|
||
|
||
### Bug Fixes
|
||
|
||
- Fix ASGI streaming responses (SSE) hanging: add chunked transfer encoding for
|
||
HTTP/1.1 responses without Content-Length header. Without chunked encoding,
|
||
clients wait for connection close to determine end-of-response.
|
||
|
||
### Changes
|
||
|
||
- Update celery_alternative example to use FastAPI with native ASGI worker and
|
||
uvloop for async task execution
|
||
|
||
### Testing
|
||
|
||
- Add ASGI compliance test suite with Docker-based integration tests covering HTTP,
|
||
WebSocket, streaming, lifespan, framework integration (Starlette, FastAPI),
|
||
HTTP/2, and concurrency scenarios
|
||
|
||
---
|
||
|
||
## 25.0.0 - 2026-02-01
|
||
|
||
### New Features
|
||
|
||
- **Dirty Arbiters**: Separate process pool for executing long-running, blocking
|
||
operations (AI model loading, heavy computation) without blocking HTTP workers
|
||
([PR #3460](https://github.com/benoitc/gunicorn/pull/3460))
|
||
- Inspired by Erlang's dirty schedulers
|
||
- Asyncio-based with Unix socket IPC
|
||
- Stateful workers that persist loaded resources
|
||
- New settings: `--dirty-app`, `--dirty-workers`, `--dirty-timeout`,
|
||
`--dirty-threads`, `--dirty-graceful-timeout`
|
||
- Lifecycle hooks: `on_dirty_starting`, `dirty_post_fork`,
|
||
`dirty_worker_init`, `dirty_worker_exit`
|
||
|
||
- **Per-App Worker Allocation for Dirty Arbiters**: Control how many dirty workers
|
||
load each app for memory optimization with heavy models
|
||
([PR #3473](https://github.com/benoitc/gunicorn/pull/3473))
|
||
- Set `workers` class attribute on DirtyApp (e.g., `workers = 2`)
|
||
- Or use config format `module:class:N` (e.g., `myapp:HeavyModel:2`)
|
||
- Requests automatically routed to workers with the target app
|
||
- New exception `DirtyNoWorkersAvailableError` for graceful error handling
|
||
- Example: 8 workers × 10GB model = 80GB → with `workers=2`: 20GB (75% savings)
|
||
|
||
- **HTTP/2 Support (Beta)**: Native HTTP/2 (RFC 7540) support for improved performance
|
||
with modern clients ([PR #3468](https://github.com/benoitc/gunicorn/pull/3468))
|
||
- Multiplexed streams over a single connection
|
||
- Header compression (HPACK)
|
||
- Flow control and stream prioritization
|
||
- Works with gthread, gevent, and ASGI workers
|
||
- New settings: `--http-protocols`, `--http2-max-concurrent-streams`,
|
||
`--http2-initial-window-size`, `--http2-max-frame-size`, `--http2-max-header-list-size`
|
||
- Requires SSL/TLS and h2 library: `pip install gunicorn[http2]`
|
||
- See [HTTP/2 Guide](guides/http2.md) for details
|
||
- New example: `examples/http2_gevent/` with Docker and tests
|
||
|
||
- **HTTP 103 Early Hints**: Support for RFC 8297 Early Hints to enable browsers to
|
||
preload resources before the final response
|
||
([PR #3468](https://github.com/benoitc/gunicorn/pull/3468))
|
||
- WSGI: `environ['wsgi.early_hints'](headers)` callback
|
||
- ASGI: `http.response.informational` message type
|
||
- Works with both HTTP/1.1 and HTTP/2
|
||
|
||
- **uWSGI Protocol for ASGI Worker**: The ASGI worker now supports receiving requests
|
||
via the uWSGI binary protocol from nginx
|
||
([PR #3467](https://github.com/benoitc/gunicorn/pull/3467))
|
||
|
||
### Bug Fixes
|
||
|
||
- Fix HTTP/2 ALPN negotiation for gevent and eventlet workers when
|
||
`do_handshake_on_connect` is False (the default). The TLS handshake is now
|
||
explicitly performed before checking `selected_alpn_protocol()`.
|
||
|
||
- Fix setproctitle initialization with systemd socket activation
|
||
([#3465](https://github.com/benoitc/gunicorn/issues/3465))
|
||
|
||
- Fix `Expect: 100-continue` handling: ignore the header for HTTP/1.0 requests
|
||
since 100-continue is only valid for HTTP/1.1+
|
||
([PR #3463](https://github.com/benoitc/gunicorn/pull/3463))
|
||
|
||
- Fix missing `_expected_100_continue` attribute in UWSGIRequest
|
||
|
||
- Disable setproctitle on macOS to prevent segfaults during process title updates
|
||
|
||
- Publish full exception traceback when the application fails to load
|
||
([#3462](https://github.com/benoitc/gunicorn/issues/3462))
|
||
|
||
- Fix ASGI: quick shutdown on SIGINT/SIGQUIT, graceful on SIGTERM
|
||
|
||
### Deprecations
|
||
|
||
- **Eventlet Worker**: The `eventlet` worker is deprecated and will be removed in
|
||
Gunicorn 26.0. Eventlet itself is [no longer actively maintained](https://eventlet.readthedocs.io/en/latest/asyncio/migration.html).
|
||
Please migrate to `gevent`, `gthread`, or another supported worker type.
|
||
|
||
### Changes
|
||
|
||
- Remove obsolete Makefile targets
|
||
([PR #3471](https://github.com/benoitc/gunicorn/pull/3471))
|
||
|
||
---
|
||
|
||
## 24.1.1 - 2026-01-24
|
||
|
||
### Bug Fixes
|
||
|
||
- Fix `forwarded_allow_ips` and `proxy_allow_ips` to remain as strings for backward
|
||
compatibility with external tools like uvicorn. Network validation now uses strict
|
||
mode to detect invalid CIDR notation (e.g., `192.168.1.1/24` where host bits are set)
|
||
([#3458](https://github.com/benoitc/gunicorn/issues/3458),
|
||
[PR #3459](https://github.com/benoitc/gunicorn/pull/3459))
|
||
|
||
---
|
||
|
||
## 24.1.0 - 2026-01-23
|
||
|
||
### New Features
|
||
|
||
- **Official Docker Image**: Gunicorn now publishes official Docker images to GitHub
|
||
Container Registry at `ghcr.io/benoitc/gunicorn`
|
||
- Based on Python 3.12 slim image
|
||
- Uses recommended worker formula (2 × CPU + 1)
|
||
- Configurable via environment variables
|
||
|
||
- **PROXY Protocol v2 Support**: Extended PROXY protocol implementation to support
|
||
the binary v2 format in addition to the existing text-based v1 format
|
||
- New `--proxy-protocol` modes: `off`, `v1`, `v2`, `auto`
|
||
- Works with HAProxy, AWS NLB/ALB, and other PROXY protocol v2 sources
|
||
|
||
- **CIDR Network Support**: `--forwarded-allow-ips` and `--proxy-allow-from` now
|
||
accept CIDR notation (e.g., `192.168.0.0/16`) for specifying trusted networks
|
||
|
||
- **Socket Backlog Metric**: New `gunicorn.socket.backlog` gauge metric reports
|
||
the current socket backlog size on Linux systems
|
||
|
||
- **InotifyReloader Enhancement**: The inotify-based reloader now watches newly
|
||
imported modules, not just those loaded at startup
|
||
|
||
### Bug Fixes
|
||
|
||
- Fix signal handling regression where SIGCLD alias caused errors on Linux
|
||
- Fix socket blocking mode on keepalive connections with async workers
|
||
- Handle `SSLWantReadError` in `finish_body()` to prevent worker hangs
|
||
- Log SIGTERM as info level instead of warning
|
||
- Print exception details to stderr when worker fails to boot
|
||
- Fix `unreader.unread()` to prepend data to buffer instead of appending
|
||
- Prevent `RecursionError` when pickling Config objects
|
||
|
||
---
|
||
|
||
## 24.0.0 - 2026-01-23
|
||
|
||
### New Features
|
||
|
||
- **ASGI Worker (Beta)**: Native asyncio-based ASGI support for running async Python
|
||
frameworks like FastAPI, Starlette, and Quart without external dependencies
|
||
- HTTP/1.1 with keepalive connections
|
||
- WebSocket support
|
||
- Lifespan protocol for startup/shutdown hooks
|
||
- Optional uvloop for improved performance
|
||
|
||
- **uWSGI Binary Protocol**: Support for receiving requests from nginx via
|
||
`uwsgi_pass` directive
|
||
|
||
- **Documentation Migration**: Migrated to MkDocs with Material theme
|
||
|
||
### Security
|
||
|
||
- **eventlet**: Require eventlet >= 0.40.3 (CVE-2021-21419, CVE-2025-58068)
|
||
- **gevent**: Require gevent >= 24.10.1 (CVE-2023-41419, CVE-2024-3219)
|
||
- **tornado**: Require tornado >= 6.5.0 (CVE-2025-47287)
|
||
|
||
---
|
||
|
||
## 23.0.0 - 2024-08-10
|
||
|
||
- minor docs fixes ([PR #3217](https://github.com/benoitc/gunicorn/pull/3217), [PR #3089](https://github.com/benoitc/gunicorn/pull/3089), [PR #3167](https://github.com/benoitc/gunicorn/pull/3167))
|
||
- worker_class parameter accepts a class ([PR #3079](https://github.com/benoitc/gunicorn/pull/3079))
|
||
- fix deadlock if request terminated during chunked parsing ([PR #2688](https://github.com/benoitc/gunicorn/pull/2688))
|
||
- permit receiving Transfer-Encodings: compress, deflate, gzip ([PR #3261](https://github.com/benoitc/gunicorn/pull/3261))
|
||
- permit Transfer-Encoding headers specifying multiple encodings. note: no parameters, still ([PR #3261](https://github.com/benoitc/gunicorn/pull/3261))
|
||
- sdist generation now explicitly excludes sphinx build folder ([PR #3257](https://github.com/benoitc/gunicorn/pull/3257))
|
||
- decode bytes-typed status (as can be passed by gevent) as utf-8 instead of raising `TypeError` ([PR #2336](https://github.com/benoitc/gunicorn/pull/2336))
|
||
- raise correct Exception when encounting invalid chunked requests ([PR #3258](https://github.com/benoitc/gunicorn/pull/3258))
|
||
- the SCRIPT_NAME and PATH_INFO headers, when received from allowed forwarders, are no longer restricted for containing an underscore ([PR #3192](https://github.com/benoitc/gunicorn/pull/3192))
|
||
- include IPv6 loopback address ``[::1]`` in default for [forwarded-allow-ips](reference/settings.md#forwarded_allow_ips) and [proxy-allow-ips](reference/settings.md#proxy_allow_ips) ([PR #3192](https://github.com/benoitc/gunicorn/pull/3192))
|
||
|
||
!!! note
|
||
- The SCRIPT_NAME change mitigates a regression that appeared first in the 22.0.0 release
|
||
- Review your [forwarded-allow-ips](reference/settings.md#forwarded_allow_ips) setting if you are still not seeing the SCRIPT_NAME transmitted
|
||
- Review your [forwarder-headers](reference/settings.md#forwarder_headers) setting if you are missing headers after upgrading from a version prior to 22.0.0
|
||
|
||
|
||
### Breaking changes
|
||
|
||
- refuse requests where the uri field is empty ([PR #3255](https://github.com/benoitc/gunicorn/pull/3255))
|
||
- refuse requests with invalid CR/LR/NUL in heade field values ([PR #3253](https://github.com/benoitc/gunicorn/pull/3253))
|
||
- remove temporary ``--tolerate-dangerous-framing`` switch from 22.0 ([PR #3260](https://github.com/benoitc/gunicorn/pull/3260))
|
||
- If any of the breaking changes affect you, be aware that now refused requests can post a security problem, especially so in setups involving request pipe-lining and/or proxies.
|
||
|
||
## 22.0.0 - 2024-04-17
|
||
|
||
- use `utime` to notify workers liveness
|
||
- migrate setup to pyproject.toml
|
||
- fix numerous security vulnerabilities in HTTP parser (closing some request smuggling vectors)
|
||
- parsing additional requests is no longer attempted past unsupported request framing
|
||
- on HTTP versions < 1.1 support for chunked transfer is refused (only used in exploits)
|
||
- requests conflicting configured or passed SCRIPT_NAME now produce a verbose error
|
||
- Trailer fields are no longer inspected for headers indicating secure scheme
|
||
- support Python 3.12
|
||
|
||
### Breaking changes
|
||
|
||
- minimum version is Python 3.7
|
||
- the limitations on valid characters in the HTTP method have been bounded to Internet Standards
|
||
- requests specifying unsupported transfer coding (order.md) are refused by default (rare.md)
|
||
- HTTP methods are no longer casefolded by default (IANA method registry contains none affected)
|
||
- HTTP methods containing the number sign (#) are no longer accepted by default (rare.md)
|
||
- HTTP versions < 1.0 or >= 2.0 are no longer accepted by default (rare, only HTTP/1.1 is supported)
|
||
- HTTP versions consisting of multiple digits or containing a prefix/suffix are no longer accepted
|
||
- HTTP header field names Gunicorn cannot safely map to variables are silently dropped, as in other software
|
||
- HTTP headers with empty field name are refused by default (no legitimate use cases, used in exploits)
|
||
- requests with both Transfer-Encoding and Content-Length are refused by default (such a message might indicate an attempt to perform request smuggling)
|
||
- empty transfer codings are no longer permitted (reportedly seen with really old & broken proxies)
|
||
|
||
|
||
### Security
|
||
|
||
- fix CVE-2024-1135
|
||
|
||
## History
|
||
|
||
- [2026](2026-news.md)
|
||
- [2024](2024-news.md)
|
||
- [2023](2023-news.md)
|
||
- [2021](2021-news.md)
|
||
- [2020](2020-news.md)
|
||
- [2019](2019-news.md)
|
||
- [2018](2018-news.md)
|
||
- [2017](2017-news.md)
|
||
- [2016](2016-news.md)
|
||
- [2015](2015-news.md)
|
||
- [2014](2014-news.md)
|
||
- [2013](2013-news.md)
|
||
- [2012](2012-news.md)
|
||
- [2011](2011-news.md)
|
||
- [2010](2010-news.md)
|