NewYour coding agent can read the release notes before it upgrades.Set up the MCP server →
PyPI · #265 most downloaded on PyPI
WSGI HTTP Server for UNIX
Last release 1 months ago
24 Aug 2026
Release timing varies
gaps range from 9 days to 2.3 years
Most releases are documented
notes for 39 of the last 60 stable releases
Nothing withdrawn
no release was ever pulled
17 years old
100 releases · first in 2010
Cleartext HTTP/2 lands, and an HTTP/2 security fix.
Cleartext HTTP/2 lands, and an HTTP/2 security fix.
http2_cleartext accepts prior-knowledge, upgrade, both or off (the
default). Prior knowledge serves a connection that opens with the HTTP/2
preface; upgrade honours an HTTP/1.1 Upgrade: h2c request. Both work on the
gthread, gevent and asgi workers.
This is for deployments where TLS is terminated by a proxy that speaks HTTP/2
upstream, so the hop into gunicorn no longer drops to HTTP/1.1. Only peers in
forwarded_allow_ips are considered; everyone else is served HTTP/1.x exactly
as if the setting were off. Each mechanism is enabled separately, so turning one
on does not turn the other on.
Do not expose a cleartext HTTP/2 port to the internet.
HTTP2Request built its headers straight from the stream, so nothing the HTTP/1
path enforces applied over HTTP/2: the underscore and header_map policy,
duplicate Host and Content-Type, control characters in values, and the
forwarded_allow_ips trust gate. An untrusted client could set SCRIPT_NAME
and forge HTTP_* entries in the WSGI environ, and decide wsgi.url_scheme
through :scheme. Both request classes now share one policy mixin, and the
scheme comes from the transport.
If you serve HTTP/2, this is the reason to upgrade.
WSGI responses were buffered whole before anything was sent; they stream now.
HEAD, 204 and 304 no longer carry a body. Events read while blocked on a
flow-control window were discarded, losing requests and body data outright.
sendfile() is refused on HTTP/2 responses rather than bypassing framing.
On the ASGI worker with the fast parser, any request carrying an Upgrade
header reached the application with an empty body, whatever the header's value
and with HTTP/2 switched off entirely. Fixed in gunicorn_h1c 0.6.9, which the
fast extra now requires.
Full changelog: https://gunicorn.org/news/
One column per quarter.
WSGI HTTP/2 responses were buffered whole : both WSGI workers collected the entire body in memory before sending anything. They write through an HTTP2Response now, so the body leaves as it is produced ( #3709 ).
No-body responses carried a body over HTTP/2 : HEAD, 204 and 304 sent application body bytes on all three workers, while the HTTP/1 path had always dropped them per RFC 9110. They no longer do ( #3709 , #3710 ).
Events lost during flow-control waits : while blocked waiting for a WINDOW_UPDATE, both HTTP/2 connections read from the socket and discarded every event that was not a stream reset or connection termination, losing requests and body data outright. They are queued for the main loop now ( #3709 , #3710 ).
sendfile() on HTTP/2 : it was guarded by cfg.is_ssl , which covered HTTP/2 only for as long as HTTP/2 implied TLS. It is refused on HTTP/2 responses directly, so cleartext cannot bypass HTTP/2 framing ( #3709 ).
Request bodies dropped on Upgrade requests : on the ASGI worker with the fast parser, any request carrying an Upgrade header reached the application with an empty body, whatever the header's value and with HTTP/2 switched off. The parser treated the header as meaning the rest of the connection was no longer HTTP/1, so it never read the body it had just been told the length of. Fixed in gunicorn_h1c 0.6.9, which the requirement below now pins ( #3711 ).
Describe http_parser in its own terms rather than as an ASGI-only setting; it applies to the WSGI workers too. Thanks to @methane ( #3704 ).
Correct the default control socket path in the gunicorn.c guide. Thanks to @cormier ( #3703 ).
State the supported Python version as 3.10+ in the README, matching requires-python . Thanks to @Rotzbua ( #3712 ).
Point CONTRIBUTING at the mkdocs settings reference instead of the retired Sphinx path. Thanks to @melbinjp ( #3690 ).
Fix the sponsor logo path on the sponsor page ( #3700 ).
tornado , h2 , setuptools and pymdown-extensions permitted vulnerable versions and now require the first clean release; pytest and httpx were unpinned…
reload_extra_files: entries containing *, ? or [ui/*/config.json watches every view's config** recurses. A pattern matchingtornado, h2, setuptools andpymdown-extensions permitted vulnerable versions and now require the firstpytest and httpx were unpinned and now carry floors. Thetornado example pinned tornado<6, which was both the source of several>=6.5.0 the tornado worker needs, so theSIGHUP did not reload the logger configuration: Arbiter.reload()
re-read the configuration file but kept using the logger built at startup,
calling only reopen_files() on its existing handlers. Changes to
logconfig, logconfig_dict, logconfig_json and loglevel were ignored
until a full restart, which in containers meant replacing the pod. The
existing logger now re-runs its setup on reload, so new handlers, formats
and levels take effect while the process identity and its listeners are
preserved, and re-running the setup no longer stacks duplicate syslog
handlers. An invalid log configuration on reload is not fatal either: the
error is reported on stderr, the previous working configuration is restored
and the master keeps running with it
(#3353).
Truncated chunked bodies accepted: RFC 9112 section 7.1.2 ends a chunked
body with 0 CRLF CRLF, the second CRLF being the mandatory empty trailer
section. ChunkedReader.parse_chunk_size() swallowed the NoMoreData raised
while scanning for it, so a body cut short right after the last chunk line was
treated as complete instead of rejected. It now raises
ChunkMissingTerminator
(#3382,
#3685).
--spew crashed on dynamically generated code: the trace hook indexed the
2-tuple returned by inspect.getsourcelines() by line number rather than
indexing the list of lines, so a frame with no __file__ raised
AttributeError: 'int' object has no attribute 'rstrip' on line 1 and
IndexError beyond it. The tuple is now unpacked and offset by the source's
starting line (#3344,
#3495).
Duplicate Host and Content-Type headers accepted: RFC 9110 section 5.3
allows only one of each, and a repeat cannot be merged into a list, so the
message means different things to gunicorn and to anything downstream. Both
are now rejected with InvalidHeader. The check lives in the policy hook
shared by both parsers, so the pure-Python and fast parsers agree. Duplicate
Content-Length was already rejected and is unchanged
(#3366,
#3548).
Non-worker children reported as failed workers: reap_workers() reaps
every child through waitpid(-1), including processes the kernel reparented
onto gunicorn when it runs as PID 1 in a container, but it logged the exit
status before checking whether the pid was ever a worker. An unrelated process
produced Worker (pid:N) exited with code M and triggered alerts. More
seriously, such a process exiting with code 3 or 4 raised HaltServer and shut
the server down. Ownership is now established first: the dirty arbiter is
reported as itself, unknown children are reaped silently at debug level, and
only real workers can halt the server
(#3220,
#3566).
Dirty arbiter exits were invisible on SIGCHLD: handle_chld() called
reap_workers() first, whose waitpid(-1) claimed the dirty arbiter before
reap_dirty_arbiter() could identify it, so the latter always hit ECHILD and
its reporting never ran. The dirty arbiter is now reaped first, and
reap_workers() recognises it if it exits mid-loop.
Dirty arbiter returned stale responses after a worker timeout: when a
request reached dirty_timeout the arbiter answered the client with a timeout
error but kept the worker connection open. The worker's late response was then
the first message waiting on that socket, so the next request routed to the
same worker received the previous request's result, and every request after it
stayed one response behind. The connection is now closed on timeout, so the
late answer is discarded with it
(#3626).
ASGI connection count leaked on server-initiated close: nr_conns was
only decremented in connection_lost(), behind a guard keyed on the same
flag _close_transport() sets first. Every close the server started (a
Connection: close response, a keepalive timeout, an error abort) leaked one
count, so ASGIWorker._shutdown() ran the full graceful_timeout and warned
about connections that were already gone. The guard now uses its own flag, so
the decrement and the rest of the cleanup run exactly once whichever side
closes first (#3661).
Inotify reloader on cwd-relative extra files: reload_extra_files entries
with no directory part (for example .env) produced an empty dirname, and
watching it raised InotifyError with ENOENT. The current directory is now
watched as . (#3377,
#3667).
StatsD zero-valued metrics: gauges, counters, histograms and timers
reporting 0 were silently dropped because the value was tested for
truthiness. Only None is skipped now
(#3676).
Spurious no-body warning from sendfile(): a HEAD, 204 or 304 response
served through sendfile() warned about dropped body bytes even when the
file was empty and nothing was dropped. It now warns only when there are
bytes to drop, matching write()
(#3684).
Bare except in the gevent websocket example: narrowed to
except Exception (#3683).
ASGI receive() cancellation: Let asyncio.CancelledError propagate
from BodyReceiver instead of swallowing it and returning
http.disconnect. Frameworks that cancel their disconnect listener after
the response completes (Django) no longer see the cancel masked, so
request_finished fires and close_old_connections() runs. Fixes idle
database connections leaking since 25.1.0
(#3627,
#3654).
Control socket leak on SIGHUP reload: The control thread is now marked
ready once its loop and server are live, and the stop paths wait on that
readiness before scheduling shutdown. Reloads no longer leak one thread and
its selector fd plus unix socket per worker, which eventually raised
"too many open files"
(#3648).
WSGI body framing on HEAD/1xx/204/304: Mirror the ASGI strip-and-warn
behavior on the WSGI path. Content-Length is stripped on 1xx/204 per
RFC 9110 section 6.4.2, body bytes are dropped for no-body responses in
both write() and sendfile(), and a single warning is logged per request
(#3413).
Arbiter.reap_workers()packaging is no longer a runtime dependency: it was only ever imported by
the gevent worker, to compare gevent's version. It moved to the gevent and
testing extras, so a plain pip install gunicorn pulls in nothing
(#3643).
Fast HTTP Parser: Require gunicorn_h1c >= 0.6.6, which rejects duplicate
Host and Content-Type headers in the C parser itself. Gunicorn already
refuses them on both the WSGI and ASGI paths, so this changes nothing that is
reachable; it moves the rejection to where the bytes are read and lets the
ASGI corpus exercise those cases against the fast parser directly.
Full changelog: https://gunicorn.org/2026-news/
Eventlet worker removed : The eventlet worker class has been dropped. Migrate to gevent , gthread , or tornado .
eventlet worker class has been dropped. Migrate to gevent, gthread, or tornado.authority-form request-target outside CONNECTasterisk-form request-target outside OPTIONSrelative-reference request-targetsContent-Length list form (RFC 9112 section 6.3)finish_body byte cap_body_receiver alive across the keepalive smuggling gate so pipelined requests cannot re-enter a closed bodyproxy_allow_ips and tighten v1/v2 parsing in the ASGI callback parser.Content-Length on HEAD and 304 responses (#3621)_handle_stream_ended to set _body_complete in the async HTTP/2 handler so request bodies finalize correctly on stream endInvalidChunkExtension mapping and fast-parser support in ASGI tests (#3565)Transfer-Encoding: chunked to 100-Continue interim responses.text key is Noneearly_hints callback to match process_headers; pass only the header name to InvalidHeader (#3588).accept())Transfer-Encoding header for BlackSheep streamingBodyReceiver._closed into separate transport and body-wait flags for clearer keepalive/EOF semantics.gunicorn_h1c >= 0.6.5. Drop the last python_only test markers; the C extension is now used wherever available (CPython only; PyPy continues to use the Python parser).h2 and uvloop to the testing extra; remove eventlet.docker/setup-qemu-action, docker/setup-buildx-action, docker/login-action, docker/build-push-action, and docker/metadata-action to current major versions.Full changelog: 25.3.0...26.0.0
HTTP/2 ASGI Body Duplication : Fix request body being received twice in HTTP/2 ASGI requests, causing JSON parsing errors with "Extra data" messages
HTTP/2 ASGI Body Duplication: Fix request body being received twice in HTTP/2
ASGI requests, causing JSON parsing errors with "Extra data" messages
(#3558)
ASGI Chunked EOF Handling: Add finish() method to callback parser to handle
chunked encoding edge case where connection closes before final CRLF after zero-chunk
HTTP/2 Documentation: Fix http_protocols examples to use comma-separated string
instead of list syntax (#3561)
Chunked Encoding: Reject chunk extensions containing bare CR bytes per RFC 9112
(#3556)
Request Line Limit: Fix --limit-request-line 0 to mean unlimited as documented,
instead of using default maximum. Works with both Python and fast C parser.
(#3563)
Fast HTTP Parser: Update to gunicorn_h1c >= 0.6.3 for asgi_headers property
and InvalidChunkExtension validation for bare CR rejection
ASGI PROXY Protocol: Add PROXY protocol v1/v2 support to callback parser
Docker Images: Update to Python 3.14
Fast HTTP Parser (gunicorn_h1c 0.4.1) : Integrate new exception types and limit parameters from gunicorn_h1c 0.4.1 for both WSGI and ASGI workers
http_parser='fast'auto mode if version not metuWSGI Async Workers: Fix InvalidUWSGIHeader: incomplete header error when using gevent or gthread workers with uwsgi protocol behind nginx. (#3552, PR #3554)
FileWrapper Iterator Protocol: Add __iter__ and __next__ methods to FileWrapper for full PEP 3333 compliance. (#3396, PR #3550)
bytearray buffer operationsbytearray.find() directly instead of converting to bytes firstlist.pop(0) (O(1) vs O(n))Fast HTTP Parser (gunicorn_h1c 0.6.0) : Integrate new exception types and limit parameters from gunicorn_h1c 0.6.0 for both WSGI and ASGI workers
Requires gunicorn_h1c >= 0.6.0 for http_parser='fast'
Falls back to Python parser in auto mode if version not met
Proper HTTP status codes for limit errors (414, 431)
uWSGI Async Workers : Fix InvalidUWSGIHeader: incomplete header error when using gevent or gthread workers with uwsgi protocol behind nginx. ( #3552 , PR #3554 )
FileWrapper Iterator Protocol : Add iter and next methods to FileWrapper for full PEP 3333 compliance. Previously only supported old-style getitem iteration which broke code explicitly using iter() or next() . ( #3396 , PR #3550 )
ASGI HTTP Parser Optimizations : Improve ASGI worker HTTP parsing performance
Callback-based parsing with direct bytearray buffer operations
Use bytearray.find() directly instead of converting to bytes first
Use index-based iteration for header parsing instead of list.pop(0) (O(1) vs O(n))
Control Interface (gunicornc) : Add interactive control interface for managing running Gunicorn instances, similar to birdc for BIRD routing daemon (
Control Interface (gunicornc): Add interactive control interface for managing
running Gunicorn instances, similar to birdc for BIRD routing daemon
(PR #3505)
show all/workers/dirty/config/stats/listenersworker add/remove/kill, dirty add/removereload, reopen, shutdown--control-socket, --control-socket-mode, --no-control-socketgunicornc for connecting to control socketDirty Stash: Add global shared state between workers via dirty.stash
(PR #3503)
Dirty Binary Protocol: Implement efficient binary protocol for dirty arbiter IPC
using TLV (Type-Length-Value) encoding
(PR #3500)
Dirty TTIN/TTOU Signals: Add dynamic worker scaling for dirty arbiters
(PR #3504)
Fix passing maxsplit in re.split() as positional argument (deprecated in Python 3.13)
Full Changelog: 25.0.2...25.0.3
Fix RuntimeError when StopIteration is raised inside ASGI response body coroutine (PEP 479 compliance)
Fix deprecation warning for passing maxsplit as positional argument in re.split() (Python 3.13+)
Fix ASGI concurrent request failures through nginx proxy
Full Changelog: 25.0.1...25.0.2
Fix ASGI concurrent request failures through nginx proxy by normalizing sockaddr tuples to handle both 2-tuple (IPv4) and 4-tuple (IPv6) formats ( PR #3485 )
Fix graceful disconnect handling for ASGI worker to properly handle client disconnects without raising exceptions ( PR #3485 )
Fix lazy import of dirty module for gevent compatibility - prevents import errors when concurrent.futures is imported before gevent monkey-patching ( PR #3483 )
Refactor: Extract _normalize_sockaddr utility function for consistent socket address handling across workers
Add license headers to all Python source files
Update copyright year to 2026 in LICENSE and NOTICE files
Fix ASGI streaming responses (SSE) hanging: add chunked transfer encoding for HTTP/1.1 responses without Content-Length header. Without chunked encodi
Eventlet Worker : The eventlet worker is deprecated and will be removed in Gunicorn 26.0. Eventlet itself is no longer actively maintained. Please mig…
Dirty Arbiters: Separate process pool for executing long-running, blocking
operations (AI model loading, heavy computation) without blocking HTTP workers
(PR #3460)
--dirty-app, --dirty-workers, --dirty-timeout,--dirty-threads, --dirty-graceful-timeouton_dirty_starting, dirty_post_fork,dirty_worker_init, dirty_worker_exitPer-App Worker Allocation for Dirty Arbiters: Control how many dirty workers
load each app for memory optimization with heavy models
(PR #3473)
workers class attribute on DirtyApp (e.g., workers = 2)module:class:N (e.g., myapp:HeavyModel:2)DirtyNoWorkersAvailableError for graceful error handlingworkers=2: 20GB (75% savings)HTTP/2 Support (Beta): Native HTTP/2 (RFC 7540) support for improved performance
with modern clients (PR #3468)
--http-protocols, --http2-max-concurrent-streams,--http2-initial-window-size, --http2-max-frame-size, --http2-max-header-list-sizepip install gunicorn[http2]examples/http2_gevent/ with Docker and testsHTTP 103 Early Hints: Support for RFC 8297 Early Hints to enable browsers to
preload resources before the final response
(PR #3468)
environ['wsgi.early_hints'](headers) callbackhttp.response.informational message typeuWSGI Protocol for ASGI Worker: The ASGI worker now supports receiving requests
via the uWSGI binary protocol from nginx
(PR #3467)
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)
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)
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)
Fix ASGI: quick shutdown on SIGINT/SIGQUIT, graceful on SIGTERM
eventlet worker is deprecated and will be removed ingevent, gthread, or another supported worker type.Fix forwarded_allow_ips and proxy_allow_ips to remain as strings for backward compatibility with external tools like uvicorn. Network validation now u
forwarded_allow_ips and proxy_allow_ips to remain as strings for backward192.168.1.1/24 where host bits are set)Full Changelog: 24.1.0...24.1.1
Official Docker Image: Gunicorn now publishes official Docker images to GitHub Container Registry (PR #3454)
Official Docker Image: Gunicorn now publishes official Docker images to GitHub Container Registry (PR #3454)
ghcr.io/benoitc/gunicornPROXY Protocol v2 Support: Extended PROXY protocol implementation to support the binary v2 format in addition to the existing text-based v1 format (PR #3451)
--proxy-protocol modes: off, v1, v2, autoauto mode (default when enabled) detects v1 or v2 automaticallyCIDR Network Support: --forwarded-allow-ips and --proxy-allow-from now accept CIDR notation (e.g., 192.168.0.0/16) for specifying trusted networks (PR #3449)
Socket Backlog Metric: New gunicorn.socket.backlog gauge metric reports the current socket backlog size on Linux systems (PR #3450)
InotifyReloader Enhancement: The inotify-based reloader now watches newly imported modules, not just those loaded at startup (PR #3447)
finish_body() for faster timeout detection on slow or abandoned connections (PR #3453)SSLWantReadError in finish_body() to prevent worker hangs during SSL renegotiation (PR #3448)unreader.unread() to prepend data to buffer instead of appending (PR #3442)RecursionError when pickling Config objects (PR #3441)raise from in glogging.py (PR #3440)pip install gunicorn==24.1.0
Or use the official Docker image:
docker pull ghcr.io/benoitc/gunicorn:24.1.0
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
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
eventlet: Require eventlet >= 0.40.3 (CVE-2021-21419, CVE-2025-58068)
ASGI Worker (Beta): Native asyncio-based ASGI support for running async Python frameworks like FastAPI, Starlette, and Quart without external dependencies
uWSGI Binary Protocol: Support for receiving requests from nginx via uwsgi_pass directive
Documentation Migration: Migrated to MkDocs with Material theme
pip install gunicorn==24.0.0
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 p…
Gunicorn 23.0.0 has been released. This version improve HTTP 1.1. support and which improve safety
You're invited to upgrade asap your own installation.
minor docs fixes (3217, 3089, 3167)
worker_class parameter accepts a class (3079)
fix deadlock if request terminated during chunked parsing (2688)
permit receiving Transfer-Encodings: compress, deflate, gzip (3261)
permit Transfer-Encoding headers specifying multiple encodings. note: no parameters, still (3261)
sdist generation now explicitly excludes sphinx build folder (3257)
decode bytes-typed status (as can be passed by gevent) as utf-8 instead of raising TypeError (2336)
raise correct Exception when encounting invalid chunked requests (3258)
the SCRIPT_NAME and PATH_INFO headers, when received from allowed forwarders, are no longer restricted for containing an underscore (3192)
include IPv6 loopback address [::1] in default for forwarded-allow-ips and proxy-allow-ips (3192)
** NOTE **
The SCRIPT_NAME change mitigates a regression that appeared first in the 22.0.0 release
Review your forwarded-allow-ips setting if you are still not seeing the SCRIPT_NAME transmitted
Review your 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 (3255)
refuse requests with invalid CR/LR/NUL in heade field values (3253)
remove temporary --tolerate-dangerous-framing switch from 22.0 (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.
Fix CVE-2024-1135
Gunicorn 22.0.0 has been released. This version fix the numerous security vulnerabilities. You're invited to upgrade asap your own installation.
Gunicorn 22.0.0 has been released. This version fix the numerous security vulnerabilities. You're invited to upgrade asap your own installation.
Changes:
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) are refused by default (rare)
- 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)
- 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
Gunicorn 21.2.0 has been released. This version fix the issue introduced in the threaded worker.
Gunicorn 21.2.0 has been released. This version fix the issue introduced in the threaded worker.
Changes:
21.2.0 - 2023-07-19
===================
fix thread worker: revert change considering connection as idle .
*** NOTE ***
This is fixing the bad file description error.
gunicorn 21.1.0 has been released. This version fix the issue introduced in the threaded worker.
gunicorn 21.1.0 has been released. This version fix the issue introduced in the threaded worker.
Gunicorn 21 is out with miscellaneous changes. Enjoy!
Gunicorn 21 is out with miscellaneous changes. Enjoy!
We made this release major to start our new release cycle. More info will be provided on our discussion forum.
fix documentation build
support python 3.11 fix gevent and eventlet workers fix threads support (gththread): improve performance and unblock requests SSL: noaw use SSLContext object HTTP parser: miscellaneous fixes remove unecessary setuid calls fix testing improve logging miscellaneous fixes to core engine
Full Changelog: https://github.com/benoitc/gunicorn/compare/21.0.0...21.0.1
Nothing published for this version
document WEB_CONCURRENCY is set by, at least, Heroku
wsgi_app--timeout = 0$PORT environment variablesocket.sendfile instead of os.sendfileInotifyError when a file
is added to the working directory--log-dict-config CLI flag because it never had a working format
(the logconfig_dict setting in configuration files continues to work)** Breaking changes **
** Documentation **
** Others **
fix binding a socket using the file descriptor
bdist_rpm buildfixed load of a config file without a Python extension
socketfromfd.fromfd when defaults are not setnote: we now warn when we load a config file without Python Extension
fixed the way the config module is loaded. __file__ is now available
__file__ is now availablewsgi.input_terminated. It is always true.__repr__ method to Config instancesocketfromfd.fromfd functionrequest smuggling <https://portswigger.net/research/http-desync-attacks-request-smuggling-reborn>_RecursionError.note this release add official support for applications loaded from a factory function as documented in Flask and other places.
Nothing published for this version
Fixed fdopen RuntimeWarning in Python 3.8
fdopen RuntimeWarning in Python 3.8StopIteration and KeyboardInterrupt exceptions with same body together in Arbiter.run()setproctitle module to extras_require in setup.pyutil.import_moduletypes.SimpleNamespace in tests utilsSourceFileLoader instead instead of execfile_importlib instead of __import__ and eval`datadog <https://www.datadoghq.com>_ tags for statsd metricsparse_address util added testfutures import in gthread modulewsgi.input_terminated extensiontornado <https://www.tornadoweb.org/>_ 5 and 6 support--bind to open file descriptors--ssl-version flagResourceWarning when reading a Python config moduleInotifyReloadeder: handle module.__file__ is None/dev/shm as a convenient alternative to making your own tmpfs mount in fchmod FAQ--max-requests documentationNothing published for this version
fix: address a regression that prevented syslog support from working (#1668, #1773)
REMOTE_ADDR on versions of Python 3 affected by
Python Issue 30205 <https://bugs.python.org/issue30205>_
(#1755, #1796)AttributeError when --reload is not passed
in case of a :exc:SyntaxError raised from the WSGI application.
(#1805, #1806)gunicorn.workers.async was renamed to
gunicorn.workers.base_async since async is now a reserved word
in Python 3.7.
(#1527)fix: secure scheme headers when bound to a unix socket (#1766, #1767)
deprecation: the gaiohttp worker is deprecated, see the worker-class documentation for more information (#1338, #1418, #1569)
--reload-extra-file
(#1527)--logging-config-dict
(#1087, #1110, #1602)--config flag in the GUNICORN_CMD_ARGS environment
variable (#1576, #1581)SO_REUSEPORT by default and add the --reuse-port setting
(#1553, #1603, #1669)inotify on MacOS no longer breaks the reloader
(#1540, #1541)TypeError when SO_REUSEPORT is not available
(#1501, #1491)--umask=0 correctly (#1622, #1632)/ in request path (#1512, #1511)USR1 signal to a new greenlet under gevent
(#1645, #1651)USR1 signal using handler._open to
support subclasses of FileHandler (#1739, #1742)gaiohttp worker is deprecated, see the
worker-class documentation for more information
(#1338, #1418, #1569)fix: continue if SO_REUSEPORT seems to be available but fails
The previously deprecated gunicorn_django command has been removed. Use the [](http://docs.gunicorn.org/en/stable/run.html#gunicorn-cmd) command-line…
gunicorn_django command has been removed.
Use the command-line interface instead.django_settings setting has been removed.
Use the raw-env setting instead.ssl.PROTOCOL_TLSv1 to ssl.PROTOCOL_SSLv23.child_exit callback (#1394)improvement of the binary upgrade behaviour using USR2: remove file lockin
--capture-output setting to capture stdout/stderr tot the log file (#1271)sendfile() via the SENDFILE` environment variable (#1252)fix: Ensure response to HEAD request won't have message body
== 19.5.0 ==
=== Core ===
=== Workers ===
=== Logging ===
=== Documentation ===
=== Tests ===
fix: NameError fileno in gunicorn.http.wsgi
== 19.4.5 ==
fix: check if a fileobject can be used with sendfile(2)
== 19.4.4 ==
fix: don't check if a file is writable using os.stat with SELINUX
== 19.4.3 ==
improvement: handle HaltServer in manage_workers
== 19.4.2 ==
=== Core ===
=== Logging ===
=== Documentation ===
=== Testing ===
== 19.4.1 == - fix tornado worker
== 19.4.1 ==
Nothing published for this version
Nothing published for this version
Gunicorn 19.2.1 is a patch release with fixes.
Gunicorn 19.2.1 is a patch release with fixes.
Full changelog is available here:
https://github.com/benoitc/gunicorn/compare/19.2...19.2.1
You can find the documentation here:
http://docs.gunicorn.org/en/19.2.1/
Latest version is also available on Pypi:
https://pypi.python.org/pypi/gunicorn/19.2.1
Nothing published for this version
Gunicorn 19.1.1 is a minor release with some fixes.
Gunicorn 19.1.1 is a minor release with some fixes.
PyTest class in setup.py.Full changelog is available here:
https://github.com/benoitc/gunicorn/compare/19.1...19.1.1
You can find the documentation here:
http://docs.gunicorn.org/en/19.1.1/
Latest version is also available on Pypi:
https://pypi.python.org/pypi/gunicorn/19.1.1
Nothing published for this version
Nothing published for this version
With this release the commands `gunicorn_django` and `gunicorn_paster` are now deprecated. They will be removed in the next major release R19. You can…
Gunicorn 18.0 is a major release with new features and fixes. With this release the commands gunicorn_django and gunicorn_paster are now deprecated. They will be removed in the next major release R19. You can now easily launch your django or paster applications by only using the gunicorn command line. See the documentation and the following changes for more more information.
-e/--env command line argument to pass an environment variables to
gunicorn--chdir command line argument to specified directory
before apps loading.--paste command line argument to set the paster config filegunicorn_django is now deprecated. You should now
run your application with the WSGI interface installed with your project (see
https://docs.djangoproject.com/en/1.4/howto/deployment/wsgi/gunicorn/) for
more infos.gunicorn_paste is deprecated. You now should use
the new --paste argument to set the configuration file of your paster
application.Full changelog is available here:
https://github.com/benoitc/gunicorn/compare/17.5...18.0
You can find the documentation here:
http://docs.gunicorn.org/en/18.0/
Latest version is also available on Pypi:
https://pypi.python.org/pypi/gunicorn/18.0
Gunicorn 17.5 is a service release with mostly a number of small corrections and user contributions. But there are some new functions worth mentioning
Gunicorn 17.5 is a service release with mostly a number of small corrections and user contributions. But there are some new functions worth mentioning as well:
gunicorn command.Full changelog is available here:
https://github.com/benoitc/gunicorn/compare/0.17.4...17.5
You can find the documentation here:
http://docs.gunicorn.org/en/17.5/
Latest version is also available on Pypi:
https://pypi.python.org/pypi/gunicorn/17.5
With this release, the versioning of Gunicorn is changing. Gunicorn is stable since a long time and there is no point to release a "1.0" now. It should have been done since a long time. 0.17 really meant it was the 17th stable version. From the beginning we have only 2 kind of releases:
So from now we will apply the following versioning <major>.<service>. For example 17.5 is a service release.
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Your coding agent can read these notes before it upgrades. Set up the MCP server →