路由(Router)
框架約定了app/router.js文件用於統一所有路由規則。
Router 主要用來描述請求URL和具體承擔執行動作的 Controller 的對應關系
定義路由(Router)
// app/router.js 里面定義 URL 路由規則
module.exports = app => {
const { router, controller } = app;
router.get('/user/:id', controller.user.info); // 動態路由傳參
};
// app/controller 目錄下面實現 Controller
// app/controller/user.js
class UserController extends Controller {
async info() {
this.ctx.body = `hello ${ctx.params.id}`, 使用params接收
}
}
Router詳細定義說明,完整路由定義包括5個主要部分
router.verb('path-match', app.controller.action);
router.verb('router-name', 'path-match', app.controller.action);
router.verb('path-match', middleware1, ..., middlewareN, app.controller.action);
router.verb('router-name', 'path-match', middleware1, ..., middlewareN, app.controller.action);
1. verb: 用戶觸發動作,get,post等所有HTTP方法
2. router-name: 給路由取一個別名,可以通過 Helper 提供的輔助函數 pathFor 和 urlFor 來生成 URL
3. path-match: 路由URL路徑
4. middleware1: 在router里面可以配置多個中間件
5. controller: 指定路由映射到具體的controller上
注意事項
1. 在router定義中,可以支持多個middleware(中間件)
2. controller必須定義在app/controller目錄中
3. 一個文件中可以包含多個Controller定義,定義路由的時候可以通過${fileName}.${functionName}的方式指定對應的controller
4. Controll支持子目錄,可以通過${directoryName}.${fileName}.${functionName}的方式獲取
// app/router.js
module.exports = app => {
const { router, controller } = app;
router.get('/home', controller.home);
router.get('/user/:id', controller.user.page); // 動態路由,可以接收參數id
router.post('/admin', isAdmin, controller.admin);
router.post('/user', isLoginUser, hasAdminPermission, controller.user.create);
router.post('/api/v1/comments', controller.v1.comments.create); // app/controller/v1/comments.js
};
參數獲取
Query String方式
// app/router.js
module.exports = app => {
app.router.get('/search', app.controller.search.index);
};
// app/controller/search.js
exports.index = async ctx => {
ctx.body = `searchInfo: ${ctx.query.name}`; // => 'searchInfo: egg'
};
// curl http://127.0.0.1:7001/search?name=egg
參數命名方式(動態路由)
// app/router.js
module.exports = app => {
app.router.get('/user/:id/:name', app.controller.user.info);
};
// app/controller/user.js
exports.info = async ctx => {
ctx.body = `userInfo: ${ctx.params.id}, ${ctx.params.name}`; // => 'userInfo: 123, xiaoming'
};
// curl http://127.0.0.1:7001/user/123/xiaoming
表單內容的獲取
// app/router.js
module.exports = app => {
app.router.post('/form', app.controller.form.post);
};
// app/controller/form.js
exports.post = async ctx => {
ctx.body = `body: ${JSON.stringify(ctx.request.body)}`;
};
// 模擬發起post請求
let options = {
url: '/form',
method: 'post',
data: {name: 'jack', age: 18},
headers: {'Content-Type': 'application/json'}
}
axios(options).then(data=> {console.log(data)})
//=> 'body: {name: 'jack', age: 18}' promise對象
// 注意,這里直接發起post請求會報錯
// 原因:框架內部針對表單POST請求均會驗證CSRF的值,因此我們在表單提交時,請帶上CSRF key 進行提交
// 校驗是因為框架中內置了安全插件egg-security,提供了一些安全的實踐,默認是開啟的,
// 詳情查看:https://eggjs.org/zh-cn/core/security.html#安全威脅csrf的防范
// 如果需要關閉其中一些安全防范,直接設置該項的 enable 屬性為 false 即可
// config/config.default.js
exports.security = {
csrf: false
};
重定向
內部重定向
// app/router.js
module.exports = app => {
app.router.get('/home/index', app.controller.home.index);
app.router.redirect('/', '/home/index', 302); //根路由重定向/home/index路由
};
// app/controller/home.js
exports.index = async ctx => {
ctx.body = 'hello controller';
};
// curl -L http://localhost:7001
外部重定向
// app/router.js
module.exports = app => {
app.router.get('/search', app.controller.search.index);
};
// app/controller/search.js
exports.index = async ctx => {
const type = this.ctx.request.query.type;
const q = this.ctx.request.query.q || 'node.js';
if (type === 'bing') {
this.ctx.redirect(`http://localhost:7001/home/index?q=${q}`);
} else {
this.ctx.redirect(`http://localhost:7001/user/123/jack?q=${q}`);
}
};
// curl http://localhost:7001/search?type=bing&q=node.js
// curl http://localhost:7001/search?q=node.js
多路由映射
// app/router.js
module.exports = app => {
require('./router/news')(app);
require('./router/admin')(app);
};
// app/router/news.js
module.exports = app => {
app.router.get('/news/list', app.controller.news.list);
app.router.get('/news/detail', app.controller.news.detail);
};
// app/router/admin.js
module.exports = app => {
app.router.get('/admin/user', app.controller.admin.user);
app.router.get('/admin/log', app.controller.admin.log);
};