大多数RESTful API并不是真正的RESTful

大多数RESTful API并不是真正的RESTful

Hacker News 摘要

原标题:Most RESTful APIs aren't really RESTful

在谈论REST时,了解罗伊·托马斯·菲尔丁的论文是非常重要的。他在2000年发布的论文《网络基于软件架构的建筑风格与设计》中介绍了代表性状态转移(REST)这一建筑风格,旨在设计可扩展、高性能和可维护的网络系统,尤其是网络服务。论文分析了网络基于系统的建筑风格,并识别其优缺点。它将REST定义为一种专为现代网络优化的建筑风格,强调可扩展性、简单性和适应性。菲尔丁展示了REST原则如何影响网络的成功,并倡导在设计分布式系统时采用REST,提供通用的、无状态的接口以及明确的基于资源的交互。

菲尔丁在其论文中并未规定使用HTTP动词(如GET、POST、PUT、DELETE)的具体应用或专注于CRUD风格的API,REST的实现通常与此无关。他明确批评了CRUD风格API对REST的过度简化,强调许多所谓的“RESTful”API未能实现关键的REST约束,特别是缺乏使用超媒体来驱动应用状态转移。在他2008年的博客中,菲尔丁指出:“如果应用状态(因此API)不是由超媒体驱动的,那么它就不能被称为RESTful,也不能是一个REST API。”这突显了他的观点:没有超媒体控制,API就无法满足REST建筑风格的要求。

超媒体控制是嵌入在资源表示中的元素,引导客户端了解他们可以采取什么后续行动。人们在理解REST时常见的误解包括:REST等同于CRUD(虽然通常是这样,但并非总是),资源是实体(通常指持久性实体),RESTful API不应使用动词。然而,这些实际上是API设计时由创作者选择的决策,与REST本身无关。

那么“由超媒体驱动”意味着什么?菲尔丁批评中的“未被超媒体驱动”指的是许多声称为RESTful的API缺乏“超媒体作为应用状态的引擎”(HATEOAS)。HATEOAS是REST的一个基本原则,要求客户端通过嵌入在服务器响应中的超媒体链接动态发现操作和交互,而不是依赖于外部知识(例如API文档)。

核心问题是客户端-服务器的耦合。在许多项目中,服务器的URI结构的微小变化需要多个客户端应用程序的协调(往往是痛苦的)部署。采用HATEOAS的方法通过解耦客户端与服务器的命名空间直接解决了这个问题,从而提高了可演变性。简单实现HATEOAS就能让你的API更接近RESTful原则,而不是辩论API中是否允许使用动词。

关于REST中的“资源”,人们常常争论。很多人认为资源是来自服务器的数据结构,甚至与持久性实体相等。菲尔丁表示,REST的关键抽象是资源。任何可以命名的信息都可以是资源:文件或图像、时间服务(例如“洛杉矶今天的天气”)、其他资源的集合、非虚拟对象(例如一个人)等等。换句话说,任何可能作为超文本引用目标的概念都应属于资源的定义。资源是一个到一组实体的概念映射,而不是在任何特定时间对应于映射的实体。

在RFC 3986中,“资源”一词的使用是一般性的,涵盖了任何可能通过URI被识别的事物。资源可以是物理对象、概念、文件、服务,甚至是虚拟或抽象的事物——只要它能够被唯一识别和表示。菲尔丁在2008年表达了对将任何HTTP接口称为REST API的愤怒。他列出了六条规则,供设计人员在称自己的API为RESTful API前考虑。

首先,REST API不应依赖于任何单一的通信协议,任何通过URI进行标识的协议元素都必须允许使用任何URI方案。其次,REST API不应对通信协议进行任何更改,而仅仅是在未指定的标准协议中填补细节。第三,REST API应将大部分描述精力集中在定义用于表示资源和驱动应用状态的媒体类型上,而不是关注URI的结构或操作。第四,REST API不应定义固定的资源名称或层次结构,服务器必须有自由控制自己的命名空间。第五,REST API不应有对客户端显著的“类型”资源。第六,REST API的使用应该从初始URI(书签)开始,接下来的所有应用状态转换都必须由客户端根据服务器提供的选择进行驱动。

不过,许多API并未真正遵循这些原则。使用更简单、类似RPC的风格的广泛采用可能是由于对工具和开发人员体验的实际取舍。围绕如OpenAPI的规格迅速发展,提供了即时的好处,开发团队无法抗拒。这些工具提供了强大的功能,如自动生成客户端/服务器代码、交互式文档和请求验证。对于一支面临交付压力的团队而言,OpenAPI定义所提供的清晰、静态合约被视为“足够好”,而HATEOAS的长期架构收益显得抽象且不紧迫。

此外,构建真正的基于超媒体的客户端的初始认知负担被认为是一个显著的障碍。开发人员可能觉得似乎更容易读取文档并硬编码URI模板,而不是编写一个能动态解析_links部分并在运行时发现“orders” URI的客户端。在许多常见场景中,例如前端单页应用与后端由同一团队开发时,客户端和服务器已经紧密耦合。在这种情况下,HATEOAS所解决的主要问题——解耦客户端与服务器的URI结构,并没有显现出明显的痛点,因此更简单的、以文档驱动的方法成为了最低阻力的选择。

综上所述,菲尔丁的规则强调,一个真正RESTful的API应将超媒体(HATEOAS)作为交互的核心机制,而不仅仅是将HTTP作为一种传输方式。REST在本质上是协议无关的;HTTP只是使用REST的便捷方式。客户端应通过嵌入在表示中的链接和标准化关系动态发现和访问资源,而不是依赖于硬编码的URI结构、类型或外部文档。这样可以使REST系统在耦合性方面变得松散、可演变,并与网络本身的运行方式保持一致:通过表述、发现和转化。

REST并不是将内部对象模型暴露在HTTP之上,而是构建像网络一样运行的分布式系统。因此,我个人更倾向于避免使用“RESTful”这一术语,改为使用“HTTP” APIs。构建符合项目和API消费者需求的解决方案,无需过多关注REST的教条。不少比实际资源标识符的格式更为重要,例如API的消费者是谁、学习和使用API的易难程度、使用是否直观,以及可能的限制和版本控制策略。通过在资源表示中使用HATEOAS和引用模式定义(如XSD或JSON架构),可以使客户端理解数据结构并动态导航API,从而支持通用或自适应客户端。

如果您正在为外部开发人员构建公共API,而不受控制,则可以投资于HATEOAS。如果您为同一团队控制的单个前端构建后端,采用更简单的RPC风格API可能是更实用的选择。


原文:https://florian-kraemer.net//software-architecture/2025/07/07/Most-RESTful-APIs-are-not-really-RESTful.html

评论:https://news.ycombinator.com/item?id=44507076

Report Page