REST 的十条戒律

2025-06-07

REST 的十条戒律

过去十年来,我一直在研究的核心内容之一就是 API。从单客户端使用的简单 API,到多设备和多用途的 API,应有尽有。这些年来,我也有机会接触过许多第三方 API,比如 Stripe、Twilio 以及其他一些不那么热门和引人注目的 API。几乎所有这些 API 都是基于 REST 的,并且在某些方面都独具特色。

REST 如此流行的原因有很多。它简单易懂、灵活多变、适用于任何规模,拥有强大的社区和丰富的工具。但除此之外,我想说,REST 之所以如此受欢迎,很大程度上是因为它的老对手 SOAP 实在太糟糕了。如果你曾经使用过或接触过 SOAP,你就知道!它的客户端很糟糕,人们只能用 XML 做他们想做的事情,它很笨重,身份验证有时也很棘手……谢天谢地,JSON 和基于 REST 的 API 赢得了这场战斗。

另一方面,也有一些更新、更先进的参与者试图从基于 REST 的 API 中分一杯羹。我当然指的是 GraphQL。GraphQL 也基于 JSON,并且具备 REST 的一些优点,例如灵活性、性能和可扩展性……就我个人而言,GraphQL 的两个主要缺点是:它是由 Facebook 开发的;以及它将 API 设计流程转移到了客户端。我的意思是,它让移动开发者和前端开发者负责构建他们自己的临时 API 并进行数据库查询。我不知道你是怎么想的,但我认为这并非最佳方案。别误会,我喜欢移动开发者和前端开发者,但他们可能缺乏数据库设计、编写查询和构建 API 的经验。你可能不会让后端开发者去设计应用程序,也不会让汽车修理工去修理飞机,更不会让兽医去做人体手术。他们能做到吗?或许吧,或许吧。他们应该吗?我不这么认为。

在我看来,REST 仍然是丛林之王,而且短期内不会被取代。REST唯一的问题是,归根结底,它既不是标准,也不是协议。相反,它只是一套“架构约束”。不把某样东西称为标准,真是个奇葩的说法 🤣 但这恰恰激发了很多人的兴趣。他们倾向于自行其是,或者根据自己(误解的)理解来实现这些约束。为了避免这种误解,我决定写下我认为的 REST API 十诫。遵循这些戒律,你将获得移动开发者的喜爱、其他后端开发者的钦佩,并在 Twitter 上成为明星😎。

就像歌里唱的:你不愿跟随我进入丛林吗?

1.务实

这真的很简单。如果你正在构建 REST API,你应该使用 JSON 来接收和响应数据,而不是 XML,也不是其他格式。JSON。

是的,JSON 并非“必需”,因为 REST 并非标准,但它是那些你不得不做的事情之一。就像你每天穿衣服、每晚睡觉或每天喝一杯拉基亚(rakija)一样。也许你还没明白最后那部分,但你明白我的意思了😆 我们越早让所有人放弃 XML 转而使用 JSON,对每个人就越好。如果你不确定为什么 JSON 更好,我随便列举几个理由:

  • 它更容易使用、书写和阅读——任何人都可以阅读,甚至你的奶奶也可以阅读
  • 速度更快,占用的内存空间更少
  • 它不需要特殊的依赖项或包来解析它
  • 每种有意义的编程语言都对其有很好的支持

如果这仍然显得抽象,我建议您从互联网上下载一个随机的 XML 文件并尝试解析它。作为一个在 21 世纪不得不多次这样做的人,我可以向您保证,您一定会哭着回到 JSON。在 2021 年,您根本没有理由使用 XML 而不是 JSON……是的,如果您拥有遗留的企业系统,我理解您的痛苦,但即使是这种情况也在改变。越来越多的大型过时企业正在将其内部和外部 API 从 XML 和 SOAP 更新为 JSON 和 REST。

JSON 不仅应该用于响应端,也应该用于请求端。因此,与其使用 form-data 或 x-www-form-urlencoded 发送数据,不如直接使用 JSON 格式发送。这样对每个人来说,读取、编写、测试和管理都更简单。

