【问题标题】:Trouble connecting to Graphql subscriptions?无法连接到 Graphql 订阅?
【发布时间】:2021-09-11 05:55:46
【问题描述】:

我已关注 Apollo 文档,但似乎仍然在连接订阅时遇到问题。这是我的代码:在前端,我可以看到它正在尝试连接但正在记录: WebSocket 连接到 'ws://localhost:4000/subscriptions' 失败: 我一直在关注这个:https://www.apollographql.com/docs/apollo-server/data/subscriptions/ 但似乎文档有点落后,所以我可能遗漏了一些东西。

客户:

import ReactDOM from 'react-dom';
import './index.css';
import Routes from './routes';
import 'semantic-ui-css/semantic.min.css';
import { setContext } from '@apollo/client/link/context';
import { WebSocketLink } from '@apollo/client/link/ws';
import { getMainDefinition } from '@apollo/client/utilities';

import { 
  ApolloProvider, 
  ApolloClient, 
  HttpLink, 
  InMemoryCache, 
  split, 
} from '@apollo/client';

// Http link
const httpLink = new HttpLink({ uri: 'http://localhost:4000/graphql' });

// Websocket link
const wsLink = new WebSocketLink({
  uri: 'ws://localhost:4000/subscriptions',
  options: {
    reconnect: true
  }
});

// Attach auth headers to requests
const middlewareLink = setContext((_, { headers }) => {
  // get the authentication token from local storage if it exists
  const token = localStorage.getItem('token');
  const refreshToken = localStorage.getItem('refreshToken');

  // return the headers to the context so httpLink can read them
  return {
    headers: {
      ...headers,
      x_token: token ? `${token}` : "",
      x_refresh_token: refreshToken ? `${refreshToken}`: ""
    }
  }
});


// Combine
const httpLinkWithMiddleware = middlewareLink.concat(httpLink);

// Split link - either http or ws depending on graphql 
const splitLink = split(
  ({ query }) => {
    const definition = getMainDefinition(query);
    return (
      definition.kind === 'OperationDefinition' &&
      definition.operation === 'subscription'
    );
  },
  wsLink,
  httpLinkWithMiddleware,
);

// Create client with link
const client = new ApolloClient({
  link: splitLink,
  cache: new InMemoryCache(),
});

// Provide client
const App = (
  <ApolloProvider client={client}>
    <Routes />
  </ApolloProvider>
)

// Render
ReactDOM.render(
  App,
  document.getElementById('root')
);

服务器:

import express from 'express';
import path from 'path';
import { fileLoader, mergeTypes, mergeResolvers } from 'merge-graphql-schemas';
import { ApolloServer } from 'apollo-server-express';
import { refreshTokens } from './auth';
import models from './models';
import cors from 'cors';
import jwt from 'jsonwebtoken';

const SECRET = "";
const SECRET2 = "";

const typeDefs = mergeTypes(fileLoader(path.join(__dirname, './schema')));
const resolvers = mergeResolvers(fileLoader(path.join(__dirname, './resolvers')));

const PORT = 4000;
const app = express();

// Cors
app.use(cors('*'));

// Add tokens
const addUser = async (req, res, next) => {
  const token = req.headers['x_token'];
  if (token) {
    try {
      const { user } = jwt.verify(token, SECRET);
      req.user = user;
    } catch (err) {
      const refreshToken = req.headers['x_refresh_token'];
      const newTokens = await refreshTokens(token, refreshToken, models, SECRET, SECRET2);
      if (newTokens.token && newTokens.refreshToken) {
        res.set('Access-Control-Expose-Headers', 'x_token', 'x_refresh_token');
        res.set('x_token', newTokens.token);
        res.set('x_refresh_token', newTokens.refreshToken);
      }
      req.user = newTokens.user;
    }
  }
  next();
};

app.use(addUser);

// Create server
const server = new ApolloServer({
   typeDefs, 
   resolvers,
   subscriptions: {
     path: '/subscriptions'
   },
   context: ({req, res, connection}) => { 
     const user = req.user;
     return { models, SECRET, SECRET2, user }; 
    },
});

// Apply middleware
server.applyMiddleware({ app });

// Sync and listen
models.sequelize.sync({force: true}).then(x => {
  app.listen({ port: PORT }, () => {
    console.log(`???? Server ready at http://localhost:${PORT}${server.graphqlPath}`);
    console.log(`???? Subscriptions ready at ws://localhost:${PORT}${server.subscriptionsPath}`);
  }
  );
});

任何帮助将不胜感激......

【问题讨论】:

    标签: node.js reactjs express graphql apollo


    【解决方案1】:

    我在服务器中看不到创建 websocket 的声明。比如:

    const WebSocket = require('ws');
    const graphQLWebSocket = new WebSocket.Server({noServer: true});
    

    然后也输入:

    server.installSubscriptionHandlers(graphQLWebSocket);
    

    server.applyMiddleware({ app });的行之后

    更多信息here

    【讨论】:

      猜你喜欢
      • 2022-08-07
      • 2021-01-08
      • 2018-08-24
      • 2019-12-11
      • 1970-01-01
      • 1970-01-01
      • 2020-12-17
      • 2017-12-05
      • 2021-12-19
      相关资源
      最近更新 更多