- SIGINT/SIGQUIT triggers immediate shutdown, skipping connection waits
- SIGTERM triggers graceful shutdown, waiting for connections
- Arbiter forwards SIGQUIT to workers if received during graceful shutdown
- Workers have 2s to exit cleanly after quick shutdown before SIGKILL
- Add get_app_workers_attribute() to read workers class attribute
- Update _parse_app_specs() to check class attribute when no config override
- Add Docker-based e2e tests for per-app worker allocation
- Add test apps: HeavyModelApp (workers=2), LightweightApp
- Add unit tests for get_app_workers_attribute function
- Add integration tests for class attribute detection
Allow dirty apps to specify how many workers should load them, enabling
significant memory savings for heavy applications like ML models.
- Add `workers` class attribute to DirtyApp (None = all workers)
- Add `parse_dirty_app_spec()` to parse "module:Class:N" format
- Add `DirtyNoWorkersAvailableError` for app-specific error handling
- Update DirtyArbiter with per-app worker tracking and routing
- Maintain backward compatibility when no dirty_apps configured
Example: 8 workers x 10GB model = 80GB RAM needed
With workers=2: 2 x 10GB = 20GB RAM (75% savings)
Configuration formats:
- Class attribute: `workers = 2` on DirtyApp subclass
- Config format: `module:class:N` (e.g., `myapp.ml:HugeModel:2`)
- Fix mobile side menu not displaying on iPad by keeping site_nav
content but hiding sidebar on desktop via CSS
- Fix broken links in asgi.md and guides/http2.md
- Add HTTP/2 guide to navigation
- Add explicit do_handshake() in base_async.py before ALPN check
when do_handshake_on_connect is False
- Mark eventlet worker as deprecated (removal in 26.0)
- Add HTTP/2 gevent example with Docker and tests
- Update documentation to reflect eventlet deprecation
- Remove eventlet websocket example (gevent version exists)
The ALPN fix ensures HTTP/2 works correctly with gevent and eventlet
workers when do_handshake_on_connect config is False (the default).
Without explicit handshake, selected_alpn_protocol() returns None.
- Reorder exception handlers: specific exceptions before ProtocolError
- Extract _wait_for_flow_control_window() to reduce return statements
- Refactor flow control waiting to avoid too-many-return-statements
- Add three tuning profiles: Conservative, Balanced, High Concurrency
- Document pros/cons and trade-offs for each HTTP/2 setting
- Add Linux kernel tuning parameters for high concurrency
- Add Docker-specific tuning recommendations
- Include benchmark results from h2load testing
- Send GOAWAY with correct error codes for protocol violations
- Handle StreamClosedError and FlowControlError gracefully
- Return False instead of raising for missing/closed streams
- Handle flow control window overflow per RFC 7540
- Fix reader race condition and add h2 exception handling
- Wait for WINDOW_UPDATE when flow control window is zero/negative
- Use h2 exception's error_code for INITIAL_WINDOW_SIZE violations
Add complete HTTP/2 example in examples/http2_features/:
- ASGI app showing priority access and trailer sending
- Test script using raw h2 library for HTTP/2 testing
- Docker setup for easy testing
- Documentation update referencing the example
The example demonstrates:
- Reading http.response.priority extension in ASGI scope
- Sending http.response.trailers messages
- Multiple streams on the same connection
- Guard early_hints callback against calls after response started
- Fix :authority precedence over Host header per RFC 9113 section 8.3.1
- Add nginx early_hints documentation link
- Use standard port 443 in curl examples
- Add pylint disable comments for global-statement in lazy import pattern
- Remove unnecessary pass statements in error subclasses
- Remove useless return None at end of _handle_request_received methods
- Add docs/content/guides/http2.md with comprehensive HTTP/2 guide
- Quick start and requirements
- Configuration options and settings
- Worker compatibility matrix
- HTTP 103 Early Hints usage for WSGI and ASGI
- Production deployment with nginx
- Troubleshooting guide
- Update docs/content/asgi.md to reflect HTTP/2 support
- Update docs/content/2026-news.md with 25.0.0 release featuring
HTTP/2 and Early Hints
- Regenerate docs/content/reference/settings.md with HTTP/2 settings
Implement HTTP 103 Early Hints as modern replacement for HTTP/2 Server Push.
This allows servers to send resource hints before the final response,
enabling browsers to preload assets in parallel.
WSGI support:
- Add wsgi.early_hints callback to environ dict
- Apps can call environ['wsgi.early_hints'](headers) to send 103 responses
- Silently ignored for HTTP/1.0 clients (don't support 1xx responses)
ASGI support:
- Handle http.response.informational message type
- Apps can await send({"type": "http.response.informational", "status": 103, ...})
HTTP/2 support:
- Add send_informational() method to HTTP2ServerConnection
- Add async send_informational() method to AsyncHTTP2Connection
- Wire up early hints in gthread worker for HTTP/2 requests
Includes unit tests and Docker integration tests for all protocols.
Integrate HTTP/2 support with gunicorn workers:
- sync worker: Add warning that HTTP/2 is not supported
- gthread worker: Full HTTP/2 support
- ALPN negotiation with explicit handshake for deferred SSL
- HTTP/2 connection lifecycle management
- Per-stream request handling with WSGI
- AsyncHTTP2Connection: Async version for ASGI workers
- Same features as sync version with async/await
- Proper flow control with chunked data sending
- ASGI worker: HTTP/2 support via AsyncHTTP2Connection
- AsyncWorker base: HTTP/2 connection handling
- tornado worker: Add warning that HTTP/2 is not supported
Also exports helper functions from http2 module.
The `test` and `coverage` targets rely on `setup.py` which was removed "about
10 years ago". There is apparently no interest in fixing them. This change
removes them to avoid confusion.
As per https://github.com/benoitc/gunicorn/issues/3386
Force early setproctitle initialization by calling getproctitle()
immediately after import. This ensures setproctitle captures the
argv/environ memory layout before systemd.listen_fds() modifies
the environment by removing LISTEN_FDS and LISTEN_PID.
Without this fix, if LISTEN_FDS is the first environment variable,
setproctitle fails to detect argv correctly and silently fails.
Fixes#3430
Tests the ASGI worker with direct HTTP requests without uWSGI protocol.
Includes tests for GET, POST, query strings, path handling, keepalive,
large bodies, and custom headers.
The wsgi.create() function expects req._expected_100_continue but
UWSGIRequest didn't have this attribute, causing an AttributeError.
Set to False since uWSGI runs behind a frontend server that handles
100-continue negotiation.