-
StoryI am implementing a middle-ware gateway component to manage GraphQL API calls exchanged between client and server. I am trying make my gateway to work with the latest "graphql-ws" protocol, as well as the legacy "subscriptions-transport-ws" protocol (As there will be old users who use it still) I would like to know in default case, if its possible for the server side to accept an array of sub protocols and choose whatever it supports and send that back to client. The MDN explanation for web-sockets states that
My sample server code looks like this (same as your sample server code)
If I write a simple nodejs server using "graphql-ws" and "ws", and if my client send the subprotocol header values as "graphql-transport-ws, graphql-ws" server code always read the first protocol and works fine, but if the header values are in order "graphql-ws, graphql-transport-ws" it doesn't work because the first unsupported protocol is picked. As I checked, "graphql-ws" also support writing in this in a customizable way (support legacy subscriptions-transport-ws). But, server side developer should explicitly write the protocol reading part for that. Shouldn't choosing values from protocol header array be the default behavior even for simple cases? Acceptance criteriaClient will be able to send comma separated multiple sub protocol header values in any order. |
Beta Was this translation helpful? Give feedback.
Replies: 3 comments 8 replies
-
Hi there, the client is fixed using Instead, what you should do is check one by one. To check if this library ("graphql-transport-ws") is supported, you can do something like: function supportsGraphQLTransportWS(url: string): Promise<boolean> {
return new Promise((resolve) => {
const client = createClient({
url, // enpoint you want to check
retryAttempts: 0, // dont retry, fail immediately
lazy: false, // connect as soon as the client is created, so as soon as this function is called
on: {
closed: () => resolve(false), // connection rejected, NOT supported
connected: () => {
resolve(true); // connected = supported
client.dispose(); // dispose of client after check
},
},
});
});
}
const supported = await supportsGraphQLTransportWS('wss://somwhere.out/there');
if (supported) {
// use graphql-ws
} else {
// use subscriptions-transport-ws
} Furthermore, regarding the server-side, you can indeed support both the legacy and the current subprotocol. Please refer to the "ws server usage with subscriptions-transport-ws backwards compatibility" recipe. |
Beta Was this translation helpful? Give feedback.
-
Added a "Client usage supported check" recipe with c47dcf0. |
Beta Was this translation helpful? Give feedback.
-
Hi, I'm the maintainer of graphql-python/gql and I really think you should reconsider and allow graphql-ws to work if its subprotocol is present later in the subprotocols provided list by the client. The client can and should read the answer of the backend in the It should work correctly right now with the current gql code. If you allow this, it would permit the client to support both the apollo and graphql-ws protocol automatically (currently it works only with your backwards-compatible recipe) |
Beta Was this translation helpful? Give feedback.
Hi there,
the client is fixed using
"graphql-transport-ws"
subprotocol intentionally because it does not know which subprotocol the server chose when multiple are supplied. The client just knows if the connection was accepted or not. This means that sending both subprotocols (["graphql-transport-ws", "graphql-ws"]
) from thecreateClient
will break if the latter is selected by the server due to subprotocol mismatch.Instead, what you should do is check one by one. To check if this library ("graphql-transport-ws") is supported, you can do something like: