路由&跨域&CURL
路由
基础版
路由定义了 请求路径(URL) 和 控制器(Controller) 之间的映射关系,即用户访问的网址应交由哪个控制器进行处理。我们打开 app/router.js
看一下:
js
module.exports = (app) => {
const { router, controller } = app;
router.get("/", controller.home.index);
};
- 路由定义
- 找到 router.js 在里面写对应的路由信息 比如
js
module.exports = (app) => {
const { router, controller } = app;
router.get("/login", controller.get.login.index);
};
- 这句代码的意思是:
bash
用户用get方法访问路径是login的时候,由controller下面的get文件夹下面的login.js文件下面的index这个方法来处理
- 动词介绍
可以看到,路由文件导出了一个函数,接收 app 对象作为参数,通过下面的语法定义映射关系:
js
router.verb("path-match", controllerAction);
其中verb
一般是 http 动词的小写,举例
动词 | 名称 |
---|---|
HEAD | router.head |
OPTIONS | router.options |
GET | router.get |
PUT | router.put |
POST | router.post |
PATCH | router.patch |
DELETE | router.delete 或 router.del |
除此之外,还有一个特殊的动词 router.redirect
表示重定向。
- 函数匹配
而 controllerAction 则是通过点(·)语法指定 controller 目录下某个文件内的某个具体函数,例如:
bash
controller.home.index // 映射到 controller/home.js 文件的 index 方法
controller.v1.user.create // controller/v1/user.js 文件的 create 方法
- 其他
- RestFul 风格
Egg Router 支持以 Restful 风格定义路由,例如:
js
router.resources("posts", "/posts", controller.posts);
上述代码定义了以下映射关系:
- GET /posts -> controller.posts.index
- GET /posts/new -> controller.posts.new
- GET /posts/:id -> controller.posts.show
- GET /posts/:id/edit -> controller.posts.edit
- POST /posts -> controller.posts.create
- PATCH /posts/:id -> controller.posts.update
- PUT /posts/:id -> controller.posts.update
- DELETE /posts/:id -> controller.posts.destroy
只需要到controller中实现对应的方法即可
- 路由重定向
js
router.redirect("/home", "/");
插件版 egg-router-plus
这个插件好处就 2 点 1.自动导入 router 文件夹下面的文件夹(仅一层)下面的 js 文件 2.支持 namespace 命名空间
- 安装
bash
npm install egg-router-plus --save
- 配置
在 config/plugin.js 中启用插件:
js
exports.routerPlus = {
enable: true,
package: "egg-router-plus",
};
- 使用
特别注意 controller 下面的文件夹名字和路由名必须小写,注意:prefix 和 path 不能是正则表达式,prefix 不能是 /。
- (1) 在 app 目录下新建一个 router 文件夹
在这个文件夹下面新建一个 xxx.js 文件(你自己定义的路由文件)
- (2) 在 xxx.js 里面写路由信息
js
module.exports = (app) => {
const { router, controller } = app;
// router
const subRouter = router.namespace("/login");
subRouter.get("/:id", controller.login.loginapi.index);
// 这个结果就是 /login/:id ,调用controller/login文件夹下面的loginapi.js文件下面的index方法
};
- (3) 在控制器里面实现对应的方法
js
const { Controller } = require("egg");
class LoginController extends Controller {
async index() {
const { ctx } = this;
const result = ctx.params.id;
ctx.body = `测试登陆有没有${result}`;
}
}
module.exports = LoginController;
- 使用中间件(后续会说)
bash
router.verb('path-match', app.controller.action);
router.verb('path-match', middleware1, ..., middlewareN, app.controller.action);
router.verb('router-name', 'path-match', app.controller.action);
router.verb('router-name', 'path-match', middleware1, ..., middlewareN, app.controller.action);
路由参数
GET 有两种方式
- 第一种 自由模式 通过
?
例如:?id=3&name=xxx
通过ctx.query
获取
js
// 自由传参模式 通过?
async getquery() {
const { ctx } = this;
const result = JSON.stringify(ctx.query);
ctx.body = `<h1>getquery: ${result}</h1>`;
}
- 第二种 严格模式 通过路径 例如
/:name/:id
通过ctx.params
获取
/:name/:id?
表示 id 可以传或者不传,这里的?只能放到结尾
js
async getyangequery() {
const { ctx } = this;
const result = JSON.stringify(ctx.params);
ctx.body = `<h1>getquery: ${result}</h1>`;
}
POST
- 通过
ctx.request.body
获取
js
async postquery() {
const { ctx } = this;
const result = JSON.stringify(ctx.request.body);
ctx.body = `<h1>postquery: ${result}</h1>`;
}
跨域
安装
bash
npm i egg-cors --save
配置插件
- {app_root}/config/plugin.js
js
exports.cors = {
enable: true,
package: "egg-cors",
};
配置
- config / config.default.js 目录下配置
js
config.security = {
// 关闭 csrf
csrf: {
enable: false,
},
// 跨域白名单
domainWhiteList: ["http://localhost:3000"],
};
// 允许跨域的方法
config.cors = {
origin: "*",
allowMethods: "GET, PUT, POST, DELETE, PATCH",
// cookie跨域配置
credentials: true,
};
CURL
有的时候服务器也需要给别的服务器发送请求,这个时候就需要用到 curl
创建对应的路由和 控制器
- 路由(新建 httpclient.js)
js
module.exports = (app) => {
const { router, controller } = app;
// router
const HttpRouter = router.namespace("/httpclient");
HttpRouter.get("/get", controller.httpclient.httpclient.get);
HttpRouter.post("/post", controller.httpclient.httpclient.post);
};
控制器里面使用 curl
js
"use strict";
const Controller = require("egg").Controller;
class HttpClientController extends Controller {
async get() {
const { ctx } = this;
// 示例:请求一个 npm 模块信息
const result = await ctx.curl("https://httpbin.org/get?foo=bar", {
// 自动解析 JSON 响应
dataType: "json",
// 3 秒超时
timeout: 3000,
//头部
headers: {},
});
ctx.body = result.data; // 响应结果
}
async post() {
const { ctx } = this;
const result = await ctx.curl("https://httpbin.org/post", {
// 必须指定 method
method: "POST",
// 通过 contentType 告诉 HttpClient 以 JSON 格式发送
contentType: "json",
data: {
hello: "world",
now: Date.now(),
},
// 明确告诉 HttpClient 以 JSON 格式处理返回的响应 body
dataType: "json",
headers: {},
});
ctx.body = result.data;
}
}
module.exports = HttpClientController;