REST 深度进阶

发表于 3年以前  | 总阅读数:226 次

说起来,REST 出现已经很久了。

从早期的三层架构,到现在的多层、微服务,核心内容之一就是 API --- 从非常简单的 API,到多设备多用途的 API,包括一些外接的三方,像 BAT 的公共服务,简单的、麻烦的,都是 API。而这些 API,又基本上都是基于 REST 的。

今天我们不去详细解释 REST,只说说 REST 应用中间的一些要点。

REST 应用之多,是有他的原因的。他很容易理解,很灵活,并且可以适用于任何规模的应用。

当然,REST 并不是唯一的规范,还有 SOAP、GraphQL。但是,这只是字面上的并列的规范。所有的规范用过了,你就会知道:SOAP 很笨重,有时候还很古怪:你需要花大量的心思去想接口的表示,而不是逻辑本身。至于 GraphQL,又延伸的太多了,居然需要调用 API 的客户端去考虑和设计,这绝不是个好主意。

好吧,这个问题见仁见智,我们不展开讨论。

不管怎么说,在我看来,REST 仍然是 API 接口规范的王者,并且不会在短时间内被取代。

在我的习惯中,使用 REST 会有以下几个约束。

1 . 使用 JSON 数据

别误解,这是我的习惯,不是 REST 的。

REST 并没有规定使用什么样的格式来传递数据,XML 也行,JSON 也行。但是在我的团队中,JSON 传递数据是一个硬性要求。

相比较而言,JSON 比 XML 有太多的优势了:

  • 更易于使用、书写和阅读
  • 更快,占用的内存空间更少
  • 不需要特殊的依赖项或包来解析
  • 主流的编程语言对 JSON 都有支持

如果不理解这些优势,没关系,去网上随便找一个 XML,试着自己解析一下看看。熟悉大厂的各种开放平台的同学们也会有直觉的感觉:早期的 SOAP 和 XML,已经被逐步替换为了 REST 和 JSON。

此外,这里说的使用 JSON 数据,不仅仅是响应数据,还包括请求数据。不要使用 form-data 或者 x-www-form-urlencoded 发送数据,转成 JSON 发送,会更容易阅读、编写、测试和管理。

真心的,如果你这么做了,我会替所有开发的同学们感谢你。

2 . 认真对待方法

想一下,你有没有见到过只用 GET 方法来处理一切事情的 API?

这并不是不可以,只不过,这样的写法说明没有深入理解这个工具,以及 HTTP 的准确的工作方式。要知道,HTTP 中每个方法都被设计为处理特定的工作和内容。

这儿我逐个说说:

GET - 在仅仅用于读数据时,应该用 GET。不写入、不更新,只读取数据。这个概念很简单。而且,在这个前提下,相同的请求一定会返回相同的结果。

POST - 看字面的意思就明白,就是存储一些东西,像是在数据库中创建一条记录、在某处写入一些内容。通常来说,可以选择很多种方式 POST 数据:multipart/form-data、x-www-form-urlencoded、application/json 或者 text/plain,等等,很多。不过,我们要求只使用 application/json 方式,这样做可以保持开发和调用的一致性。

PUT - 字意就是更新内容。所以当我们需要更新数据时,就需要定义为 PUT 方法。当然,也可以用来创建新数据。

DELETE - 删除,很好理解。

PATCH - 打补丁,对于已经存在的数据进行更新操作。这个跟 PUT 有一点点区别,通常 PATCH 是有范围的,更新需要更新的内容,而 PUT 更多时候是更新整个数据。

当然,在某些文章里,还会有 OPTIONS、HEAD、TRACE等等,这些用得少,就不说了。想了解的,可以去查 HTTP 相关的文档。

说这么多,重要的是 --- 既然 HTTP 提供了这样的方法定义,我们完全可以把任何 CRUD 的操作对映到这些方法,而不是只用 GET,这决不是一个好习惯。

3 . 注意语义

