最小化 HTTP/3 服务器


🌐 Minimal HTTP/3 server

import { listen } from 'node:quic';

const encoder = new TextEncoder();

const endpoint = await listen((session) => {
  // The session.onstream callback fires for each new client-initiated stream.
}, {
  sni: { '*': { keys: [defaultKey], certs: [defaultCert] } },
  // ALPN defaults to 'h3'.
  onheaders(headers) {
    // `this` is the QuicStream. Pseudo-headers are available on the
    // request header block (`:method`, `:path`, `:scheme`,
    // `:authority`).
    if (headers[':path'] === '/health') {
      this.sendHeaders({ ':status': '200', 'content-type': 'text/plain' });
      const w = this.writer;
      w.writeSync(encoder.encode('ok\n'));
      w.endSync();
    } else {
      this.sendHeaders({ ':status': '404' }, { terminal: true });
    }
  },
});

console.log('listening on', endpoint.address); 

服务器端备注:

🌐 Server-side notes:

  • onheaders 设置在 listen() 级别会将其应用到每一个传入流(它在 onstream 触发之前就已连接)。在 onstream 内部设置它对于 HTTP/3 来说太晚,因为请求 HEADERS 帧是到达流上的第一件事。
  • this.sendHeaders(headers, { terminal: true }) 将响应 HEADERS 帧标记为终止帧(后面没有正文)。
  • 对于主体响应,先发送头部,然后写入 this.writer 并调用 endSync() 来发送正文并干净地关闭流。