Skip to content

路由&跨域&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 动词的小写,举例

动词名称
HEADrouter.head
OPTIONSrouter.options
GETrouter.get
PUTrouter.put
POSTrouter.post
PATCHrouter.patch
DELETErouter.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;