Benoit Chesneau 75b46bf6cf Add HTTP 103 Early Hints support (RFC 8297)
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.
2026-01-27 09:57:32 +01:00
..
2026-01-27 09:57:32 +01:00
2026-01-27 09:57:32 +01:00
2026-01-27 09:57:32 +01:00
2026-01-27 09:57:32 +01:00
2026-01-27 09:57:32 +01:00
2026-01-27 09:57:32 +01:00

HTTP/2 Docker Integration Tests
================================

This directory contains Docker-based integration tests for HTTP/2 support
in Gunicorn. These tests verify real HTTP/2 connections using actual HTTP/2
clients, both directly to Gunicorn and through an nginx reverse proxy.

Prerequisites
-------------

- Docker and Docker Compose
- OpenSSL (for generating test certificates)
- Python with ``httpx[http2]`` installed

Running the Tests
-----------------

1. Install test dependencies::

    pip install -e ".[testing]"

2. Generate SSL certificates (done automatically by tests, or manually)::

    cd tests/docker/http2
    openssl req -x509 -newkey rsa:2048 \
        -keyout certs/server.key \
        -out certs/server.crt \
        -days 1 -nodes \
        -subj "/CN=localhost"

3. Run the Docker integration tests::

    # From the project root
    pytest tests/docker/http2/ -v

   Or with Docker Compose manually::

    cd tests/docker/http2
    docker compose up -d
    pytest -v
    docker compose down -v

Test Categories
---------------

- **TestDirectHTTP2Connection**: Direct HTTP/2 connections to Gunicorn
- **TestConcurrentStreams**: HTTP/2 multiplexing with concurrent streams
- **TestHTTP2BehindProxy**: HTTP/2 through nginx reverse proxy
- **TestHTTP2Protocol**: ALPN negotiation and protocol fallback
- **TestHTTP2ErrorHandling**: Error responses over HTTP/2
- **TestHTTP2Headers**: HTTP/2 header handling
- **TestHTTP2Performance**: Performance-related tests

Architecture
------------

::

    +--------+     HTTP/2      +-----------+
    | Client | --------------> | Gunicorn  |
    +--------+                 | (port 8443)|
         |                     +-----------+
         |
         |     HTTP/2      +-------+    HTTPS     +-----------+
         +---------------> | nginx | -----------> | Gunicorn  |
                           | proxy |              | (port 8443)|
                           | (8444)|              +-----------+
                           +-------+

Files
-----

- ``docker-compose.yml`` - Service definitions
- ``Dockerfile.gunicorn`` - Gunicorn container with HTTP/2
- ``Dockerfile.nginx`` - nginx HTTP/2 proxy
- ``nginx.conf`` - nginx configuration
- ``app.py`` - Test WSGI application
- ``conftest.py`` - Pytest fixtures for Docker
- ``test_http2_docker.py`` - Integration tests

Troubleshooting
---------------

If tests fail to start:

1. Check Docker is running::

    docker info

2. Check service logs::

    cd tests/docker/http2
    docker compose logs gunicorn-h2
    docker compose logs nginx-h2

3. Verify certificates::

    openssl x509 -in certs/server.crt -text -noout

4. Test manually with curl::

    curl -k --http2 https://localhost:8443/
    curl -k --http2 https://localhost:8444/