【翻译】REST API设计思路一瞥

翻译文章,原作者:Akansha Yadav
原文1:A Look at REST API Design Patterns
原文2:A Look at REST API Design Patterns: Advanced

第一篇

在这篇文章里,我们探讨一下 Restul Webservice API 设计中有用的一些模式。通常,设计模式可以理解为程序员总结出来的一些经验,用这些经验可以解决程序或系统设计时的常见问题。

一、什么是Rest架构风格

REST架构风格有一组典型的特征,这也构成了REST风格架构约束


Rest架构风格
  1. 客户端-服务器端(Client-server)
  2. 无状态(Statelessness)
  3. 可缓存(Cacheable)
  4. 统一接口(Uniform interface)
  5. 分层系统(Layered systems)

二、Restful API 设计目标:

RESTful API设计时应考虑的目标:Restful API 应该简单明了、明确、易于使用、结构合理,最重要的是,可以使用标准化的 HTTP 方法(GET、POST、PUT、DELETE)进行访问。

1. 能用,好用

接口能力,指对对象或环境进行操作的能力。具有清晰目标的API能让开发者容易的理解其设计意图并无障碍地按预期的用法来使用。

2. 松耦合

会有多种客户端连接到同一个后端服务器。当服务内部表示发生变化时,应该不影响到客户端的对API使用。在松散耦合的设计中,API 是独立的,在一个中的修改不会影响消费者的代码。 在 API 中,组件是会被添加、修改或替换的。 但是,松耦合的设计思路能够让你在对API做调整时,为使用API的消费者提供更大的灵活性和可重用性。在添加、替换或更改其元素时为客户提供了更好的 API 灵活性和可重用性。 设计良好的 API 表现出松散耦合和跨服务边界的良好组合功能,以最大限度地提高可扩展性因素。

3. 利用已有的 Web 架构

RESTful API 应该使用 HTTP 作为传输层。 HTTP 的基础设施、服务器或客户端库已经应用广泛。 RESTful API 应该充分利用这些HTTP 方法,例如 GET、PUT 、POST标准HTTP方法。

三、Restful API设计模式

API 设计模式提了一些样板方法或策略,来解决软件架构师或API 设计人员希望在其 API 设计中解决的的特定或重复出现的问题。

1. 无状态的(Statelessness)

客户端和服务器之间的通信应该是无状态的,这意味着每个客户端的请求中都包含服务器处理它而需要的全部信息。因此,没有全局状态,从而降低了服务器的复杂性。
  好消息是,一些 Restful Web 框架已为无状态提供了开箱即用的方案。例如 Spring Boot 的 REST API 框架。

2.内容协商(Content Negotiation)

内容协商是一种机制或过程,服务器和客户端可以在其通信初时始选择后续通信过程中的数据表示格式。
  HTTP 规范已经提出了一组标准标报文头,通过这些报文头客户端可以得知其所请求的资源的基本信息以及资源所采用的表示格式。
  因此,REST 服务使用 HTTP 标准报文头机制就能实现内容协商。当客户端发出请求时,设置“Accept”报文头,传入客户端和服务器可以处理的文件类型列表即可。而无需专门额外的内容协商步骤或通信。
  例如。在Spring中,我们可以在@GetMapping注解中使用produces属性

@GetMapping(
  path="/investors/{investorId}/stocks/{symbol}", 
  produces={MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE})

3. 模板化URI(URI Templates)

通常,客户端发请求时需要添加参数,服务器也得告知客户端如何在URI中传这些参数。服务端开发人员需要能够描述其服务将所使用的URI布局。所以我们可以使用URI模板。 URI 模板提供了一种将一组资源描述为变量的方法。

例如。如果有多个资源,

人:https://swapi.co/api/people/
行星:https://swapi.co/api/planets/
电影:https://swapi.co/api/films/
物种:https://swapi.co/api/species/

我们可以简单地使用 https://swapi.co/api/{resource_id}/ 作为 URI 模板
Spring Boot 提供的 @PathVariable 注解帮助我们在代码中无缝实现 URI 模板模式。

4. 封装与一致性(Design for Intent)

RESTful API 的设计应当满足满足用户提供或将会的需求(封装),但不能暴程序内部的数据表示。并且接口在执行数据变更时,应当满足数据的完整与一致性,将必须的变更传播到相关联的数据对象。

译注:原文中 Design for intent 似乎来源于CAD领域,用来描述原理设计图与实物设计之间的设计约束,设计约束能在原理设计与实物设计之间传播。参考:
1 https://www.ptc.com/en/blogs/cad/design-intent-explained
2 https://community.cadence.com/cadence_blogs_8/b/ic-cn/posts/virtuoso-design-intent

原文: Design for intent is a method that expresses the different
relationships between objects so that changes to one object automatically propagates changes to others.
In a RESTful API world, the API should be developed to ensure they meet the requirements of the desired use cases provided and faced by users, but without exposing the internal business objects. Design for intent is a strategic design pattern that's intended to influence or result in specific and additional user behaviors.

5. 分页(Pagination)

