這期內(nèi)容當(dāng)中小編將會(huì)給大家?guī)?lái)有關(guān)怎么在koa2中使用中間件,文章內(nèi)容豐富且以專業(yè)的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。
創(chuàng)新互聯(lián)公司是一家專業(yè)從事做網(wǎng)站、成都網(wǎng)站設(shè)計(jì)的網(wǎng)絡(luò)公司。作為專業(yè)網(wǎng)站制作公司,創(chuàng)新互聯(lián)公司依托的技術(shù)實(shí)力、以及多年的網(wǎng)站運(yùn)營(yíng)經(jīng)驗(yàn),為您提供專業(yè)的成都網(wǎng)站建設(shè)、網(wǎng)絡(luò)營(yíng)銷推廣及網(wǎng)站設(shè)計(jì)開(kāi)發(fā)服務(wù)!使用
普通使用方法
需要注意的是引入的koa-router是一個(gè)方法,引入后需要執(zhí)行這個(gè)方法。
const Koa = require('koa'); const app = new Koa(); const router = require('koa-router')(); // 配置路由url // 默認(rèn)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 = \`Hello, ${name}!
\`; }); // 注冊(cè)路由 app.use(router.routes(), router.allowedMethods());
也可以按需引入并注冊(cè)路由,可注冊(cè)多個(gè)路由。
不同請(qǐng)求下接收的參數(shù)獲取
router.get
通過(guò)ctx.query獲取參數(shù)
router.post
通過(guò)ctx.request.body獲取參數(shù)
動(dòng)態(tài)路由 router.get('/:id', func)
通過(guò)ctx.params獲取參數(shù)
遍歷注冊(cè)router
首先引入nodejs中的fs模塊,使用fs的readdirSync方法獲取到指定目錄的所有文件名,遍歷引入路由模塊并注冊(cè)。
const fs = require('fs');
// fs.readdirSync 獲取指定目錄下的所有文件名稱,遍歷引入路由模塊并注冊(cè) fs.readdirSync('./routes').forEach(route=> { let api = require(\`./routes/${route}\`); app.use(api.routes(), api.allowedMethods()); });
koa-router中的其它api
router.prefix(prefix) 添加url前綴
設(shè)置已經(jīng)初始化的路由器實(shí)例的路徑前綴
router.prefix('/user'); router.post('/login', function(ctx, next) { ... }); // 實(shí)際路徑 /user/login
router.use(url|[url1,url2,...], (ctx, next) => {...}) 路由中間件
使用場(chǎng)景:我們通常需要通過(guò)驗(yàn)證用戶和用戶權(quán)限來(lái)判定用戶是否能使用該接口,如果在每個(gè)接口都寫一次驗(yàn)證非常麻煩且不好維護(hù)。這時(shí)我們就需要路由中間件先進(jìn)行驗(yàn)證,再執(zhí)行下面操作。
router.use的第一個(gè)參數(shù)為一個(gè)路徑或者由多個(gè)需要使用中間件的路徑組成的數(shù)組(需要注意的是,如果路由設(shè)置了url前綴,需要在設(shè)置前綴后注冊(cè)中間件,參數(shù)中的url不需要設(shè)置前綴)。
router.use的第二個(gè)參數(shù)為函數(shù),函數(shù)傳遞ctx和next兩個(gè)參數(shù),可通過(guò)ctx進(jìn)行權(quán)限驗(yàn)證后,判斷是否執(zhí)行next調(diào)用接口。這里特別需要注意的是函數(shù)使用next的時(shí)候需要添加await,如果不添加,在調(diào)用接口前,接口就會(huì)返回結(jié)果,前臺(tái)則無(wú)法獲取到數(shù)據(jù)。
// 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請(qǐng)求
處理post請(qǐng)求時(shí),我們會(huì)遇到一個(gè)問(wèn)題,無(wú)論是node的request對(duì)象還是koa的request對(duì)象,都沒(méi)辦法解析request的body,我們就需要下載并引入一個(gè)解析body的中間件koa-bodyparser,koa-bodyparser的具體配置詳見(jiàn)下面的說(shuō)明,這里我們直接放入使用方式。
// 引入路由文件 const index = require('./routes/index.js'); const user = require('./routes/user.js'); // 引入解析request.body的中間件 const bodyparser = require('koa-bodyparser'); // 注冊(cè)bodyparser,需要注意,bodyparser的注冊(cè)一定要在router路由注冊(cè)之前 app.use(bodyparser({ enableTypes:\['json', 'form', 'text'\] })); ... // 注冊(cè)routes app.use(index.routes(), index.allowedMethods()); app.use(user.routes(), user.allowedMethods());
koa-bodyparser
如上所述,koa-bodyparser用于解析request.body,因?yàn)閚ode和koa的request無(wú)法解析body。
下載
npm i koa-bodyparser
使用
const bodyparser = require('koa-bodyparser');
在注冊(cè)運(yùn)行時(shí),bodyparser方法中可傳入對(duì)象,作相應(yīng)配置。
- enableTypes:解析器只在配置了enableTypes時(shí)解析請(qǐng)求類型,默認(rèn)是['json', 'form']。
- encoding:請(qǐng)求編碼,默認(rèn)是utf-8。
- formLimit:urlencoded body的imit如果主體最終大于此限制,則返回一個(gè)413錯(cuò)誤代碼。默認(rèn)是56 kb。
- jsonLimit:json主體的限制。默認(rèn)是1 mb。
- textLimit:文本主體的限制。默認(rèn)是1 mb。
- strict:當(dāng)設(shè)置為true時(shí),JSON解析器將只接受數(shù)組和對(duì)象。默認(rèn)是正確的。參見(jiàn)正文中的嚴(yán)格模式。在嚴(yán)格模式下,ctx.request。body總是一個(gè)對(duì)象(或數(shù)組),這避免了很多類型判斷。但文本正文總是返回字符串類型。
- detectJSON:自定義json請(qǐng)求檢測(cè)函數(shù)。默認(rèn)為null。
app.use(bodyparser({ detectJSON: function (ctx) { return /\\.json$/i.test(ctx.path); } }));
- extendTypes:支持?jǐn)U展類型
app.use(bodyparser({ extendTypes: { json: \['application/x-javascript'\] // 解析application/x-javascript 類型 作為JSON字符串 } }));
- onerror:支持自定義錯(cuò)誤句柄,如果koa-bodyparser拋出一個(gè)錯(cuò)誤,您可以自定義響應(yīng)如下:
app.use(bodyparser({ onerror: function (err, ctx) { ctx.throw('body parse error', 422); } }));
- disableBodyParser:可以通過(guò)設(shè)置ctx動(dòng)態(tài)禁用body解析器。disableBodyParser = true。
app.use(async (ctx, next) => { if (ctx.path === '/disable') ctx.disableBodyParser = true; await next(); }); app.use(bodyparser());
koa-logger
請(qǐng)求響應(yīng)監(jiān)聽(tīng)日志
下載
npm i koa-logger
使用
~~// 引入日志中間件 const logger = require('koa-logger'); // 注冊(cè)日志中間件 app.use(logger()); ~~
koa-session
用于Koa的簡(jiǎn)單會(huì)話中間件。默認(rèn)為基于cookie的會(huì)話,并支持外部存儲(chǔ)。
session
我們知道,http協(xié)議是無(wú)狀態(tài)的,當(dāng)用戶進(jìn)行登錄后,并不會(huì)保存賬戶密碼,如果我們需要維持用戶的登錄狀態(tài),就需要使用一些方法。目前主流的用戶認(rèn)證方法有基于token和基于session兩種方式。
基于token的認(rèn)證可以使用koa-jwt中間件,基于session的認(rèn)證則使用標(biāo)題的koa-session。
下載
npm i koa-session
使用
app.js 入口文件中注冊(cè)session
const CONFIG = { key: 'koa:sess', /\*\* (string) cookie key (default is koa:sess) \*/ /\*\* (number || 'session') maxAge in ms (default is 1 days) \*/ // 狀態(tài)保存大時(shí)間,默認(rèn)為一天 maxAge: 86400000, autoCommit: true, /\*\* (boolean) 自動(dòng)保存頭部 (default true) \*/ overwrite: true, /\*\* (boolean) 能否覆蓋 (default true) \*/ httpOnly: true, /\*\* (boolean) httpOnly or not (default true) \*/ signed: true, /\*\* (boolean) signed or not (default true) \*/ /\*\* (boolean) 強(qiáng)制在每個(gè)響應(yīng)上設(shè)置會(huì)話標(biāo)識(shí)符cookie。過(guò)期將重置為原始maxAge,重新設(shè)置過(guò)期倒計(jì)時(shí)。 (default is false) \*/ rolling: false, /\*\* (boolean) 當(dāng)會(huì)話快過(guò)期時(shí)續(xù)訂會(huì)話,這樣我們可以始終保持用戶登錄。(default is false)\*/ renew: false, }; // 如果你所有都為默認(rèn)配置,則不需要傳遞配置參數(shù),app.use(session(app))即可 app.use(session(sessionConfig, app));
session的使用
注冊(cè)后可以通過(guò)上下文ctx找到session屬性,下面代碼將用戶信息存入session屬性中,并創(chuàng)建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) // 如果有字段類型錯(cuò)誤 if(result.error) { return ctx.response.body = { status: 400, msg: result.error.details}; } let { username, password } = result.value // 驗(yàn)證過(guò)后的數(shù)據(jù) // 查找是否有該用戶 const userInfo = await usersModel.findByName(username) // 如果有該用戶,繼續(xù)驗(yàn)證密碼是否正確 if (userInfo) { const userInfo2 = await usersModel.findOne({ username, password }) if (userInfo2) { ctx.response.body = {state: 200, msg: '登錄成功'} // 設(shè)置session ctx.session.userInfo = userInfo2 } else { ctx.response.body = {state: 410, msg: '密碼錯(cuò)誤'} } // 如果沒(méi)有該用戶,返回結(jié)果 } else { ctx.response.body = {state: 410, msg: '該用戶不存在'} } return ctx.response.body }
koa-router路由中間件中驗(yàn)證session,這里需要注意的是next()方法前一定要使用await,不然程序不會(huì)等待next()方法執(zhí)行。
export const verifyUser = async (ctx, next) => { if (ctx.session.userInfo) { await next() } else { return ctx.response.body = { state: 401, msg: '無(wú)權(quán)限訪問(wèn)' } } }
koa2-cors
用于解決跨域問(wèn)題
下載
npm install koa2-cors
使用
app.use(cors())
上述就是小編為大家分享的怎么在koa2中使用中間件了,如果剛好有類似的疑惑,不妨參照上述分析進(jìn)行理解。如果想知道更多相關(guān)知識(shí),歡迎關(guān)注創(chuàng)新互聯(lián)成都網(wǎng)站設(shè)計(jì)公司行業(yè)資訊頻道。
另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內(nèi)外云服務(wù)器15元起步,三天無(wú)理由+7*72小時(shí)售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國(guó)服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡(jiǎn)單易用、服務(wù)可用性高、性價(jià)比高”等特點(diǎn)與優(yōu)勢(shì),專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場(chǎng)景需求。