Bun

HTTP 服务器

本页面主要记录 Bun 原生 Bun.serve API。Bun 还实现了 fetch 以及 Node.js httphttps 模块。

这些模块已重新实现,以使用 Bun 的快速内部 HTTP 基础设施。您可以直接使用这些模块;依赖这些模块的框架(如 Express)应开箱即用。有关粒度兼容性信息,请参阅 运行时 > Node.js API

要使用干净的 API 启动高性能 HTTP 服务器,建议的方法是 Bun.serve

Bun.serve()

使用 Bun.serve 在 Bun 中启动 HTTP 服务器。

Bun.serve({
  fetch(req) {
    return new Response("Bun!");
  },
});

fetch 处理程序处理传入请求。它接收一个 Request 对象,并返回一个 ResponsePromise<Response>

Bun.serve({
  fetch(req) {
    const url = new URL(req.url);
    if (url.pathname === "/") return new Response("Home page!");
    if (url.pathname === "/blog") return new Response("Blog!");
    return new Response("404!");
  },
});

要配置服务器将侦听的端口和主机名

Bun.serve({
  port: 8080, // defaults to $BUN_PORT, $PORT, $NODE_PORT otherwise 3000
  hostname: "mydomain.com", // defaults to "0.0.0.0"
  fetch(req) {
    return new Response("404!");
  },
});

要在 Unix 域套接字 上侦听

Bun.serve({
  unix: "/tmp/my-socket.sock", // path to socket
  fetch(req) {
    return new Response(`404!`);
  },
});

错误处理

要激活开发模式,请设置 development: true。默认情况下,开发模式处于启用状态,除非 NODE_ENVproduction

Bun.serve({
  development: true,
  fetch(req) {
    throw new Error("woops!");
  },
});

在开发模式下,Bun 将使用内置错误页面在浏览器中显示错误。

Bun 的内置 500 页面

要处理服务器端错误,请实现一个 error 处理程序。当发生错误时,此函数应返回一个 Response 以提供给客户端。此响应将取代 development 模式下的 Bun 默认错误页面。

Bun.serve({
  fetch(req) {
    throw new Error("woops!");
  },
  error(error) {
    return new Response(`<pre>${error}\n${error.stack}</pre>`, {
      headers: {
        "Content-Type": "text/html",
      },
    });
  },
});

Bun.serve 的调用返回一个 Server 对象。要停止服务器,请调用 .stop() 方法。

const server = Bun.serve({
  fetch() {
    return new Response("Bun!");
  },
});

server.stop();

TLS

Bun 开箱即用支持 TLS,由 BoringSSL 提供支持。通过传入 keycert 的值来启用 TLS;启用 TLS 需要同时提供这两个值。

Bun.serve({
  fetch(req) {
    return new Response("Hello!!!");
  },

  tls: {
    key: Bun.file("./key.pem"),
    cert: Bun.file("./cert.pem"),
  }
});

keycert 字段需要 TLS 密钥和证书的内容而不是其路径。它可以是字符串、BunFileTypedArrayBuffer

Bun.serve({
  fetch() {},

  tls: {
    // BunFile
    key: Bun.file("./key.pem"),
    // Buffer
    key: fs.readFileSync("./key.pem"),
    // string
    key: fs.readFileSync("./key.pem", "utf8"),
    // array of above
    key: [Bun.file("./key1.pem"), Bun.file("./key2.pem")],
  },
});

如果您的私钥使用密码加密,请提供 passphrase 值以对其进行解密。

Bun.serve({
  fetch(req) {
    return new Response("Hello!!!");
  },

  tls: {
    key: Bun.file("./key.pem"),
    cert: Bun.file("./cert.pem"),
    passphrase: "my-secret-passphrase",
  }
});

或者,你可以通过传递 ca 的值来覆盖受信任的 CA 证书。默认情况下,服务器将信任 Mozilla 策划的众所周知的 CA 列表。当指定 ca 时,Mozilla 列表将被覆盖。

Bun.serve({
  fetch(req) {
    return new Response("Hello!!!");
  },
  tls: {
    key: Bun.file("./key.pem"), // path to TLS key
    cert: Bun.file("./cert.pem"), // path to TLS cert
    ca: Bun.file("./ca.pem"), // path to root CA certificate
  }
});

要覆盖 Diffie-Hellman 参数

Bun.serve({
  // ...
  tls: {
    // other config
    dhParamsFile: "/path/to/dhparams.pem", // path to Diffie Hellman parameters
  },
});

对象语法

到目前为止,本页上的示例都使用了显式的 Bun.serve API。Bun 还支持备用语法。

server.ts
import {type Serve} from "bun";

export default {
  fetch(req) {
    return new Response("Bun!");
  },
} satisfies Serve;

不要将服务器选项传递到 Bun.serve,而是 export default 它。此文件可以按原样执行;当 Bun 看到一个包含 fetch 处理程序的 default 导出的文件时,它会在后台将其传递到 Bun.serve 中。

流式传输文件

要流式传输文件,请返回一个 Response 对象,其中 BunFile 对象作为主体。

Bun.serve({
  fetch(req) {
    return new Response(Bun.file("./hello.txt"));
  },
});

⚡️ 速度 — Bun 在可能的情况下自动使用 sendfile(2) 系统调用,从而在内核中启用零拷贝文件传输,这是发送文件的最快方式。

你可以使用 Bun.file 对象上的 slice(start, end) 方法发送文件的一部分。这会自动在 Response 对象上设置 Content-RangeContent-Length 头。

Bun.serve({
  fetch(req) {
    // parse `Range` header
    const [start = 0, end = Infinity] = req.headers
      .get("Range") // Range: bytes=0-100
      .split("=") // ["Range: bytes", "0-100"]
      .at(-1) // "0-100"
      .split("-") // ["0", "100"]
      .map(Number); // [0, 100]

    // return a slice of the file
    const bigFile = Bun.file("./big-video.mp4");
    return new Response(bigFile.slice(start, end));
  },
});

基准

以下是 Bun 和 Node.js 实现的一个简单 HTTP 服务器,它对每个传入的 Request 响应 Bun!

Bun
Node
Bun
Bun.serve({
  fetch(req: Request) {
    return new Response("Bun!");
  },
  port: 3000,
});
Node
require("http")
  .createServer((req, res) => res.end("Bun!"))
  .listen(8080);

Bun.serve 服务器在 Linux 上每秒可以处理大约比 Node.js 多 2.5 倍的请求。

运行时每秒请求数
Node 16~64,000
Bun~160,000
image

参考

查看 TypeScript 定义