记住 - 如有疑问 - 请使用 JSON。我们全体开发人员在此先行致谢。

2. 有条不紊

你绝对想不到,我见过多少次 API 只用 GET 方法来实现从存储数据到过滤的所有功能 🤪 作为开发者,你应该始终努力理解所使用的工具,因此,如果你正在开发 API,了解 HTTP 的具体工作原理至关重要。每种 HTTP 方法都被设计用于特定场景。让我们逐一介绍它们,看看何时应该使用它们。

在开始之前,我们先来简单说明一下。在描述 HTTP 方法时,人们经常使用“安全”和“幂等”这样的词。这些词听起来很美好也很神秘,但其实并不复杂。简单来说,“安全”意味着“仅就绪”。您可以向该端点发出请求,而无需担心更新、销毁或更改值。另一方面,“幂等”意味着您可以向同一端点发出多个请求,而无需更改任何内容或获得不同的结果。一般来说,所有安全方法同时也是幂等的,但并非所有幂等方法都是安全的🙃。我知道一开始可能会让人困惑,但我们会在下文中解释。

GET

读取数据时,应该使用 GET 方法。GET 方法不存储、不更新、不修改数据,只读取数据。这个概念非常简单,不会让人感到困惑。既然我们知道 GET 方法应该只用于读取数据,并且它们总是返回相同的数据,那么我们可以说 GET 请求是安全且幂等的。

POST

当您发出 POST 请求时,世界上的每个人都希望您通常存储某些内容。这意味着您将在数据库中创建一个新行,在某处写入某些内容,或者根据需要从无到有创建某些内容。您可以使用多种内容类型将数据发送到 POST 方法:multipart/form-data 或 x-www-form-urlencoded 或 raw(application/json、text/plain……等)。在构建 REST API 时,我建议客户端以 application/json 的形式发送数据。这样,我们既能保持一致并符合 JSON 精神,又能发送 JSON 数据让您轻松发出非常复杂的请求。最后,POST 操作并不安全,因为它们会改变服务器端的内容,而且它们肯定不是幂等的,因为向同一端点发出两个请求会导致不同的资源。

PUT

请求最常用于更新内容。它也可以用于创建新记录,但这样做的目的是让客户端定义新资源的 ID。因此,为了简化操作,只需在需要更新资源时使用 PUT 即可。PUT 当然不是一个安全的操作,因为它会在服务器端进行更改,但你会喜欢这一点,因为它是一个幂等操作。

DELETE

我觉得这个很容易理解。当你想删除资源时,只需使用 DELETE 方法即可。当然,这不是一个安全的操作,但有人说它是幂等的,也有人说它不是。

PATCH

补丁请求旨在再次更新资源,但与 PUT 不同,它只能更新更改的数据,而 PUT 可以更新整个资源。它既不安全,也不具备幂等性。

现在我们已经了解了基础知识,接下来看看现实世界中的情况。大多数人使用 GET 和 POST,有些人使用 PUT 和 DELETE。我很少看到有人使用 PATCH。我建议你使用所有可用的 HTTP 方法,因为它们的设计初衷就是如此。你可以将任何 CRUD 操作映射到 POST、GET、UPDATE 和 DELETE。我强烈建议你永远不要使用 GET 来创建或更新数据。千万不要。

3. 语义化

语义化

这可能是你唯一一次听到我建议某人遵循语义规范。但在这种情况下,语义规范很重要,关键在于正确命名。我经常看到 API 文档中所有东西的命名约定都很糟糕。在我看来,每一个优秀的 REST APi 都应该让普通人都能轻松理解。从端点名称到输入参数,再到 JSON 键,都应如此。

那么我们就从 API 端点开始吧。这里的规则也很简单

  • 使用名词而不是动词
  • 使用复数而不是单数

之所以应该使用名词,是因为正如我们上面所见,当你发出 HTTP 请求时,你已经在使用动词了。每个 HTTP 方法(GET、POST、PUT、PATCH)在英语中都是动词。因此,使用两个动词是没有意义的——不是吗?如果你将一个 API 端点命名为 ,/getUsers并且你正在发出一个 GET 请求来查看所有用户,当你大声读出这句话时,听起来会很奇怪。GET /getUsers毫无意义。

