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 相关文章推荐
javascript获取网页中指定节点的父节点、子节点的方法小结
Apr 24 Javascript
从零学JSON之JSON数据结构
May 19 Javascript
jQuery中的编程范式详解
Dec 15 Javascript
jquery实现删除一个元素后面的所有元素功能
Dec 21 Javascript
Bootstrap每天必学之响应式导航、轮播图
Apr 25 Javascript
JavaScript兼容浏览器FF/IE技巧
Aug 14 Javascript
jquery实现拖动效果(代码分享)
Jan 25 Javascript
Jquery把获取到的input值转换成json
May 15 jQuery
Vue 表单控件绑定的实现示例
Aug 11 Javascript
原生js实现表格翻页和跳转
Sep 29 Javascript
vue解决跨域问题(推荐)
Nov 10 Javascript
js 实现Material UI点击涟漪效果示例
Sep 23 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/09/25 PHP
微信自定义分享php代码分析
2016/11/24 PHP
php封装json通信接口详解及实例
2017/03/07 PHP
js类后台管理菜单类-MenuSwitch
2007/09/12 Javascript
详解JavaScript中undefined与null的区别
2014/03/29 Javascript
jQuery学习笔记之jQuery.extend(),jQuery.fn.extend()分析
2014/06/09 Javascript
JQuery表格拖动调整列宽效果(自己动手写的)
2014/09/01 Javascript
js+css实现导航效果实例
2015/02/10 Javascript
jQuery实现带渐显效果的人物多级关系图代码
2015/10/16 Javascript
jQuery时间插件jquery.clock.js用法实例(5个示例)
2016/01/14 Javascript
微信小程序开发(一) 微信登录流程详解
2017/01/11 Javascript
JS实现css hover操作的方法示例
2017/04/07 Javascript
使用mint-ui开发项目的一些心得(分享)
2017/09/07 Javascript
BootStrap TreeView使用实例详解
2017/11/01 Javascript
JavaScript中 ES6变量的结构赋值
2018/07/10 Javascript
JS中的算法与数据结构之链表(Linked-list)实例详解
2019/08/20 Javascript
微信自定义分享链接信息(标题,图片和内容)实现过程详解
2019/09/04 Javascript
python类继承用法实例分析
2014/10/10 Python
Python使用Scrapy爬取妹子图
2015/05/28 Python
使用Django的模版来配合字符串翻译工作
2015/07/27 Python
python 文件查找及内容匹配方法
2018/10/25 Python
python中tkinter的应用:修改字体的实例讲解
2019/07/17 Python
.dcm格式文件软件读取及python处理详解
2020/01/16 Python
如何在Python对Excel进行读取
2020/06/04 Python
Python自动登录QQ的实现示例
2020/08/28 Python
Python连接mysql方法及常用参数
2020/09/01 Python
Web前端绘制0.5像素的几种方法
2017/08/11 HTML / CSS
基于CSS3的CSS 多栏(Multi-column)实现瀑布流源码分享
2014/06/11 HTML / CSS
英国Office鞋店德国网站:在线购买鞋子、靴子和运动鞋
2018/12/19 全球购物
Ancheer官方户外和运动商店:销售电动自行车
2019/08/07 全球购物
中学教师师德承诺书
2014/05/23 职场文书
婚礼答谢词
2015/01/04 职场文书
《我要的是葫芦》教学反思
2016/02/18 职场文书
解决python绘图使用subplots出现标题重叠的问题
2021/04/30 Python
Python中使用Opencv开发停车位计数器功能
2022/04/04 Python