Comments (22)
@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.
OK, the subscription request doesn't even seem to be getting to the server...need to debug that...
from apollo.
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.
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.
@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.
@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.
@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.
@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.
@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.
Will post the code and error in a few mins
from apollo.
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.
This is the crash I got on iOS. I got it before on Android as well, but then it went away. Very confusing...
from apollo.
Show me your typeDefs, how you define this server-side, and also the resolvers
from apollo.
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.
@ujwal-setlur we already solved this issue with async auth header, let me find it in one of our code-bases
from apollo.
@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.
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.
@theodorDiaconu, will do! Thanks a lot for your help and attention! Yes, I do use setContext for HttpLink, and it works well.
from apollo.
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.
I will open a documentation PR soon.
from apollo.
All issues reported here have been resolved. None of them were issues with this package. Closing.
from apollo.
@theodorDiaconu, I have opened a documentation PR. Hopefully, it is useful!
from apollo.
Related Issues (20)
- Authentication Directives HOT 1
- [Question] Fields resolved by external API HOT 6
- me query returns null HOT 6
- apollo db not work HOT 2
- [Question] How to expose links' metadata in schema HOT 1
- Shouldn't require resolvers for links. HOT 2
- Query lock-down on production
- Decouple Apollo Client to NPM
- Could I use this package for `Meteor + Vue`? HOT 2
- Get `userId = null`? HOT 1
- See what we can learn from here.
- Get the loader from cultofcoders:apollo
- Deep filtering
- `userId` is `undefined` in `matb33:collection-hooks` HOT 1
- Support Apollo Client 3.0
- test 2 p
- test 1 p
- test 1
- Project Management
- \ttest se tset
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from apollo.