我一直看到的另一个常见问题是使用单数而不是复数作为端点名称。这当然大错特错。您希望您的 API 端点一致、简单且合乎逻辑。如果使用复数,那么对于每个 HTTP 方法,您都可以使用相同的 URI。如果这样做,GET /users您将列出所有用户,如果这样做,POST /users您将创建一个用户。所以,同样的 URI,不同的 HTTP 方法(动词)。如果您希望查看单个用户的详细信息,那就更酷了 - 您请求GET /users/:id获取信息。所以正如您所见 - 它仍然是相同的起始资源名称,只是更深入。如果您使用单数,则GET /user意味着您希望获取单个用户,并且在其他情况下您将需要更多不同的 URI。复数更有意义。

总结一下,让我们看几个好的和坏的例子,这样我们就能 100% 清楚了。

很好👍🏻

  • GET /users
  • POST /users
  • GET /users/23
  • PUT /users/23
  • DELETE /users/23
  • GET /users/23/comments

糟糕👎🏻

  • GET /user/23
  • GET /listAllUsers
  • POST /user/create
  • PUT /updateUser/23
  • GET /userComments/23

我想你已经明白了😀。其实很简单,只要看看上面的例子,你就知道哪些听起来不错,哪些更有意义。

关于端点命名的几点补充说明:尽量使用单个单词,而不是多个单词。如果确实需要使用多个单词,请在它们之间使用连字符。另外,为了您的利益,请在 URI 中使用全部小写字母。

总结本节,我想快速回顾一下请求和响应数据中 JSON 键的命名约定。关于这一点存在很多争议,尤其是考虑到有三种可能的方案:驼峰命名法 (camelCase)、蛇形命名法 (snake_case) 和脊柱命名法 (spinal-case)。同样,没有人能阻止你使用其中任何一种,理论上你并没有错。但是,我建议使用蛇形命名法 (snake_case)。为什么?Stripe 使用它。PayPal 使用它。Facebook 使用它……你明白我的意思。就我个人而言,我觉得蛇形命名法更容易阅读,这就是为什么我们所有的 API 都使用蛇形命名法。也有一些类似的研究表明,可读性方面,蛇形命名法比驼峰命名法更有优势。

4. 确保安全

我直接说:如果你在 2021 年还没有使用 HTTPS,那真是太丢脸了。你的 REST API 应该毫无疑问地在 HTTPS 上运行。使用 HTTPS 只是提供了 HTTP 所不具备的安全性。它可以保护你的用户免受中间人攻击,并加密客户端和 API 之间的通信。苹果和谷歌等许多其他巨头很快也会强制你启用 HTTPS。最棒的是,现在你可以免费获得 SSL 证书。使用 AWS 和 Route 53 等服务、Azure 等效服务或名为 Let's encrypt 的服务。它们都运行良好,我可以亲自作证。你也可以随时购买高级 SSL 证书。无论你做什么,只需在下一个 API 上使用 HTTPS。你以后会感谢我的。

另一件让我最难过的事情是,我看到某个 API 没有使用任何形式的授权。如果你正在构建一个 API,你只需要能够控制谁有权访问它。这很简单,但很多人不这么做,因为他们觉得它太复杂,难以实现、使用和维护。其实没必要。你可以先使用 Bearer Tokens,2 分钟内就能设置好。如果你不想连接数据库,它们甚至不需要连接。当你准备好后,可以切换到更复杂的解决方案,比如 JWT 或 oAuth。有很多理由说明你应该拥有某种身份验证解决方案。首先,你可以控制 API 的访问权限以及访问权限的级别。如果出现问题,比如你的 API 被垃圾邮件攻击、被黑客攻击等等,你可以直接关闭暴露的密钥。你还可以使用 API 密钥来跟踪 API 的集成情况,是否有人进行了过多的 API 调用,以及客户端是否出现了异常行为。最后,您甚至可以使用 API 调用来收集有关您的客户、用户和 API 的统计数据。

