ardatan / graphql-mesh

🕸️ GraphQL Federation Framework for any API services such as REST, OpenAPI, Swagger, SOAP, gRPC and more...
https://the-guild.dev/graphql/mesh
MIT License
3.3k stars 347 forks source link

Support `graphql-ws` protocol for outgoing subscription requests graphql source #2066

Closed ntziolis closed 3 years ago

ntziolis commented 3 years ago

The Problem:

Enabling the ability to connect graphql sources that are not yet graphql-transport-ws compliant would further extend the use cases for GraphQL Mesh. In addition it could assist in speeding up the transition to the new protocol since one barrier of entry (server side handling of the new protocol) would be removed or at least phased (at some point people should upgrade their downstream sources).

Our Use Case:

Describe the solution you'd like

There are 2 general approaches:

We have already tested the first approach successfully via monkey patch. Afterwards Mesh was capable of receiving incoming requests in the new protocol but making outgoing requests with the legacy protocol.

Here is the patch we used: https://gist.github.com/ntziolis/e6eff864709b737aadbe82e1ca763010

This is what we replaced after copying the source from @graphql-tools/url-loader:

  buildWSSubscriber(pointer: string, webSocketImpl: typeof WebSocket, headers: Record<string,string>): Subscriber {
    const WS_URL = switchProtocols(pointer, {
      https: 'wss',
      http: 'ws',
    });
    const subscriptionClient = new SubscriptionClient(WS_URL, {
      connectionParams: () => {
        return {
          headers
        }
      }
    }, webSocketImpl);

    return async ({ document, variables }: { document: DocumentNode; variables: any }) => {
      return observableToAsyncIterable(
        subscriptionClient.request({
          query: document,
          variables,
        })
      ) as AsyncIterator<ExecutionResult<any>>;
    };
  }
ntziolis commented 3 years ago

We are happy to take on the implementation but before starting wanted some input in which solution path you would prefer or if any support for the legacy protocol is not an option for you.

ardatan commented 3 years ago

I think you are referring to subscription-transport-ws by graphql-ws. We'd love to have both supported in url-loader. It sounds good to me :)

ntziolis commented 3 years ago

Yes that's what I was referring to. I'll get right on it then and create 2 Prs:

ardatan commented 3 years ago

Thank you @ntziolis ! We'd love to merge and release new versions for those.

ntziolis commented 3 years ago

@ardatan Any preferences on how the config option for the graphql handler should be named? I would suggest adding a boolean flag. Something like useLegacyWsProtocol. But I'll go with whatever you prefer.

This flag would default to false. We can then pass this flag directly to the loader:

Btw the naming scheme of the libs their protocols is VERY confusing :D

ardatan commented 3 years ago

Yes they are confusing unfortunately :D So I am fine with your approach.

ntziolis commented 3 years ago

PR for part one was just created. Part 2 is already done but requires part one to be released.

See for part 2 here: https://github.com/Urigo/graphql-mesh/compare/master...ntziolis:support-legacy-ws-protocol

ntziolis commented 3 years ago

For anyone finding this, once released this can be configured via

sources: 
  - name: countries
    handler:
      graphql: 
        endpoint: https://countries.trevorblades.com/
        # this is the new flag
        useWebSocketLegacyProtocol: true