参考:https://tech.meituan.com/koa-restql.html

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

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

本文将介绍如何利用 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/feed 或 GET /feed?user_id=:id:获取某个用户的帖子,应该返回一个数组。
  • GET /user/:id/feed/:feed_id 或 GET /feed/:id:获取指定的帖子,应该返回一个对象。

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

抽象出规则

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

支持的 HTTP 方法:

HTTP verb CRUD
GET Read
POST Create
PUT Create/Update
DELETE Delete

支持的带有 body 的 HTTP 方法:

HTTP verb List Single
POST Array/Object ×
PUT Array/Object Object

说明

  • 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())

通过 restql 参数

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

  • 禁止通过restql访问关联:

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

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

RestQL:现代化的 API 开发方式的更多相关文章

  1. 【转】RestQL:现代化的 API 开发方式

    原文:http://tech.meituan.com/koa-restql.html RestQL:现代化的 API 开发方式 李鑫 ·2016-08-12 11:26 koa-restql 已经在  ...

  2. graphql 新API 开发方式

    我们知道 GraphQL 使用 Schema 来描述数据,并通过制定和实现 GraphQL 规范 定义了支持 Schema 查询的 DSQL (Domain Specific Query Langua ...

  3. 一篇文章帮你梳理清楚API设计时需要考虑的几个关键点

    本文作者是Enchant的架构师,他最近研究了Netflix.SoundCloud.谷歌.亚马逊.Spotify等公司的微服务实践,并根据自己的理解总结出了一套适用于现代Web和云技术的微服务实战经验 ...

  4. 【Azure API 管理】在APIM中使用客户端证书验证API的请求,但是一直提示错误"No client certificate received."

    API 管理 (APIM) 是一种为现有后端服务创建一致且现代化的 API 网关的方法. 问题描述 在设置了APIM客户端证书,用户保护后端API,让请求更安全. 但是,最近发现使用客户端证书的API ...

  5. 将声音文件加入VC

    概述 VC++是微软公司开发的一个IDE(集成开发环境),换句话说,就是使用c++的一个开发平台.有些软件就是这个编出来的...另外还有VB,VF.只是使用不同语言...但是,VC++是Windows ...

  6. 【转】33 个 2017 年必须了解的 iOS 开源库

    1.IGListKit,作者是Instagram Engineering Instagram 程序员做的,IGListKit 是数据驱动的 UICollectionView 框架,为了构建快速和可扩展 ...

  7. 33 个 2017 年必须了解的 iOS 开源库

    本文翻译自Medium,原作者为Pawe? Bia?ecki 照片版权:(Unsplash/Markus Pe) 你好,iOS 开发者们!我的名字叫 Pawe?,我是一个独立 iOS 开发者,并且是  ...

  8. Oracle WebLogic Server 12c 新特性

    美国时间2011年 12月9日,Oracle公司正式发布WebLogic 12c版本,c是cloud的缩写.截止当前(2013年8月)最新版本为Oracle WebLogic Server 12c ( ...

  9. 33 个 2017 年必须了解的 iOS/swift 开源库第三方库

    本文翻译自Medium,原作者为 Paweł Białecki<img src="https://pic3.zhimg.com/v2-c786777447261347b0d97 ...

随机推荐

  1. unbuntu 14安装 golang

    golang目前有两种编译,一种是golang官方提供的,另外一个是gnu提供的gccgo.这里安装的是Golang,从仓库安装(apt-get)        sudo apt-get instal ...

  2. Monkeyrunner测试环境搭建

    Monkey手机APP压力测试,是对手机发送伪随机命令,对手机进行按键,触摸等操作,MonkeyRunner是对其发送重复操作的命令,是Monkey的进阶版,可以设置重复的操作或者是重现步骤等.相比较 ...

  3. html5物理定位误差大 解决办法

    学生党在做比赛作品,项目中需求要用到定位功能并以地图形式展现.所以思路就是用h5的geolocation 获取经纬度,通过百度地图api将经纬度转换成详细的地址以及地图.在笔记本电脑做测试,定位总有超 ...

  4. 链表推导式 【list comprehension】

    x for x in x 链表推导式 [list comprehension]链表推导式提供了一个创建链表的简单途径,无需使用 map(), filter() 以及 lambda.返回链表的定义通常要 ...

  5. LOG算子

    原文:http://blog.csdn.net/songzitea/article/details/12851079 背景引言 在博文差分近似图像导数算子之Laplace算子中,我们提到Laplace ...

  6. 如何弹出WiFi提示列表。

    如果你的程序中用到了WiFi,想在没有有效WiFi的时候出现如图所示的提示该怎么做? 其实很简单, 只需要在Info.plist中添加如下Key/Value UIRequiresPersistentW ...

  7. SpringMVC中controller的几种返回值

    String :跳转到对应的返回值中. return “/index”: ModelAndView: 控制页面跳转方式: 1. ModelAndView modelAndView = new Mode ...

  8. iOS:UITableView相关(18-10-20更)

    UITableView用得较多,遇到的情况也较多,单独记录一篇. 一.零散的技巧 二.取cell 三.cell高度 四.导航栏.TableView常见问题相关 五.自定义左滑删除按钮图片 六.仅做了解 ...

  9. 清理 Xcode 10 记录

    1,清理 ~/Library/Developer/CoreSimulator/Devices 说明:该目录存放当前的所有模拟器,每个标识符代表一台机器,清理掉避免存在旧版本的模拟器缓存 执行: 关闭模 ...

  10. File、Paths和Files类的使用详解

    Paths:通过get()方法返回一个Path对象,Path用于表示文件路径和文件. Files:提供了大量处理文件的方法,例如文件复制.读取.写入,获取文件属性.快捷遍历文件目录等..... Fil ...