我的观点是 -对待你的 API 就像对待你的房子一样。我相信你的门都有钥匙,而且你只会把钥匙交给重要的人。你的 API 也应该如此。

另一件需要注意的事情是通过网络发送超级敏感数据。我们讨论过这个问题,以及使用 SSL 加密通信的重要性。这是第一步。第二步是不要返回可能敏感且不会被应用程序或网站使用的数据。我指的是用户地址、电话号码、社会安全号码 (SSN) 或任何其他形式的身份证明。如果您不使用这些数据,就不要发送。如果您正在使用这些数据,请务必确保访问该 API 并获取响应的人就是您返回数据的实际使用者。我知道这听起来很简单,但实际上人们会做出各种疯狂的事情。主要是因为他们认为“哦,不会有什么事,这只是一个小 API,没人知道”……相信我。人们会发现,如果你允许他们这样做,他们就会利用这一点。所以千万不要这么做。

在结束之前,我想谈谈 UUID 与 ID 之间的争论。我一直很喜欢 ID,因为它们更短更快,但我认为 UUID 带来的安全和隐私优势更为重要。UUID更安全。您仍然可以在数据库中保留一个自动递增的 ID 列,但在将模型暴露给 API 时,请尝试使用 UUID。虽然这只是一个简短的建议,但可以帮您省去很多麻烦。

最后我想谈的是通用基础设施安全。如果您使用 AWS 或 Azure,您将拥有优势。API 网关在防火墙和 DDoS 攻击检测方面为您提供了额外的安全性。如果可以,请尽量使用它们。任何能够阻止特定 IP 或用户的机制都是您应该始终关注的。如果您使用的是运行 Apache 的传统服务器,那么这里有两个快速实用的小技巧,可以帮助您避免一些后续的麻烦。

第一个很简单:保持软件更新。Apache、PHP、Composer 软件包、NPM 软件包……所有一切。确保你始终运行最新、最好的软件。

其次,默认情况下,Apache 会在每个请求中发送一个响应标头,告知潜在攻击者您正在运行哪个版本的 Apache。标头的键名为Server,默认值可能类似于:Apache/2.4.1 (Unix)。您需要在这里快速隐藏您的 Apache 版本。

只需打开/etc/apache2/conf-enabled/security.conf并将ServerTokens值设置为Prod。之后运行 sudo systemctl restart apache2 ,您的服务器就比昨天更安全了。恭喜!

开启后,您还可以快速/etc/apache2/conf-enabled/security.conf关闭ServerSignature。只需将其设置为 ,Off即可再次确保安全。

一般来说,你应该每季度召开一次安全会议,讨论如何提升安全性、如何改进、如何保持安全等问题。你肯定不想被黑客攻击、遭受 DDoS 攻击或类似事件的袭击。相信我。

5. 井然有序

还有什么比对 API 进行版本控制更好的保持井然有序的方法呢?😀 我知道你已经多次读过这篇文章,并且想过类似这样的想法:“哦,我的 API 太小了,而且只有一个客户端在用,所以我不会使用版本控制”。我曾经也是你们中的一员。我这样做过。我也说过这样的话。更明智一点,对 API 使用版本控制。这是你早期能做出的最佳决定。

语义化

我一直对版本控制犹豫不决的原因是,在我看来,API 级别从 v1 跳到 v2 的情况很少发生。我说很少是指在科技领域——所以一年一次😁 知道版本控制对我来说没有意义。但是我错了。是的,大的跳跃并不经常发生,但如果你有一个正在使用或开发的平台或应用程序,你会更频繁地进行小规模的更新。我指的是每周或每月对模型、数据类型、结构或流程的更新,这些更新对于不更新应用程序或其他内容的人来说是危险的。要做到这一点,如果你没有启用版本控制,那么每次进行 GIT 提交时你都会汗流浃背。你不仅要确保你的代码不会破坏任何东西或任何人,还需要知道某个应用程序版本的行为方式。一点也不好玩,相信我。