在团队开发 API 时,有一个严格的要求,就是 API 名称需要有语义感。语义感这个词是我自己生造的,不是什么高大上的东西,就是要求写的 API 名称能使用正确的英文和次序,能够让人看得懂。都 9021 年了,居然还有人用拼音首字符,说出来你敢信吗?

在我看来,所有的 API 都应该可以在不看注释和说明的情况下被调用方理解,从调用端点,到参数,和 JSON 的键。

这儿,我参考了国外的一些规则。规则也很简单:

  • 用名词,别用动词。想一下,上面列出的方法,本身就是动词,比方说:GET /clients,就很好理解,如果换成 GET /getClients,总觉得怪怪的。
  • 一定要准确使用单数和复数,针对一条数据,就用单数;针对多条数据,就一定用复数。感觉一下 GET /client 和 GET /clients 的区别。当然,对于单个数据来说,通常还需要某种 ID 的存在:GET /client/id。

下面用一些例子来理解一下这个规则。

// 好的方式
GET /clients
POST /clients
GET /client/23
PUT /client/23
DELETE /client/23
GET /client/23/comments

// 不好的方式
GET /clients/23
GET /listAllClients
POST /client/create
PUT /updateClient/23
GET /clientComments/23

这儿要多说两句:规则只是规则,不用那么死板的去记。要把这种规则理解了,并习惯性地应用在编程的过程中,变成一种类似肌肉记忆的东西。

4 . 随时留心 API 的安全

就算你做得不是公开的 API,也一定要记着,使用某些手段,让你的 API 安全起来。这是 API 编程一个基本的要求。

这又有几个方面的要求:

1. 使用 HTTPs

HTTPs 已经出来非常久了,而且,如果你对接过大厂的 API,你会发现使用 HTTPs 是一个基本的要求。

HTTPs 提供了一种比 HTTP 更安全的方式,可以在基本网络层面除去中间人攻击,并加密调用端和 API 的通讯。在编程时,使用 HTTPs 是个成本最低但又确实有效的安全方式。

把使用 HTTPs 当成一个标准和习惯,有一天你会感谢自己的。

2. 从构建 API 开始,就要做到控制访问

你看得没错,是从构建 API 开始。

不需要做得很麻烦,但要有控制,要能控制谁能访问这个 API。通常可以先加入一个简单的 JWT Auth,等 API 成形后,再转为 OAuth。目的很简单,就是控制访问。如果真出现了 API 被攻击什么的,简单地关闭暴露的密钥就可以了。当然,我们还可以用密钥来跟踪 API 的调用,包括调用量、调用异常等。

3. 小心对待敏感数据

API 代表了网络,代表了通讯。在网络和通讯上,传递敏感数据一定要小心再小心。我们前边提到了一定使用 HTTPs,也是因为这个。如果不想面向监狱编程,一定要确保这些敏感数据通过正确的方式,给到正确的调用方。

看了一眼数据,就被追了刑责,这是我身边的真事。

4. 确保运行环境的安全

网关、防火墙,有就用上,别因为麻烦就关掉。更深的内容,可以扔给运维,但基础的部分,自己要懂要会。

5 . 版本控制

API 叠代升级,是每个开发的会面对的事。有时候,升级仅仅是逻辑的改变,而更多时候,是会改变输入输出结构的。这种情况下,保持和维护 API 的版本很重要。作为后端开发人员,我们无法保证调用端会随时同步进行相应的改动。极端情况下,改变内部逻辑,也有可能影响到调用端。

API 版本控制,不用犹豫,马上开始使用。不要觉得某个 API 比较小,或者调用端少,就不去做。记着,任何的代码改动,对于不更新应用或其它内容的调用者来说都是有风险的。你不仅需要确保你的代码不会破坏任何东西或任何人,还需要知道某个应用版本的表现。这件事一点都不好玩。

