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"