当API有许多数据可提供时,API 应该设计为分批次给出要查找的数据(分页)。
  分页是一种返回整体中部分数据的方法。让服务器无需太大计算量也能服务整个数据,同时也可以降低了客户端负载和计算量。分页技术同时要求API提供如何逐页访问服务器的所有数据的信息的方式。例如:xxx.api.com/students?page=2。
分页的资源表示方式有三种方式:

  1. 基于偏移量(Offset-based, eg. offset=&limit= or page=1&size=10
  2. 基于时间(Time-based, eg. from=2022-01-01T00:00:00
  3. 基于游标(Cursor-based, eg next=xxxx

6. 易发现(Discoverability)

易发现是 API 设计中的一个非常重要的因素,帮助开发人员以编程方式确定被访问的站点是否启用了 API,这将是 API 的最关键职责。
  使用以下两种方式,我们可以确保 API 对开发人员的可发现性,
  1. 通过有效的 HTTP 方法
  当客户端使用无效的 HTTP 方法调用 REST 服务时,该请求的响应应该以 405 HTTP 错误代码结束;即 405 Method Not Allowed。除了错误代码之外,响应标头还应为客户端提供灵活性,以查找允许在其响应中使用标头的受支持方法。
  2.提供新建资源的URI
  将 URI 作为Location Header的一部分作为对新创建资源的响应是另一种可发现性方法。作为位置返回的 URI 将可通过 GET 获得。
  在 Sprint 引导中,它为可发现性提供了开箱即用的解决方案。使用@GetMapping 注解。

7. Unicode

让API 能支持各种语言文字的简便而强大的方法是让API支持 Unicode字符集。
  Unicode 是一个支持对全世界文字进行数字化的编码标准。它对每种语言的每个字符都编了唯一一个的代码,有中文、韩文和阿拉伯文以等等。唯一的代码编码使几乎所有文字、符号都可以跨平台、程序和设备进行识别。

四、API 设计原则

通常,在设计高质量的 Restful API 时应遵循以下标准指南。

  1. 无处不在的网络标准
  2. 灵活性
  3. 标准化
  4. 优化
  5. 粒度
  6. 沙盒或学习区


    Rest Api 路径设计

对于想要接触 RESTful 服务的人来说,这应该是一个很好的起点,不仅有基础知识,还有基本模式。

第二篇:续编

这是上篇的续,补充谈论两个API设计事项

简介:设计模式是软件设计和开发生命周期中重要但经常被忽视的方面。 在上一篇文章中,我们回顾了一些基本的 REST API 设计模式。 在这篇,来让我们看一下 RESTful API 架构中的一些更高级的设计模式。

一、API的版本化

很难在一次设计编写完所有 API,因此多数情况下避免版本控制是不行的。 在控制 API 版本时,我们希望遵循的一般经验规则如下:

当有新的设计与旧的不兼容,会破坏现有客户端逻辑时时,API 的主要版本应当升级
当有缺陷修复或结构兼容的修改时,API的小版本应该升级

版本控制的不同途径:

1 通过 URI 路径前缀

主要和次要版本号可以是 URI 的一部分,例如,要表示 API 的 v1 或 v2,URI 可以是 http://localhost:9090/v1/bookshttp://localhost:9090/v2/books

@GetMapping({"/v1/books","/v1.1/books","/v2/books"})  
publicListfetchAllBooks(){}

2 通过查询参数

实现版本引用的另一个方法是将其作为请求参数的一部分。
http://localhost:9090/books?version=1

@GetMapping("/books")
public ListfetchAllBooksForGivenVersionAsParameter(
@RequestParam("version") Stringversion) throws VersionNotSupportedException{
  if(!(version.equals("1.1") ||version.equals("1.0"))) {
  throw new VersionNotSupportedException("version "+version);}
  return bookService.fetchAllBooks();
}

3 通过自定义 header

定义一个包含请求中版本号的新header,作为请求标头本身的一部分。自定义header允许客户端维护相同的 URI,而不必担心版本升级时要改路径。

4 通过内容协商(content-negotiation)

通过 Accept(请求)header提供版本信息以及响应中的内容类型(媒体)是首选方式,因为这有助于版本 API 而不会对 URI 产生任何影响。

@GetMapping(value="/books",headers="Accept=application/books-v1+json")
public List fetchAllBooks() throws  VersionNotSupportedException {
  return getBooks();
}

二、鉴权

授权:用户授权是 API 设计实践中的一个重要课题。

1. 使用默认密钥授权:

使用 spring-security,我们可以轻松地保护我们的 Web API。 我们可以查阅详细的 Spring Security 文档:https://spring.io/projects/spring-security

2. 凭证授权

在许多实时情况下,我们需要使用特定凭据来访问 API,而不是使用默认凭据。

Url重定向:使用标准的HTTP返回码如3xx,并带有Location头,然后通过接收301 Moved Permanent或307 Temporary Redirect,服务客户端可以获取重定向信息。

Url重定向模式建议使用标准 HTTP header,并提供在重定向时要保持对重新向之前的url的引用。

小结

希望这篇文章能够帮助想要学习的人更深入直观地了解直观的 REST API 设计模式。当然,设计模式的对面是反模式,它们看起来很合理,但在执行时会适得其反。而且,反模式很难发现。

如有任何建议,欢迎评论留言。

你可能感兴趣的:(【翻译】REST API设计思路一瞥)