玩转 koa

715 阅读3分钟

简介

Koa 是现在最流行的基于Node.js平台的web开发框架。

  • koa 是由 Express 原班人马打造的
  • 致力于成为一个更小、更富有表现力、更健壮的 Web 框架。
  • koa 不在内核方法中绑定任何中间件,它仅仅提供了一个轻量优雅的函数库,使得编写 Web 应用变得得心应手。

官网:koajs.com/

中文社区:www.koajs.com.cn/

安装

npm i koa

hello world

  • Koa 应用程序是一个包含一组中间件函数的对象,它是按照类似堆栈的方式组织和执行的。
const Koa = require('koa');
const app = new Koa();

app.use(async ctx => {
  ctx.body = 'Hello World';
});

app.listen(3000);

级联中间件

app.use(fn1);
app.use(fn2);
app.use(fn3);

const Koa = require('koa');
const app = new Koa();

// x-response-time

app.use(async (ctx, next) => {
  const start = Date.now();
  await next();
  const ms = Date.now() - start;
  ctx.set('X-Response-Time', `${ms}ms`);
});

// logger

app.use(async (ctx, next) => {
  const start = Date.now();
  await next();
  const ms = Date.now() - start;
  console.log(`${ctx.method} ${ctx.url} - ${ms}`);
});

// response

app.use(async ctx => {
  ctx.body = 'Hello World';
});

app.listen(3000);

上下文(Context)

  • Koa Context 将 node 的 request 和 response 对象封装到单个对象中,为编写 Web 应用程序和 API 提供了许多有用的方法

  • ctx.request // 这是 koa Request

  • ctx.response // 这是 koa Response

  • ctrx.req //原始的http请求对象

  • ctx.res //原始的http响应对象

  • ctx.app 应用程序实例引用

  • ctx.request是Koa2中context经过封装的请求对象

  • 绕过 Koa 的 response 处理是 不被支持的

获取请求参数

const Koa = require('koa');
const app = new Koa();
app.use(async (ctx) => {
    console.log(ctx.method); //获取请求方法
    console.log(ctx.url);    //获取请求URL
    console.log(ctx.query);  //获取解析的查询字符串对象
    console.log(ctx.querystring); //根据 ? 获取原始查询字符串
    console.log(ctx.headers);//获取请求头对象
    ctx.body = ctx.url;
});

app.listen(3000, () => {
    console.log('server is starting at port 3000');
});

获取请求体

const querystring = require('querystring');
const app = new Koa();
app.use(async (ctx) => {
    if (ctx.method == 'GET') {
        ctx.set('Content-Type', 'text/html;charset=utf-8');
        ctx.body = (
            `
            <form method="POST">
               <input name="username" >
               <input type="submit">
            </form>
            `
        );
    } else if (ctx.method == 'POST') {
        ctx.set('Content-Type', 'application/json');
        ctx.body = await parsePostBody(ctx);
    } else {
        ctx.body = 'Not Allowed';
    }
});
/**
* 自己封装函数处理post提交的数据
*/
function parsePostBody(ctx) {
    return new Promise(function (resolve, reject) {
        let buffers = [];
        ctx.req.on('data', function (data) {
            buffers.push(data);
        });
        ctx.req.on('end', function (data) {
            let body = buffers.toString();
            body = querystring.parse(body);
            resolve(body);
        });
        ctx.req.on('error', function (errdata) {
            reject(err);
        });
    });
}

app.listen(3000, () => {
    console.log('server is starting at port 3000');
});

使用中间件获取普通请求体

koa-bodyparser

npm i koa-bodyparser -S
const Koa = require('koa');
const querystring = require('querystring');
const bodyParser = require('koa-bodyparser');
const app = new Koa();
app.use(bodyParser());
app.use(async (ctx) => {
    if (ctx.method == 'GET') {
        ctx.set('Content-Type', 'text/html;charset=utf-8');
        ctx.body = (
            `
            <form method="POST">
               <input name="username" >
               <input type="submit">
            </form>
            `
        );
    } else if (ctx.method == 'POST') {
        ctx.set('Content-Type', 'application/json');
        ctx.body = ctx.request.body;
    } else {
        ctx.body = 'Method Not Allowed';
    }
});