只需选择最适合您和您的团队的版本控制方案即可。软件世界中最常见的版本控制方案是:MAJOR.MINOR.PATCH。我认为 PATCH 部分有点多,但如果您愿意,可以使用该方案。我通常使用v1.1,然后一直到v1.9。因此,使用主版本号,您会更改 API 的核心部分,例如身份验证、核心模型、流程等。使用次版本号和补丁版本号,您通常会添加或删除一些较小的功能,以某种方式调整数据结构或类似操作。

另一件可能让你感到困惑的事情是如何真正实现版本控制,因为有很多方法可以实现。你可以使用以下方式进行版本控制:URI 路径、请求标头、查询参数或内容协商。每种方法都有其优缺点,但我建议使用基于 URL 的版本控制。它最有意义,而且在很多层面上都最容易理解。从进行更新、仅通过 URL 了解所使用的版本,到指向正确的文档版本,一切都是如此。REST API 主要基于 URI,我认为我们应该延续这一传统,使用基于 URI 的版本控制。例如:

  • api.domain.com/v1/auth/login
  • api.domain.com/v1.2/auth/login
  • api.domain.com/v1.4.5/auth/login
  • api.domain.com/v2/auth/login

总而言之,尽早开始使用版本控制,可以避免以后出现问题,并能够扩展 API。

6.保持一致

你可能听过这样一句话:“一致性是将平庸转化为卓越的关键”。这在生活中和 API 设计中都是如此,信不信由你。优秀 API 的特质之一就是一致性。我首先关注的是资源/模型的一致性,其次是命名、URI、HTTP 代码等其他方面的一致性

众所周知,API 可以归结为资源。资源可以是任何内容,例如用户、文章、书籍、产品等等。每个资源可以包含多个属性、对象或数组。资源的结构基于数据库中的数据或其他业务逻辑。保持资源响应的一致性是 API 成功的关键。您不能让端点返回截然不同的资源结构。尽管这听起来很诱人,或者是一种优化方法,但您应该避免这样做。实现 API 的移动开发者会像圣经一样遵循您提供的结构。如果您在每个端点上都发送不同的内容,他或她会非常沮丧,这是任何人都不希望看到的。因此,请始终发送相同的资源结构。如果没有数据,请将其作为空值、对象或数组发送。让我们从实际角度来谈谈,假设我们有一个“文章”资源,有时该文章可能有评论,有时可能没有。有时加载评论是合理的,有时则不合理。这没问题,但仍然要尝试在结构方面保持一致的响应。

当你获取一篇文章时,你也想加载评论,如下所示:

    {
       "status":true,
       "message":"Getting details for article with UUID: 5b8f6db5-7848-490e-95a7-f7146dd2e30c",
       "article":{
          "title":"Sample title 1",
          "description":"Sample description 1",
          "image":"https://domain.com/image-1,jpg",
          "uuid":"eec33d99-e955-408e-a64a-abec3ae052df",
          "comments":[
             {
                "text":"Great article",
                "user":{
                   "name":"John Doe",
                   "uuid":"5b8f6db5-7848-490e-95a7-f7146dd2e30c"
                }
             },
             {
                "text":"Nice one",
                "user":{
                   "name":"Jane Doe",
                   "uuid":"2ececb69-d208-46c2-b560-531cb716d25d"
                }
             }
          ]
       }
    }
Enter fullscreen mode Exit fullscreen mode

但是当您加载文章列表或刚刚创建文章并且没有评论时,您应该返回以下内容:

    {
       "status":true,
       "message":"Article list was a success",
       "articles":[
          {
             "title":"Sample title 1",
             "description":"Sample description 1",
             "image":"https://domain.com/image-1,jpg",
             "uuid":"eec33d99-e955-408e-a64a-abec3ae052df",
             "comments":[]
          },
          {
             "title":"Sample title 2",
             "description":"Sample description 2",
             "image":"https://domain.com/image-2,jpg",
             "uuid":"b8ee70a8-1128-4670-9368-83953fdf722b",
             "comments":[]
          }
       ]
    }
Enter fullscreen mode Exit fullscreen mode

因此,即使客户端期望看到评论数组,他们仍然会收到,但数组内容为空。这样,您就不会更改模型并删除对象/数组。

只要坚持不懈,你就能为自己和他人节省大量时间。

