无法连接到 Graphql 订阅?

Posted

技术标签:

【中文标题】无法连接到 Graphql 订阅?【英文标题】:Trouble connecting to Graphql subscriptions? 【发布时间】: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`);
  
  );
);

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

【问题讨论】:

【参考方案1】:

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

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

然后也输入:

server.installSubscriptionHandlers(graphQLWebSocket);

server.applyMiddleware( app );的行之后

更多信息here。

【讨论】:

以上是关于无法连接到 Graphql 订阅?的主要内容,如果未能解决你的问题,请参考以下文章

SQL2008订阅发布,进程无法连接到 Subscriber

Apollo 客户端无法连接到 GraphQL 服务器(http 调用执行失败)

通过 apollo 连接到 graphql-yoga 服务器进行订阅的正确方法是啥?

该进程无法连接到订阅服务器“xxxxxx”

Prisma-docker 无法连接到服务器

Vert.x - 带有 DataInputStreams 的 GraphQL 订阅