Koa学习与使用

1、koa框架

简介

       Koa是基于Node.js的下一代web框架;该框架除了本身koa库之外,还包括一些列家族中间件,如koa-body,koa-jwt,koa-route,koa-router等。koa通过使用use方法加载这些中间件,每个中间件接收两个参数,ctx对象和next函数,通过调用next将执行权交给下一个中间件。

 

Koa使用

const Koa = require('koa');

// 创建一个Koa对象
const app = new Koa();

// 对于任何请求,app将调用该异步函数处理请求:
app.use(async (ctx, next) => {

    let start = new Date();

    await next();

    let ms = new Date() - start;

    console.log(`${ctx.url}${JSON.stringify(ctx.query)} - ${ms} ms`);

});

// 错误处理,如token超时

app.use((ctxnext=> {

    return next().catch((err=> {

        // console.warn("Token Authentication", err); // Print the stack trace

        if (err.status === 401) {

            ctx.status = 401;

            ctx.body = 'Protected resource, use Authorization header to get access\n';

            // todo.. 可以ctx.body返回错误信息给用户

            return;

        } else {

            throw err;

        }

    });

});

 

app.listen(3000);
console.log('app started at port 3000...');

 

其他以上代码的参数解析如下:

ctx:由koa传入的封装了request和response的变量,我们可以通过它访问request和response;

next:是koa传入的将要处理的下一个异步函数。

await next():处理下一个异步函数,由async标记的函数称为异步函数,在异步函数中,可以用await调用另一个异步函数。

 

Koa 中 GET传值通过request接收,有两种方式: query 和 querystring

query:返回的是参数对象。 {name: 'jack', age: 12}

querystring:返回的是请求字符串。 name=jack&age=12

 

2、中间件

2.1 koa-router

koa-router是一个路由中间件,负责处理URL的映射。

1)加载koa-router

const Koa = require('koa');

// 1. 直接调用的方式

const router = require('koa-router')();

// 2. 单独创建router的实例

// const Router = require('koa-router');

const router = new Router({

  prefix: '/api'   // url添加前缀

});

router.get('/'async ctx => {

    ctx.body = 'Hello Router';

})

// 启动路由

app.use(router.routes())

  .use(router.allowedMethods())

app.listen(3000err => {

    if (errthrow err;

    console.log('runing...');

});

2)路由

router.get('/get/user'async (ctxnext=> {

  console.log(111)

  await next();

})

router.put('/put/user'async (ctxnext=> {

  console.log(222)

  await next();

})

router.post('/post/user'async ctx => {

  console.log(333)

  ctx.body = 'Hello'

}) 

如果在koa已经处理了next,则路由中不需要再次处理,因为koa会自动条用next处理下一个异步函数。

2.2 koa-body

koa-body可以实现文件上传,同时可以让koa获取post请求的参数。用于替换koa-bodyparser(处理post请

求)和koa-multer(处理图片/文件上传)

1)加载koa-body

const koaBody = require('koa-body');

const app = new koa();

app.use(koaBody({

  multipart:true// 支持文件上传

  encoding:'gzip',

  formidable:{

    uploadDir:path.join(__dirname,'public/upload/'), // 设置文件上传目录

    keepExtensions: true,           // 保持文件的后缀

    maxFieldsSize:2 * 1024 * 1024,  // 文件上传大小

    onFileBegin:(name,file=> {    // 文件上传前的设置

      // Todo...

    },

  }

})); 

2)使用koa-body

router.post('/api/file',async (ctx)=>{

  let _files = ctx.request.files;

  let _para = ctx.request.body;

  ctx.body = JSON.stringify(ctx.request.files);

});

3)参数

参数名

描述

类型

默认值

patchNode

将请求体打到原生 node.js 的ctx.req

Boolean

false

patchKoa

将请求体打到 koa 的 ctx.request 中

Boolean

true

jsonLimit

JSON 数据体的大小限制

String / Integer

1mb

formLimit

限制表单请求体的大小

String / Integer

56kb

textLimit

限制 text body 的大小

String / Integer

56kb

encoding

表单的默认编码

String

utf-8

multipart

是否支持 multipart-formdate 的表单

Boolean

false

urlencoded

是否支持 urlencoded 的表单

Boolean

true

text

是否解析 text/plain 的表单

Boolean

true

json

是否解析 json 请求体

Boolean

true

jsonStrict

是否使用 json 严格模式,true 会只处理数组和对象

Boolean

true

formidable

配置更多的关于 multipart 的选项

Object

{}

onError

错误处理

Function

function(){}

stict

严格模式,启用后不会解析  GET, HEAD, DELETE  请求

Boolean

true

2)formidable 的相关配置参数

