Giter Club home page Giter Club logo

Comments (22)

ujwal-setlur avatar ujwal-setlur commented on August 28, 2024 1

@theodorDiaconu, this works for me:

const wsLink = new WebSocketLink({
  uri: constants.GRAPHQL_SUBSCRIPTION_ENDPOINT,
  options: {
    reconnect: true,
    connectionParams: () => ( // a promise that resolves to return the loginToken
    new Promise((resolve, reject) => { // eslint-disable-line no-undef,no-unused-vars
      getLoginToken().then(token => {
        if (token) {
          resolve({
            [constants.AUTH_TOKEN_KEY]: token
          });
        } else {
          resolve({
            [constants.AUTH_TOKEN_KEY]: ""
          });
        }
      });
    })
    )
  }
});

This works as well:

const wsLink = new WebSocketLink({
  uri: constants.GRAPHQL_SUBSCRIPTION_ENDPOINT,
  options: {
    reconnect: true,
    connectionParams: getLoginToken().then(token => {
      return {
        [constants.AUTH_TOKEN_KEY]: token
      };
    })
  }
});

Both require that subscriptions-transport-ws be patched this PR or following this comment.

from apollo.

ujwal-setlur avatar ujwal-setlur commented on August 28, 2024

OK, the subscription request doesn't even seem to be getting to the server...need to debug that...

from apollo.

ujwal-setlur avatar ujwal-setlur commented on August 28, 2024

It seems the websocket connection to the server is closing immediately. I tried command line utilities like wsc and wscat to connect to ws://localhost:3000/subscriptions.

wscat -c ws://localhost:3000/subscriptions                                                                                                         ✘ 255 feature/infrastructure ✚ ✱
connected (press CTRL+C to quit)
disconnected
wsc ws://localhost:3000/subscriptions                                                                                                                    feature/infrastructure ✚ ✱
Connected to ws://localhost:3000/subscriptions
> Connection closed

But GraphiQL can connect via browser. Doesn't GraphiQL also use websockets for subscriptions?

from apollo.

ujwal-setlur avatar ujwal-setlur commented on August 28, 2024

Actually, I don't think the websocket issue is the problem. I used react-native-websocket to open a websocket from within my app to ws://localhost:3000/subscriptions, and it worked. A socket is created and opened and does not immediately close.

However, the subscription request does not reach the subscription resolver on the server, so either there is a problem with the WebSocketLink or with the subscription query.

from apollo.

theodorDiaconu avatar theodorDiaconu commented on August 28, 2024

@ujwal-setlur I would first advise you to test a barebones subscription, without apollo-live-client to make sure it works properly. Maybe there are certain security rules that prevent websocket connections ?

from apollo.

theodorDiaconu avatar theodorDiaconu commented on August 28, 2024

@ujwal-setlur to make sure this works, can you run your subscription in GraphiQL ? It should work automatically. If all works there I think the problem may be on RN side

from apollo.

ujwal-setlur avatar ujwal-setlur commented on August 28, 2024

@theodorDiaconu, actually I tried that. That is not working either, My app actually crashed when I tried something like this:

const observable = client.subscribe({ query: SUBSCRIBE_GROUPS });
const subscription = observable.subscribe({ <--- this crashed the app
  next({ data }) {
    // data is your payload
    // do something with it
  },
});

Continuing to debug...

from apollo.

ujwal-setlur avatar ujwal-setlur commented on August 28, 2024

@theodorDiaconu, yes, as I said in the initial problem report, subscription via GraphiQL works so the server side is set up fine, I believe. Yes, problem is clearly on RN side.

from apollo.

theodorDiaconu avatar theodorDiaconu commented on August 28, 2024

@ujwal-setlur In that case there's something going on at RN level... something acting up with the client, what is the error ? why is your app crashing ?

from apollo.

ujwal-setlur avatar ujwal-setlur commented on August 28, 2024

Will post the code and error in a few mins

from apollo.

ujwal-setlur avatar ujwal-setlur commented on August 28, 2024

Actually, the code is not crashing anymore. Maybe I had it in the wrong place before. This is what I have in my component:

export default class MyComponent extends Component {
  constructor(props) {
    super(props);
  }

  componentDidMount() {
    this.subscribeGroups();
  }

  subscribeGroups() {
    console.log("subscribing groups");
    const observable = this.props.client.subscribe({
      query: SUBSCRIBE_GROUPS
    });
    const subscription = observable.subscribe({
      next({data}) {
        console.log("got data");
        // data is your payload
        // do something with it
      }
    });
  }