关于 API 版本控制的详细实现,我前边一篇推文,可以去看看。[传送门] 至于版本的方式,倒是不那么重要,可以看个人的习惯,v1、v2、v3也可以,v1.0、v1.1、v1.2也可以。按照微软的建议,是采用 Major.Minor.Patch 的方式。不过我自己觉得带上 Patch 部分有点太长了。

所以,在我的习惯中,应用版本控制后,API 的 URL会是这样的:

GET /v1.7/clients
POST /v1.7/clients
GET /v1.7/client/23
PUT /v1.7/client/23
DELETE /v1.7/client/23
GET /v1.7/client/23/comments

听我的,马上开始 API 的版本控制。

6 . 保持响应的一致

一致性是好的 API 的优秀品质。开发中,我们应该在各种方面做到一致,包括命名、URI、请求、响应等。而在这里面,响应的一致性是我对团人的一个硬性要求。

API 是要让别人去调用的。保持资源响应的一致,是对调用者最大的善意。在某个坛子上,我看到过建议每个端点返回不同资源结构的说法。如果你也看到过类似的内容,忘了它,那是错的。

记着这句话:保持资源响应的一致,是对调用者最大的善意。

API 开发时,尽可能发送相同的响应结构。如果没有数据,就将其作为空值、空对象或空数据发送。

我们拿论坛的文章结构举个例子。

文章数据的结构通常是这样(有简化,不要纠结):

{
    "title": "文章标题",
    "description": "文章内容",
    "comments":
    [
        {
            "text": "回复1",
            "user": "张三"
        },
        {
            "text": "回复1",
            "user": "张三"
        }
    ]
}

如果需要返回一条数据,并且要列出评论时,结果会是这样:

{
    "message": "fetch data successed",
    "status": true,
    "article":
    {
        "title": "文章标题",
        "description": "文章内容",
        "comments":
        [
            {
                "text": "回复1",
                "user": "张三"
            },
            {
                "text": "回复1",
                "user": "张三"
            }
        ]
    }
}

如果需要返回一个文章列表,并且没有评论时,会是这样:

{
    "message": "fetch data successed",
    "status": true,
    "articles":
    [
        {
            "title": "文章标题1",
            "description": "文章内容1",
            "comments": []
        },
        {
            "title": "文章标题2",
            "description": "文章内容2",
            "comments": []
        }
    ]
}

看到了吧?这样的方式下,我们对于里面元素 article 里结构是完全一样的,而对于整个返回结构,也是相似的。

坚持这样做,可以为自己和他人节省大量的时间。

7 . 重视出错后的返回信息

API 开发,应该既能处理正确的请求,也能处理错误的请求。错误的请求并不可怕,可怕的是你没有考虑到,或者考虑到了,但没有给到调用端足够的细节。

在 API 返回中,很多人在这里会忽略 HTTP 的状态代码,也就是 HttpStatus。

HTTP 协议,为我们定义了超过 50 种不同的状态代码,涵盖了几乎所有的场景。每个代码都有独特的含义,应该在独特的场景中使用。这个内容网上有很多,我就简单列一下:

1xx - 信息性响应代码,简单说就是一个状态通知。

2xx - 成功响应代码。所有的成功都会在这个范围。通常我们见到的是 200,但也有别的成功情况。

3xx - 重定向响应代码。请求被服务器重定向到另一个 URL,就会有这个返回。

4xx - 客户端错误响应代码。最常见的是 400,请求协议格式或内容错误。

5xx - 服务器错误响应。最常见的是 500,服务端程序,也就是 API 的内部,有内存溢出或异常抛出。

开发中,我们可以充分并准确使用这些状态码。这样,所有的开发人员,会在相同的认识层次上理解问题的状态和原因,从而使得 API 变得普遍易懂、一致和标准。

这不是 REST 的标准,但应该作为我们开发 REST 的标准。

有了状态码,这只是第一步。当运行出错时,我们需要向调用端提供尽可能多的细节。当然,这并不容易,我们需要能够考虑并预测 API 会如何出错,调用者会做什么,不会做什么。所以,通常一个 API 第一步是进行严格的请求数据验证:数据是否存在、值是否在我们期望的范围内、是否可以将他们存入数据库。

拿上面的例子来说,GET /client/23,取 clientId = 23 的数据,我们需要做以下的工作:

  • 检查请求是否有 clientId 参数,如果没有,应该是一个 400 的状态
  • 检查传入的 clientId = 23 的记录是否存在,如果不存在,返回响应 404
  • 如果找到记录,则返回响应 200

这只是一个简单的例子,真实的编程时,需要考虑的会更多。

而且,除了状态码外,还要返回相应的错误消息,例如:输入参数 clientId 没有输入、ID 为 23 的数据记录不存在,等等。

重要的是,提供详细的错误信息,可以帮助开发者和调用方了解到底什么地方发生了问题。

放心,调用者不会将这些信息显示给最终用户,但可以通过这些信息来快速的定位和解决问题。

8 . 尽可能优化

在现代编程中,API 在体系中的角色,绝对是整个操作的大脑。所以,对于 API 的开发,最基本的要求是快速和优化,决不能让 API 成为整个系统和生态的痛点。

要求就这么简单。

我们可以做很多事情来确保交付一个具备良好性能和可伸缩性的 API。来看看我们能做什么?

首先是数据库级别的优化。通常说 API 慢的时候,十有八九与数据库有关。糟糕的数据库设计、复杂的查询、缓慢的硬件环境,甚至缺乏缓存,都是慢的理由。所以,开发过程中,应该随时关注并始终优化数据库结构、查询、索引以及与数据库交互的所有内容。

接下来是缓存。很多人不愿意用缓存,因为会将代码变复杂。但是从实际效果上,越大、越复杂的系统,越应该通过缓存传递数据。有时候,缓存数据库查询能减少 100% 的加载时间。而绝大多数数据,不会进行频繁的改变。把缓存用起来,调用端的兄弟们,会把你当亲兄弟的。

另一个影响性能的因素是 API 发送到调用端的数据量。要做到确保 API 只返回调用端需要的数据,而不是全部。如果可能,不要每次都返回完整的模型细节和关系。试一下,但要与响应中的返回模型保持一致。

最后,别忘了压缩。如果可以,使用 Brotli,或者至少也使用 Gzip 来压缩数据。简单的配置,可以获得减少 50-75% 的传输数据,多好!

9 . 做个体贴的开发者

这个要求无关技术,但我还是想写出来。

作为一个开发人员,我们要明白,项目不是一个人的事。当我们写完最后一行代码,提交并合并后,你可能会认为工作已经完成。但不是,对其他很多人来说,这才是个刚刚开始。

很多人在我们完成了工作后,才能开始他们的工作。所以,我们需要以多种方式准备 API。我们要确保 API 能正常工作,要有很好的文档,更重要的事,我们需要准备好集成支持。不过文档写得有多好,在集成过程中,及以后的过程中,总会有问题,各种问题。

所以,设身处地的为他人着想,尽量让他们的工作变得容易些。构建一个良好的API,遵循我们在这里定义的规则,编写优秀的文档,并为所有人服务。

10 . 写完了

写完了。

上面九条,是我团队中执行的标准和要求。

这里我也必须说, REST 本身并不是一个标准,所以也不会有人告诉你什么是对的,什么是错的。开发的时候多想一下:作为开发人员,我们每天都在寻找使代码更好、更漂亮、更高效的模式,那么为什么不在 API 中也做同样的事呢?

全文完。

本文由哈喽比特于3年以前收录,如有侵权请联系我们。
文章来源:https://mp.weixin.qq.com/s/uZnxbhbVLA301qRskds5TQ

 相关推荐

刘强东夫妇:“移民美国”传言被驳斥