参数名

描述

类型

默认值

maxFields

限制字段的数量

Integer

1000

maxFieldsSize

限制字段的最大大小

Integer

2 * 1024 * 1024

uploadDir

文件上传的文件夹

String

os.tmpDir()

keepExtensions

保留原来的文件后缀

Boolean

false

hash

如果要计算文件的 hash,则可以选择 md5/sha1

String

false

multipart

是否支持多文件上传

Boolean

true

onFileBegin

文件上传前的一些设置操作

Function

function(name,file){}

2.3 Koa-jwt与koawebtoken

Koa-jwt提供路由权限控制,它会对具有权限控制资源的请求进行检查,同时可以设置不需要检查的指定接

口,设定之后权限检查便会绕过这些接口。

koawebtoken用于签发和解析token。

签发:jwt.sign(payload, secretOrPrivateKey, [options, callback]),

参数如下:

payload必须是一个object, buffer或者string。请注意, expiresIn只有当payload是object字面量时才可以设置。

secretOrPrivateKey:包含HMAC算法的密钥或RSA和ECDSA的PEM编码私钥的string或buffer。

options:

  • algorithm:加密算法(默认值:HS256)
  • expiresIn:以秒表示或描述时间跨度zeit / ms的字符串。如60,"2 days","10h","7d",Expiration time,过期时间
  • notBefore:以秒表示或描述时间跨度zeit / ms的字符串。如:60,"2days","10h","7d"
  • audience:Audience,观众
  • issuer:Issuer,发行者
  • jwtid:JWT ID
  • subject:Subject,主题
  • noTimestamp
  • Header

options参数可以缩写,expiresIn,notBefore,audience,subject,issuer的缩写形式是exp,nbf,aud,sub和iss。exp,nbf,iat是NumericDate类型。

jwt.verify(token,secretOrPublicKey,[options,callback])

验证token的合法性

1)使用

const Koa = require('koa')

const Router = require('koa-router')

const jwt = require('jsonwebtoken');

const koaBody = require('koa-body')

const koaJwt = require('koa-jwt'//路由权限控制

const app = new Koa()

const  router = new Router()

//秘钥

const jwtSecret = 'jwtSecret'

const tokenExpiresTime = 1000 * 60 * 60 * 24 * 7

// Custom 401 handling if you don't want to expose koa-jwt errors to users

app.use(function(ctxnext){

    return next().catch((err=> {

        if (401 == err.status) {

            ctx.status = 401;

            ctx.body = 'Protected resource, use Authorization header to get access\n';

        } else {

            throw err;

        }

    });

});

app.use(koaJwt({

  secret: jwtSecret

}).unless({   // 以下接口不验证,其他接口都需要token验证(是否超时)jwt自动实现

  path: [

      /\/user\/login/,

      /\/user\/register/,

      /\/user\/setPwd/,

      /\/admin\/login/,

      /\/admin\/setPwd/,

  ]

}));

router.post('/user/login'koaBody(), (ctx=> {

    const user = ctx.request.body

    if (user && user.name){

        // Todo... e.g: get user.id from db

        let payload = {

          iss: jwtSecret,

          id: user.id,

          type: USER_TYPE.user

        }

        const token = jwt.sign(payload,  jwtSecret, {expiresIn: '12h'});

        ctx.body = {

            code:1,

            msg: 'login success!',

            token

        }

    }else {

        ctx.body = {

            code:-1,

            msg: 'login fail!'

        }

    }

})

router.get('/userInfo'ctx => {

  let token = ctx.header.authorization

  ctx.body = {

      token:token,

      user:ctx.state.user

  }

  //获取payload数据

 let payload = jwt.verify(token.split(' ')[1], jwtSecret);

  console.log(payload)

})

app.use(router.routes())

app.use(router.allowedMethods())

app.listen(3000, () => {

    console.log('app listening 3000...')

})

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值