Deno QUIC端点处理Chrome导航连接的问题咨询
Hey there! Let's unpack what's going on with your Deno QUIC setup and Chrome's navigation requests—you're hitting classic "low-level protocol vs. application layer" confusion here, which is totally normal when working with raw QUIC streams.
First: Why are the incoming bytes gibberish?
The byte arrays you're seeing aren't random noise—they're HTTP/3 frames, wrapped in QUIC streams. Here's the breakdown:
- When you force Chrome to use QUIC for
https://localhost, it's actually speaking HTTP/3 (the standard application layer protocol built on top of QUIC). - HTTP/3 doesn't send plaintext requests like older HTTP versions. Instead, it uses:
- QPACK (a header compression algorithm) to shrink request headers (like
GET /,Host: localhost, etc.) - Structured frames (HEADERS, DATA, SETTINGS, etc.) to encapsulate all data sent over QUIC streams.
- QPACK (a header compression algorithm) to shrink request headers (like
Your current code just reads raw bytes from the QUIC stream without parsing the HTTP/3 protocol, so decoding them as Unicode will always result in garbage text.
Second: Why does sending "Hello World!" trigger a QUIC error?
Chrome isn't expecting a raw string—it's expecting a valid HTTP/3 response that follows the protocol rules. A proper HTTP/3 response needs:
- A HEADERS frame containing the status code (e.g.,
200 OK) and response headers (likeContent-Type: text/html), compressed with QPACK. - Optional DATA frames containing the actual content (your HTML or text).
- Proper stream management (closing streams only after all required frames are sent, respecting QUIC's flow control rules).
When you send a raw string and immediately close the stream, Chrome can't parse it as a valid HTTP/3 response, so it throws the ERR_QUIC_PROTOCOL_ERROR.
How to fix this (the easy way)
Deno has experimental built-in support for HTTP/3 via the standard library, which handles all the low-level protocol parsing for you. You don't need to work directly with Deno.QuicEndpoint unless you're trying to build a custom protocol on top of QUIC.
Here's a revised version of your code using serveHttp3 (note: you'll need to run Deno with the --unstable flag since HTTP/3 support is experimental):
import { serveHttp3 } from "https://deno.land/std@0.200.0/http/http3.ts"; import SSL from './SSL.js'; console.log("HTTP/3 server running at https://localhost:443"); const server = serveHttp3({ port: 443, alpnProtocols: ['h3'], // Prioritize HTTP/3 over h2 ...(SSL.default ?? SSL), }); for await (const conn of server) { for await (const requestEvent of conn) { // Handle the request just like a regular HTTP request console.log(`Received request: ${requestEvent.request.method} ${requestEvent.request.url}`); // Send a valid HTTP/3 response with HTML content requestEvent.respondWith( new Response("<h1>Hello from Deno HTTP/3!</h1>", { headers: { "Content-Type": "text/html; charset=utf-8", }, }), ); } }
If you really want to use raw QUIC (for learning)
If your goal is to understand the QUIC/HTTP/3 stack in depth, you'll need to implement the HTTP/3 protocol yourself. This involves:
- Handling control streams (like the SETTINGS frame that Chrome sends first to negotiate protocol parameters)
- Implementing QPACK header compression/decompression
- Parsing HTTP/3 frames from QUIC streams
- Constructing valid response frames to send back
This is a huge undertaking—you'll want to reference the official HTTP/3 spec and maybe look at open-source HTTP/3 implementations for guidance. But for most projects, using the built-in serveHttp3 is the practical choice.
内容来源于stack exchange

