先看看下面这段代码:
const koa = require('koa2');
const app = new koa();
app.use(async (ctx, next) => {
if (ctx.request.path === '/') { // 首页
ctx.response.status = 200;
ctx.response.body = 'index';
} else if (ctx.request.path === '/list') { // 列表页
ctx.response.status = 200;
ctx.response.body = 'list';
} else {
ctx.throw(404, 'Not found'); // 404
}
await next();
});
app.listen(3000);
显然,在实际工作中,这样很难处理包含众多 path 和复杂业务逻辑。早就有人封装成特定的插件共享到社区,解决我们这个问题的模块,叫做 koa-router,接下来我们使用它。
一、安装
npm i -S koa-router
npm i -S koa-bodyparser
相关内容:
koa第七章:路由管理模块
二、用例
// app.js
const path = require('path');
const Koa = require('koa');
const Router = require('koa-router');
const bodyParser = require('koa-bodyparser');
const app = new Koa();
const router = new Router();
const router1 = new Router({prefix:'/users'});
// log request URL:
app.use(async (ctx, next) => {
console.log(`Process ${ctx.request.method} ${ctx.request.url}...`);
await next();
});
router.get('/', async (ctx, next) => {
ctx.response.body = `<h1>Index</h1>
<form action="/signin" method="post">
<p>Name: <input name="name" value="koa"></p>
<p>Password: <input name="password" type="password"></p>
<p><input type="submit" value="Submit"></p>
</form>`;
});
// curl -i http://localhost:3000/signin/ -d "name=koa&&password=12345"
router.post('/signin', async (ctx, next) => {
// console.log(ctx);
// console.log(ctx.request);
// console.log(ctx.request.body); // undefined
console.log(ctx.request.rawBody);
// 无论是Node.js提供的原始request对象,还是koa提供的request对象,都不提供解析request的body的功能!
// 所以,我们又需要引入另一个middleware来解析原始request请求,然后,把解析后的参数,绑定到ctx.request.body中。
ctx.body = ctx.request.body;
var name = ctx.body.name || '',
password = ctx.body.password || '';
console.log(`signin with name: ${name}, password: ${password}`);
ctx.response.type = 'text/html';
if (name === 'koa' && password === '12345') {
ctx.response.body = `<h1>Welcome, ${name}!</h1>`;
} else {
ctx.response.body = `<h1>Login failed!</h1>
<p><a href="/">Try again</a></p>`;
}
});
router.get('home', '/h/:id', (ctx, next) => { // 命名路由
ctx.response.body = '<h1>home</h1>';
});
var findM = async function(id) {
var user = 'unkown';
switch (id) {
case '1':
user = 'xusx';
break;
}
return user;
};
// 多个中间件
router.get(
'/m/:id', async (ctx, next) => { // log:1->3->5->4->2
return findM(ctx.params.id).then(function(user) {
console.log('1');
ctx.user = user;
next();
console.log('2');
// 不是 await next();
// 等待仅在异步函数中有效
// 当一个中间件调用 next() 则该函数暂停并将控制传递给定义的下一个中间件。
// 当在下游没有更多的中间件执行后,堆栈将展开并且每个中间件恢复执行其上游行为。
});
}, async (ctx, next) => {
console.log('3');
console.log(`user:${ctx.user}`);
next();
// return next(); 执行这句,后面log.4就不会执行了
console.log('4');
}, ctx => {
console.log('5');
ctx.response.body = `<h1>${ctx.user}</h1>`;
}
);
router.get('/page', async (ctx, next) => {
ctx.body = `Request Body: ${JSON.stringify(ctx.request.body)}`;
});
router.post('/page', async (ctx, next) => {
ctx.response.body = '<h1>page</h1>';
// ctx.body = `Request Body: ${JSON.stringify(ctx.request.body)}`;
});
router.all('/other', ctx => {
ctx.redirect('/');
ctx.status = 301;
});
router1.get('/', async (ctx, next) => { // responds to "/users"
console.log(ctx);
ctx.response.body = '<h1>/users</h1>';
});
router1.get('/:id', async (ctx, next) => { // responds to "/users/:id"
// http://127.0.0.1:3000/users/1?a=2&b=3
console.log(ctx);
console.log(ctx.params);
console.log(ctx.query);
console.log(ctx.querystring);
ctx.response.body = '<h1>/users/:id</h1><div>'+ctx.params.id+'</div>';
});
app.use(bodyParser());
app.use(router.routes());
app.use(router.allowedMethods());
app.use(router1.routes());
// app.use(router1.allowedMethods());
// 404:确保它被添加在所有其他内容之后
// app.use(function *(){
// this.body = 'Invalid URL!'; // or this.redirect('/someotherspot');
// });
app.use(async ctx =>{
ctx.body = 'Invalid URL!!!';
});
app.listen('3000',(err)=>{
if(err){
console.log('服仵器启动失败');
}else{
console.log('服务器启动成功');
}
});
koa-bodyparser必须在router之前被注册到app对象上。
koa-bodyparser是个很不错的选择,支持x-www-form-urlencoded, application/json等格式的请求体,但它不支持form-data的请求体,需要借助 formidable 这个库,也可以直接使用 koa-body 或 koa-better-body 或 koa-multer。