koa第四章:URL中间件koa-router和koa-bodyparser用法

作者: xusx 分类: JavaScript 发布时间: 2022-03-28 15:26 浏览:32

先看看下面这段代码:

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。

如果觉得我的文章对您有用,请随意赞赏。您的支持将鼓励我继续创作!