最近由于开发一个本身的博客网站,学习了koa2的搭建,写了一些本身认为比较重要或须要知道的koa2中间件做用和使用场景。javascript
路由中间件java
npm i koa-router
须要注意的是引入的koa-router是一个方法,引入后须要执行这个方法。node
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());
也能够按需引入并注册路由,可注册多个路由。npm
经过ctx.query获取参数json
经过ctx.request.body获取参数api
经过ctx.params获取参数跨域
首先引入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()); });
设置已经初始化的路由器实例的路径前缀cookie
router.prefix('/user'); router.post('/login', function(ctx, next) { ... }); // 实际路径 /user/login
使用场景:咱们一般须要经过验证用户和用户权限来断定用户是否能使用该接口,若是在每一个接口都写一次验证很是麻烦且很差维护。这时咱们就须要路由中间件先进行验证,再执行下面操做。 session
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(); });
处理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用于解析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());
请求响应监听日志
npm i koa-logger
~~// 引入日志中间件 const logger = require('koa-logger'); // 注册日志中间件 app.use(logger()); ~~
用于Koa的简单会话中间件。默认为基于cookie的会话,并支持外部存储。
咱们知道,http协议是无状态的,当用户进行登陆后,并不会保存帐户密码,若是咱们须要维持用户的登陆状态,就须要使用一些方法。目前主流的用户认证方法有基于token和基于session两种方式。
基于token的认证可使用koa-jwt中间件,基于session的认证则使用标题的koa-session。
npm i koa-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));
注册后能够经过上下文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: '无权限访问' } }
}
用于解决跨域问题
npm install koa2-cors
app.use(cors())