@@ -3,11 +3,9 @@ title: 路由(Router)
3
3
order : 6
4
4
---
5
5
6
- Router 主要用来描述请求 URL 和具体承担执行动作的 Controller 的对应关系,
7
- 框架约定了 ` app/router.js ` 文件用于统一所有路由规则。
8
-
9
- 通过统一的配置,我们可以避免路由规则逻辑散落在多个地方,从而出现未知的冲突,集中在一起我们可以更方便的来查看全局的路由规则。
6
+ Router 主要用来描述请求 URL 和具体承担执行动作的 Controller 的对应关系,框架约定了 ` app/router.js ` 文件用于统一所有路由规则。
10
7
8
+ 通过统一的配置,我们可以避免路由规则逻辑散落在多个地方,从而出现未知的冲突。集中在一起,我们可以更方便地来查看全局的路由规则。
11
9
## 如何定义 Router
12
10
13
11
- ` app/router.js ` 里面定义 URL 路由规则
@@ -35,7 +33,6 @@ class UserController extends Controller {
35
33
```
36
34
37
35
这样就完成了一个最简单的 Router 定义,当用户执行 ` GET /user/123 ` ,` user.js ` 这个里面的 info 方法就会执行。
38
-
39
36
## Router 详细定义说明
40
37
41
38
下面是路由的完整定义,参数可以根据场景的不同,自由选择:
@@ -47,37 +44,37 @@ router.verb('path-match', middleware1, ..., middlewareN, app.controller.action);
47
44
router .verb (' router-name' , ' path-match' , middleware1, ... , middlewareN, app .controller .action );
48
45
```
49
46
50
- 路由完整定义主要包括 5 个主要部分:
51
-
52
- - verb - 用户触发动作,支持 get, post 等所有 HTTP 方法,后面会通过示例详细说明。
53
- - router.head - HEAD
54
- - router.options - OPTIONS
55
- - router.get - GET
56
- - router.put - PUT
57
- - router.post - POST
58
- - router.patch - PATCH
59
- - router.delete - DELETE
60
- - router.del - 由于 delete 是一个保留字,所以提供了一个 delete 方法的别名。
61
- - router.redirect - 可以对 URL 进行重定向处理,比如我们最经常使用的可以把用户访问的根目录路由到某个主页。
62
- - router-name 给路由设定一个别名,可以通过 Helper 提供的辅助函数 ` pathFor ` 和 ` urlFor ` 来生成 URL。(可选)
63
- - path-match - 路由 URL 路径。
64
- - middleware1 - 在 Router 里面可以配置多个 Middleware。(可选)
65
- - controller - 指定路由映射到的具体的 controller 上,controller 可以有两种写法:
66
- - ` app.controller.user.fetch ` - 直接指定一个具体的 controller
67
- - ` 'user.fetch' ` - 可以简写为字符串形式
47
+ 路由的完整定义主要包括以下五个主要部分:
48
+
49
+ - ` verb ` : 用户触发动作,支持 get、 post 等所有 HTTP 方法,后面会通过示例详细说明。
50
+ - ` router.head ` : HEAD
51
+ - ` router.options ` : OPTIONS
52
+ - ` router.get ` : GET
53
+ - ` router.put ` : PUT
54
+ - ` router.post ` : POST
55
+ - ` router.patch ` : PATCH
56
+ - ` router.delete ` : DELETE
57
+ - ` router.del ` : 由于 delete 是一个保留字,所以提供了一个 delete 方法的别名。
58
+ - ` router.redirect ` : 可以对 URL 进行重定向处理,比如我们最经常使用的可以把用户访问的根目录路由到某个主页。
59
+ - ` router-name ` : 给路由设定一个别名,可以通过 Helper 提供的辅助函数 ` pathFor ` 和 ` urlFor ` 来生成 URL。(可选)
60
+ - ` path-match ` : 路由 URL 路径。
61
+ - ` middlewareN ` : 在 Router 里面可以配置多个 Middleware。(可选)
62
+ - ` controller ` :指定路由映射到的具体 controller 上,controller 可以有两种写法:
63
+ - ` app.controller.user.fetch ` : 直接指定一个具体的 controller。
64
+ - ` 'user.fetch' ` : 可以简写为字符串形式。
68
65
69
66
### 注意事项
70
67
71
- - 在 Router 定义中, 可以支持多个 Middleware 串联执行
68
+ - 在 Router 定义中,可以支持多个 Middleware 串联执行。
72
69
- Controller 必须定义在 ` app/controller ` 目录中。
73
- - 一个文件里面也可以包含多个 Controller 定义,在定义路由的时候 ,可以通过 ` ${fileName}.${functionName} ` 的方式指定对应的 Controller。
74
- - Controller 支持子目录,在定义路由的时候 ,可以通过 ` ${directoryName}.${fileName}.${functionName} ` 的方式指定对应的 Controller。
70
+ - 一个文件里面也可以包含多个 Controller 定义,在定义路由时 ,可以通过 ` ${fileName}.${functionName} ` 的方式指定对应的 Controller。
71
+ - Controller 支持子目录,在定义路由时 ,可以通过 ` ${directoryName}.${fileName}.${functionName} ` 的方式指定对应的 Controller。
75
72
76
- 下面是一些路由定义的方式 :
73
+ 以下是一些路由定义的方式 :
77
74
78
75
``` js
79
76
// app/router.js
80
- module .exports = ( app ) => {
77
+ module .exports = app => {
81
78
const { router , controller } = app;
82
79
router .get (' /home' , controller .home );
83
80
router .get (' /user/:id' , controller .user .page );
@@ -89,20 +86,18 @@ module.exports = (app) => {
89
86
90
87
### RESTful 风格的 URL 定义
91
88
92
- 如果想通过 RESTful 的方式来定义路由,
93
- 我们提供了 ` app.router.resources('routerName', 'pathMatch', controller) ` 快速在一个路径上生成 [ CRUD] ( https://en.wikipedia.org/wiki/Create,_read,_update_and_delete ) 路由结构。
89
+ 如果想用 RESTful 的方式定义路由,我们提供了 ` app.router.resources('routerName', 'pathMatch', controller) ` 方法,快速在一个路径上生成 [ CRUD] ( https://en.wikipedia.org/wiki/Create,_read,_update_and_delete ) 路由结构。
94
90
95
91
``` js
96
92
// app/router.js
97
- module .exports = ( app ) => {
93
+ module .exports = app => {
98
94
const { router , controller } = app;
99
95
router .resources (' posts' , ' /api/posts' , controller .posts );
100
96
router .resources (' users' , ' /api/v1/users' , controller .v1 .users ); // app/controller/v1/users.js
101
97
};
102
98
```
103
99
104
- 上面代码就在 ` /posts ` 路径上部署了一组 CRUD 路径结构,对应的 Controller 为 ` app/controller/posts.js ` 接下来,
105
- 你只需要在 ` posts.js ` 里面实现对应的函数就可以了。
100
+ 上述代码就在 ` /posts ` 路径上部署了一组 CRUD 路径结构,对应的 Controller 为 ` app/controller/posts.js ` 。接下来,只需在 ` posts.js ` 里面实现对应的函数即可。
106
101
107
102
| Method | Path | Route Name | Controller.Action |
108
103
| ------ | --------------- | ---------- | ----------------------------- |
@@ -131,11 +126,10 @@ exports.update = async () => {};
131
126
exports .destroy = async () => {};
132
127
```
133
128
134
- 如果我们不需要其中的某几个方法,可以不用在 ` posts.js ` 里面实现,这样对应 URL 路径也不会注册到 Router。
135
-
129
+ 如果我们不需要其中的某些方法,可以省略在 ` posts.js ` 里面的实现,这样对应的 URL 路径也不会注册到 Router 中。
136
130
## router 实战
137
131
138
- 下面通过更多实际的例子,来说明 router 的用法。
132
+ 下面通过更多实际的例子,来说明 ` router ` 的用法。
139
133
140
134
### 参数获取
141
135
@@ -173,7 +167,7 @@ exports.info = async (ctx) => {
173
167
174
168
#### 复杂参数的获取
175
169
176
- 路由里面也支持定义正则,可以更加灵活的获取参数 :
170
+ 路由里面也支持定义正则,可以更加灵活地获取参数 :
177
171
178
172
``` js
179
173
// app/router.js
@@ -186,8 +180,8 @@ module.exports = (app) => {
186
180
187
181
// app/controller/package.js
188
182
exports .detail = async (ctx ) => {
189
- // 如果请求 URL 被正则匹配, 可以按照捕获分组的顺序,从 ctx.params 中获取。
190
- // 按照下面的用户请求,`ctx.params[0]` 的 内容就是 `egg/1.0.0`
183
+ // 如果请求 URL 被正则匹配,可以按照捕获分组的顺序,从 ctx.params 中获取。
184
+ // 按照下面的用户请求,`ctx.params[0]` 的内容就是 `egg/1.0.0`
191
185
ctx .body = ` package:${ ctx .params [0 ]} ` ;
192
186
};
193
187
@@ -213,17 +207,15 @@ exports.post = async (ctx) => {
213
207
214
208
> 附:
215
209
216
- > 这里直接发起 POST 请求会** 报错** :'secret is missing'。错误信息来自 [ koa-csrf/index.js#L69] ( https://github.com/koajs/csrf/blob/2.5.0/index.js#L69 ) 。
217
-
218
- > ** 原因** :框架内部针对表单 POST 请求均会验证 CSRF 的值,因此我们在表单提交时,请带上 CSRF key 进行提交,可参考[ 安全威胁 csrf 的防范] ( https://eggjs.org/zh-cn/core/security.html#安全威胁csrf的防范 )
210
+ > 这里直接发起 POST 请求会** 报错** :'secret is missing'。错误信息来源于 [ koa-csrf/index.js#L69] ( https://github.com/koajs/csrf/blob/2.5.0/index.js#L69 ) 。
219
211
220
- > ** 注意 ** :上面的校验是因为框架中内置了安全插件 [ egg-security ] ( https://github.com/eggjs/egg- security ) ,提供了一些默认的安全实践,并且框架的安全插件是默认开启的,如果需要关闭其中一些安全防范,直接设置该项的 enable 属性为 false 即可 。
212
+ > ** 原因 ** :框架内部针对表单 POST 请求均会验证 CSRF 的值,因此我们在表单提交时,需要带上 CSRF key 进行提交。具体可参考 [ 安全威胁 CSRF 的防范 ] ( https://eggjs.org/zh-cn/core/ security.html#安全威胁csrf的防范 ) 。
221
213
222
- > 「除非清楚的确认后果,否则不建议擅自关闭安全插件提供的功能。」
214
+ > ** 注意 ** :上述校验是因为框架中内置了安全插件 [ egg-security ] ( https://github.com/eggjs/egg-security ) ,提供了一些默认的安全实践,并且框架的安全插件默认是开启的。如果需要关闭一些安全防范,直接设置相应选项的 ` enable ` 属性为 ` false ` 即可。
223
215
224
- > 这里在写例子的话可临时在 ` config/config.default.js ` 中设置
216
+ > 虽然不推荐,但如果确实需要关闭某些安全功能,可以在 ` config/config.default.js ` 中设置以下代码:
225
217
226
- ```
218
+ ``` javascript
227
219
exports .security = {
228
220
csrf: false
229
221
};
@@ -303,7 +295,7 @@ exports.index = async (ctx) => {
303
295
### 中间件的使用
304
296
305
297
如果我们想把用户某一类请求的参数都大写,可以通过中间件来实现。
306
- 这里我们只是简单说明下如何使用中间件,更多请查看 [ 中间件] ( ./middleware.md ) 。
298
+ 这里我们仅简单说明如何使用中间件,更多信息请参考 [ 中间件] ( ./middleware.md ) 。
307
299
308
300
``` js
309
301
// app/controller/search.js
@@ -325,7 +317,7 @@ module.exports = (app) => {
325
317
' s' ,
326
318
' /search' ,
327
319
app .middleware .uppercase (),
328
- app .controller .search ,
320
+ app .controller .search . index ,
329
321
);
330
322
};
331
323
@@ -334,9 +326,9 @@ module.exports = (app) => {
334
326
335
327
### 太多路由映射?
336
328
337
- 如上所述,我们并不建议把路由规则逻辑散落在多个地方,会给排查问题带来困扰 。
329
+ 如上所述,我们不建议在多个地方分散路由规则,这可能会导致问题排查困难 。
338
330
339
- 若确实有需求,可以如下拆分 :
331
+ 如果确实存在需求,可以采用如下方法拆分 :
340
332
341
333
``` js
342
334
// app/router.js
@@ -358,4 +350,4 @@ module.exports = (app) => {
358
350
};
359
351
```
360
352
361
- 也可直接使用 [ egg-router-plus] ( https://github.com/eggjs/egg-router-plus ) 。
353
+ 如果需要更好的路由组织方式,也可以直接使用 [ egg-router-plus] ( https://github.com/eggjs/egg-router-plus ) 。
0 commit comments