Skip to content

Add subscriptions connection_init behaviour #597

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 3 commits into from

Conversation

TheBolliwood
Copy link

@TheBolliwood TheBolliwood commented Apr 1, 2020

This implements a reply and on_connect handler to GQL_CONNECTION_INIT based on Apollo subscriptions transport ws Protocol

This lets the client send a connection_init message with a custom payload to the server. The server handles this with a on_connect closure.
It replies GQL_CONNECTION_ACK if the connection is established and GQL_CONNECTION_ERROR if refused (with an error provided by on_connect).

I'm a bit sceptical about the #[allow(dead_code)] I added, but I thought it may be useful to keep type_name in the struct WsPayload.

  • Ensure proper formatting
  • Run all tests
  • Update the CHANGELOG

An example to use this would be (based on this)

graphql_subscriptions(
    websocket,
    coordinator,
    ctx,
    Some(|payload: &Value| {
        if let Some(token) = payload["authorization"].as_str() {
            if token == "foobar" {
                return Ok(())
            }
        }
        Err("Connection prohibited".to_string())
    }),
)
.map(|r| {
    if let Err(e) = r {
        println!("Websocket error: {}", e);
    }
})
.boxed()

With an apollographql client one could use

options: {
  connectionParams: {
    authorization: "foobar",
  },
},

as options for apollo-link-ws WebSocketLink (see apollo docs).
(for apollo server this would be: Apollo Server Websocket Authentification)

@TheBolliwood TheBolliwood marked this pull request as ready for review April 1, 2020 13:21
@LegNeato
Copy link
Member

LegNeato commented Apr 1, 2020

Thanks for the PR! Looks useful. I wonder if we should generalize this and have a Handler trait that lets you inject logic for all message types, not only connect. @nWacky, thoughts?

(As an aside, would love to model this as a state machine with session types).

@nWacky
Copy link
Contributor

nWacky commented Apr 3, 2020

@TheBolliwood,

looks useful, thank you 😀

@LegNeato,

I think it would be useful to insert logic for subscriptions lifecycle like Apollo does.

We could have a struct SubscriptionServer that could take in a deserialized request and do the needed logic. I like the idea of it being a state machine. SubscriptionServer could be constructed before hand with all needed lifecycle hooks and passed to graphql_subscriptions. graphql_subscriptions could then handle deserializing requests and yielding responses to the client.

I believe SubscriptionServer could be a stream or a channel that would yield deserializeable responses

@LegNeato
Copy link
Member

LegNeato commented Aug 2, 2020

I believe master has a superset of these changes. Please let me.know if not!

@LegNeato LegNeato closed this Aug 2, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants