RestQL:现代化的 API 开发方式

koa-restql 已经在 github 开源并在 npm 发布。感兴趣的同学可以前往围观一下。欢迎 Pull Request,同时热烈欢迎 Star。

在现代的业务系统中,后端开发工作基本上可以被拆分为三项:

  • 接口鉴权。例如判断是不是当前系统的用户,以及该用户是否有权限访问接口。
  • 与其他系统的交互。例如调用第三方的服务,或内部搭建的其他服务。
  • 数据操作。基本上所有需要持久化存储的系统都会在这项工作上耗费大量时间。

本文将介绍如何利用 RestQL 来非常有效地减少「数据操作」相关的工作量。

现状与挑战

我们先来做个假设。

  • 假设系统中有 60 张表,每张表对应的接口都要有四种 CRUD 的 API。那么就需要后端工程师写60 * 4 = 240个API。
  • 假设上述 60 张表中,40 张表存的是资源类的数据,其余 20 张表为关系类的数据,也就是说每张表和 20 张表都要进行关联,每个关联也需要四种 CRUD 操作,那么又要增加40 * 20 * 4 = 3200个API。

所以在上述假设场景中,后端工程师要编写 3200 + 240 = 3440 个 API。而且这还不是全部,假如后端代码需要 100% 的测试覆盖,那么工程师们就要写至少 3440 个测试!

60 张表 = 3440 个 API + 3440 个单元测试

众所周知,数据操作 API 的实现过程基本上是重复的,有的同学甚至认为这是低端的,体现不出工程师价值的工作,纯粹的「体力活」。但是却没有一个能真正解放生产力的方案。

解决思路

尽管我们把数据库抽象成了「关系型」数据库,把操作数据的命令抽象成了 SQL ,同时我们也有了 MySQL 客户端,甚至是 sequelize 这种非常方便的库,也有「RESTful」API 命名规则,但是接口的实现从来都是需要工程师们自己用手敲出来的。

如果说我看得比别人远,那是因为我站在巨人的肩膀上。

所以我们在现有的技术基础上再抽象,把已有的东西重新组合起来,拼装成一个新的工具,帮助工程师从「体力活」中解脱出来,解放生产力。

什么样的工具

最开始的时候,我们最先需要明确的问题就是:「我们需要什么样的工具?」或者说「这种工具要帮我们解决什么问题?」。

实际上我们从刚才的假设中,已经可以得出结论:我们希望有一个工具可以让工程师免于编写数据操作 API,把数据库操作直接映射到 HTTP RESTful API 上

调用方式

如何请求

为了解释「如何请求」,我们先从一些公认的规则出发,举一个例子,然后再从例子中抽象出一些规则。

注意:为了更便于理解,我们把所有的命名从客户端一直穿透到数据库,所以请不要纠结于我们在定义一个 API 时名词单复数的问题。

基本用例

几乎所有的系统都会有一个用户表(user)。根据 RESTful 规则的约定,我们应该把访问 user 表的 API 路径定义为 /user,并把 CRUD 的访问方法映射到 HTTP 协议中的四种方法:GETPOSTPUTDELETE

比如:

  • GET /user:获取用户列表,应该返回一个数组。
  • GET /user/:id:获取指定的用户,应该返回一个对象。
  • POST /user:创建一个用户,应该返回被存储的对象,状态码应该为 201(Created)。
  • PUT /user:修改一个用户的信息,应该返回修改后的对象。
  • DELETE /user/:id:删除一个用户,状态码应该为 204(No Content)。

如果 user 表有一个关系表 feed,那么我们的路径就会再复杂一点:

  • GET /user/:id/feedGET /feed?user_id=:id:获取某个用户的帖子,应该返回一个数组。
  • GET /user/:id/feed/:feed_idGET /feed/:id:获取指定的帖子,应该返回一个对象。

上述的例子中还会衍生出其他的数据操作,不仅仅只有 GET,这里不一一列举了。

抽象出规则

上一节中,列举了要提供一个表的数据访问 API,大概要实现哪些路由。从这些枚举中,可以找出其中的规律,总结出一套规则。最终我们在「把能实现的路由,全部实现」的原则基础上,开发了 RestQL 的 koa 版本。

支持的 HTTP 方法:

HTTP verbCRUD
GETRead
POSTCreate
PUTCreate/Update
DELETEDelete

支持的带有 body 的 HTTP 方法:

HTTP verbListSingle
POSTArray/Object×
PUTArray/ObjectObject

说明

  • List 路径为返回值为数组的路径,包括:
    • /resource
    • /resource/:id/association, association 为 1:n 关系
    • /resource/:id/association, association 为 n:m 关系
  • Single 路径为返回值为单个对象的路径,包括:
    • /resource/:id
    • /resource/:id/association, association 为 1:1 关系
    • /resource/:id/association/:id, association 为 1:n 关系
    • /resource/:id/association/:id, association 为 n:m 关系

如何使用

我们已经开源了 koa-restql,koa 应用开发者可以通过 npm 安装它:

npm install koa-restql

然后在 koa 应用的代码中引用 RestQL:

const koa       = require('koa')
const RestQL    = require('koa-restql')let app = koa()
// Build APIs from `sequelize.models`
let restql = new RestQL(sequelize.models)
app.use(restql.routes())

常见问题

修改参数

用户可以通过querystring来修改参数。强烈建议使用qs对 querystring 进行解析,例如:

qs.stringify({a: 1, b:2}) // => a=1&b=2

RestQL 中的querystring仅有 3 条规则:

  • 所有不以_开头的键,都会被放进sequelize#query()where参数中。例如:

    // query
    {name: "Li Xin"
    }
    // option for sequelize
    {where: {name: "Li Xin"}
    }
    
  • 所有以_开头的键,都会被放进sequelize#query()的参数中,和where保持平级。例如:

    // query
    {_limit: 10
    }
    // option for sequelize
    {limit: 10
    }
    
  • 当需要使用关系时,可以用关系名称的字符串代替关系对象传入。例如需要使用include时:

    // query
    {_include: ['friends']
    }
    // option for sequelize
    {include: [models.user.association.friends]
    }
    

访问控制

通常来说,我们有两种方法实现访问控制:

通过中间件

在 koa 应用挂载 RestQL 的 router 之前,可以实现一个鉴权中间件,控制用户的访问权限:

app.use(authorizeMiddleware)
app.use(restql.routes())

Authorize Middleware

通过 restql 参数

在使用sequelize定义关联时,我们可以设定restql参数,实现访问控制。例如:

  • 禁止通过restql访问关联:

    models.user.hasOne(models.privacy,{restql: {ignore: true}}
    )
    
  • 禁止通过restql使用指定的 HTTP 方法访问关联

    models.user.hasOne(models.privacy,{restql: {ignore: ['get']}}
    )
    

其他语言/框架

目前我们仅实现了基于nodekoa的版本,还没有其他语言/框架的实现版本。欢迎开发者提交其他语言/框架的实现到 RestQL 组。

