Skip to content
我们的赞助商
Open in Anthropic

处理程序

Handler - 接受 HTTP 请求并返回响应的函数。

typescript
import { Elysia } from 'elysia'

new Elysia()
    // 函数 `() => 'hello world'` 是一个处理程序
    .get('/', () => 'hello world')
    .listen(3000)

处理程序可以是文字值,也可以是内联值。

typescript
import { Elysia, file } from 'elysia'

new Elysia()
    .get('/', 'Hello Elysia')
    .get('/video', file('kyuukurarin.mp4'))
    .listen(3000)

使用内联值始终返回相同的值,这有助于优化静态资源(如文件)的性能。

这使得 Elysia 可以提前编译响应以优化性能。

TIP

提供内联值并不是缓存。

静态资源值、头部和状态可以使用生命周期动态改变。

上下文

上下文包含每个请求唯一的请求信息,除了 store (全局可变状态),不被共享。

typescript
import { 
Elysia
} from 'elysia'
new
Elysia
()
.
get
('/', (
context
) =>
context
.
path
)
// ^ 这是上下文

上下文只能在路由处理程序中访问。它包括:

属性

  • body - HTTP 消息,表单或文件上传。
  • query - 查询字符串,包含额外搜索参数的 JavaScript 对象。(查询从路径名后“?”号开始提取)
  • params - Elysia 的路径参数,解析为 JavaScript 对象
  • headers - HTTP 头部,请求的附加信息,如 User-Agent、Content-Type、缓存提示等。
  • cookie - 一个全局可变信号存储,用于交互 Cookie(包括获取和设置)
  • store - Elysia 实例的全局可变存储

工具函数

  • redirect - 重定向响应的函数
  • status - 返回自定义状态码的函数
  • set - 应用于响应的属性:

其他属性

status

返回自定义状态码的函数,并支持类型缩小。

typescript
import { Elysia } from 'elysia'

new Elysia()
    .get('/', ({ status }) => status(418, "Kirifuji Nagisa"))
    .listen(3000)
localhost

GET

