[译] 将现有的 API 从 REST 迁移到 GraphQL

简介: 本文讲的是[译] 将现有的 API 从 REST 迁移到 GraphQL,最近的六个月内我发现几乎每一场有关于 Web 开发的大会都谈论到了 GraphQL。也有大量与其相关的文章被发表。但是所有的这些几乎都是在讲 GraphQL 的基础概念或者是新特性,说得很表面。
本文讲的是[译] 将现有的 API 从 REST 迁移到 GraphQL,

将现有的 API 从 REST 迁移到 GraphQL

最近的六个月内我发现几乎每一场有关于 Web 开发的大会都谈论到了 GraphQL。也有大量与其相关的文章被发表。但是所有的这些几乎都是在讲 GraphQL 的基础概念或者是新特性,说得很表面。因此我打算谈谈我在真实大型系统中采用 GraphQL 的个人经验。

REST 有什么问题

REST(一如 SOAP)没有分离传输、安全和数据逻辑层面。这会带来很多问题。让我们来看看其中的几个。

GET 查询能力的低下

用 GET 语句进行复杂深入的查询是不可能的。假设我们需要查询用户。举一个很简单的例子:

GET /users/?name=Homer

然后想象一下,我们需要查找名字是 Homer 或者 Marge 的用户。事情就变得有点棘手了。当然,我们可以为这种需求定义一些分隔符。

GET /users/?name=Homer|Marge

但是,不要忘记转义这些字符!并且牢记,如果有人的名字中包含 “|” 那么你就完蛋啦。如果要结合两个不同的字段那么就更复杂了。更别说是需要同时满足上面两种条件的查询。

目前我们一般都是使用字段来查询对应的内容。但是也时常需要用查询语句来传递一些服务数据。比如页码:

GET /users/?name=Homer|Marge&limit=10&offset=20

按逻辑来说,我们后端的查询解析器应该会将 limit 和 offset 识别为数据库的字段,因为他们被声明为和 “name” 字段同级的参数名。

我们可以发明我们自己的语法或是用 POST 方法(这是不对的,因为这是一个幂等请求)但是这看起来像是在造轮子。

数据更新的问题

使用 PUT 发送整个对象是最简单的 REST 更新数据的方式。但显而易见的是,当你仅仅只需要更新 1 Mb 大小的对象中的一个字段时,这并不是最有效的方式。

HTTP 还有一个 PATCH 方法。但是它有一个问题。用算法来定义 如何更新实体 并不简单。现有多个规范建议你应该如何去做,比如 RFC 6902,RFC 7396 以及许多自定义解决方案。

命名问题

我猜测每个曾与 REST 打交道的开发者都明白这种感受,当你不知道如何去命名你的新路由时。并非所有的业务实例都可以被描述为资源。例如我们想要搜索带有商店信息的商品。

GET /search?product_name=IPhone&shop_name=IStore

这里的资源是什么?商品?商店?搜索?

天哪,我的 API 不再是 REST 风格了!

另一个典型的例子便是用户登录。这里的资源又是什么?Spoiler:这里没有资源,这里只是个远程过程调用而已。

后端处理 REST

app.post((req, res) => {
  const user = db.getUserByName(req.headers.name);
  const user = db.getUserByName(req.query.name);
  const user = db.getUserByName(req.path.name);
  const user = db.getUserByName(req.body.name);
});

这是一个 Express 路由的例子。这里我们试图获取用户的 ID 来查找用户。让我们看一看 API 函数通常应该是什么样子:

函数接收参数,进行特定的处理并返回特定的结果。

在这个 Express 路由的例子中我们的参数是什么?一个巨大杂乱的 req 对象,而我们仅需要其中很小的一部分数据。

当然,这也是 Express 的一个问题(准确的说是 Node 的 HTTP 模块的问题),但是这样的接口也是因为 HTTP 的实现逐步进化而产生的 - 请求参数可以在任何位置,所以如果你本人不知道它或者没有使用描述良好的文档时想要准确知道参数位置是不可能的。

这就是为什么使用没有接口文档的 REST 是如此的痛苦。

GraphQL

在这里我们假设你早就熟悉 GraphQL 的基础知识。如果没有,你可以从 Apollo 写的关于GraphQL 基础知识的介绍开始。

正如我们前面所展示的,REST 存在一些 GraphQL 所没有的设计上的问题。并且 GraphQL 有着巨大的发展潜力。

首先 GraphQL 提供 RPC 访问方式,这意味着你将不受客户端-服务端的交互限制。GraphQL 有它自己的类型系统,这意味不再有令人误解的错误和漏洞。并且类型系统意味着你的客户端可以提供 item 级别的数据智能缓存。还拥有大量像是网络连接(游标和分页)、批处理、延时等的面向 Web 的特性。它 使你的客户端-服务端交互尽可能的高效

但是 REST 仍然是业内标准

是的,无论我们是否喜欢,REST 都是近几年 API 的主流形式。

但是我们仍然可以为一些内部需求(比如对接一些高级客户端)去使用 GraphQL,其他的使用 REST。

为此,我们需要将 REST 路径包装成 GraphQL 类型。这里有一些文章和例子(被提到最多的是 swapi-rest-graphql)关于从 REST 迁移到 GraphQL。但是它们建议使用自定义解析器,这无法满足拥有成百上千路径的大型项目。