7. 保持优雅

如果你正在构建 API,那么失败是必然的。这很正常,这是意料之中的事。如果你的 API 出现错误或问题,你不应该感到难过。你应该感到难过的是,你没有提供详细信息,并确保你的 API 比其他 API 更智能

从最开始,我发现开发人员最常忽略的就是 HTTP 状态码。如果您不知道的话,HTTP 几乎涵盖了所有可以想象到的场景。您只需要知道使用哪个状态码并将其发送回客户端即可。HTTP 响应状态码有 50 多种,它们各自都有其独特的含义,应该在特定的场景中使用。我不会一一介绍,但我们会列出最常见的几类。我们列出了:

  • 信息响应代码(以 1xx 开头)
  • 成功响应代码(以 2xx 开头)
  • 重定向响应代码(以 3xx 开头)
  • 客户端错误响应代码(以 4xx 开头)
  • 服务器错误响应代码(以 5xx 开头)

所以你真的拥有了所有你需要的状态。从正常、未授权、未找到、内部服务器错误到“我是茶壶”等等,应有尽有。没错,最后一个状态是真实的。这证明了开发 HTTPS 的人真是个十足的笑话大王!

无论如何,每种状态都有其含义。这些含义是普遍接受和理解的。因此,中国的开发人员和德国的开发人员都会明白,如果你发送 401(未授权)状态码,你的意思是客户端没有发送正确的身份验证详细信息。由于我们响应的是 401(未授权)状态码,所以每个人都明白这是一个客户端错误,需要在客户端而不是 API 上修复。我再次举一个例子,但我的意思是,你应该在适当的情况下使用适当的 HTTP 状态码。使用它们将有助于你的 API 变得普遍易懂、一致且标准化。即使 REST 不是标准,这也是你应该遵循的标准之一 😀

一旦 HTTP 状态码生效,我们就需要在出现问题时向客户端提供尽可能多的详细信息。为了实现这一点,我们需要做很多事情。首先,我们必须能够预测我们的 API 可能如何失败,其他人可能会做什么,不会做什么,谁会不遵守规则等等……所以,第一步是进行强有力且严格的数据验证,尤其是在创建内容之前。获得数据后,您必须检查数据是否有效!这意味着要检查 ID 是否真实存在,值是否符合我们的预期,以及是否能够将其存储在数据库中……完成所有这些操作并使用合适的状态码进行响应,将使您的 API 使用起来更加便捷。假设您有一个端点,它接受 user_id 并获取用户个人资料。如果我们应用预测可能发生情况的策略,我们将执行以下操作:

  1. 检查请求是否具有 user_id 参数 - 如果没有,则响应 400 Bad Request
  2. 检查给定的 user_id 是否确实存在于系统中 - 如果不存在则响应 404(未找到)
  3. 如果 user_id 返回结果,则响应 200(OK)

正如您所见,我们有多个故障保险装置,并且在所有故障保险装置中,我们都使用了正确且可理解的响应代码进行响应。

最后,一旦我们设置了响应代码,并预测了 API 可能出现的问题,我们只需要尽可能地清晰地表达。我知道对于我们这些开发人员来说,做到这一点很难,但相信我,这是你能做的最好的事情之一。当出现问题时,我们的 REST API 应该有一个通用的错误响应模型。如果有了这个模型,客户端开发人员就可以依靠它向用户更深入地解释问题所在。假设用户在手机上输入了无效的电子邮件地址。该信息以某种方式发送到 API,API 会触发验证和错误,并返回 400(错误请求)错误码。除此之外,API 还应该发送一个通用的错误响应模型,允许客户端向最终用户显示所有消息。在这种情况下,你可能会返回一条错误消息:“输入了无效的电子邮件地址”。客户端可以读取该消息并将其显示给用户。同样,我们需要确保能够涵盖从验证到服务器错误的所有场景。为了实现这一点,最好能提出一个通用的误差模型,使其适用于任何场景。我建议你使用以下模型:

    {
       "title":"Invalid data",
       "message":"The data you entered is not valid",
       "errors":[
          {
            "field": "email",
            "message":"The email address you provided is not real"
          },
          {
            "field": "phone_number",
            "message":"You did not enter a phone number at all"
          }
       ]
    }
