Apollo iOS GraphQL Subscription Error: "Invalid HTTP upgrade"

936 views Asked by At

I'm trying to get a GraphQL subscription from SoundtrackYourBrand working within my iOS app. The queries/mutations work fine but when I use the web socket I get either error 400 or 403 ("Invalid HTTP upgrade") or 1011 (no message) depending on how I've set the authorisation token.

Error WebSocketError(payload: nil, error: Optional(Starscream.WSError(type: Starscream.ErrorType.upgradeError, message: "Invalid HTTP upgrade", code: 403)), kind: ApolloWebSocket.WebSocketError.ErrorKind.networkError)

Error WebSocketError(payload: nil, error: Optional(Starscream.WSError(type: Starscream.ErrorType.protocolError, message: "", code: 1011)), kind: ApolloWebSocket.WebSocketError.ErrorKind.networkError)

I'm using Apollo to work with the graphQL API. And it works for mutations/queries. I've set up a splitNetwork Transport as per the Apollo docs here.

var wssURL: String = "wss://api.soundtrackyourbrand.com/v2"

    client = {
        let request = URLRequest(url: wssURL)
        let authPayload = ["Authorization" : "Bearer \(token)"]
        let webSocketTransport = WebSocketTransport(request: request, connectingPayload: authPayload)
        
        let client = URLSessionClient()
        let cache = InMemoryNormalizedCache()
        let store = ApolloStore(cache: cache)
        let provider = NetworkInterceptorProvider(store: store, client: client)
        let normalTransport = RequestChainNetworkTransport(interceptorProvider: provider, endpointURL: endpointURL, additionalHeaders: ["authorization" : "Bearer \(token)"])
        
        let splitNetworkTransport = SplitNetworkTransport(
            uploadingNetworkTransport: normalTransport,
            webSocketNetworkTransport: webSocketTransport
        )
        
        return ApolloClient(networkTransport: splitNetworkTransport, store: store)
        
    }()

While above is the way Apollo suggests doing authorisation, in the SoundtrackYourbrand docs it says set the token as a query parameter: "You won't be using any headers, so the token need to be passed as a query parameter."

In which case should I set up the websocket like below.

The below code gives me the protocol error 1011, while the above code gives the 400/403 "Invalid HTTP upgrade" error.

    client = {
        
        let queryItems = [URLQueryItem(name: "Authorization", value: "Bearer \(token)")]
        var urlComps = URLComponents(string: wssURL)!
        urlComps.queryItems = queryItems
        let result = urlComps.url!
        let request = URLRequest(url: result)
        let webSocketTransport = WebSocketTransport(request: request)
        
        let client = URLSessionClient()
        let cache = InMemoryNormalizedCache()
        let store = ApolloStore(cache: cache)
        let provider = NetworkInterceptorProvider(store: store, client: client)
        let normalTransport = RequestChainNetworkTransport(interceptorProvider: provider, endpointURL: endpointURL, additionalHeaders: ["authorization" : "Bearer \(token)"])
        
        let splitNetworkTransport = SplitNetworkTransport(
            uploadingNetworkTransport: normalTransport,
            webSocketNetworkTransport: webSocketTransport
        )
        
        return ApolloClient(networkTransport: splitNetworkTransport, store: store)
        
    }()

Also should my starting URL be:

  1. wss://api.soundtrackyourbrand.com/v2
  2. wss://api.soundtrackyourbrand.com/v2/websocket

Looking at the docs I would think it should be 2), but after getting a subscription working in the SoundtrackYourbrand workspace, which uses 1) I assume I must use 1).

In the workspace I use the WS URL provided by default: wss://api.soundtrackyourbrand.com/v2, and then set the authorisation header to "Bearer ••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••...". And that works, but can't seem to replicate it in the iOS app with Apollo

What am I doing wrong?

Any help would be greatly appreciated!

0

There are 0 answers