Skip to main content

channels-webtransport

Experimental WebTransport support for Django Channels, backed by PyWebTransport.

This is deliberately a thin package: it translates a PyWebTransport session into a small, versioned ASGI extension and provides a Channels-style async consumer. It is suitable for experimentation and internal projects while the WebTransport ASGI protocol is still being designed. It is not yet a stable public protocol.

Install

The package requires Python 3.12 or newer.

uv add channels-webtransport

For a local checkout:

uv add --editable ../channels-webtransport

Configure Django

Add the package to INSTALLED_APPS so Django discovers the management command:

INSTALLED_APPS = [
    # ...
    "channels",
    "channels_webtransport",
]

ASGI_APPLICATION = "project.asgi.application"

WEBTRANSPORT = {
    "HOST": "127.0.0.1",
    "PORT": 4433,
    "CERTFILE": BASE_DIR / "certs" / "localhost.crt",
    "KEYFILE": BASE_DIR / "certs" / "localhost.key",
    # Any remaining PyWebTransport ServerConfig keyword arguments:
    "OPTIONS": {},
}

The same root ASGI application can route HTTP, WebSocket, and WebTransport scopes:

# project/asgi.py
import os

from channels.routing import ProtocolTypeRouter, URLRouter
from django.core.asgi import get_asgi_application
from django.urls import path

from app.consumers import EchoWebTransportConsumer

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "project.settings")

application = ProtocolTypeRouter(
    {
        "http": get_asgi_application(),
        "webtransport": URLRouter([path("wt/echo/", EchoWebTransportConsumer.as_asgi())]),
    }
)

Create a consumer in the usual Channels style:

# app/consumers.py
from channels_webtransport import AsyncWebTransportConsumer


class EchoWebTransportConsumer(AsyncWebTransportConsumer):
    async def receive_datagram(self, data: bytes) -> None:
        await self.send_datagram(data)

    async def receive_stream(self, stream: int, data: bytes, end_stream: bool) -> None:
        await self.send_stream(stream, data, end_stream=end_stream)

Then run the WebTransport listener alongside the normal HTTP/ASGI server:

uv run python manage.py runwebtransport

runwebtransport owns a separate HTTP/3-over-UDP listener. Your normal Daphne/Uvicorn process continues to serve HTTP and WebSocket traffic. Command-line flags override settings:

uv run python manage.py runwebtransport \
  --host 127.0.0.1 --port 4433 \
  --certificate certs/localhost.crt --private-key certs/localhost.key

Local TLS and browser testing

WebTransport requires HTTPS and HTTP/3. Generate a short-lived development certificate with PyWebTransport:

mkdir -p certs
uv run python -c \
  'from pywebtransport.utils import generate_self_signed_cert; generate_self_signed_cert(hostname="localhost", output_dir="certs", validity_days=13)'

For a Python client, pass ssl.CERT_NONE only in local tests. Browsers require the SHA-256 certificate hash in serverCertificateHashes for a self-signed certificate, and the certificate must be valid for no more than 14 days. Chromium-based browsers have the broadest development support. See examples/browser_echo.html for a client.

Serve the example from localhost, paste the certificate hash into it, and open http://localhost:8000/browser_echo.html:

uv run python -m http.server --directory examples 8000

Consumer test helper

Most consumer logic can be tested without opening a UDP socket:

from channels_webtransport.testing import WebTransportCommunicator


async def test_echo():
    communicator = WebTransportCommunicator(EchoWebTransportConsumer.as_asgi(), "/wt/echo/")
    connected, _ = await communicator.connect()
    assert connected

    await communicator.send_datagram(b"hello")
    assert await communicator.receive_datagram() == b"hello"
    await communicator.disconnect()

The package test suite also starts a real loopback QUIC server and client:

uv run pytest

Experimental ASGI contract

The scope has type="webtransport", ordinary HTTP request fields, and scope["webtransport"]["spec_version"] == "0.1".

Messages received by the application:

  • webtransport.connect
  • webtransport.datagram.receive with data
  • webtransport.stream.open with stream, direction, and initiated_by
  • webtransport.stream.receive with stream, data, and end_stream
  • webtransport.stream.reset and webtransport.stream.stop_sending
  • webtransport.disconnect with code and reason

Messages sent by the application:

  • webtransport.accept, optionally with subprotocol
  • webtransport.close, with session code/reason, or pre-accept HTTP status
  • webtransport.datagram.send with data
  • webtransport.stream.send with stream, data, and end_stream
  • webtransport.stream.reset and webtransport.stream.stop_receiving

Version 0.1 supports datagrams and client-created bidirectional and unidirectional streams. Server-created streams, a synchronous consumer, and a standardized ASGI extension are outside this first release. HTTP middleware that expects an HTTP scope will not automatically apply; authenticate the CONNECT request using the WebTransport scope headers or a short-lived ticket.

Development

uv sync --all-groups
uv run ruff check .
uv run mypy
uv run pytest
uv build

Licensed under the MIT License.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

channels_webtransport-0.0.1.tar.gz (10.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

channels_webtransport-0.0.1-py3-none-any.whl (13.9 kB view details)

Uploaded Python 3

File details

Details for the file channels_webtransport-0.0.1.tar.gz.

File metadata

  • Download URL: channels_webtransport-0.0.1.tar.gz
  • Upload date:
  • Size: 10.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for channels_webtransport-0.0.1.tar.gz
Algorithm Hash digest
SHA256 34cdf7a0cf7fea468abd9bac065e9de586f5d39afcd5119d3e9a970bd217df76
MD5 d85274989a7aa594476c88615abc1a2b
BLAKE2b-256 c8a04e3361c7b9d09c5d089089e82043413d207703de08ec49a11c9182323579

See more details on using hashes here.

Provenance

The following attestation bundles were made for channels_webtransport-0.0.1.tar.gz:

Publisher: release.yml on Dank-del/channels-webtransport

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file channels_webtransport-0.0.1-py3-none-any.whl.

File metadata

File hashes

Hashes for channels_webtransport-0.0.1-py3-none-any.whl
Algorithm Hash digest
SHA256 8cb828fcb65c691906bb00eff353e3d4eacda42c1f47515216d8adee709fbcff
MD5 e96ab8ebcefa8c67931200a434202540
BLAKE2b-256 092dd2474ce6b7e90dac6549b5eda6e7966ad3433df23da63e6fbee52ca24126

See more details on using hashes here.

Provenance

The following attestation bundles were made for channels_webtransport-0.0.1-py3-none-any.whl:

Publisher: release.yml on Dank-del/channels-webtransport

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

0.0.1 This release

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page