Enter fullscreen mode Exit fullscreen mode

错误的 JSON 结构很简单。我们用标题消息来大致描述发生了什么。很多时候,开发者并不会选择向最终用户显示完整的错误详情。他们可能会在 iPhone 上使用提醒模式来显示错误信息或标题。但我们还会发送一个错误数组,其中包含特定的错误和相应的消息。提供详细的错误信息将帮助您以及其他使用 API 的开发者了解究竟出了什么问题。即使您没有向最终用户显示它们,您仍然可以在发出请求或使用Treblle等服务时查看它们。

所以请记住,一定要尽可能多地预测问题。即使没有人使用这些信息,也要提供足够的失败原因的详细信息,并使用普遍理解的 HTTP 响应代码语言。

8. 聪明一点

这一点比其他方面更具哲学性,但在我看来,它是优秀 REST API 的支柱之一。如果你思考 API 在现代平台、服务或应用中的角色,我们可以说 API 是整个操作的大脑。这是因为你的每个客户端(iPhone 应用、Android 应用、网站、物联网设备)都会与同一个 API 通信。这意味着我们的 API 是整个生态系统中最重要的部分,我们的 API 应该能够处理所有事情。请允许我补充一下,这可以说是非常优雅了。

语义化

智能 API 应该做的首要事情就是保护其最宝贵的资产——数据库。这意味着它应该清理、清除并防止任何不良数据进入数据库。做到这一点的方法是确保验证从应用程序发送到客户端的所有内容,并拒绝任何看起来不合适的数据。但是,当我们拒绝某些数据时,我们也应该向客户端提供明确的原因,以便他们了解为什么会发生某些事情,或者在本例中没有发生某些事情。

任何优秀且智能的 API 都会自行处理复杂的流程,而无需依赖客户端的帮助。最简单的示例就是在您的应用中注册用户。对于所有客户端来说,这应该是一个 API 调用,客户端在调用时发送数据并获取用户对象。但是,API 应该在后台处理所有潜在的后勤工作,例如:在 MailChimp 新闻通讯上注册该用户、将推送令牌存储到 Firebase、向用户发送欢迎电子邮件等等……客户端不应该调用多个 API 端点来实现这些功能。如果我们将所有内容打包到一个端点,那么您可以随时轻松更改流程,而客户端甚至不必意识到这一点。只要您从他们那里获取所需的数据,API 就可以始终完全控制整个业务逻辑和流程。

确保 API 针对跨平台解决方案进行了优化。当您处理多个平台或设备(如 iPhone、Android 手机、电脑、电视等)时,API 应该能够适应它们。这意味着 API 应该足够灵活,以处理可能来自所有客户端的不同输入,并且仍然支持客户端完成其工作。可调整大小的图像就是一个很好的例子。如果您有一个提供包含图像的内容的 API,您可能不想将 4000x4000px 的图像发送到手机,但也许您会发送到电视或网站。智能 API 会知道哪个客户端正在访问该端点,并会自行返回优化的资源,甚至允许客户端请求特定大小。还有很多这样的例子,但您明白我的意思了。

你对客户端的依赖越少越好。智能 API 总是会考虑到客户端的缺陷,并在可能的情况下进行纠正。

9. 保持精益

一个好的 API,如果不快速且优化,又算什么呢?你的 API 不应该成为整个生态系统的痛点。就这么简单。你可以采取很多措施来确保提供一个优秀 API 应有的性能和可扩展性。让我们来看看其中的一些。

实现快速和优化始于数据库级别。每当我听到有人说他们的 API 很慢时,十有八九都与数据库有关。要么是糟糕的数据库设计,要么是复杂的查询,要么是缓慢的基础架构,要么是缺乏缓存。您应该始终优化数据库结构、查询、索引以及与数据库交互的所有其他内容。处理好这些问题后,下一件要关注的事情就是确保尽可能提供缓存数据。缓存数据库查询有时可以将加载时间减少 100%。因此,如果您有一个 API 端点可以向用户显示他们的个人资料或类似内容,我相信它不会每 5 分钟更改一次。明智一点,缓存数据。您的用户和调用该 API 的客户端会喜欢它。

