Skip to main content
你可以通过使用 routes 属性(用于静态路径、参数和通配符)或通过 fetch 方法处理未匹配请求,向 Bun.serve() 添加路由。 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
百分号编码的路由参数值会自动解码,支持 Unicode 字符。无效的 unicode 会被替换成 Unicode 替代字符 &0xFFFD;

静态响应

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

文件响应与静态响应的区别

在路由中提供文件时,行为因缓冲文件内容还是直接传输而异:
静态路由 (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 对象作为 body 的 Response
⚡️ 速度 — Bun 会在可能的情况下自动使用 sendfile(2) 系统调用, 在内核级实现零拷贝文件传输—这是发送文件最快的方式。
你可以使用 Bun.file 对象的 slice(start, end) 方法发送文件的部分内容。此方法会自动为 Response 设置 Content-RangeContent-Length 头部。

fetch 请求处理器

fetch 处理器用于处理未被任一路由匹配的入站请求。它接收一个 Request 对象,返回一个 ResponsePromise<Response>
fetch 处理器支持 async/await:
也支持基于 Promise 的响应:
你还可以从 fetch 处理器访问 Server 对象。它是传递给 fetch 函数的第二个参数。