  render() {
    return (
      <Container>
        <Content>
          <ReactiveQuery
            query={GET_GROUPS}
            subscription={SUBSCRIBE_GROUPS}
          >
            {({data, loading, error}) => {
               if (loading) return <Text>
                                     Loading
                                   </Text>;
               if (error) return <Text>
                                   {error}
                                 </Text>;
             
               return <Text>
                        {JSON.stringify(data)}
                      </Text>;
             }}
          </ReactiveQuery>
        </Content>
      </Container>
      );
  }
}

The code does not crash, but I don't see the subscription reaching the server side. It makes me think the ws link is not set up right?

from apollo.

ujwal-setlur avatar ujwal-setlur commented on August 28, 2024

This is the crash I got on iOS. I got it before on Android as well, but then it went away. Very confusing...

screen shot 2018-05-21 at 11 02 46 pm

from apollo.

theodorDiaconu avatar theodorDiaconu commented on August 28, 2024

Show me your typeDefs, how you define this server-side, and also the resolvers

from apollo.

ujwal-setlur avatar ujwal-setlur commented on August 28, 2024

OK, I identified the culprit! I was setting an option for the Meteor auth token in the WebSocketLink, but it was with an asynchronous call:

const wsLink = new WebSocketLink({
  uri: constants.GRAPHQL_SUBSCRIPTION_ENDPOINT,
  options: {
    reconnect: true,
    connectionParams: () => ({
      [constants.AUTH_TOKEN_KEY]: getLoginToken() // <-- This asynchronous call caused the problem!
    })
  }
});

I had patched subscriptions-trasnport-ws to allow for async calls to set header per apollographql/subscriptions-transport-ws#348, but clearly this is not working. When I just use:

const wsLink = new WebSocketLink({
  uri: constants.GRAPHQL_SUBSCRIPTION_ENDPOINT,
  options: {
    reconnect: true
  }
});

then things work! I will have to figure out another way of setting the async auth header.

Thanks for the help!

from apollo.

theodorDiaconu avatar theodorDiaconu commented on August 28, 2024

@ujwal-setlur we already solved this issue with async auth header, let me find it in one of our code-bases

from apollo.

theodorDiaconu avatar theodorDiaconu commented on August 28, 2024

@ujwal-setlur here you go:

import { AsyncStorage } from 'react-native'
import ApolloClient from 'apollo-client'
import { HttpLink } from 'apollo-link-http'
import { setContext } from 'apollo-link-context'
import { InMemoryCache } from 'apollo-cache-inmemory'
import {
  from,
} from 'apollo-client-preset'

export function initialize() {
  const httpLink = new HttpLink({
    uri: 'http://192.168.1.146:3000/graphql',
  })

  const authMiddleware = setContext(() =>
    AsyncStorage.getItem('Meteor.loginToken').then(loginToken => ({
      headers: {
        'meteor-login-token': loginToken,
      },
    })))

  const client = new ApolloClient({
    link: from([authMiddleware, httpLink]),
    cache: new InMemoryCache({
      dataIdFromObject: object => object._id || null,
    }),
  })

  return client
}

The logic is to use a middleware for setting token for both websocket and http links.

Edit: this won't solve the issue for connectionParams and WebsocketLink

from apollo.

theodorDiaconu avatar theodorDiaconu commented on August 28, 2024

Sorry, I now realise that this approach wouldn't work for Websockets, but I think with websockets the logic is that you can use getLoginToken() that reads from somewhere, and when that something changes, just reconnect. And problem solved. Also if you do solve this, would you be kind enough to submit a PR updating docs in here ? If not just leave the solution here so others won't head into this issue.

from apollo.

ujwal-setlur avatar ujwal-setlur commented on August 28, 2024

@theodorDiaconu, will do! Thanks a lot for your help and attention! Yes, I do use setContext for HttpLink, and it works well.

from apollo.

ujwal-setlur avatar ujwal-setlur commented on August 28, 2024

When login token changes, reset the websocket connection:

wsLink.subscriptionClient.close(false, false);
// wait a little while for the connection to be established before you initiate any subscriptions

at the appropriate place.

from apollo.

ujwal-setlur avatar ujwal-setlur commented on August 28, 2024

I will open a documentation PR soon.

from apollo.

ujwal-setlur avatar ujwal-setlur commented on August 28, 2024

All issues reported here have been resolved. None of them were issues with this package. Closing.

from apollo.

ujwal-setlur avatar ujwal-setlur commented on August 28, 2024

@theodorDiaconu, I have opened a documentation PR. Hopefully, it is useful!

from apollo.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.