app.listen(3000, () => {
    console.log('server is starting at port 3000');
});

获取包含文件的请求体

koa-better-body

npm i koa-better-body
const Koa = require('koa');
const querystring = require('querystring');
const path = require('path');
const convert = require('koa-convert');
const bodyParser = require('koa-better-body');
const app = new Koa();
app.use(convert(bodyParser({
    uploadDir: path.join(__dirname, 'uploads'),
    keepExtensions: true
})));
app.use(async (ctx) => {
    if (ctx.method == 'GET') {
        ctx.set('Content-Type', 'text/html;charset=utf-8');
        ctx.body = (
            `
            <form method="POST" enctype="multipart/form-data">
               <input name="username" >
               <input name="avatar" type="file" >
               <input type="submit">
            </form>
            `
        );
    } else if (ctx.method == 'POST') {
        ctx.set('Content-Type', 'application/json');
        console.log(ctx.request.fields);
        ctx.body = ctx.request.body;
    } else {
        ctx.body = 'Method Not Allowed';
    }
});

app.listen(3000, () => {
    console.log('server is starting at port 3000');
});

路由中间件

koa-router

npm i  koa-router

单路由

const Koa = require('koa');
const Router = require('koa-router');
const app = new Koa();

let user = new Router();
user.get('/user', function (ctx) {
    ctx.body = 'get user ';
}).get('/query/:id', function (ctx) {
    ctx.body = ctx.params;
}).post('/user', function (ctx) {
    ctx.body = 'post user ';
}).get('/home', function (ctx) {
    ctx.body = 'get home ';
});
app.use(user.routes());

app.listen(3000, () => {
    console.log('server is starting at port 3000');
});

多级路由

let user = new Router();
user.get('/add', function (ctx) {
    ctx.body = 'get user add ';
});

let article = new Router();
article.get('/add', function (ctx) {
    ctx.body = 'get article add ';
});

let router = new Router();
router.use('/user', user.routes());
router.use('/article', article.routes());
app.use(router.routes());

会话-cookie

  • ctx.cookies.get(name,[optins]):读取上下文请求中的cookie。
  • ctx.cookies.set(name,value,[options]):在上下文中写入cookie。
    • domain:写入cookie所在的域名
    • path:写入cookie所在的路径
    • maxAge:Cookie最大有效时长
    • expires:cookie失效时间
    • httpOnly:是否只用http请求中获得
    • overwirte:是否允许重写
app.use(async (ctx, next) => {


    if (ctx.url == '/write') {
        ctx.cookies.set('name', 'gogery');
        ctx.body = 'write cookie';
    } else {
        next();
    }
});
app.use(async (ctx) => {
    if (ctx.url == '/read') {
        ctx.body = ctx.cookies.get('name');
    }
});

会话-session

koa-session

npm install koa-session
const Koa = require('koa');
const session = require('koa-session');
const app = new Koa();
app.keys = ['some secret string'];

app.use(session({}, app));
app.use(async (ctx) => {
    let visit = ctx.session.visit;
    if (visit) {
        visit = visit + 1;
    } else {
        visit = 1;
    }
    ctx.session.visit = visit;
    ctx.body = `这是你的第${visit}次访问`;
});
app.listen(3000);

模板引擎

koa-view

npm i koa-views ejs
const Koa = require('koa');
const views = require('koa-views');
const path = require('path');
const app = new Koa();
app.use(views(path.join(__dirname, './views'), {
    extension: 'ejs'
}));

app.use(async ctx => {
    await ctx.render('index', { title: '模板引擎' });
});

app.listen(3000, () => {
    console.log('server is starting at port 3000');

静态资源中间件

koa-static

npm i koa-static
const static = require('koa-static')
const app = new Koa()
app.use(static(path.join( __dirname,  'public')))
app.use( async ( ctx ) => {
  ctx.body = 'File Not Found'
})