京东创始人刘强东和其妻子章泽天最近成为了互联网舆论关注的焦点。有关他们“移民美国”和在美国购买豪宅的传言在互联网上广泛传播。然而,京东官方通过微博发言人发布的消息澄清了这些传言,称这些言论纯属虚假信息和蓄意捏造。

发布于:1年以前  |  808次阅读  |  详细内容 »

博主曝三大运营商,将集体采购百万台华为Mate60系列

日前,据博主“@超能数码君老周”爆料,国内三大运营商中国移动、中国电信和中国联通预计将集体采购百万台规模的华为Mate60系列手机。

发布于:1年以前  |  770次阅读  |  详细内容 »

ASML CEO警告:出口管制不是可行做法,不要“逼迫中国大陆创新”

据报道,荷兰半导体设备公司ASML正看到美国对华遏制政策的负面影响。阿斯麦(ASML)CEO彼得·温宁克在一档电视节目中分享了他对中国大陆问题以及该公司面临的出口管制和保护主义的看法。彼得曾在多个场合表达了他对出口管制以及中荷经济关系的担忧。

发布于:1年以前  |  756次阅读  |  详细内容 »

抖音中长视频App青桃更名抖音精选,字节再发力对抗B站

今年早些时候,抖音悄然上线了一款名为“青桃”的 App,Slogan 为“看见你的热爱”,根据应用介绍可知,“青桃”是一个属于年轻人的兴趣知识视频平台,由抖音官方出品的中长视频关联版本,整体风格有些类似B站。

发布于:1年以前  |  648次阅读  |  详细内容 »

威马CDO:中国每百户家庭仅17户有车

日前,威马汽车首席数据官梅松林转发了一份“世界各国地区拥车率排行榜”,同时,他发文表示:中国汽车普及率低于非洲国家尼日利亚,每百户家庭仅17户有车。意大利世界排名第一,每十户中九户有车。

发布于:1年以前  |  589次阅读  |  详细内容 »

研究发现维生素 C 等抗氧化剂会刺激癌症生长和转移

近日,一项新的研究发现,维生素 C 和 E 等抗氧化剂会激活一种机制,刺激癌症肿瘤中新血管的生长,帮助它们生长和扩散。

发布于:1年以前  |  449次阅读  |  详细内容 »

苹果据称正引入3D打印技术,用以生产智能手表的钢质底盘

据媒体援引消息人士报道,苹果公司正在测试使用3D打印技术来生产其智能手表的钢质底盘。消息传出后,3D系统一度大涨超10%,不过截至周三收盘,该股涨幅回落至2%以内。

发布于:1年以前  |  446次阅读  |  详细内容 »

千万级抖音网红秀才账号被封禁

9月2日,坐拥千万粉丝的网红主播“秀才”账号被封禁,在社交媒体平台上引发热议。平台相关负责人表示,“秀才”账号违反平台相关规定,已封禁。据知情人士透露,秀才近期被举报存在违法行为,这可能是他被封禁的部分原因。据悉,“秀才”年龄39岁,是安徽省亳州市蒙城县人,抖音网红,粉丝数量超1200万。他曾被称为“中老年...

发布于:1年以前  |  445次阅读  |  详细内容 »

亚马逊股东起诉公司和贝索斯,称其在购买卫星发射服务时忽视了 SpaceX

9月3日消息,亚马逊的一些股东,包括持有该公司股票的一家养老基金,日前对亚马逊、其创始人贝索斯和其董事会提起诉讼,指控他们在为 Project Kuiper 卫星星座项目购买发射服务时“违反了信义义务”。

发布于:1年以前  |  444次阅读  |  详细内容 »

苹果上线AppsbyApple网站,以推广自家应用程序

据消息,为推广自家应用,苹果现推出了一个名为“Apps by Apple”的网站,展示了苹果为旗下产品(如 iPhone、iPad、Apple Watch、Mac 和 Apple TV)开发的各种应用程序。

发布于:1年以前  |  442次阅读  |  详细内容 »

特斯拉美国降价引发投资者不满:“这是短期麻醉剂”

