Add http3 module: HTTP/3 in the Java HTTP Client (JEP 517), opt-in, discovery modes, fallback timings, proxy downgrade and a packet-loss comparison
Co-Authored-By: Claude Sonnet 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01KqJyCidz3ZgRyHABv2GVJh
This commit is contained in:
@@ -0,0 +1,46 @@
|
||||
"""Minimal HTTP/3 server on aioquic (the library Hypercorn uses for QUIC). It answers the same paths as app.py.
|
||||
Hypercorn's own QUIC listener proved unreliable under packet loss (its UDPServer task dies on a KeyError and the
|
||||
port then goes silent), so HTTP/3 is served from here and Hypercorn serves only TCP."""
|
||||
import asyncio, ssl
|
||||
from aioquic.asyncio import QuicConnectionProtocol, serve as quic_serve
|
||||
from aioquic.h3.connection import H3_ALPN, H3Connection
|
||||
from aioquic.h3.events import HeadersReceived, DataReceived
|
||||
from aioquic.quic.configuration import QuicConfiguration
|
||||
from aioquic.quic.events import ProtocolNegotiated
|
||||
|
||||
from app import respond # (path, http_version, host, port) -> (status, headers, body)
|
||||
|
||||
class H3Protocol(QuicConnectionProtocol):
|
||||
def __init__(self, *a, **kw):
|
||||
super().__init__(*a, **kw)
|
||||
self._http = None
|
||||
self._pending = {}
|
||||
|
||||
def quic_event_received(self, event):
|
||||
if isinstance(event, ProtocolNegotiated) and event.alpn_protocol in H3_ALPN:
|
||||
self._http = H3Connection(self._quic)
|
||||
if self._http is None:
|
||||
return
|
||||
for ev in self._http.handle_event(event):
|
||||
if isinstance(ev, HeadersReceived):
|
||||
self._pending[ev.stream_id] = dict(ev.headers)
|
||||
if ev.stream_ended: self._reply(ev.stream_id)
|
||||
elif isinstance(ev, DataReceived) and ev.stream_ended:
|
||||
self._reply(ev.stream_id)
|
||||
|
||||
def _reply(self, stream_id):
|
||||
h = self._pending.pop(stream_id, None)
|
||||
if h is None: return
|
||||
status, headers, body = respond(h[b":path"].decode(), "3", "127.0.0.1", self._port)
|
||||
self._http.send_headers(stream_id, [(b":status", str(status).encode())] + headers)
|
||||
self._http.send_data(stream_id, body, end_stream=True)
|
||||
self.transmit()
|
||||
|
||||
_port = 4433
|
||||
|
||||
async def start(port, certfile, keyfile):
|
||||
H3Protocol._port = port
|
||||
cfg = QuicConfiguration(is_client=False, alpn_protocols=H3_ALPN)
|
||||
cfg.load_cert_chain(certfile, keyfile)
|
||||
await quic_serve("127.0.0.1", port, configuration=cfg, create_protocol=H3Protocol)
|
||||
await asyncio.Event().wait()
|
||||
Reference in New Issue
Block a user