默认情况下 GraphQL API 是 RESTful 吗? [英] Is a GraphQL API RESTful by default?

查看:20
本文介绍了默认情况下 GraphQL API 是 RESTful 吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对 REST 的理解很简单,即资源需要某种自我描述方式.我的理解是,这与任何一种协议(即 HTTP)无关,理论上有多种方法可以实现这一点.这是基于对此处 SO 问题的回答:SOAP vs REST(差异)(和与这个问题的糟糕答案不同:Relay 和 Graphql 是 RESTful 吗?)

由于 GraphQL API 是通过 introspection 自我描述的,这并不意味着 GraphQL默认情况下是 RESTful,因为客户端可以使用自省来找出如何查询它?

解决方案

虽然 GraphQL 是 经常被提及作为 REST 的替代品,两者实际上解决了不同的问题.

REST,首先,不是一种协议,而只是一种风格,如果正确且充分地应用它,只会将客户端与服务器分离.因此,遵循 REST 原则的服务器将为客户端提供采取进一步步骤所需的任何信息.客户端最初在没有任何先验知识的情况下开始,并通过发出请求和处理响应动态学习.HATEOAS 描述了 REST 架构应该基于的交互模型.因此,它指出应该使用链接来请求驱动其内部流的新信息.在使用与 Web 表单 (HTML) 类似的表示形式时,服务器可以向客户端教授所需的输入.通过客户知道的各个元素的可供性,无需任何需求对于外部文档,该怎么做.IE.它可能会找到几个选项来选择一个或多个选项,输入或更新一些自由文本或按下一些按钮.在 HTML 表单中,通常会触发 POST 请求并将输入的数据作为 application/x-www-form-urlenceded 发送到服务器,尽管表单元素本身可能定义了一些不同的东西.

虽然 REST 与协议无关,这意味着它可以建立在许多协议之上,但 HTTP 可能是最突出的一种.RESTful 客户端的一个常见示例是我们都熟悉的 Web 浏览器.它将首先调用带有书签的 URI 或调用在地址栏中输入的 URI,然后继续进行.

HTTP 没有指定必须发送请求或响应的表示形式,而是将其留给客户端和服务器进行协商.这有助于解耦,因为客户端和服务器都可以依赖公共接口 (HTTP) 并且只与用于交换数据的已知媒体类型强绑定.缺少相应的 mime 类型支持)将通过相应的 HTTP 状态代码指示他的另一个对等方,它不理解,因此无法提供所请求的媒体类型格式.媒体类型只是数据负载的语法和语义的人类可读文档,因此是 REST 架构中最重要的部分.甚至 Fielding 声称:

<块引用>

REST API 应该将几乎所有的描述性工作用于定义用于表示资源和驱动应用程序状态的媒体类型,或用于为现有标准媒体定义扩展关系名称和/或支持超文本的标记类型.描述在感兴趣的 URI 上使用什么方法的任何努力都应该在媒体类型的处理规则范围内完全定义(并且在大多数情况下,已经由现有媒体类型定义).[此处的失败意味着带外信息正在推动交互而不是超文本.]

媒体类型教对等点如何解析和解释接收到的有效负载并真正理解它,尽管很多人仍然将 REST 与基于 JSON 的 HTTP API 与过度设计的 URI 混淆,他们投入了大量精力赋予 URI 某种逻辑意义,而实际上客户端和服务器都不会解释它,因为它们可能会使用为 URI 提供的链接关系名称.

另一方面,GraphQL 基本上只是一种查询语言,它使客户端能够请求它想要从服务器检索的特定字段和元素.松散地说,它是某种用于 Web 的 SQL,或者如 外勤术语远程数据访问 (RDA).因此,它必须事先了解可用数据,以某种方式将客户端耦合到服务器.如果服务器将重命名某些字段,客户端可能无法进一步检索此类信息,尽管我不是 GraphQL 专家.

如上所述,REST 经常与基于 JSON 的 HTTP API 混淆,该 API 允许对直接映射的数据库条目/实体执行查询.请记住,REST 并不禁止这样做,尽管它的重点是对等点的解耦,而不是某些 Web 公开数据库条目的检索方面.正如 Jim Webber 在 2011 年 REST 的一次精彩演讲中指出的那样,您不只是公开数据库表,而是创建了一个域应用程序协议,客户端将遵循该协议 就像在基于文本的电脑游戏或典型的互联网网上商店系统中.

特别是 GraphQL 的链接内省文档让我想起了 Java 中的反射,它与可用的实际类模型耦合.如果数据模型中的某些内容发生变化,GraphQL 交互的行为如何?它能够改变和适应吗?为一个 API 构建的客户端是否能够开箱即用地与其他 API 一起使用?所有这些都是真正的 RESTful 客户端的基本要求.它基本上必须适应未来的变化,因为服务器可以随时自由发展.它还不应假设某些端点返回某些类型 但使用内容类型协商来请求它可以处理的表示.