另一个影响性能的因素是通过 API 发送给客户端的数据量。请确保您的资源和模型只返回客户端所需的数据,而不是全部。如果您返回的是项目集合,则可能不需要每次都提供完整的模型详细信息和关系。如果这样做可以加快速度,那就这样做吧,但始终要尽量与响应中返回的模型保持一致。这意味着,如果您没有加载关系,则返回一个空数组;如果您没有加载计数,则返回 0,依此类推。一致性是构建优秀 REST API 的关键。

另一个非常简单的方法就是启用压缩,以减少响应大小并提高性能。最常用的是 Gzip 压缩。在 Apache 中,它默认启用,并带有一个名为 的模块mod_deflate。启用后,您通常可以看到一个响应头,其Accept-Encoding内容类似于gzip, compress。即使默认启用了压缩,您仍然需要将其“应用”到您的 API 响应中。为此,我们必须在默认 Apache 配置中添加一些规则。让我们像这样打开配置文件:sudo nano /etc/apache2/conf-available/000-default.conf并添加这个漂亮的内容:https://gist.github.com/cindreta/57db9a11ef0ad88f96ba2da59f64bb7e

这告诉 Apache 对各种 MIME 类型(例如 application/javascript、application/json 等)应用 Gzip 压缩。保存后,我们只需输入 sudo systemctl restart apache2 重启 Apache 即可。您的 API 响应现在比以前小了 50-75%。是不是很简单?!

10. 体贴

最后这部分我会简短地讲一下,因为我们对 REST 的理解已经有些过了(它永远不会过时😀),但我不想低估它的重要性。对于我们后端开发者来说,开发 API 的过程相当孤独。基本上只有你、一堆代码和你最喜欢的测试工具。你可能认为,当你写完最后一行代码并将其合并到生产分支时,工作就完成了。但事实并非如此。对许多其他人来说,这段旅程才刚刚开始。

很多人只有在你完成工作后才会开始他们的工作。为了让他们能够做好工作,你需要以多种方式准备你的 API。你必须确保它能够正常工作,有完善的文档,更重要的是,你必须准备好提供集成支持。无论你的文档写得多么好,在集成过程中以及之后,总会存在一些问题、疑虑和难题。

设身处地为他人着想,努力让他们的工作更轻松。构建良好的 API,遵循我们在这里定义的规则,编写优秀的文档,并为所有人提供帮助。

考虑使用一些工具来帮助您应对构建、交付和运行 API 过程中的诸多挑战。您猜对了,其中一个工具就是Treblle。只需将 Treblle 添加到您的 API,即可获得支持 OpenAPI 规范的自动生成文档。然后,您将获得实时监控和日志记录,以便了解其他人的操作并更好地帮助他们。最后,您甚至会获得基于相同规则的高质量 API 核心。当然,我们在设计时考虑到了整个团队的需求。因为我们知道眼见为实,这里有一个视频介绍我们如何提供帮助:

---

希望我能够简化并解释您在构建 REST API 时可能遇到的一些常见问题。再次强调,REST 并非标准,因此没有人能指出您的做法是否正确。但请思考一下:作为开发人员,我们每天都在寻找模式来改进代码、使其更美观、更高效,那么为什么不对 API 也采取同样的方法呢?如果我们开始遵循一些模式,我们就能拥有一个更加健康、更加美观的生态系统。

最后,我想引用一位伟人——本·帕克(Ben Parker)的话来结束本文。他就像我们所有人的叔叔一样。他曾经睿智地说过:“能力越大,责任越大。”这句话用在 REST API 上再贴切不过了。

附言:如果您喜欢这些文章,请在我的Twitter上打招呼或在LinkedIn上关注我。

文章来源:https://dev.to/cindreta/the-10-rest-commandments-13jk
PREV
现代 Rails 闪现消息(第一部分):ViewComponent、Stimulus 和 Tailwind CSS
NEXT
使用 Amazon Web Services 创建 API 端点