# koa2服务端-中间件

# http处理流程

  • http请求
    • 路由操作
    • 权限处理
    • 数据安全
  • 业务操作
    • 请求数据解析
    • 数据库操作
    • 数据处理
  • http响应
    • 响应操作

# koa洋葱模型

# 简介

基于 洋葱模型 的HTTP中间件处理流程

  • 中间件开始执行
  • 中间件生命周期中
    • 前置操作
    • 等待其他中间件执行完成
    • 后置操作
  • 中间件执行完成

# 示例

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

// 最外层的中间件
app.use(async (ctx, next) => {
    console.log(`第 1 个执行`);
    await next();
    console.log(`第 6 个执行`);
});

// 第二层中间件
app.use(async (ctx, next) => {
    console.log(`第 2 个执行`);
    await next();
    console.log(`第 5 个执行`);
});

// 最里层的中间件
app.use(async (ctx, next) => {
    console.log(`第 3 个执行`);
    ctx.body = "Hello world.";
    console.log(`第 4 个执行`);
});

app.listen(3000, () => {
    console.log(`Server port is 3000.`);
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

# async中间件开发

function log( ctx ) {
    console.log( ctx.method, ctx.header.host + ctx.url )
}

module.exports = function () {
  return async function ( ctx, next ) {
    log(ctx);
    await next()
  }
}
1
2
3
4
5
6
7
8
9
10

# 中间件开发示例

# logger

放置于中间件最上层

module.exports = (options) => async (ctx, next) {
  try {
    const date = new Date()
    // 下一个中间件
    await next()
    const endDate = new Date()
    // trace
    logger4.trace(`${date}: ${ctx.url}: ${endDate - date}`)
  } catch (err) {
    console.log(err)
    // 记录err
    logger4.error(`${date}: ${ctx.url}, ${err}`)
  }
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# token验证

module.exports = (options) => async (ctx, next) {
  try {
    // 获取 token
    const token = ctx.header.authorization
    if (token) {
      try {
          // 验证 token
          await verify(token)
      } catch (err) {
        console.log(err)
      }
    }
    // 下一个中间件
    await next()
  } catch (err) {
    console.log(err)
  }
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

# 中间件使用示例

const Koa = require('Koa');
const app = new Koa();
const logger = require('./logger')
const token = require('./token')

app.use(logger())
app.use(token())

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

// 普通函数
app.use((ctx, next) => {
  const start = Date.now();
  return next().then(() => {
    const ms = Date.now() - start;
    console.log(`${ctx.method} ${ctx.url} - ${ms}ms`);
  });
});


app.listen(3000, () => {
    console.log(`Server port is 3000.`);
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

# 常用中间件

# koa-static

静态资源处理

const app = new Koa()
const koaStatic = require('koa-static')
app.use(koaStatic(
  path.join(__dirname, staticPath)
))
1
2
3
4
5

# koa-bodyparser

读取请求体数据,ctx.request.body

const koaBodyParser = require('koa-bodyparser')
// 设置ctx.request.body
app.use(koaBodyParser())
1
2
3

# koa-body

请求中文件资源处理,ctx.request.files

const koaBody = require('koa-body')
app.use(koaBody({ multipart: true }))
1
2

# koa-router

路由处理

const router = require('koa-router')()
router.get('/', cb)
router.use(`/person`, person.routes(), person.allowedMethods())
app.use(router.routes())
1
2
3
4