建议使用永不抛出(never-throw)方式返回status,而非抛出错误,因为它:

  • 允许 TypeScript 检查返回值是否符合响应模式的类型
  • 基于状态码支持自动补全的类型缩小
  • 支持端到端类型安全的错误处理的类型缩小(参考 Eden

Set

set 是一个可变属性,代表通过 Context.set 访问的响应。

ts
import { 
Elysia
} from 'elysia'
new
Elysia
()
.
get
('/', ({
set
,
status
}) => {
set
.
headers
= { 'X-Teapot': 'true' }
return
status
(418, '我是茶壶')
}) .
listen
(3000)

set.headers

允许我们附加或删除响应头,以对象形式表示。

typescript
import { 
Elysia
} from 'elysia'
new
Elysia
()
.
get
('/', ({
set
}) => {
set
.
headers
['x-powered-by'] = 'Elysia'
return 'a mimir' }) .
listen
(3000)

TIP

Elysia 为区分大小写提供了小写自动补全以保持一致性,例如使用 set-cookie 而非 Set-Cookie

redirect 遗留

将请求重定向到其他资源。

typescript
import { 
Elysia
} from 'elysia'
new
Elysia
()
.
get
('/', ({
redirect
}) => {
return
redirect
('https://youtu.be/whpVWVWBW4U?&t=8')
}) .
get
('/custom-status', ({
redirect
}) => {
// 你还可以设置自定义状态码来重定向 return
redirect
('https://youtu.be/whpVWVWBW4U?&t=8', 302)
}) .
listen
(3000)

使用重定向时,返回值不是必须的且会被忽略,因为响应来自其他资源。

set.status 遗留

设置默认状态码(如果未提供)。

建议在只需返回特定状态码,但允许用户返回自定义值的插件中使用,例如 HTTP 201/206 或 403/405 等。

typescript
import { 
Elysia
} from 'elysia'
new
Elysia
()
.
onBeforeHandle
(({
set
}) => {
set
.
status
= 418
return 'Kirifuji Nagisa' }) .
get
('/', () => 'hi')
.
listen
(3000)

status 函数不同,set.status 无法推断返回值类型,因此无法检查返回值是否符合响应模式。

TIP

HTTP 状态码指示响应类型。如果路由处理程序成功执行且无错误,Elysia 将返回状态码 200。

你也可以使用状态码的常用名字替代数字来设置状态码。

typescript
// @errors 2322
import { 
Elysia
} from 'elysia'
new
Elysia
()
.
get
('/', ({
set
}) => {
set
.
status
return 'Kirifuji Nagisa' }) .
listen
(3000)

Elysia 提供一个可变信号用以交互 Cookie。

无需显式的 get/set,你可以直接访问 cookie 名称并读取或更新其值。

typescript
import { 
Elysia
} from 'elysia'
new
Elysia
()
.
get
('/set', ({
cookie
: {
name
} }) => {
// 读取
name
.
value
// 设置
name
.
value
= "新值"
})

更多信息见 模版:Cookie

Redirect

将请求重定向到其他资源。

typescript
import { 
Elysia
} from 'elysia'
new
Elysia
()
.
get
('/', ({
redirect
}) => {
return
redirect
('https://youtu.be/whpVWVWBW4U?&t=8')
}) .
get
('/custom-status', ({
redirect
}) => {
// 你也可以设置自定义状态码来重定向 return
redirect
('https://youtu.be/whpVWVWBW4U?&t=8', 302)
}) .
listen
(3000)

使用重定向时,返回值不是必须且会被忽略,因为响应来自其他资源。

表单数据

可以通过直接从处理程序返回 form 工具来返回 FormData

typescript
import { Elysia, form, file } from 'elysia'

new Elysia()
	.get('/', () => form({
		name: 'Tea Party',
		images: [file('nagi.web'), file('mika.webp')]
	}))
	.listen(3000)

这种模式非常有用,即使需要返回文件或多部分表单数据。

返回单个文件

或者,你也可以直接返回单个文件,不用包裹在 form

typescript
import { Elysia, file } from 'elysia'

new Elysia()
	.get('/', file('nagi.web'))
	.listen(3000)

通过使用带 yield 关键字的生成器函数返回响应流。

typescript
import { Elysia } from 'elysia'

const app = new Elysia()
	.get('/ok', function* () {
		yield 1
		yield 2
		yield 3
	})

在此示例中,我们使用 yield 关键字实现响应的流式传输。

服务器发送事件 (SSE)

Elysia 通过提供 sse 工具支持 服务器发送事件

typescript
import { 
Elysia
,
sse
} from 'elysia'
new
Elysia
()
.
get
('/sse', function* () {
yield
sse
('hello world')
yield
sse
({
event
: 'message',
data
: {
message
: '这是一个消息',
timestamp
: new
Date
().
toISOString
()
}, }) })

当值被包裹在 sse 中时,Elysia 会自动将响应头设置为 text/event-stream,并格式化数据为 SSE 事件。

服务器发送事件中的头部

头部只能在第一个数据块(chunk)被 yield 之前设置。

typescript
import { 
Elysia
} from 'elysia'
const
app
= new
Elysia
()
.
get
('/ok', function* ({
set
}) {
// 这会设置头部
set
.
headers
['x-name'] = 'Elysia'
yield 1 yield 2 // 这不会生效
set
.
headers
['x-id'] = '1'
yield 3 })

一旦第一个数据块被 yield,Elysia 会将头部发送给客户端,因此之后更改头部没有效果。

条件流

如果响应返回而没有 yield,Elysia 将自动把流转换为普通响应。

typescript
import { Elysia } from 'elysia'

const app = new Elysia()
	.get('/ok', function* () {
		if (Math.random() > 0.5) return 'ok'

		yield 1
		yield 2
		yield 3
	})

这让我们能够根据条件选择流式传输响应或返回普通响应。

自动取消

在响应流完成之前,如果用户取消请求,Elysia 会自动停止生成器函数。

Eden

Eden 会将流式响应解释为 AsyncGenerator,允许我们用 for await 循环消费流。

typescript
import { 
Elysia
} from 'elysia'
import {
treaty
} from '@elysiajs/eden'
const
app
= new
Elysia
()
.
get
('/ok', function* () {
yield 1 yield 2 yield 3 }) const {
data
,
error
} = await
treaty
(
app
).
ok
.
get
()
if (
error
) throw
error
for await (const
chunk
of
data
)
console
.
log
(
chunk
)

Request

Elysia 基于 Web 标准 Request,支持 Node、Bun、Deno、Cloudflare Worker、Vercel Edge Function 等多种运行时。

typescript
import { Elysia } from 'elysia'

new Elysia()
	.get('/user-agent', ({ request }) => {
		return request.headers.get('user-agent')
	})
	.listen(3000)

允许你在必要时访问底层请求信息。

Server 仅 Bun 支持

服务器实例为 Bun 服务器实例,允许访问服务器信息,如端口号或请求 IP。

仅当使用 listen 运行 HTTP 服务器时,服务器实例才可用。

typescript
import { Elysia } from 'elysia'

new Elysia()
	.get('/port', ({ server }) => {
		return server?.port
	})
	.listen(3000)

请求 IP 仅 Bun 支持

可以通过 server.requestIP 方法获取请求 IP。

typescript
import { Elysia } from 'elysia'

new Elysia()
	.get('/ip', ({ server, request }) => {
		return server?.requestIP(request)
	})
	.listen(3000)

扩展上下文 高级概念

Elysia 默认提供一个最小的上下文,允许我们使用状态、装饰、派生和解析来扩展上下文以满足我们的特定需求。

有关如何扩展上下文的更多信息,请参见 扩展上下文