Skip to main content
使用 Bun.serve()routes 属性添加路由(静态路径、参数和通配符),或使用 fetch 方法处理未匹配的请求。 Bun.serve() 的路由器基于 uWebSocket 的树形方法,增加了 SIMD 加速的路由参数解码JavaScriptCore 结构缓存,以进一步突破现代硬件的性能极限。

基本设置

server.ts
Bun.serve() 中的路由接收一个 BunRequest(它扩展了 Request)并返回一个 ResponsePromise<Response>。这使得在发送和接收 HTTP 请求时使用相同的代码变得更加容易。

异步路由

Async/await

在路由处理器中使用 async/await 来返回 Promise<Response>

Promise

你也可以从路由处理器中返回 Promise<Response>

路由优先级

路由按优先级顺序匹配:
  1. 精确路由(/users/all
  2. 参数路由(/users/:id
  3. 通配符路由(/users/*
  4. 全局捕获路由(/*

类型安全的路由参数

当路径作为字符串字面量传递时,TypeScript 会解析路由参数,因此在访问 request.params 时编辑器会显示自动补全。
index.ts
Bun 会自动解码百分比编码的路由参数值,包括 Unicode 字符。无效的 Unicode 将被替换为 Unicode 替换字符(\uFFFD)。

静态响应

路由也可以是 Response 对象(无需处理器函数)。Bun.serve() 会对其进行零分配调度优化,适用于健康检查、重定向和固定内容:
静态响应在初始化后不会分配额外内存。通常,至少比手动返回 Response 对象有 15% 的性能提升。 静态路由响应在服务器对象的生命周期内被缓存。要重新加载静态路由,请调用 server.reload(options)

文件响应 vs 静态响应

从路由提供文件服务时,行为取决于你是将文件内容缓冲到内存中还是直接提供文件:
静态路由new Response(await file.bytes()))在启动时将内容缓冲到内存中:
  • 请求期间零文件系统 I/O——内容完全从内存提供
  • ETag 支持——自动生成和验证 ETag 用于缓存
  • If-None-Match——当客户端 ETag 匹配时返回 304 Not Modified
  • 没有 404 处理——文件缺失会导致启动时错误,而非运行时 404
  • 内存使用——完整文件内容存储在 RAM 中
  • 最适合:小型静态资源、API 响应、频繁访问的文件
文件路由new Response(Bun.file(path)))每次请求都从文件系统读取:
  • 每次请求都进行文件系统读取——检查文件是否存在并读取内容
  • 内置 404 处理——如果文件不存在或无法访问,返回 404 Not Found
  • Last-Modified 支持——使用文件修改时间用于 If-Modified-Since 头部
  • If-Modified-Since——自客户端缓存版本以来文件未更改时返回 304 Not Modified
  • 范围请求支持——自动处理带有 Content-Range 头部的部分内容请求
  • 流式传输——使用支持背压的缓冲读取器,内存效率高
  • 内存高效——传输期间仅缓冲小块数据,而非整个文件
  • 最适合:大文件、动态内容、用户上传、频繁变化的文件

流式传输文件

要流式传输文件,返回一个以 BunFile 对象作为主体的 Response 对象。
⚡️ 速度 — Bun 在可能的情况下自动使用 sendfile(2) 系统调用,在内核中实现零拷贝文件传输——这是发送文件的最快方式。
要发送文件的一部分,使用 Bun.file 对象上的 slice(start, end) 方法。Bun 会自动在 Response 对象上设置 Content-RangeContent-Length 头部。

fetch 请求处理器

fetch 处理器对没有匹配到路由的传入请求运行。它接收一个 Request 对象,并返回一个 ResponsePromise<Response>
fetch 处理器支持 async/await:
也支持基于 Promise 的响应:
fetch 处理器还将 Server 对象作为其第二个参数接收。