nodejs express restful api插件restframework-express使用

restframework-express是基于nodejs后端服务框架express用于构建RESTful Web API的一个强大且十分灵活的express工具包插件

npm https://www.npmjs.com/package/restframework-express
在你的express项目中使用 npm i restframework-express

源码、示例移步https://github.com/lvhaoran88/restframework-express

感谢你的star,欢迎Fork

我能做什么:

  • 已写好声明文件,在各大编辑器中语法提示完美支持

  • router集中管理

  • ES6之后,引入了class 关键字来创建类。因此我们使用CBV模式来开发接口,让业务更易于查找、维护

  • 全局/局部的用户(auth)认证

  • 全局/局部的权限(permision)认证

  • 全局/局部的访问频率限制

  • ORM及非ORM数据源序列化、反序列化

  • 在线可视的API

  • 自定义全局异常处理

1. 快速使用

  • 需求条件

    • nodejs
    • express 4.x+
  • 安装

npm i restframework-express
  • 你可以在这里观看当前支持的示例

2.视图

2.1 APIView的使用

views.js

const express = require("express")
const {APIView} = require("restframework-express/views")  // 导入APIView组件

let app = express()
app.use(express.json())

// 创建自定义视图类,继承 APIView
class MyAPIView extends APIView {
    
    // http get请求方法
    get(req, res, next) {
        return res.json({hello: "restful"})
    }
    
  
    // http post请求方法
    post(req, res){
        data = req.body
      return res.json({msg: "post - success"})
    }
    
    // http put请求方法
    put(req, res){
        date = req.body
        return res.json({msg: "put - success"})
    }
    
  
    // http patch请求方法
    patch(req, res){
        data = req.body
        return res.json(msg: "patch - sucess")
    }
  
    // http delete请求方法
    delete(req, res){
        data = req.body
        return res.json(msg: "delete - sucess")
    }
}

// 注册路由、视图  调用.asView()方法
app.all("/test/", MyAPIView.asView())

// 监听 3000端口 开启服务
app.listen("3000", "0.0.0.0")

3. auth认证

3.1 使用自定义认证

const {APIView} = require('restframework-express/views')
cosnt {BaseAuthentication} = require("restframework-express/authentications")
const {AuthenticationFailed} = = require("restframework-express/exceptions")
// 1.自定义auth认证类继承BaseAuthentication
class MyAuth extends BaseAuthentication {
    // 2.需要重写 authenticate方法
    authenticate(req) {
        // 加入 可以再当次请求中获取你自定义的数据 username值
        if (req.body.username) {
          // 3.认证通过 你需要返回一个数组(ts中为元组) 第一个值给 user 第二个值给auth
          // 或者是你在使用 数据库ORM等 返回一个可以表示用户信息的对象给user的位置
            return [req.body.username, null]
        } else {
            // 4.如果认证不错通过,你需要抛出AuthenticationFailed异常
            throw new AuthenticationFailed("认证失败")
        }
    }
}

// 5.在视图中使用认证类
class MyAPIView extends APIView {
        // 6.在视图类中 制定 authentication_classes给一个数组(ts中为元组),内容是上面我们自定义的认证类
    authenticationClasses = [MyAuth]

        post(req, res) {
        console.log(req.user)  // 7.认证通过这里你会拿到当前定义的用户对象
        console.log(req.auth)  // 7.这是一个auth 也是你在你自定义的认证类中返回的
        return res.json({code: 0, msg: "success", data: {hello: "world,auth认证通过"}})
    }
}

app.all("/auth/", MyAPIView.asView())

4.权限认证组件

4.1 自定义权限认证组件

建议权限组件配合auth认证组件使用当然你也可以不用

const {APIView} = require('restframework-express/views')
const {AuthenticationFailed, PermissionDenied} = = require("restframework-express/exceptions")
cosnt {BaseAuthentication} = require("restframework-express/authentications")
const {BasePermission} = = require("restframework-express/permissions")

