This commit is contained in:
2026-04-19 11:33:11 +09:00
parent 867ae25fa0
commit da8d91b87f
43 changed files with 4044 additions and 15 deletions
@@ -0,0 +1,47 @@
from __future__ import annotations
import asyncio
from dataclasses import dataclass
@dataclass
class Http3Info:
supported: bool = False
error: str | None = None
async def probe_http3(host: str, port: int, sni: str | None, timeout: float = 6.0) -> Http3Info:
"""Attempt a QUIC handshake to determine HTTP/3 availability.
Uses aioquic if available. On any failure returns supported=False.
"""
try:
from aioquic.asyncio.client import connect
from aioquic.quic.configuration import QuicConfiguration
from aioquic.quic.events import HandshakeCompleted
except Exception as e:
return Http3Info(supported=False, error=f"aioquic unavailable: {e}")
info = Http3Info()
try:
configuration = QuicConfiguration(
is_client=True,
alpn_protocols=["h3", "h3-29"],
verify_mode=None,
)
try:
import ssl as _ssl
configuration.verify_mode = _ssl.CERT_NONE
except Exception:
pass
host_for_quic = sni or host
async def _run():
async with connect(host, port, configuration=configuration, server_name=host_for_quic) as client:
await client.wait_connected()
return True
ok = await asyncio.wait_for(_run(), timeout=timeout)
info.supported = bool(ok)
except Exception as e:
info.supported = False
info.error = f"{e.__class__.__name__}: {e}"
return info