参考链接

  • GitHub, https://github.com/koajs/koa
  • GitHub, https://github.com/sequelize/sequelize
  • GitHub, [meituan-dianping/koa-restql][https://github.com/Meituan-Dianping/koa-restql]

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/478120.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

论文浅尝 | KnowEdu: 一个自动构建教育知识图谱的系统

笔记整理 | 崔凌云,天津大学硕士链接:https://ieeexplore.ieee.org/stamp/stamp.jsp?arnumber8362657动机基于知识图的广泛应用和在教育领域日益增长的需求,作者提出了一个名为KnowEdu的系统,以自动构建教育知识图。通过利用教育…

我在斯坦福做科研的碎碎念

文 | Jazon编 | 小轶大家好,我是 Jazon。作为 AI 科研工作者,我们的目光不该只聚焦在开发新技术、刷榜打 SoTA 上。学界如职场,还有很多技术之外的软实力需要培养。这篇文章里,我想以我个人的经历作为切入点,聊一聊与此…

论文浅尝 | 用于学习知识图谱嵌入的一种基于注意力机制的新型异构 GNN 框架HRAN...

笔记整理 | 李爽,天津大学链接:http://hfbix45521e79b0484907sowxo0fubpp9b6xwx.fiiz.eds.tju.edu.cn/stamp/stamp.jsp?tp&arnumber9359364动机知识图谱 (KG) 嵌入旨在研究嵌入表示以保留 KG 的固有结构。图神经网络(GNN)作为一种有效的图表示技术&…

分布式队列编程优化篇

“分布式队列编程”是一个系列文,之前我们已经发布了《分布式队列编程模型、实战》,主要剖析了分布式队列编程模型的需求来源、定义、结构以及其变化多样性;根据作者在新美大实际工作经验,给出了队列式编程在分布式环境下的一些具…

LeetCode 443. 压缩字符串(双指针)

1. 题目 给定一组字符,使用原地算法将其压缩。 压缩后的长度必须始终小于或等于原数组长度。 数组的每个元素应该是长度为1 的字符(不是 int 整数类型)。 在完成原地修改输入数组后,返回数组的新长度。 进阶: 你能…

程序员在体制内的工作与生活是怎样的?

文 | 森林鱼(转载于公众号:森林鱼的时光)前言这篇文章原本是要在公众号上更新的,但考虑到修改问题,还是放在了这边。公众号那边会放一个最终相对完整的版本,日常更新与整理的话还是会在这边。主要是想尽量客…

开源开放 | 一个用于文言文实体识别与关系抽取等任务的开源数据集C-CLUE(CCKS2021)...

OpenKG地址:http://openkg.cn/dataset/c-clueGitHub地址:https://github.com/jizijing/C-CLUE网站地址:http://152.136.45.252:60002/pages/login.html开放许可协议:CC BY-SA 4.0 (署名相似共享)贡献者&…

谷歌:一篇论文,让研究者吃我三份安利

文 | 白鹡鸰想用Transformer做CV编 | 小轶想用Transformer做NLP前言计算机视觉、机器学习,这两个词会让你想到什么?相信绝大多数人第一反应都是CNN,而持续关注这些领域发展的人,则会进一步联想到近几年大火的Transformer&#xff…

LeetCode 290. 单词规律(哈希)

1. 题目 给定一种规律 pattern 和一个字符串 str ,判断 str 是否遵循相同的规律。 这里的 遵循 指完全匹配,例如, pattern 里的每个字母和字符串 str 中的每个非空单词之间存在着双向连接的对应规律。 示例1: 输入: pattern "abba&q…

开源开放 | 一个用于知识驱动的零样本学习研究的开源数据集KZSL(CCKS2021)

OpenKG地址:http://openkg.cn/dataset/k-zslGitHub地址:https://github.com/China-UK-ZSL/Resources_for_KZSL开放许可协议:CC BY-SA 4.0 (署名相似共享)贡献者:浙江大学(耿玉霞、陈卓、陈华钧)&#xff0c…

LeetCode 1022. 从根到叶的二进制数之和(递归)

1. 题目 给出一棵二叉树,其上每个结点的值都是 0 或 1 。每一条从根到叶的路径都代表一个从最高有效位开始的二进制数。例如,如果路径为 0 -> 1 -> 1 -> 0 -> 1,那么它表示二进制数 01101,也就是 13 。 对树上的每一…

别再Prompt了!谷歌提出tuning新方法,强力释放GPT-3潜力!

文 | Yimin_饭煲编 | 炼丹学徒如果评选NLP圈的2020年度十大关键词,那么GPT-3(Language Models are Few shot Learners) 一定榜上有名。GPT-3庞大的参数量,优异的性能至今仍让圈内圈外人都津津乐道,而OpenAI发布的OpenAI API&#…

大数据:任务调度,手把手教你

大数据:任务调度https://blog.csdn.net/qq_43713049/article/details/116985497 文章目录 任务调度一、任务流调度的需求二、任务流调度的工具三、Oozie的简介四、Oozie的2种使用方式五、WorkFlow 与 Fork 和 Join六、SubFlow:子工作流七、定时调度的实现…

人脸识别 | 你的论文离CVPR , 还有多远?

最近,一则人脸识别安全性问题的新闻上了热搜。(图片来自网络)虽然让不少人产生了“人在家中坐,债从天上来”的担忧,但也不由感叹人脸识别的发展与普及。人脸识别发展至今,已经在众多领域中占领重要地位。这…

LeetCode 455. 分发饼干(贪心)

1. 题目 假设你是一位很棒的家长,想要给你的孩子们一些小饼干。但是,每个孩子最多只能给一块饼干。对每个孩子 i ,都有一个胃口值 gi ,这是能让孩子们满足胃口的饼干的最小尺寸;并且每块饼干 j ,都有一个尺…

开源开放 | 高质量体育赛事摘要数据集SGSum(CCKS2021)

OpenKG地址:http://openkg.cn/dataset/sgsumGitHub:https://github.com/krystalan/SGSum开放许可协议:CC BY-SA 4.0 (署名相似共享)贡献者:苏州大学(王佳安、张汀依、瞿剑峰、李直旭&#xff09…

消息队列设计精要

消息队列已经逐渐成为企业IT系统内部通信的核心手段。它具有低耦合、可靠投递、广播、流量控制、最终一致性等一系列功能,成为异步RPC的主要手段之一。 当今市面上有很多主流的消息中间件,如老牌的ActiveMQ、RabbitMQ,炙手可热的Kafka&#x…

数学教育中的AI:NeurIPS’21 Workshop 欢迎投稿!

Workshop主页:https://mathai4ed.github.io数学推理是一种人类独特的智慧能力,也是人类在对科学和知识的探寻道路上不可缺少的基石。不过,数学学习通常是一项极具挑战性的过程,因为它依赖于指导者对学习内容的设计、教学和评估。从…

LeetCode 696. 计数二进制子串

1. 题目 给定一个字符串 s,计算具有相同数量0和1的非空(连续)子字符串的数量,并且这些子字符串中的所有0和所有1都是组合在一起的。 重复出现的子串要计算它们出现的次数。 示例 1 : 输入: "00110011" 输出: 6 解释: 有6个子串具有相同数量…

论文浅尝 - ISWC2021 | 当知识图谱遇上零样本视觉问答

论文题目:Zero-shot Visual Question Answering using Knowledge Graph本文作者:陈卓(浙江大学)、陈矫彦(牛津大学)、耿玉霞(浙江大学)、Jeff Z. Pan(爱丁堡大学)、苑宗港(华为)、陈华钧(浙江大学)发表会议:ISWC 2021论文链接:htt…