浅谈KOA2 Restful方式路由初探
程序员文章站
2022-11-25 23:21:14
前言
最近考虑将服务器资源整合一下,作为多端调用的api
看到restful标准和orm眼前一亮,但是找了不少版本路由写的都比较麻烦,于是自己折腾了半天
ap...
前言
最近考虑将服务器资源整合一下,作为多端调用的api
看到restful标准和orm眼前一亮,但是找了不少版本路由写的都比较麻烦,于是自己折腾了半天
api库结构
考虑到全部对象置于顶层将会造成对象名越来长,同时不便于维护,故采取部分的分层结构
如workflow模块内的prototypes,instances等等,分层的深度定义为层级
可访问的对象集合(collection)的属性满足restful设计
-- workflow(category) -- prototypes(collection) -- [method] ... -- [method] ... -- instances(collection) -- users(collection) --[method] list #get :object/ --[method] instance #get :object/:id -- ... -- ...
restful api 接口
将restful api接口进行标准化命名
.get('/', ctx=>{ctx.error('路径匹配失败')}) .get('/:object', restfulapimethods.list) .get('/:object/:id', restfulapimethods.get) .post('/:object', restfulapimethods.post) .put('/:object/:id', restfulapimethods.replace) .patch('/:object/:id', restfulapimethods.patch) .delete('/:object/:id', restfulapimethods.delete) .get('/:object/:id/:related', restfulapimethods.related) .post('/:object/:id/:related', restfulapimethods.addrelated) .delete('/:object/:id/:related/:relatedid', restfulapimethods.delrelated)
api对象
这个文件是来自微信小程序demo,觉得很方便就拿来用了,放于需要引用的根目录,引用后直接获得文件目录结构api对象
const _ = require('lodash') const fs = require('fs') const path = require('path') /** * 映射 d 文件夹下的文件为模块 */ const mapdir = d => { const tree = {} // 获得当前文件夹下的所有的文件夹和文件 const [dirs, files] = _(fs.readdirsync(d)).partition(p => fs.statsync(path.join(d, p)).isdirectory()) // 映射文件夹 dirs.foreach(dir => { tree[dir] = mapdir(path.join(d, dir)) }) // 映射文件 files.foreach(file => { if (path.extname(file) === '.js') { tree[path.basename(file, '.js')] = require(path.join(d, file)) tree[path.basename(file, '.js')].iscollection = true } }) return tree } // 默认导出当前文件夹下的映射 module.exports = mapdir(path.join(__dirname))
koa-router分层路由的实现
创建多层路由及其传递关系
执行顺序为
1 -- 路径匹配
-- 匹配到‘/'结束
-- 匹配到对应的restfulapi执行并结束
-- 继续
2 -- 传递中间件 nest
3 -- 下一级路由
4 -- 循环 to 1
const definedrouterdepth = 2 let routers = [] for (let i = 0; i < definedrouterdepth; i++) { let route = require('koa-router')() if (i == definedrouterdepth - 1) { // 嵌套路由中间件 route.use(async (ctx, next) => { // 根据版本号选择库 let apiversion = ctx.headers['api-version'] ctx.debug(`------- (api版本 [${apiversion}]) --=-------`) if (!apiversion) { ctx.error('版本号未标记') return } let apiroot = null try { apiroot = require(`../restful/${apiversion}`) } catch (e) { ctx.error ('api不存在,请检查header中的版本号') return } ctx.debug(apiroot) ctx.apiroot = apiroot ctx.debug('---------------------------------------------') // for(let i=0;i<) await next() }) } route .get('/', ctx=>{ctx.error('路径匹配失败')}) .get('/:object', restfulapimethods.list) .get('/:object/:id', restfulapimethods.get) .post('/:object', restfulapimethods.post) .put('/:object/:id', restfulapimethods.replace) .patch('/:object/:id', restfulapimethods.patch) .delete('/:object/:id', restfulapimethods.delete) .get('/:object/:id/:related', restfulapimethods.related) .post('/:object/:id/:related', restfulapimethods.addrelated) .delete('/:object/:id/:related/:relatedid', restfulapimethods.delrelated) if (i != 0) { route.use('/:object', nest, routers[i - 1].routes()) } routers.push(route) } let = router = routers[routers.length - 1]
nest中间件
将ctx.apiobject设置为当前层的api对象
const nest= async (ctx, next) => { let object = ctx.params.object let apiobject = ctx.apiobject || ctx.apiroot if(!apiobject){ ctx.error('api装载异常') return } if (apiobject[object]) { ctx.debug(`ctx.apiobject=>ctx.apiobject[object]`) ctx.debug(apiobject[object]) ctx.debug(`------------------------------------`) ctx.apiobject = apiobject[object] } else { ctx.error(`api接口${object}不存在`) return } await next() }
restfulapimethods
let restfulapimethods = {} let methods = ['list', 'get', 'post', 'replace', 'patch', 'delete', 'related', 'addrelated', 'delrelated'] for (let i = 0; i < methods.length; i++) { let v = methods[i] restfulapimethods[v] = async function (ctx, next) { let apiobject = ctx.apiobject || ctx.apiroot if (!apiobject) { ctx.error ('api装载异常') return } let object = ctx.params.object if (apiobject[object] && apiobject[object].iscollection) { ctx.debug(` --- restful api [${v}] 调用--- `) if (typeof apiobject[object][v] == 'function') { ctx.state.data = await apiobject[object][v](ctx) ctx.debug('路由结束') return //ctx.debug(ctx.state.data) } else { ctx.error(`对象${object}不存在操作${v}`) return } } ctx.debug(` --- 当前对象${object}并不是可访问对象 --- `) await next() } }
需要注意的点
1、koa-router的调用顺序
2、涉及到async注意next()需要加await
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
上一篇: 欺骗图片:坑人骗人*人等同于谋财害命啊!
下一篇: 日本乡村大妈玩疯了的图片~蹿红互联网!