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 相关文章推荐
些很实用且必用的小脚本代码
Jun 26 Javascript
List the Stored Procedures in a SQL Server database
Jun 20 Javascript
extjs 学习笔记(三) 最基本的grid
Oct 15 Javascript
jQuery asp.net 用json格式返回自定义对象
Apr 07 Javascript
JavaScript的document对象和window对象详解
Dec 30 Javascript
JSON传递bool类型数据的处理方式介绍
Sep 18 Javascript
浅谈javascript回调函数
Dec 07 Javascript
jQuery+AJAX实现网页无刷新上传
Feb 22 Javascript
JavaScript如何实现在文本框(密码框)输入提示语
Dec 25 Javascript
JS实现获取当前URL和来源URL的方法
Aug 24 Javascript
JS原生带小白点轮播图实例讲解
Jul 22 Javascript
Router解决跨模块下的页面跳转示例
Jan 11 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实现计数器方法小结
2015/01/05 PHP
PHP 配置后台登录以及模板引入
2017/01/24 PHP
PHP中OpenSSL加密问题整理
2017/12/14 PHP
基于laravel缓冲cache的用法详解
2019/10/23 PHP
jQuery(1.3.2) 7行代码搞定跟随屏幕滚动的层
2009/05/21 Javascript
JavaScript 放大镜 放大倍率和视窗尺寸
2011/05/09 Javascript
在javascript中执行任意html代码的方法示例解读
2013/12/25 Javascript
玩转方法:call和apply
2014/05/08 Javascript
jQuery中toggle()函数的使用实例
2015/04/17 Javascript
AngularJS学习笔记之ng-options指令
2015/06/16 Javascript
javascript类型系统 Array对象学习笔记
2016/01/09 Javascript
利用原生JS自动生成文章标题树的实例
2016/08/22 Javascript
老生常谈Javascript中的原型和this指针
2016/10/09 Javascript
jQuery、layer实现弹出层的打开、关闭功能
2017/06/28 jQuery
vue实现通讯录功能
2018/07/14 Javascript
vue 根据选择的月份动态展示日期对应的星期几
2021/02/06 Vue.js
[49:21]2018DOTA2亚洲邀请赛3月30日 小组赛B组 Effect VS iG
2018/03/31 DOTA
python实现JAVA源代码从ANSI到UTF-8的批量转换方法
2015/08/10 Python
分析python请求数据
2018/08/19 Python
python函数的万能参数传参详解
2019/07/26 Python
python 列表推导式使用详解
2019/08/29 Python
python实现126邮箱发送邮件
2020/05/20 Python
TensorFlow-gpu和opencv安装详细教程
2020/06/30 Python
你不知道的葡萄干处理法、橙蜜处理法、二氧化碳酵母法
2021/03/17 冲泡冲煮
项目经理的岗位职责
2013/11/23 职场文书
工地门卫岗位职责
2013/12/30 职场文书
大三毕业自我鉴定
2014/01/15 职场文书
部队党性分析材料
2014/02/16 职场文书
大跃进口号
2014/06/16 职场文书
民政局离婚协议书范本
2014/10/20 职场文书
个人典型事迹材料
2014/12/30 职场文书
家长给老师的感谢信
2015/01/20 职场文书
汽车4S店销售经理岗位职责
2015/04/02 职场文书
2015年村级财务管理制度
2015/08/04 职场文书
2016圣诞节贺卡寄语
2015/12/07 职场文书
2016年优秀共产党员先进事迹材料
2016/02/29 职场文书