最佳实践之 Restful API 设计指南

2,366 阅读7分钟

🤖 原文链接:medium.com/hackernoon/…

Facebook、Google、GitHub、Netflix 和一些其他的科技巨头可以让开发者与产品通过接口来消费他们的数据,并且成为了他们的平台。

即使你不为其他开发者或者产品提供 API,对于应用程序来说,拥有精心设计的 api 总是非常重要的。

在互联网上有很多关于 API 设计最佳实践的讨论,对此并没有官方指南。

API 是一个接口,许多开发人员通过它与数据进行交互。一个设计良好的 API 总是非常容易使用,并使开发人员的生活非常顺利。API 是开发人员的 GUI,如果它令人困惑,那么开发人员将开始寻找替代方案或停止使用它。开发人员的体验是衡量 api 质量的最重要指标。

一、术语表

以下是与 REST api 相关的最重要的术语。

  • 资源是一个对象或某物的表示形式,它具有一些相关的数据,并且可以有一组对其进行操作的方法。例如,动物、学校和员工是资源,对这些资源执行删除、添加、更新等操作。
  • 集合是资源的集合,例如 Companies 是 Company 资源的集合。
  • URL(统一资源定位符)是一条路径,通过它可以定位资源并对其执行一些操作。

二、API 路径

为了方便理解,我们可以为拥有员工的公司写一些 API。

/getAllEmployees 是一个可以获取员工列表的 API。关于一个公司的更多 API 如下所示:

  • /addNewEmployee
  • /updateEmployee
  • /deleteEmployee
  • /deleteAllEmployees
  • /promoteEmployee
  • /promoteAllEmployees

对于不同的操作,还有很多类似的 API 路径。所有这些都将包含许多重复的动作。因此,当 API 数量增加时,所有这些 API 路径的维护工作都很繁重。

到底哪里出现了问题

URL 只应该包含资源(名词)而不能包含动作(动词)。API 路径 /addNewEmployee 包含动作 addNew 以及资源名称 Employee

怎样做才是正确的

/companies 是一个很好的例子,其不包含动作。那么问题就来了,我们如何告诉服务器要在「公司」资源上执行的操作,即:是添加、删除还是更新?

这就是 HTTP 方法(GET、POST、DELETE、PUT)(也称为动词)发挥作用的地方。

在 API 路径中,资源总是一个集合,如果我们想访问资源的一个实例,我们总是可以在 URL 中传递 id。

  • GET 方法请求 /companies 应该能够得到所有的公司;
  • GET 方法请求 /companies/34 应该能够得到 id 为 34 的公司详情;
  • DELETE 方法请求 /companies/34 应该会删除 id 为 34 的公司;

在一些其他用例中,如果我们在一个资源合集下有一个资源(例如公司中的员工),那么一些简单的 API 路径会是这样:

  • GET /companies/3/employees 应该会获取 id 为 3 的所有员工;
  • GET /companies/3/employees/45 应该会获取 id 为 3 的公司中 id 为 45 的员工详情;
  • POST /companies 应该或创建一个新公司,并且会返回刚刚创建的新公司的详细信息;

API 现在是不是更加精确和一致了 😎

总结: 路径应该包含资源的复数形式,HTTP 方法应该定义对资源执行的操作类型。

三、HTTP 方法(动词)

HTTP 定义了几组方法,这些方法指示要对资源执行的操作类型。

URL 是一个句子,其中资源是名词,HTTP 方法是动词。

下面列举一些比较重要的 HTTP 方法:

  1. GET 方法从资源中获取数据,并且不应该产生副作用。例如: /companies/3/employees 会返回 id 为 3 的公司中的所有员工。
  2. POST 方法会请求服务器在数据库中创建一个资源,通常是提交一个 form 表单。例如: /companies/3/employees/john 会为 id 为 3 的公司创建一个新的员工。POST 是非幂等的,这意味着多个请求将产生不同的效果。
  3. PUT 方法会请求更新资源,或者在资源不存在的情况下创建资源。例如:/companies/3/employees/john 会要求服务器更新,或者在资源不存在的情况下创建 id 为 3 的公司员工集合中的 John 资源。PUT 是幂等的,这意味着多个请求将产生相同的效果。
  4. DELETE 方法会请求从数据库中删除该资源或者实例。例如:/companies/3/employees/john/ 会要求服务器删除 id 为 3 的公司员工集合中的 John 资源。

我们将在 另一篇文章 中讨论其他一些方法。

四、HTTP 状态码

当客户端通过 API 向服务器发出请求时,客户端应该知道反馈,是失败了、传递了请求还是请求错误了。HTTP 状态码是一组标准化的代码,在不同的场景中有不同的解释。服务器应该始终返回正确的状态代码。

以下是一些比较重要的 HTTP 状态码分类:

2xx(成功)

这些状态代码表示服务器已接收并成功处理了请求的操作。

  • 200 Ok 表示 GET、POST 或者 PUT 成功执行的标准 HTTP 响应;
  • 201 Created 无论何时创建新实例,都应该返回此状态代码。例如:使用 POST 方法创建一个新的实例,应该总是返回 201 状态码;
  • 204 No Content 表示请求已成功处理,但未返回任何内容。DELETE 是一个比较好的例子。 DELETE /companies/43/employees/2 API 将会删除 id 为 43 的公司中 id 为 2 的员工信息,我们不需要返回 API 的 Response 中的任何数据,因为我们显式地要求系统删除。如果出现像数据库中不存在 id 为 2 的员工,然后响应码将不会是 2xx 而是 4xx。

3xx(重定向)

  • **304 Not Modified **指示客户端的缓存中已经有响应。因此,不需要再次传输相同的数据。

4xx(客户端错误)

  • 400 Bad Request 表示客户端的请求未被处理,因为服务器无法理解客户端的请求。
  • 401 Unauthorized 表示不允许客户端访问资源,应该用所需的凭据重新请求。
  • 403 Forbidden 表示请求是有效的,客户端已通过身份验证,但客户端由于任何原因不允许访问页面或资源。例如,有时授权的客户端不被允许访问服务器上的目录。
  • 404 Not Found 表示请求的资源现在不可用。
  • 410 Gone 表示已被有意移动的请求资源不再可用。

5xx(服务器错误)

  • 500 Internal Server Error 表示请求是有效的,但服务器完全混淆了,请求服务器为某些意外情况服务。
  • 503 Service Unavailable 表示服务器关闭或无法接收和处理请求。大多数情况下,服务器正在进行维护。

五、字段名称约定

您可以遵循任何字段名称约定,但要确保在整个应用程序中保持一致。如果请求正文或响应类型是 JSON,那么请使用 camelCase 来保持一致性。

六、API 版本

当你的 API 被全世界使用时,用一些破坏性的改变来升级 API 也会导致使用你的 API 的现有产品或服务被破坏。

http://api.yourservice.com/v1/companies/34/employees 是一个很好的例子,他在 API 路径中有一个版本信息。如果有任何重大的更新,我们可以将这组新 API 命名为 v2v1.x.x