GraphQL 订阅的多部分 HTTP 协议
允许客户端通过多部分 HTTP 协议实时接收更新
要在GraphOS Router上执行GraphQL subscription operations,客户端应用不需要通过WebSocket进行通信。相反,它们使用HTTP与多部分响应。这种多部分协议建基于GraphOS Router用于支持以下规范:通过HTTP进行增量交付规范,该规范被GraphOS Router用于支持.css-1lvdtfu{font-family:var(--chakra-fonts-mono);font-size:calc(1em / 1.125);-webkit-padding-start:var(--chakra-space-1);padding-inline-start:var(--chakra-space-1);-webkit-padding-end:var(--chakra-space-1);padding-inline-end:var(--chakra-space-1);padding-top:var(--chakra-space-0-5);padding-bottom:var(--chakra-space-0-5);border-radius:var(--chakra-radii-sm);color:var(--chakra-colors-text);background-color:var(--chakra-colors-silver-400);}.chakra-ui-dark .css-1lvdtfu:not([data-theme]),[data-theme=dark] .css-1lvdtfu:not([data-theme]),.css-1lvdtfu[data-theme=dark]{background-color:var(--chakra-colors-black-200);}@defer
指令。
如果您正在向新的GraphQL客户端库添加协议支持,请使用此参考。Apollo客户端、Apollo Kotlin和Apollo iOS都支持此协议。Apollo Client还提供了针对Relay和urql库的网络适配器。
执行一个订阅
要在GraphOS Router上执行subscription,GraphQL客户端需要发送一个与查询和mutations请求格式几乎相同的HTTP请求。
唯一的不同是请求应包含以下Accept
头:
Accept: multipart/mixed;subscriptionSpec="1.0", application/json
💡 提示
边界boundary
的值应该始终是总是是graphql
,和subscriptionSpec的值应该始终是
总是是1.0
。
随着订阅事件的发生,路由器会发送符合RFC1341中指定的多部分内容定义的HTTP响应"部分"。
可能的响应示例可能如下所示
--graphqlContent-Type: application/json{}--graphqlContent-Type: application/json{"payload": {"data": { "newPost": { "id": 123, "title": "Hello!"}}}}--graphql--
- 如果请求使用HTTP/1,则响应包括
Transfer-Encoding: chunked
标题。 - 如果请求使用HTTP/2(它提供了对数据流的自带支持),则不使用分块编码不被使用(实际上它是不允许)。
心跳
当客户端订阅保持活动状态时,GraphOS Router会发送定期的"心跳"响应部分,以防止任何中间件关闭连接。心跳体的主体是一个空的JSON对象,客户端应该默默地忽略:
--graphqlContent-Type: application/json{}--graphql--
消息和错误格式
此协议在响应有效负载本身中区分传输级别错误和GraphQL错误。这是因为在GraphQL规范中定义了GraphQL响应格式定义,意外字段可能令人困惑或甚至破坏客户端的打字。
除了心跳之外,每个响应部分主体都包含一个payload
属性,该属性包含标准GraphQL响应属性。如果发生传输级别错误,则payload属性可以是null。
如果发生GraphQL级别的错误,则GraphOS路由器有时仍然可以返回部分数据,并且订阅连接应保持打开。这些错误提供在payload属性内:
{"payload": {"errors": [...],"data": {...},"extensions": {...}}}
如果发生致命的传输级别错误,则路由器会发送一个包含顶级errors
字段和payload
字段为null的消息,然后关闭连接:
{"payload": null,"errors": [...]}
这两种类型的errors
都遵循GraphQL错误格式,但顶级errors
never include locations
或path
.