I try to subscribe our Android client with the Apollo client v3.0.0-beta05. For me it is not possible so do a successful subscription. This is how i create the Apollo-Client:
Is this the right way to add an authentication to wss? My error response is:
Caused by: com.apollographql.apollo3.exception.ApolloWebSocketClosedException: WebSocket Closed code='1002' reason=''
at com.apollographql.apollo3.network.ws.DefaultWebSocketEngine$open$webSocket$1.onClosing(OkHttpWebSocketEngine.kt:60)
at okhttp3.internal.ws.RealWebSocket.onReadClose(RealWebSocket.kt:378)
at okhttp3.internal.ws.WebSocketReader.readControlFrame(WebSocketReader.kt:220)
at okhttp3.internal.ws.WebSocketReader.processNextFrame(WebSocketReader.kt:104)
at okhttp3.internal.ws.RealWebSocket.loopReader(RealWebSocket.kt:293)
at okhttp3.internal.ws.RealWebSocket$connect$1.onResponse(RealWebSocket.kt:195)
at okhttp3.internal.connection.RealCall$AsyncCall.run(RealCall.kt:519)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.lang.Thread.run(Thread.java:920)
Is there any chance your API is public? We could then double check. But if it’s not, I don’t think there’s a standard way to handle authentication so it’s hard to tell.
At this point, I’d recommend double checking the url. If that’s not enough, usually running through a proxy like Charles will highlight the difference and hint at what the problem might be.
Ok, now i got the subscription and everything works. The SubscriptionWsProtocol is part of the ApolloClient instance and this is a singleton.
But, is there an option to refresh the Token in the SubscriptionWsProtocol? (The Interceptors work only on http and not with ws calls)
What happen if the token is invalid?
This is a very good question and the fact that most implementations are server-dependent make it very hard to test against. Not too mention the relative absence of public GraphQL servers supporting subscriptions.
In your specific case, I’d expect that the WebSocket would throw an error and that you would be able to restart it? SubscriptionWsProtocol.connectionPayload is a lambda so you can execute code to refresh your token inside the lambda if needed.
You might need to use the beta06-SNAPSHOT for this as we recently fixed a bug when errors happen.
In all cases, if you ever have a network dump of what happens when the token expires, it’d be awesome if you could share it, we could add that to unit tests.
I’m getting a SubscriptionOperationException with cause = null and message = “Operation error on MySubscription” | payloadMessage = message = “Must provide document.”.
Do I need to care about some incompatibility with the server version? I saw that in the client version 2 the connection payload was inserted to the json message and now we have the following code inside the SubscriptionWsProtocol.kt :
val message = mutableMapOf<String, Any?>(
"type" to "connection_init",
)
val payload = connectionPayload()
if (payload != null) {
message.put("payload", payload)
}
I’m still having a migration issue with subscriptions. Here’s my apollo client ws config.
val subscriptionWsProtocol = SubscriptionWsProtocol.Factory(
connectionPayload = { mapOf("Authorization" to accessToken, "x-timezone" to "America/Los_Angeles") }
)
val webSocket = WebSocketNetworkTransport.Builder()
.serverUrl(GRAPHQL_SUBSCRIPTION_WEBSOCKET_URL)
.protocol(subscriptionWsProtocol)
.addHeader("Accept-Encoding", "gzip, deflate, br")
.addHeader("Accept-Language", "en,zh-CN;q=0.9,zh;q=0.8")
The connection is working fine, but I’m having an error when I’m trying to subscribe with the following error message: Must provide document.
I’m seeing that document in this case means Operation.DOCUMENT, and this field is passed to the query field in the payload by calling Operation.document() inside the DefaultHttpRequestComposer.composePayload(request).
if (sendDocument) {
queryParams.put("query", operation.document())
}
But, debugging the connection payload I realized that the query field is null, even that the sendDocument flag is enabled by default for the SubscriptionWsProtocol.
What should I do to fix this problem? Because on the iOS side we have the query filled with the Operation.DOCUMENT properly.
Yes, the persisted queries are being enabled in the Apollo Client build phase.
I did some tests about the Persisted Queries and sendDocument(true), if we use persisted query the document is not sent, even if we force it using sendDocument(true). So, I just created an extension for the subscription method that disable persisted queries for subscriptions