koa-router 入门与使用
koa-router
Koa 的路由中间件
使用方式
new Router([opts]);
创建一个路由.
选项参数:
- opts :
Object
- opts.prefix :
String
- 设置路由的前缀
例子:
基本用法:
const Koa = require("Koa");
const Router = require("@koa/router");
// 初始化 koa 实例
const app = new Koa();
// 初始化路由实例
const router = new Router();
// 设置路由
router.get("/", ctx => {
// ctx.router 可以访问
// 做一些当前路由的处理
});
// 注册路由中间件
app.use(router.routes()).use(router.allowedMethods());
router.get|put|post|patch|delete|del => Router
创建 router
请求方法, 请求可以是上面的 get|put|post|patch|delete|del
之一, 比如 router.get()
和 router.post()
。
路由请求中的第一个参数, 如 /
会和 URL
模式进行匹配, 如果匹配成功就掉对应的 回调函数
或 控制器
对路由请求进行处理。
router.all()
会匹配所有的请求方法。
router
.get("/", (ctx, next) => {
ctx.body = "Hello,World";
})
.post("/users", (ctx, next) => {
// ...
})
.put("/users/:id", (ctx, next) => {
// ...
})
.del("/users/:id", (ctx, next) => {
// ...
})
.all("/users/:id", (ctx, next) => {
ctx.body = ctx.params;
});
如果路径匹配时, 它的路径在 ctx._matchedRoute
可访问, 如果命名, 则名称在 ctx._matchedRouteName
中可用。
路由路径将被转换为正则表达式, 使用到的转换库是 path-to-regexp
的规则。
匹配请求时暂时将不考虑查询字符串。
命名路由
路由可以选择有名称。这允许生成 URL 并在开发过程中轻松重命名 URL, 方便在开发过程中使用和通过 ctx._matchedRouteName
来访问当前路由器的名称。
router.get("user", "/users/:id", ctx => {
console.log(ctx._matchedRouteName); // user
ctx.body = ctx.params;
});
多个中间件
可以给当前路由匹配, 提供多个中间件函数。
router.get(
"/users/:id",
async (ctx, next) => {
if (ctx.params.id === "1") {
await next();
} else {
ctx.status = 401;
ctx.body = "无权访问";
}
},
ctx => {
ctx.body = ctx.params;
}
);
可以做一些权限校验等, 这个路由内部 Layer
是横向存储中间件的。
嵌套路由
支持嵌套路由
// 论坛路由实例
const forums = new Router();
// 帖子路由实例
const posts = new Router();
posts.get("/", (ctx, next) => {
ctx.body = ctx.request.url;
});
posts.get("/:pid", (ctx, next) => {
ctx.body = {
url: ctx.request.url,
params: ctx.params
};
});
// 注册嵌套路由
forums.use("/forums/:fid/posts", posts.routes(), posts.allowedMethods());
// 注册路由中间件
app.use(forums.routes());
路由器前缀
路由路径可以在路由器级别加上前缀。
// 初始化路由实例
const router = new Router({
prefix: "/users"
});
router.get("/", ctx => {
ctx.body = ctx.url;
});
router.get("/:id", ctx => {
ctx.body = ctx.params;
});
// 注册路由中间件
app.use(router.routes()).use(router.allowedMethods());
URL 参数
动态路由会通过正则匹配到值后, 将作为 key
和 value
的形式添加到 ctx.params
属性上。
router.get("/:category/:title", (ctx, next) => {
console.log(ctx.params);
// => { category: 'programming', title: 'how-to-node' }
});
path-to-regexp 模块用于将路径转换成正则表达式。
router.routes()
=> Function
返回分配给与请求匹配的路由的路由器中间件。
router.use([path], middleware)
=> Router
使用给定的中间件
中间件按照 .use()
定义的顺序运行。它们是按顺序调用的, 请求从第一个中间件开始, 并按照中间件栈的方式工作。
// session 中间件会在 authorize 中间件之前执行
router.use(session()).use(authorize());
// 仅在给定路径下使用中间件
router.use("/users", userAuth());
// 在 /users 或 /admin 路径下调用 userAuth 中间件
router.use(["/users", "/admin"], userAuth());
app.use(router.routes());
router.prefix(prefix)
=> Router
为已经初始化的路由器实例设置路径前缀
// 初始化路由实例
const router = new Router().prefix("/users");
router.get("/", ctx => {
ctx.body = ctx.url;
});
router.get("/:id", ctx => {
ctx.body = ctx.params;
});
// 注册路由中间件
app.use(router.routes()).use(router.allowedMethods());
router.allowedMethods([options])
=> Function
返回单独的中间件函数, 用于处理响应选项请求, 其中包含允许的方法和运行的头部字段。
例子
const Koa = require("koa");
const Router = require("@koa/router");
const app = new Koa();
const router = new Router();
app.use(router.routes());
app.use(router.allowedMethods());
或者
const Koa = require("koa");
const Router = require("@koa/router");
const Boom = require("boom");
const app = new Koa();
const router = new Router();
app.use(router.routes());
app.use(
router.allowedMethods({
throw: true,
notImplemented: () => new Boom.notImplemented(),
methodNotAllowed: () => new Boom.methodNotAllowed()
})
);
router.redirect(source, destination, [code])
=> Router
用可选的 30x
状态代码重定向 source
到 destination
路径。
source
和 destination
都可以是路由名称。
// 初始化路由实例
const router = new Router();
router.get("/", ctx => {
ctx.body = "Hello";
});
router.get("about", "/about", ctx => {
ctx.body = "重定向到了这里";
});
router.redirect("/user", "about");
// 注册路由中间件
app.use(router.routes()).use(router.allowedMethods());
router.route(name)
=> Layer | false
通过名字搜索路由
// 初始化路由实例
const router = new Router();
router.get("/", ctx => {
ctx.body = "Hello";
});
router.get("about", "/about", ctx => {
ctx.body = "重定向到了这里";
});
router.redirect("/user", "about");
console.log(router.route("about"));
/**
Layer {
opts: {
end: true,
name: 'about',
sensitive: false,
strict: false,
prefix: '',
ignoreCaptures: undefined
},
name: 'about',
methods: [ 'HEAD', 'GET' ],
paramNames: [],
stack: [ [Function] ],
path: '/about',
regexp: /^\/about(?:\/(?=$))?$/i { keys: [] }
}
*/
router.url(name, params, [options])
=> String | Error
生成路由 URL, 获取命名为 params 的路由名称和地图
router.get("user", "/users/:id", (ctx, next) => {
// ...
});
router.url("user", 3);
// => "/users/3"
router.url("user", { id: 3 });
// => "/users/3"
router.use((ctx, next) => {
// redirect to named route
ctx.redirect(ctx.router.url("sign-in"));
});
router.url("user", { id: 3 }, { query: { limit: 1 } });
// => "/users/3?limit=1"
router.url("user", { id: 3 }, { query: "limit=1" });
// => "/users/3?limit=1"