Skip to content
Advertisement

Subscription not connecting using ApolloServer

I am trying to get a subscription up and running with ApolloServer (v 2.2.2). I had a setup that all-of-a-sudden just stopped working. When I try to connect to the subscription in graphiql/PlaygroundI get the error:

{
  "error": "Could not connect to websocket endpoint ws://localhost:4000/graphql. Please check if the endpoint url is correct."
}

As I have rest-endpoints in my app I need to have express but I can’t get the minimal example from below running:

import http from 'http';
import { ApolloServer, PubSub } from 'apollo-server-express';
import express from 'express';

const pubsub = new PubSub();

// The DB
const messages = [];

const typeDefs = `
type Query {
  messages: [String!]!
}
type Mutation {
  addMessage(message: String!): [String!]!
}
type Subscription {
  newMessage: String!
}

schema {
  query: Query
  mutation: Mutation
  subscription: Subscription
}
`;

const resolvers = {
  Query: {
    messages() {
      return messages;
    }
  },
  Mutation: {
    addMessage(root, { message }) {
      let entry = JSON.stringify({ id: messages.length, message: message });
      messages.push(entry);
      pubsub.publish('newMessage', { entry: entry });
      return messages;
    },
  },
  Subscription: {
    newMessage: {
      resolve: (message) => {
        return message.entry;
      },
      subscribe: () => pubsub.asyncIterator('newMessage'),
    },
  },
};

const app = express();

const PORT = 4000;

const server = new ApolloServer({
  typeDefs,
  resolvers,
  subscriptions: {
    onConnect: () => console.log('Connected to websocket'),
  }
});

server.applyMiddleware({ app })

const httpServer = http.createServer(app);
server.installSubscriptionHandlers(httpServer);

httpServer.listen(PORT, () => {
  console.log(`🚀 Server ready at http://localhost:${PORT}${server.graphqlPath}`)
  console.log(`🚀 Subscriptions ready at ws://localhost:${PORT}${server.subscriptionsPath}`)
})

The other endpoints work fine but it is unable to create the WebSocket. As far as I understand it I shouldn’t have to use a different server or port (see https://www.ably.io/concepts/websockets). I’ve tinkered with SubsciptionServer but this should be handled by installSubscriptionHandlers (here’s the code).

Advertisement

Answer

The it turns out that Firefox has issues with websockets (see this bug report that has been re-appeared even after the supposed fix).

In Firefox it works directly after starting a novel browser but after some hot reloading it stops working. The following helps out with starting out fresh but not with the reloading issue:

const wsLink = new WebSocketLink({
  uri: SUBSCRIPTION_URI,
  options: {
    reconnect: true,
    timeout: 20000,
    lazy: true,
  },
});

window.addEventListener('beforeunload', () => {
  // @ts-ignore - the function is private in typescript
  wsLink.subscriptionClient.close();
});

I think the bug is related to this SO-question: “websocket was interrupted while page is loading” on Firefox for Socket.io

If you want to test different solutions I’ve created an example repo: https://github.com/gforge/subscription_example that works both by itself and with a Docker container.

User contributions licensed under: CC BY-SA
7 People found this is helpful
Advertisement