web-dev-qa-db-ja.com

ApolloServerを使用してサブスクリプションが接続されていません

サブスクリプションを取得してApolloServer(v 2.2.2)を使用しようとしています。突然、すべてが機能しなくなったという設定がありました。 graphiql/Playgroundのサブスクリプションに接続しようとすると、次のエラーが発生します。

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

アプリにレストエンドポイントがあるので、エクスプレスが必要ですが、以下の実行から最小限の例を取得できません。

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}`)
})

他のエンドポイントは正常に機能しますが、WebSocketを作成できません。私が理解している限り、別のサーバーやポートを使用する必要はありません( https://www.ably.io/concepts/websockets を参照)。 SubsciptionServerをいじくり回しましたが、これはinstallSubscriptionHandlersで処理する必要があります( コードはこちら )。

6
Max Gordon

FirefoxにWebSocketに問題があることが判明しました(想定される修正後も再表示された このバグレポート を参照)。

Firefoxでは、新しいブラウザを起動した直後に機能しますが、ホットリロード後に機能しなくなります。以下は、最初からやり直すのに役立ちますが、リロードの問題には役立ちません。

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();
});

バグはこのSOに関連していると思います-質問: Socket.ioのFirefoxで「ページの読み込み中にwebsocketが中断されました」

さまざまなソリューションをテストしたい場合は、リポジトリの例を作成しました: https://github.com/gforge/subscription_example それ自体とDockerコンテナの両方で機能します。

0
Max Gordon