这些应该会给你足够的洞察力,让你自己确定 GraphQL 是否可以是 RESTful.在我看来不是,但我对 GraphQL 的见解相当有限,TBH.

<小时><块引用>

因为 graphql 会发布有关其类型的元数据,所以(我认为)构建一个可以使用任何 graphql 端点的 graphql 客户端是完全合理的......

SOAP 做了完全相同的事情,尽管它仍然是一个 RPC 协议.客户端可以在运行时查找 ...?wsdl 信息,然后根据 WSDL 中定义的模式动态生成请求,尽管通常发生的是一些预先生成的存根类是基于编译到特定客户端的 WSDL 数据生成的.动态生成请求的客户端仍然需要一个例程来定义要创建的消息类型以及消息需要哪些数据作为输入.

虽然 SOAP 可能在一个 WSDL 中定义多个端点,但在大多数情况下只定义了一个.这个端点通常只对 POST 请求进行操作,即使在以后 (SOAP 1.2) GET 也是可能的.

根据Fielding 的论文<块引用>

REST 使用资源标识符来标识组件之间交互中涉及的特定资源.

,GraphQL 中的资源标识符是什么?GraphQL 的文档指出

<块引用>

... 相比之下,GraphQL 的概念模型是一个实体图.因此,GraphQL 中的实体不是由 URL 标识的.相反,GraphQL 服务器在单个 URL/端点上运行,通常是/graphql,并且对给定服务的所有 GraphQL 请求都应指向此端点.

与 SOAP 类似,所有请求都针对单个端点.如果您考虑缓存,这会产生一些影响,这是 REST 暗示的进一步约束.如果 URI 是用于在缓存中存储响应的键,那么响应如何缓存?

虽然从消费者的角度来看,所有的聚合内容和灵活性可能很好,但它们可能不符合 REST 的约束,尽管 Fielding 本人声称 REST 并不适用于所有情况,并且 设计师应该选择适合他们需求的风格,因为并非每种风格都是每个问题的银弹".甚至 Mike Amundsen 表示 GraphQL 至少违反了 REST 架构强加的 3 个约束,尽管 GraphQL似乎已经将默认检索方法从 POST 更改为 GET.

通常,如果您的目标是长期存在的 API,这些 API 应该在未来可以自由发展,并且必须与大量客户端打交道,尤其是那些不在您直接控制之下的客户端,那么这就是 REST 开始大放异彩的时候.Fielding 承认,大多数开发人员在考虑长期问题时都会遇到问题.对于单个前端到后端系统或与自己的 API 交互的定制客户端,REST 可能不是应该遵循的架构.

最后但并非最不重要的一点,在稍后的推文中外勤陈述<块引用>

没有 REST 端点这样的东西.有资源.仅受 URL 长度限制的可数无限资源集.客户端可以 POST 到 REST 服务以创建一个 GraphQL 查询资源,然后使用 REST 的所有优势获取该资源......

我的解释是,不要过多关注证明 GraphQL 是否是 REST 的合理性,而是考虑如何将其优势整合到整体设计中.

My understanding of REST is simply that a resource needs some means of self-describing itself. My understanding is that this isn't specifically tied to any one protocol (i.e. HTTP) and that there are theoretically numerous ways of achieving this. This is based on an answer to a SO question here: SOAP vs REST (differences) (and unlike the terrible answer to this question: Are Relay and Graphql RESTful?)

Since a GraphQL API is self-describing via introspection, doesn't that mean that GraphQL is RESTful by default since a client can use introspection to figure out how to query it?

解决方案

While GraphQL is often mentioned as the replacement for REST, both tackle different problems actually.

REST, to start with, is not a protocol but just a style, which, if applied correctly and fully, just decouples clients from servers. A server following the REST principals will therefore provide the client with any information needed to take further steps. A client initially starts without any a-priori knowledge and learns on the fly through issuing requests and processing responses. HATEOAS describes the interaction model a REST architectue should be build upon. It thereby states that a link should be used to request new information which drives its internal flow. On utilizing similar representation to Web forms (HTML) a server can teach a client on needed inputs. Through the affordance of the respective elements a client knows, without any need for external documentation, what to do. I.e. It might find a couple of options to chose one or multiple options from, enter or update some freetext or push some buttons. In HTML forms usually trigger a POST request and send the entered data as application/x-www-form-urlenceded to the server though the form element itself may define something different.

While REST is protocol agnostic, meaning it can be build up ontop of many protocols, HTTP is probably the most prominent one. A common sample for a RESTful client is the Web browser we are all to familiar with. It will start by invoking either a bookmarked URI or invoke one entered in the address bar and progress from there on.

HTTP doesn't specify the representation the request or response has to be sent in but leaves that to clients and servers negotiating them. This helps in decoupling as both client and servers can rely on the common interface (HTTP) and only bind strongly onto the known media types used to exchange data in. A peer not being able to process a document in a certain representation (due to the lack of the respective mime type support) will indicate his other peer via a respective HTTP status code that it does not understand, and therefore can't serve, the requested media-type format. The media type, which is just a human readable documentation of the syntax and the semantics of the data payload, is therefore the most important part in a REST architecture. Even Fielding claimed:

A REST API should spend almost all of its descriptive effort in defining the media type(s) used for representing resources and driving application state, or in defining extended relation names and/or hypertext-enabled mark-up for existing standard media types. Any effort spent describing what methods to use on what URIs of interest should be entirely defined within the scope of the processing rules for a media type (and, in most cases, already defined by existing media types). [Failure here implies that out-of-band information is driving interaction instead of hypertext.]

A media type teaches a peer how to parse and interpret the received payload and to actually make sense out of it, though plenty of people still confuse REST for a JSON based HTTP API with over-engineered URIs they put to much effort in to give the URI some kind of logical sense when actually neither client nor server will interpret it anyway as they will probably use the link relation name given for the URI.

GraphQL on the other hand is a basically just a query language which gives the client the power to request specific fields and elements it wants to retrieve from the server. It is, loosely speaking, some kind of SQL for the Web, or as Fielding termed it just a Remote Data Access (RDA). It therefore has to have some knowledge of the available data beforehand which couples clients somehow to the server. If the server will rename some of the fields, the client might not be able to retrieve that kind of information further, though I'm not a GraphQL expert.

As stated above, REST is often confused for a JSON based HTTP API that allows to perform queries on directly mapped DB entries/entities. Keep in mind that REST doesn't prohibit this, though its focus is on the decoupling of peers not the retrieval aspect of some Web exposed database entries. As Jim Webber pointed out in a great talk back in 2011 in REST you don't simply expose database tables, you create a domain application protocol which clients will follow along like in a text-based computer game or in a typical Webshop system on the internet.

Especially the linked introspection documentation of GraphQL reminds me of reflection in Java, which couples to the actual class model available. If something along the datamodel changes, how does the GraphQL interaction behave? Is it able to change and adapt? Is a client built for one API able to work with an other API out of the box? All these are basically requirements for a true RESTful client. It basically has to adept to changes in future as the server is free to evolve anytime. It further shouldn't assume certain endpoints returning certain types but use content type negotiation to request a representation it can work upon.

These should give you enough insights to determine for yourself whether GraphQL can be RESTful or not. In my opinion it isn't, but my insights into GraphQL are rather limited, TBH.


Because graphql publishes Metadata about its types, it's entirely plausible (I think) to build a graphql client that could consume any graphql endpoint ...

SOAP did the exact same thing, though it was still an RPC protocol. A client could look up the ...?wsdl information at run-time and then generate a request according to the schema defined in the WSDL dynamically, though what usually happened was that some pre-generated stub-classes were generated based on the WSDL data that got compiled into a specific client. A client dynamically generating a request still needed a routine that defines what message-type to create and what data the message required as input.

While SOAP could potentially define multiple endpoints within a WSDL, in most cases only one was defined though. This endpoint usually only operates on POST requests even when later on (SOAP 1.2) GET would have been possible also.

According to Fielding's thesis

REST uses a resource identifier to identify the particular resource involved in an interaction between components.

, what would be the resource identifier in GraphQL? GraphQL's documentation states that

... In contrast, GraphQL's conceptual model is an entity graph. As a result, entities in GraphQL are not identified by URLs. Instead, a GraphQL server operates on a single URL/endpoint, usually /graphql, and all GraphQL requests for a given service should be directed at this endpoint.

Similar to SOAP, all the request are targeted towards a single endpoint. This has some impact if you consider caching, which is a further constraint REST implies. How are responses cacheable if the URI is the key used to store the response in the cache?

While all of the aggregation stuff and the flexibility may be nice from a consumer perspective, they are, probably, not in line with the constraints of REST, though Fielding himself claimed that REST is not applicable in all situations and that designers should select a style that fits their needs as not every style is the "silver bullet" to each problem. Even Mike Amundsen stated that GraphQL violates at least 3 constraints imposed by the REST architecture, even though GraphQL seems to have changed the default retrieval method from POST to GET since.

Usually, if you aim for long-living APIs that should be free to evolve in future and that has to deal with lots of clients, especially ones not under your direct control, this is when REST starts to shine. Fielding admits that most developers have problems when thinking long-term. For a single frontend-to-backend system or for a tailor-made client interacting with the own API, REST is not the architecture one should probably follow.

Last but not least, in a later tweet Fielding stated

There is no such thing as a REST endpoint. There are resources. A countably infinite set of resources bound only by restrictions on URL length. A client can POST to a REST service to create a resource that is a GraphQL query, and then GET that resource with all benefits of REST…

which I interpret as, don't focus to much on justifying whether GraphQL is REST or not, but think about how you can integrate its benefits into the overall design.

这篇关于默认情况下 GraphQL API 是 RESTful 吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