如何使用 apollo ios 客户端实现 graphql 订阅

Posted

技术标签:

【中文标题】如何使用 apollo ios 客户端实现 graphql 订阅【英文标题】:How to implement graphql subscription using apollo ios client 【发布时间】:2019-01-14 03:58:56 【问题描述】:

我正在尝试使用 apollo ios 客户端实现 graphql 订阅。但由于缺乏文档示例而无法弄清楚。 阿波罗文档中给出的示例是:

let apollo: ApolloClient = 
  let configuration = URLSessionConfiguration.default
  // Add additional headers as needed
  configuration.httpAdditionalHeaders = ["Authorization": "Bearer <token>"] // Replace `<token>`

  let url = URL(string: "http://localhost:8080/graphql")!

  return ApolloClient(networkTransport: HTTPNetworkTransport(url: url, configuration: configuration))
()

APOLLO IOS GUIDE: Creating a client

【问题讨论】:

【参考方案1】:

按照以下步骤在 apollo ios graphql 客户端中实现订阅。

    使用 cocoapods:

      pod 'Apollo' pod 'Apollo/WebSocket' pod install

    创建客户端以支持订阅和身份验证。在AppDelegate.swift中添加以下代码:

      Websocket - 我们必须使用WebSocketTransportURLRequest 身份验证 - 我们必须将连接参数connectingPayload 中的身份验证参数传递给服务器。对于 http,我们在问题 sn-p 中提到的标头中传递它。 SplitNetworkTransport- 结合 httpwebsocket 来创建客户端。我们必须使用httpNetworkTransportwebSocketNetworkTransport


lazy var apollo: ApolloClient = 
    let authPayloads = [
        "Authorization": "Bearer "
    ]
    let configuration = URLSessionConfiguration.default
    configuration.httpAdditionalHeaders = authPayloads

let map: GraphQLMap = authPayloads 
let wsEndpointURL = URL(string: "ws://localhost:8080/subscriptions")!
let endpointURL = URL(string: "http://localhost:8080/api")!
let websocket = WebSocketTransport(request: URLRequest(url: wsEndpointURL), connectingPayload: map)
let splitNetworkTransport = SplitNetworkTransport(
    httpNetworkTransport: HTTPNetworkTransport(
        url: endpointURL,
        configuration: configuration
    ), 
    webSocketNetworkTransport: websocket
)
return ApolloClient(networkTransport: splitNetworkTransport)

()

【讨论】:

从哪里获得 wsEndpointURL?下一步我需要做什么来更新 UI? 你能帮帮我吗【参考方案2】:

我快到了。我因在 Websocket 升级中没有正确的标头而被拒绝。我最终不得不直接在URLRequest 对象上设置它们。

    var apollo: ApolloClient? 
        let authHeaders = ["X-Hasura-Access-Key": "<my_Key>", "Content-Type": "application/json"]

        let configuration = URLSessionConfiguration.default
        // Add additional headers as needed
        configuration.httpAdditionalHeaders = authHeaders

        //The string to my graph QL Server run by Hasure on AWS RDS.
        let graphQLEndpoint = "http://<my_host>/v1alpha1/graphql"
        let graphQLSubscriptionEndpoint = "ws://<my_host>/v1alpha1/graphql"
        //Take my Ec2 Server string and make a URL for the graph QL and subscriptions
        guard let httpURL = URL(string: graphQLEndpoint), let webSocketURL = URL(string: graphQLSubscriptionEndpoint) else 
            return nil
        

        let httpTransport = HTTPNetworkTransport(url: httpURL, configuration: configuration, sendOperationIdentifiers: false)

        var request = URLRequest(url: webSocketURL)

        request.setValue("<my_key>", forHTTPHeaderField: "X-Hasura-Access-Key")

        request.setValue("application/json", forHTTPHeaderField: "Content-Type")

        let webSocketTransport = WebSocketTransport(request: request, sendOperationIdentifiers: false, connectingPayload: nil)

        let splitTransport = SplitNetworkTransport(httpNetworkTransport: httpTransport, webSocketNetworkTransport: webSocketTransport)

        //Initalize the APolloClient with that URL.
        return ApolloClient(networkTransport: splitTransport)
    

在那之后升级工作了。

【讨论】:

【参考方案3】:

这是我的 ApolloClient 设置,仅用于 Web 套接字传输客户端:

let connectingPayload = ["authToken": accessToken]
let urlRequest = URLRequest(url: baseURL)
let webSocketTransport = WebSocketTransport(request: urlRequest, sendOperationIdentifiers: false, connectingPayload: connectingPayload)

let apollo = ApolloClient(networkTransport: webSocketTransport)

【讨论】:

以上是关于如何使用 apollo ios 客户端实现 graphql 订阅的主要内容,如果未能解决你的问题,请参考以下文章

为啥需要更新器/更新函数来更新 React Relay 和 Apollo 客户端中的本地缓存?

angular, apollo-client, graphQL - 从 graphql 查询中选择所有字段

使用 Apollo 链路状态缓存实现客户端过滤

使用mergeSchemas的Apollo Server模式拼接,如何使用来自单独模式的类型?

如何使用 Apollo Client 虚拟字段

如何使用 apollo 客户端在 graphql 的角度处理错误?