// 1.自定义auth认证类继承BaseAuthentication
class MyAuth extends BaseAuthentication {
    // 2.需要重写 authenticate方法
    authenticate(req) {
        // 加入 可以再当次请求中获取你自定义的数据 username值
        if (req.body.username) {
          // 3.认证通过 你需要返回一个数组(ts中为元组) 第一个值给 user 第二个值给auth
          // 或者是你在使用 数据库ORM等 返回一个可以表示用户信息的对象给user的位置
            return [req.body.username, null]
        } else {
            // 4.如果认证不错通过,你需要抛出AuthenticationFailed异常
            throw new AuthenticationFailed("认证失败")
        }
    }
}


// 自定义的 权限组件
class MyPermission extends BasePermission {
    hasPermission(req){
    // 我们在用户认证中 给request 添加一个 user属性, 这个属性是从数据库重查询出来的,如果你使用orm查询 你可以直接使用 user的链式操作
        let user = req.user  // type: Array
        //role = user.roles
        /**
        * 以下模拟 用户角色
        */
        let role = {
            "admin": ["admin", "menus"],
            "custom": ["menus"]
        }

        let needRole = ["admin", "menus"]

        let userRole = role[user] || []
        console.log(userRole)
        needRole.map(r => {
            if (userRole.indexOf(r) === -1) {
                throw new PermissionDenied("权限认证失败")
            }
        })
        
        // 认证通过 你需要返回一个 true
        return true
    }
}

// 5.在视图中使用认证类
class MyAPIView extends APIView {
    authenticationClasses = [MyAuth]  // 这是个数组 你可以给多个自定义的认证类
        permissionClasses = [MyPermission]  // 同上

        post(req, res) {
        // TODO: 你自己的逻辑
        return res.json({code: 0, msg: "success", data: {hello: "world,auth、perimission认证通过"}})
    }
}

app.all("/auth_permission/", MyAPIView.asView())

访问频率限制组件

4.1 自定义频率限制的组件

  • 频率支持格式

    rate = '4/s'  // 每秒内最多可以访问4次
    rate = '10/m'  // 每分钟内最多可以访问10次
    rate = '20/h'  // 每小时内最多可以访问20次
    rate = '4000/m'  // 每天内最多可以访问4000次
    
4.1.1 局部配置频率
const {APIView} = require('restframework-express/views')

const {SimpleRateThrottle} = require('restframework-express/throttling')
class MyRateThrottle extends SimpleRateThrottle {
    // 给当前自定义的频率组件给个标志
    // 比如这个限制是给登陆功能使用的
    scope = "login"
    // 给scope设置个频率, 登陆频率每分钟不能超过5次
    THROTTLE_RATES = {
       login: '5/m'
    }
        
        // 重写  getCacheKey方法
    getCacheKey(req, view) {
        // 返回一个字符串
        // 当前你可以根据 req.user 用户身份来标识
                id = this.getIdent(req)  // 用于登陆还没有用户信息所以这里主机ip来作为身份标识的
        return this.cacheFormat(this.scope, id)
    }
}

// 5.在视图中使用认证类
class MyAPIView extends APIView {
    // 配置频现组件
    throttleClasses = [MyRateThrottle]

        post(req, res) {
        // TODO: 你自己的逻辑
        return res.json({code: 0, msg: "success", data: {hello: "throttle认证通过"}})
    }
}

app.all("/throttle/", MyAPIView.asView())
4.1.2 全局配置频率
// 全局的 restful 配置
const api_settings = require("restframework-express/settings")  // type: Object
// 设置 scope = "test" 的 rate = '3/m'  每分钟限制3次访问
api_settings.DEFAULT_THROTTLE_RATES = {
    login: '5/m'
}

const {SimpleRateThrottle} = require('restframework-express/throttling')
// 这样你就不用在自定义组件中单个配置  THROTTLE_RATES字段
class MyRateThrottle extends SimpleRateThrottle {
    scope = "login"
        // 重写  getCacheKey方法
    getCacheKey(req, view) {
                id = this.getIdent(req)
        return this.cacheFormat(this.scope, id)
    }
}
4.1.3 全局配置频率组件

即将推出

感谢你的star, 点这里

功能持续更新中...

敬请期待!

联系我https://github.com/lvhaoran88/restframework-express

E-mail: 905097829@qq.comlvhaoran@88.com

感谢django-rest-framework

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,826评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,968评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,234评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,562评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,611评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,482评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,271评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,166评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,608评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,814评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,926评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,644评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,249评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,866评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,991评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,063评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,871评论 2 354

推荐阅读更多精彩内容