Skip to content
我们的赞助商

路由

Web 服务器使用请求的路径和方法来查找正确的资源,这被称为**“路由”**。

我们可以通过调用以HTTP 动词命名的方法来定义路由,传递路径和匹配时执行的函数。

typescript
import { Elysia } from 'elysia'

new Elysia()
    .get('/', 'hello')
    .get('/hi', 'hi')
    .listen(3000)

我们可以通过访问 http://localhost:3000 来访问 Web 服务器。

默认情况下,Web 浏览器在访问页面时会发送 GET 方法。

localhost

GET

TIP

使用上面的交互式浏览器,将鼠标悬停在蓝色高亮区域,以查看每个路径之间的不同结果。

路径类型

Elysia 中的路径可以分为 3 种类型:

  • 静态路径 - 用于定位资源的静态字符串
  • 动态路径 - 段可以是任意值
  • 通配符 - 直到特定点的路径可以是任意内容

您可以将所有路径类型结合使用,以组合您的 Web 服务器行为。

typescript
import { Elysia } from 'elysia'

new Elysia()
    .get('/id/1', 'static path')
    .get('/id/:id', 'dynamic path')
    .get('/id/*', 'wildcard path')
    .listen(3000)
localhost

GET

静态路径

静态路径是一个硬编码的字符串,用于在服务器上定位资源。

ts
import { Elysia } from 'elysia'

new Elysia()
	.get('/hello', 'hello')
	.get('/hi', 'hi')
	.listen(3000)

动态路径

动态路径匹配某些部分并捕获值,以提取额外信息。

要定义动态路径,我们可以使用冒号 : 后跟一个名称。

typescript
import { 
Elysia
} from 'elysia'
new
Elysia
()
.
get
('/id/:id', ({
params
: {
id
} }) =>
id
)
.
listen
(3000)

这里,创建了一个动态路径 /id/:id。这告诉 Elysia 捕获 :id 段的值,例如 /id/1/id/123/id/anything

localhost

GET

1

当请求时,服务器应返回以下响应:

PathResponse
/id/11
/id/123123
/id/anythinganything
/id/anything?name=saltanything
/idNot Found
/id/anything/restNot Found

动态路径非常适合包含像 ID 这样的内容,以便后续使用。

我们将命名变量路径称为路径参数或简称params

多个路径参数

您可以拥有任意数量的路径参数,这些参数将被存储到一个 params 对象中。

typescript
import { 
Elysia
} from 'elysia'
new
Elysia
()
.
get
('/id/:id', ({
params
: {
id
} }) =>
id
)
.
get
('/id/:id/:name', ({
params
: {
id
,
name
} }) =>
id
+ ' ' +
name
)
.
listen
(3000)


localhost

GET

1

服务器将响应如下:

PathResponse
/id/11
/id/123123
/id/anythinganything
/id/anything?name=saltanything
/idNot Found
/id/anything/restanything rest

可选路径参数

有时我们可能希望静态路径和动态路径解析为同一个处理程序。

我们可以通过在参数名称后添加问号 ? 来使路径参数变为可选。

typescript
import { 
Elysia
} from 'elysia'
new
Elysia
()
.
get
('/id/:id?', ({
params
: {
id
} }) => `id ${
id
}`)
.
listen
(3000)

localhost

GET

通配符

动态路径允许捕获单个段,而通配符允许捕获路径的其余部分。

要定义通配符,我们可以使用星号 *

typescript
import { 
Elysia
} from 'elysia'
new
Elysia
()
.
get
('/id/*', ({
params
}) =>
params
['*'])
.
listen
(3000)

localhost

GET

1

路径优先级

Elysia 的路径优先级如下:

  1. 静态路径
  2. 动态路径
  3. 通配符

如果路径被解析为静态的、通配符动态路径被呈现,Elysia 将解析静态路径而不是动态路径

typescript
import { Elysia } from 'elysia'

new Elysia()
    .get('/id/1', 'static path')
    .get('/id/:id', 'dynamic path')
    .get('/id/*', 'wildcard path')
    .listen(3000)
localhost

GET

HTTP 动词

HTTP 定义了一组请求方法,以指示对给定资源执行的预期操作

有几种 HTTP 动词,但最常见的是:

GET

使用 GET 的请求应仅检索数据。

POST

