I’ve setup a meteor server for subscriptions, and the socket seems to be connecting fine. However I found that the normal Meteor socket connection is Connection closed before receiving a handshake response
. Is there a way to specify a different port for either the normal Meteor socket, or the one used by the meteor/webapp
project?
Our use case is attempting to migrate to a graphql api interface incrementally.
Code below:
Server:
import { ApolloServer } from 'apollo-server-express';
import { WebApp } from 'meteor/webapp';
import { getUser } from 'meteor/apollo';
import { execute, subscribe } from 'graphql';
import { SubscriptionServer } from 'subscriptions-transport-ws';
import { makeExecutableSchema } from 'graphql-tools';
import { typeDefs } from './typedefs';
import { resolvers } from './resolvers';
const schema = makeExecutableSchema({ typeDefs, resolvers });
const server = new ApolloServer({
schema,
context: async ({ req }) => {
const user = await getUser(req.headers.authorization);
if (!user) throw new Error('must login');
return {
user,
};
},
});
server.applyMiddleware({
app: WebApp.connectHandlers,
path: '/graphql',
});
// eslint-disable-next-line
const subscriptionServer = new SubscriptionServer({
execute,
subscribe,
schema,
onConnect: async (connectionParams, webSocket) => {
// if a meteor login token is passed to the connection params from the client,
console.log('connection params!!!', connectionParams, webSocket);
// add the current user to the subscription context
// const subscriptionContext = connectionParams.meteorLoginToken
// ? await addCurrentUserToContext(context, connectionParams.meteorLoginToken)
// : context;
return {};
},
}, { server: WebApp.httpServer, path: '/subscriptions' });
WebApp.connectHandlers.use('/graphql', (req, res) => {
if (req.method === 'GET') {
res.end();
}
});
Client:
import { ApolloClient } from 'apollo-client';
import { InMemoryCache } from 'apollo-cache-inmemory';
import { ApolloLink, split } from 'apollo-link';
import { HttpLink } from 'apollo-link-http';
import { WebSocketLink } from 'apollo-link-ws';
import { MeteorAccountsLink } from 'meteor/apollo';
import { getMainDefinition } from 'apollo-utilities';
// "basic" Meteor network interface
// create a websocket uri based on your app absolute url (ROOT_URL), ex: ws://localhost:3000
const websocketUri = Meteor.absoluteUrl('subscriptions').replace(/^http/, 'ws');
console.log('websocketUri', websocketUri)
const wsLink = new WebSocketLink({
uri: websocketUri,
options: {
reconnect: true,
connectionParams: {
authToken: 'aasdfs',
},
},
});
const httpLink = new HttpLink({
uri: '/graphql',
});
// using the ability to split links, you can send data to each link
// depending on what kind of operation is being sent
const link = split(
// split based on operation type
({ query }) => {
const definition = getMainDefinition(query);
return (
definition.kind === 'OperationDefinition'
&& definition.operation === 'subscription'
);
},
wsLink,
httpLink,
);
// enhance the interface with graphql subscriptions
// enjoy graphql subscriptions with Apollo Client
export const client = new ApolloClient({
link: ApolloLink.from([
new MeteorAccountsLink(),
link,
]),
cache: new InMemoryCache(),
});