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

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

问题描述

我对REST的理解仅仅是,资源需要一些自我描述的方法.我的理解是,这并不专门与任何一种协议(即HTTP)相关联,并且从理论上讲,有许多方法可以实现此目的.这是基于以下SO问题的答案: SOAP vs REST(差异)(以及不像这个问题的可怕答案: Relay和Graphql RESTful吗?)

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?)

由于GraphQL API通过自省自描述,这并不意味着GraphQL默认情况下,RESTful是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?

推荐答案

而GraphQL是

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

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

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.

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

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不指定必须发送请求或响应的表示形式,而是将其留给协商它们的客户端和服务器.这有助于解耦,因为客户端和服务器都可以依靠公共接口(HTTP),并且只能牢固地绑定到用于交换数据的已知媒体类型上.同位体无法以某种表示形式处理文档(由于缺少相应的mime类型支持)将通过其不理解(因此无法投放)所请求的媒体类型格式的相应HTTP状态代码来指示其另一方.因此,媒体类型只是数据可读语法和数据有效载荷的语义可读文档,因此是REST体系结构中最重要的部分.甚至要求提供字段:

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:

REST API应该花费几乎所有的描述性精力来定义用于表示资源和驱动应用程序状态的媒体类型,或者为现有标准媒体定义扩展的关系名称和/或启用超文本的标记类型.花费所有精力描述应该在一种媒体类型(并且在大多数情况下,已经由现有媒体类型定义)的处理规则范围内完全定义在感兴趣的URI上使用哪种方法.[这里的失败表示带外信息正在驱动交互,而不是超文本.]

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.]

一种媒体类型可以教给对等方如何解析和解释接收到的有效负载,并从中真正理解,尽管许多人仍将REST与基于JSON的HTTP API与过度设计的URI混淆在一起,而他们为此付出了很多努力.当客户端和服务器都不会解释它时,给URI某种逻辑上的意义,因为它们可能会使用为URI提供的链接关系名称.

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基本上只是一种查询语言,它使客户端可以请求从服务器检索的特定字段和元素.从广义上讲,它是某种用于Web的SQL,或称为字段将其称为远程数据访问(RDA).因此,它必须事先具有一些可用数据的知识,从而以某种方式将客户端耦合到服务器.如果服务器将重命名某些字段,则尽管我不是GraphQL专家,但客户端可能无法进一步检索此类信息.

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.

如上所述,REST通常与基于JSON的HTTP API混淆,该HTTP API允许对直接映射的DB条目/实体执行查询.请记住,尽管REST的重点是对等体的解耦,而不是某些Web公开的数据库条目的检索方面,但它并不禁止这样做.正如吉姆·韦伯(Jim Webber)在2011年REST中的一次精彩演讲中指出的那样,您不只是公开数据库表,还创建了一个域应用程序协议,客户端将遵循

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.

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

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.

这些应该为您提供足够的见解,以便您自己确定GraphQL是否可以是RESTful.我认为不是,但是我对GraphQL的见解相当有限,TBH.

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.

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

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

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.

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

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.

根据 Fielding的论文

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

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

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

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

...相反,GraphQL的概念模型是实体图.因此,URL无法识别GraphQL中的实体.相反,GraphQL服务器在单个URL/端点(通常为/graphql)上运行,并且对给定服务的所有GraphQL请求都应定向到该端点.

... 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.

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

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?

尽管从消费者的角度来看,所有聚合的东西和灵活性可能都不错,但它们可能并不符合REST的约束,尽管菲尔丁本人声称REST并不适用于所有情况,并且设计者应选择适合自己需求的样式,因为并非每种样式都是解决每个问题的银弹" .甚至迈克·阿蒙森都说GraphQL至少违反了REST架构施加的3个约束,即使GraphQL从那时起,似乎已将默认的检索方法从POST更改为GET.

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.

通常,如果您的目标是长期使用的API,这些API将来应该可以自由发展,并且必须处理许多客户端,尤其是那些不受您直接控制的客户端,那么这就是REST开始崭露头角的时候.菲尔丁承认大多数开发人员在考虑长期问题时会遇到问题.对于单个前端到后端系统或与自己的API交互的量身定制的客户端,REST可能不是应该遵循的体系结构.

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

没有REST端点之类的东西.有资源.仅URL长度限制所约束的无数资源集合.客户端可以发布到REST服务以创建作为GraphQL查询的资源,然后使用REST的所有优点来获取该资源……

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…

我解释为,

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

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