向指定资源提交有效负载,通常导致状态更改或副作用。

PUT

使用请求的有效负载替换目标资源的当前所有表示。

PATCH

对资源应用部分修改。

DELETE

删除指定的资源。


为了处理不同的动词,Elysia 默认内置了几个 HTTP 动词的 API,类似于 Elysia.get

typescript
import { Elysia } from 'elysia'

new Elysia()
    .get('/', 'hello')
    .post('/hi', 'hi')
    .listen(3000)
localhost

GET

Elysia HTTP 方法接受以下参数:

  • path: 路径名
  • function: 用于响应客户端的函数
  • hook: 额外元数据

您可以在 HTTP Request Methods 上阅读更多关于 HTTP 方法的信息。

自定义方法

我们可以使用 Elysia.route 来接受自定义 HTTP 方法。

typescript
import { Elysia } from 'elysia'

const app = new Elysia()
    .get('/get', 'hello')
    .post('/post', 'hi')
    .route('M-SEARCH', '/m-search', 'connect') 
    .listen(3000)
localhost

GET

Elysia.route 接受以下内容:

  • method: HTTP 动词
  • path: 路径名
  • function: 用于响应客户端的函数
  • hook: 额外元数据

TIP

根据 RFC 7231,HTTP 动词区分大小写。

建议使用大写约定来定义自定义 HTTP 动词与 Elysia。

ALL 方法

Elysia 提供了 Elysia.all,用于使用与 Elysia.getElysia.post 相同的 API 来处理指定路径的任何 HTTP 方法

typescript
import { Elysia } from 'elysia'

new Elysia()
    .all('/', 'hi')
    .listen(3000)
localhost

GET

任何匹配路径的 HTTP 方法,将被处理如下:

PathMethodResult
/GEThi
/POSThi
/DELETEhi

Handle

大多数开发者使用像 Postman、Insomnia 或 Hoppscotch 这样的 REST 客户端来测试他们的 API。

但是,Elysia 可以使用 Elysia.handle 进行程序化测试。

typescript
import { Elysia } from 'elysia'

const app = new Elysia()
    .get('/', 'hello')
    .post('/hi', 'hi')
    .listen(3000)

app.handle(new Request('http://localhost/')).then(console.log)

Elysia.handle 是一个函数,用于处理发送到服务器的实际请求。

TIP

与单元测试的模拟不同,您可以预期它像发送到服务器的实际请求一样行为

但也适用于模拟或创建单元测试。

Group

在创建 Web 服务器时,您经常会有多个共享相同前缀的路由:

typescript
import { Elysia } from 'elysia'

new Elysia()
    .post('/user/sign-in', 'Sign in')
    .post('/user/sign-up', 'Sign up')
    .post('/user/profile', 'Profile')
    .listen(3000)
localhost

POST

这可以通过 Elysia.group 来改进,允许我们将多个路由分组在一起,同时为其应用前缀:

typescript
import { 
Elysia
} from 'elysia'
new
Elysia
()
.
group
('/user', (
app
) =>
app
.
post
('/sign-in', 'Sign in')
.
post
('/sign-up', 'Sign up')
.
post
('/profile', 'Profile')
) .
listen
(3000)
localhost

POST

此代码的行为与我们的第一个示例相同,并应结构化为如下:

PathResult
/user/sign-inSign in
/user/sign-upSign up
/user/profileProfile

.group() 还可以接受一个可选的守卫参数,以减少使用组和守卫一起时的样板代码:

typescript
import { 
Elysia
,
t
} from 'elysia'
new
Elysia
()
.
group
(
'/user', {
body
:
t
.
Literal
('Rikuhachima Aru')
}, (
app
) =>
app
.
post
('/sign-in', 'Sign in')
.
post
('/sign-up', 'Sign up')
.
post
('/profile', 'Profile')
) .
listen
(3000)

您可以在 scope 中找到更多关于分组守卫的信息。

前缀

我们可以通过向构造函数提供前缀来将组分离为单独的插件实例,以减少嵌套。

typescript
import { Elysia } from 'elysia'

const users = new Elysia({ prefix: '/user' })
    .post('/sign-in', 'Sign in')
    .post('/sign-up', 'Sign up')
    .post('/profile', 'Profile')

new Elysia()
    .use(users)
    .get('/', 'hello world')
    .listen(3000)
localhost

GET