koa2的中间件功能及应用示例


Posted in Javascript onMarch 05, 2020

最近因为开发一个自己的博客网站,学习了koa2的搭建,写了一些自己认为比较重要或需要知道的koa2中间件作用和使用场景。

koa-router

路由中间件

下载

npm i koa-router

使用

普通使用方法

需要注意的是引入的koa-router是一个方法,引入后需要执行这个方法。

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

// 配置路由url 
// 默认url 
router.get('/', async (ctx, next) => { 
 ctx.body = 'Hello World'; 
}); 

// 自定义url 
router.get('/hello/:name', async (ctx, next) => { 
 var name = ctx.params.name; 
 ctx.response.body = \`<h1>Hello, ${name}!</h1>\`; 
}); 

// 注册路由 
app.use(router.routes(), router.allowedMethods());

也可以按需引入并注册路由,可注册多个路由。

不同请求下接收的参数获取

router.get

通过ctx.query获取参数

router.post
通过ctx.request.body获取参数

动态路由 router.get('/:id', func)
通过ctx.params获取参数

遍历注册router

首先引入nodejs中的fs模块,使用fs的readdirSync方法获取到指定目录的所有文件名,遍历引入路由模块并注册。

const fs = require('fs'); 

// fs.readdirSync 获取指定目录下的所有文件名称,遍历引入路由模块并注册 
fs.readdirSync('./routes').forEach(route=> { 
 let api = require(\`./routes/${route}\`); 
 app.use(api.routes(), api.allowedMethods()); 
});

koa-router中的其它api

router.prefix(prefix) 添加url前缀

设置已经初始化的路由器实例的路径前缀

router.prefix('/user'); 
router.post('/login', function(ctx, next) { 
 ... 
}); 

// 实际路径 /user/login

router.use(url|[url1,url2,...], (ctx, next) => {...}) 路由中间件

使用场景:我们通常需要通过验证用户和用户权限来判定用户是否能使用该接口,如果在每个接口都写一次验证非常麻烦且不好维护。这时我们就需要路由中间件先进行验证,再执行下面操作。

router.use的第一个参数为一个路径或者由多个需要使用中间件的路径组成的数组(需要注意的是,如果路由设置了url前缀,需要在设置前缀后注册中间件,参数中的url不需要设置前缀)。

router.use的第二个参数为函数,函数传递ctx和next两个参数,可通过ctx进行权限验证后,判断是否执行next调用接口。这里特别需要注意的是函数使用next的时候需要添加await,如果不添加,在调用接口前,接口就会返回结果,前台则无法获取到数据。

// this is wrong 
 app.use(function (ctx, next) { 
  ctx.set("Access-Control-Allow-Origin", "\*"); 
  next(); 
 }); 
 // this is right 
 app.use(async function (ctx, next) { 
  ctx.set("Access-Control-Allow-Origin", "\*"); 
  await next(); 
 });

koa-bodyparser处理post请求

处理post请求时,我们会遇到一个问题,无论是node的request对象还是koa的request对象,都没办法解析request的body,我们就需要下载并引入一个解析body的中间件koa-bodyparser,koa-bodyparser的具体配置详见下面的说明,这里我们直接放入使用方式。

// 引入路由文件 
 const index = require('./routes/index.js'); 
 const user = require('./routes/user.js'); 

 // 引入解析request.body的中间件 
 const bodyparser = require('koa-bodyparser'); 

 // 注册bodyparser,需要注意,bodyparser的注册一定要在router路由注册之前 
 app.use(bodyparser({ 
  enableTypes:\['json', 'form', 'text'\] 
 })); 

 ... 

 // 注册routes 
 app.use(index.routes(), index.allowedMethods()); 
 app.use(user.routes(), user.allowedMethods());

koa-bodyparser

如上所述,koa-bodyparser用于解析request.body,因为node和koa的request无法解析body。

下载

npm i koa-bodyparser

使用

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

在注册运行时,bodyparser方法中可传入对象,作相应配置。

- enableTypes:解析器只在配置了enableTypes时解析请求类型,默认是['json', 'form']。
- encoding:请求编码,默认是utf-8。
- formLimit:urlencoded body的imit如果主体最终大于此限制,则返回一个413错误代码。默认是56 kb。
- jsonLimit:json主体的限制。默认是1 mb。
- textLimit:文本主体的限制。默认是1 mb。
- strict:当设置为true时,JSON解析器将只接受数组和对象。默认是正确的。参见正文中的严格模式。在严格模式下,ctx.request。body总是一个对象(或数组),这避免了很多类型判断。但文本正文总是返回字符串类型。
- detectJSON:自定义json请求检测函数。默认为null。

app.use(bodyparser({ 
 detectJSON: function (ctx) { 
 return /\\.json$/i.test(ctx.path); 
 } 
}));

- extendTypes:支持扩展类型

app.use(bodyparser({ 
   extendTypes: { 
   json: \['application/x-javascript'\] // 解析application/x-javascript 类型 作为JSON字符串 
   } 
  }));

- onerror:支持自定义错误句柄,如果koa-bodyparser抛出一个错误,您可以自定义响应如下:

app.use(bodyparser({ 
   onerror: function (err, ctx) { 
   ctx.throw('body parse error', 422); 
   } 
  }));

- disableBodyParser:可以通过设置ctx动态禁用body解析器。disableBodyParser = true。

app.use(async (ctx, next) => { 
   if (ctx.path === '/disable')     ctx.disableBodyParser = true; 
   await next(); 
  }); 
  app.use(bodyparser());

koa-logger

请求响应监听日志

下载

npm i koa-logger

使用

~~// 引入日志中间件 
const logger = require('koa-logger'); 

// 注册日志中间件 
app.use(logger()); ~~

koa-session

用于Koa的简单会话中间件。默认为基于cookie的会话,并支持外部存储。

session

我们知道,http协议是无状态的,当用户进行登录后,并不会保存账户密码,如果我们需要维持用户的登录状态,就需要使用一些方法。目前主流的用户认证方法有基于token和基于session两种方式。

基于token的认证可以使用koa-jwt中间件,基于session的认证则使用标题的koa-session。

下载

npm i koa-session

使用

app.js 入口文件中注册session

const CONFIG = { 
 key: 'koa:sess', /\*\* (string) cookie key (default is koa:sess) \*/ 
 /\*\* (number || 'session') maxAge in ms (default is 1 days) \*/ 
  // 状态保存最大时间,默认为一天 
 maxAge: 86400000, 
 autoCommit: true, /\*\* (boolean) 自动保存头部 (default true) \*/ 
 overwrite: true, /\*\* (boolean) 能否覆盖 (default true) \*/ 
 httpOnly: true, /\*\* (boolean) httpOnly or not (default true) \*/ 
 signed: true, /\*\* (boolean) signed or not (default true) \*/ 
 /\*\* (boolean) 强制在每个响应上设置会话标识符cookie。过期将重置为原始maxAge,重新设置过期倒计时。 (default is false) \*/ 
 rolling: false, 
 /\*\* (boolean) 当会话快过期时续订会话,这样我们可以始终保持用户登录。(default is false)\*/ 
 renew: false, 
}; 

// 如果你所有都为默认配置,则不需要传递配置参数,app.use(session(app))即可 
app.use(session(sessionConfig, app));

session的使用

注册后可以通过上下文ctx找到session属性,下面代码将用户信息存入session属性中,并创建key和value

user.js

// 用户登录 
static async login(ctx, next) {

const data = ctx.request.body 
const schema = Joi.object().keys({ 
 username: Joi.string().required(), 
 password: Joi.string().required(), 
}) 
let result = Joi.validate(data, schema) 
// 如果有字段类型错误 
if(result.error) { 
 return ctx.response.body = { status: 400, msg: result.error.details}; 
} 
let { username, password } = result.value // 验证过后的数据 
// 查找是否有该用户 
const userInfo = await usersModel.findByName(username) 
// 如果有该用户,继续验证密码是否正确 
if (userInfo) { 
 const userInfo2 = await usersModel.findOne({ username, password }) 
 if (userInfo2) { 
  ctx.response.body = {state: 200, msg: '登录成功'} 
  // 设置session 
  ctx.session.userInfo = userInfo2 
 } else { 
  ctx.response.body = {state: 410, msg: '密码错误'} 
 } 
// 如果没有该用户,返回结果 
} else { 
 ctx.response.body = {state: 410, msg: '该用户不存在'} 
} 
return ctx.response.body 
}

koa-router路由中间件中验证session,这里需要注意的是next()方法前一定要使用await,不然程序不会等待next()方法执行。

export const verifyUser = async (ctx, next) => {

if (ctx.session.userInfo) { 
 await next() 
} else { 
 return ctx.response.body = { state: 401, msg: '无权限访问' } 
} 
}

koa2-cors

用于解决跨域问题

下载

npm install koa2-cors

使用

app.use(cors())

到此这篇关于koa2的中间件功能及应用示例的文章就介绍到这了,更多相关koa2 中间件内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Javascript 相关文章推荐
js切换div css注意的细节
Dec 10 Javascript
IE网页js语法错误2行字符1、FF中正常的解决方法
Sep 09 Javascript
JS页面延迟执行一些方法(整理)
Nov 11 Javascript
CSS图片响应式 垂直水平居中
Aug 14 Javascript
js window对象属性和方法相关资料整理
Nov 11 Javascript
简单的渐变轮播插件
Jan 12 Javascript
JSON与js对象序列化实例详解
Mar 16 Javascript
浅谈Node.js 子进程与应用场景
Jan 24 Javascript
vue中el-upload上传图片到七牛的示例代码
Oct 19 Javascript
如何使用less实现随机下雪动画详解
Jan 02 Javascript
package.json中homepage属性的作用详解
Mar 11 Javascript
vue等两个接口都返回结果再执行下一步的实例
Sep 08 Javascript
微信小程序利用for循环解决内容变更问题
Mar 05 #Javascript
javascript将16进制的字符串转换为10进制整数hex
Mar 05 #Javascript
js将URL网址转为16进制加密与解密函数
Mar 04 #Javascript
基于node+websocket+html实现腾讯课堂聊天室聊天功能
Mar 04 #Javascript
VUE实现Studio管理后台之鼠标拖放改变窗口大小
Mar 04 #Javascript
微信小程序如何加载数据库真实数据的实现
Mar 04 #Javascript
微信小程序开发搜索功能实现(前端+后端+数据库)
Mar 04 #Javascript
You might like
PHP语法速查表
2006/12/06 PHP
UTF-8正则表达式如何匹配汉字
2015/08/03 PHP
thinkPHP框架整合tcpdf插件操作示例
2018/08/07 PHP
JQuery 常用操作代码
2010/03/14 Javascript
基于jquery的图片的切换(以数字的形式)
2011/02/14 Javascript
jquery 页面滚动到指定DIV实现代码
2013/09/25 Javascript
jquery中show()、hide()和toggle()用法实例
2015/01/15 Javascript
移动设备web开发首选框架:zeptojs介绍
2015/01/29 Javascript
jQuery中的pushStack实现原理和应用实例
2015/02/03 Javascript
JS实现超过长度限制后自动跳转下一款文本框的方法
2015/02/23 Javascript
js实现鼠标划过给div加透明度的方法
2015/05/25 Javascript
javascript实现的淘宝旅行通用日历组件用法实例
2015/08/03 Javascript
IE6-IE9使用JSON、table.innerHTML所引发的问题
2015/12/22 Javascript
使用struts2+Ajax+jquery验证用户名是否已被注册
2016/03/22 Javascript
Nodejs进阶:核心模块net入门学习与实例讲解
2016/11/21 NodeJs
浅谈Express异步进化史
2017/09/09 Javascript
node中的session的具体使用
2018/09/14 Javascript
Vue绑定内联样式问题
2018/10/17 Javascript
详解用场景去理解函数柯里化(入门篇)
2019/04/11 Javascript
JS如何在数组指定位置插入元素
2020/03/10 Javascript
[10:49]2014国际邀请赛 叨叨刀塔第二期为真正的电竞喝彩
2014/07/21 DOTA
Python中使用Boolean操作符做真值测试实例
2015/01/30 Python
简单实现python爬虫功能
2015/12/31 Python
python魔法方法-属性转换和类的表示详解
2016/07/22 Python
用Pycharm实现鼠标滚轮控制字体大小的方法
2019/01/15 Python
python实现超市商品销售管理系统
2019/10/25 Python
keras获得model中某一层的某一个Tensor的输出维度教程
2020/01/24 Python
jupyter notebook运行命令显示[*](解决办法)
2020/05/18 Python
Keras搭建自编码器操作
2020/07/03 Python
Python爬取微信小程序通用方法代码实例详解
2020/09/29 Python
详解基于python的图像Gabor变换及特征提取
2020/10/26 Python
List、Map、Set三个接口,存取元素时,各有什么特点?
2015/09/27 面试题
C/C++ 笔试、面试题目大汇总
2015/11/21 面试题
当文件系统受到破坏时,如何检查和修复系统?
2012/03/09 面试题
银行优秀员工事迹
2014/02/06 职场文书
海飞丝的广告词
2014/03/20 职场文书