在我最近的三个项目中我使用 Swagger 来描述 REST 接口。它或多或少都算是声明式接口描述的标准。坦白说我真的不知道那些编写庞大却毫无描述的接口的人们是如何做到的。

一方面我们把 Swagger 作为声明式 REST 接口的标准,另一方面也可以这么看 GraphQL,我们可以看到它们其实非常相似,只是除此之外 Swagger 还尝试去描述 HTTP 细节和业务逻辑。它们都描述了传入参数和传出响应的类型。这意味着我们可以在它们之间写适配器!

REST 路径是这样子的

GET /user/id

可以采用 GraphQL 类型。

所以现在我们只需一个库来帮助我们自动转换。下面这个就是!

github.com/yarax/swagg…

Swagger2graphQL 接收你的 Swagger schema 然后返回 GraphQL schema,同时解析程序将自动构建 HTTP 请求到已有的 REST 路径上。

它被构建为一个将拥有超过 150 个路径的真实大型系统迁移到 GraphQL 的副项目。我们需要在做功和问题都最少的情况下尽快地迁移到 GraphQL。

只需要克隆资源库,运行

npm install && npm start

然后访问 http://localhost:3009/graphql

你会看到封装在 petstore.swagger.io/ Swagger 示例接口上的 GraphQL 接口。

而且,有了 Swagger 和 GraphQL 编写新的路径将变得十分方便。如果你早就熟悉 GraphQL,你可能会发现有时候类型描述看起来相当冗长,因为你需要去创建大量的隐式类型。Swagger2graphQL 可以自动完成这些步骤,你只需要在 Swagger schema 中创建一个新的带有声明的路径,通常这很简单。

如果你遇到任何困难或者有疑问请向我提 issue!

同时你也可以在 Twitter 上找到我





原文发布时间为:2017年8月12日

本文来自云栖社区合作伙伴掘金,了解相关信息可以关注掘金网站。
目录
相关文章
|
14天前
|
缓存 监控 前端开发
利用GraphQL提升API开发效率
【10月更文挑战第10天】本文介绍了GraphQL的核心概念、优势及其实现步骤,探讨了其在现代开发中的应用,包括动态数据需求、单页应用和微服务架构。通过缓存策略、批处理、安全性和监控等实战技巧,提升API开发效率和用户体验。
|
24天前
|
安全 API 数据库
掌握GraphQL:现代API开发的新选择
【10月更文挑战第1天】在传统RESTful API显现出局限性后,GraphQL作为新型API查询语言和运行时,提供更灵活的数据获取方式。客户端可精确指定所需数据结构,减少传输量并提升效率。本文探讨GraphQL核心概念、优势及实施方法。尽管存在复杂性和性能优化等挑战,GraphQL仍是构建现代API的强大工具。
|
2月前
|
JSON 中间件 API
开发REST API3-11
开发REST API3-11
|
2月前
|
JSON JavaScript API
编写REST API
编写REST API
44 2
|
26天前
|
Java API Maven
使用 Smart-doc 记录 Spring REST API
使用 Smart-doc 记录 Spring REST API
29 0
|
2月前
|
API 网络架构 微服务
探索 GraphQL:现代 API 开发的新范式
GraphQL 是一种高效的 API 查询语言,允许客户端精确请求所需数据,避免了传统 RESTful API 中的数据冗余问题。它由 Facebook 开发并开源,现广泛应用于现代 Web 和移动应用。本文将介绍 GraphQL 的核心概念、优势及其在不同场景下的应用,并指导你如何构建和优化 GraphQL API。
|
3月前
|
存储 JSON API
【Azure 存储服务】使用REST API操作Azure Storage Table,删除数据(Delete Entity)
【Azure 存储服务】使用REST API操作Azure Storage Table,删除数据(Delete Entity)
【Azure 存储服务】使用REST API操作Azure Storage Table,删除数据(Delete Entity)
|
3月前
|
Java Spring API
Spring框架与GraphQL的史诗级碰撞:颠覆传统,重塑API开发的未来传奇!
【8月更文挑战第31天】《Spring框架与GraphQL:构建现代API》介绍了如何结合Spring框架与GraphQL构建高效、灵活的API。首先通过引入`spring-boot-starter-data-graphql`等依赖支持GraphQL,然后定义查询和类型,利用`@GraphQLQuery`等注解实现具体功能。Spring的依赖注入和事务管理进一步增强了GraphQL服务的能力。示例展示了从查询到突变的具体实现,证明了Spring与GraphQL结合的强大潜力,适合现代API设计与开发。
106 0
|
3月前
|
XML 安全 API
REST 和 SOAP API 有什么区别?
【8月更文挑战第31天】
124 0
|
3月前
|
JSON API 数据安全/隐私保护
哇塞!Django REST framework 太逆天啦!构建 API 服务从未如此轻松,你还不来试试?
【8月更文挑战第31天】Django REST framework(DRF)是基于Django框架的高效Web API开发工具,提供序列化、视图集、路由等功能,简化API构建流程。使用DRF可轻松实现数据的序列化与反序列化,并支持权限管理和认证机制以保障API安全。安装DRF只需通过`pip install djangorestframework`命令。要创建基本项目,先安装Django并创建新应用,定义模型、序列化器及视图集,最后配置路由。测试API时,可通过Postman发送HTTP请求验证功能。无论项目大小,DRF均能提供强大支持。
35 0