特斯拉本周在美国大幅下调Model S和X售价,引发了该公司一些最坚定支持者的不满。知名特斯拉多头、未来基金(Future Fund)管理合伙人加里·布莱克发帖称,降价是一种“短期麻醉剂”,会让潜在客户等待进一步降价。

发布于:1年以前  |  441次阅读  |  详细内容 »

光刻机巨头阿斯麦:拿到许可,继续对华出口

据外媒9月2日报道,荷兰半导体设备制造商阿斯麦称,尽管荷兰政府颁布的半导体设备出口管制新规9月正式生效,但该公司已获得在2023年底以前向中国运送受限制芯片制造机器的许可。

发布于:1年以前  |  437次阅读  |  详细内容 »

马斯克与库克首次隔空合作:为苹果提供卫星服务

近日,根据美国证券交易委员会的文件显示,苹果卫星服务提供商 Globalstar 近期向马斯克旗下的 SpaceX 支付 6400 万美元(约 4.65 亿元人民币)。用于在 2023-2025 年期间,发射卫星,进一步扩展苹果 iPhone 系列的 SOS 卫星服务。

发布于:1年以前  |  430次阅读  |  详细内容 »

𝕏(推特)调整隐私政策,可拿用户发布的信息训练 AI 模型

据报道,马斯克旗下社交平台𝕏(推特)日前调整了隐私政策,允许 𝕏 使用用户发布的信息来训练其人工智能(AI)模型。新的隐私政策将于 9 月 29 日生效。新政策规定,𝕏可能会使用所收集到的平台信息和公开可用的信息,来帮助训练 𝕏 的机器学习或人工智能模型。

发布于:1年以前  |  428次阅读  |  详细内容 »

荣耀CEO谈华为手机回归:替老同事们高兴,对行业也是好事

9月2日,荣耀CEO赵明在采访中谈及华为手机回归时表示,替老同事们高兴,觉得手机行业,由于华为的回归,让竞争充满了更多的可能性和更多的魅力,对行业来说也是件好事。

发布于:1年以前  |  423次阅读  |  详细内容 »

AI操控无人机能力超越人类冠军

《自然》30日发表的一篇论文报道了一个名为Swift的人工智能(AI)系统,该系统驾驶无人机的能力可在真实世界中一对一冠军赛里战胜人类对手。

发布于:1年以前  |  423次阅读  |  详细内容 »

AI生成的蘑菇科普书存在可致命错误

近日,非营利组织纽约真菌学会(NYMS)发出警告,表示亚马逊为代表的电商平台上,充斥着各种AI生成的蘑菇觅食科普书籍,其中存在诸多错误。

发布于:1年以前  |  420次阅读  |  详细内容 »

社交媒体平台𝕏计划收集用户生物识别数据与工作教育经历

社交媒体平台𝕏(原推特)新隐私政策提到:“在您同意的情况下,我们可能出于安全、安保和身份识别目的收集和使用您的生物识别信息。”

发布于:1年以前  |  411次阅读  |  详细内容 »

国产扫地机器人热销欧洲,国产割草机器人抢占欧洲草坪

2023年德国柏林消费电子展上,各大企业都带来了最新的理念和产品,而高端化、本土化的中国产品正在不断吸引欧洲等国际市场的目光。

发布于:1年以前  |  406次阅读  |  详细内容 »

罗永浩吐槽iPhone15和14不会有区别,除了序列号变了

罗永浩日前在直播中吐槽苹果即将推出的 iPhone 新品,具体内容为:“以我对我‘子公司’的了解,我认为 iPhone 15 跟 iPhone 14 不会有什么区别的,除了序(列)号变了,这个‘不要脸’的东西,这个‘臭厨子’。

发布于:1年以前  |  398次阅读  |  详细内容 »
 相关文章
Android插件化方案 5年以前  |  237229次阅读
vscode超好用的代码书签插件Bookmarks 2年以前  |  8063次阅读
 目录