Skip to content

serve — HTTP 服务器 ​

纯 JS 的 HTTP/1.1 服务器,暴露为全局 serve()。请求解析、路由、WebSocket 升级、响应序列化等协议语义都在 JavaScript 中实现。

全局 ​

Global类型说明
servefunction启动 HTTP 服务器。同一时刻只能有一个活跃。

serve(options, handler) ​

启动一个监听服务器并返回服务器句柄。每个 HTTP 请求调用一次 handler;其返回值 (或 resolve 的 Promise 值)作为响应发送。

js
let server = serve({ port: 8080 }, (req) => {
  if (req.pathname === '/hello') return 'Hello, world!';
  return { status: 404, headers: { 'Content-Type': 'text/plain' }, _body: 'Not found' };
});

选项 ​

选项默认说明
port8080监听 TCP 端口(0–65535)。
hostname'127.0.0.1'绑定地址。默认仅回环——需接受其他主机连接时显式传 '0.0.0.0'。
idleTimeout30000连接空闲多少 ms 后关闭;0 禁用。
ws{}WebSocket 升级路由表,以请求路径为 key。
tlsundefined{ cert, key } PEM 字符串启用 HTTPS(需 QZ_WITH_TLS)。

请求对象 ​

handler 收到一个描述请求的普通对象:

字段类型说明
methodstringHTTP 方法,如 'GET'。
urlstring含查询的原始路径,如 '/a?x=1'。
pathnamestring不含查询的路径,如 '/a'。
searchstring含 ? 的查询串,或 ''。
headersobject小写头名 → 值。
bodyReadableStream | nullContent-Length > 0 时为请求体,否则 null。
keepAliveboolean本次响应后连接是否保持。

WebSocket 路由 ​

options.ws 把路径映射到升级处理器。每个处理器收到一个含 onopen、onmessage、 onclose、onerror、send()、close() 的连接对象。

js
serve({
  port: 8080,
  ws: {
    '/chat': (conn) => {
      conn.onmessage = (ev) => {
        conn.send('echo: ' + ev.data);       // 文本帧以字符串到达
      };
      conn.onclose = () => console.log('disconnected');
    }
  }
}, (req) => 'HTTP fallback');

路由值也可以是一个含 handler 与可选 protocols 数组的对象,用于子协议协商:

js
ws: {
  '/chat': {
    handler: (conn) => { conn.onmessage = (ev) => conn.send('pong'); },
    protocols: ['chat.v1']        // 若客户端提供则通过 Sec-WebSocket-Protocol 回显
  }
}

连接对象:

成员类型说明
send(data)function发送文本(字符串)或二进制(Uint8Array)。
close(code, reason)function发送关闭帧并标记连接关闭。
onopencallbacksocket 就绪时触发。
onmessagecallback收到 { data }——文本帧为字符串、二进制帧为 Uint8Array。
onclosecallback收到 { code, reason, wasClean }。
onerrorcallback连接错误。

当客户端提供且可用原生流式 deflate 原语时(见 compress), permessage-deflate(RFC 7692)压缩自动协商。

WebSocket 握手在构建时需 QZ_WITH_TEXTCODEC=ON 与 QZ_WITH_CRYPTO_EXT=ON (经 crypto.subtle 计算 SHA-1 accept key);否则升级抛 WebSocket accept unavailable。

无匹配 ws 路由的请求得 404;缺 Sec-WebSocket-Key 的升级得 400。

TLS ​

传 tls: { cert, key } 在监听器上启用 HTTPS。构建时需 QZ_WITH_TLS=ON (见 构建选项)。

js
serve({
  port: 8443,
  tls: { cert: pemCert, key: pemKey }
}, (req) => 'secure!');

gRPC 服务器 ​

传 grpc: server 在同一监听器上注册 gRPC 服务。gRPC 栈是 纯 JS 的 h2/HPACK/protobuf 实现; 与 HTTP/1.1 处理器同一 TCP 端口——监听器按 ALPN(TLS 连接为 h2)或 PRI * HTTP/2.0 连接前导(明文 h2c)分发。

js
const server = grpc.createServer();
server.addService(reg, { Echo: (call) => ({ text: call.request.text }) });
serve({ port: 50051, grpc: server }, () => 'not-grpc');

构建时需 QZ_WITH_GRPC=ON(gRPC bundle 为可选,因为它向 polyfill 增加约 3.5k 行;见 构建选项)。

完整 unary/流式走查见 grpc-hello 示例 与 gRPC API 参考。

说明 ​

  • 支持 HTTP/1.1 keep-alive;客户端请求 close 或使用 HTTP/1.0 时响应后关闭连接。

MIT 许可证