WebSocket 连接到 'ws://localhost:4444/subscriptions' 失败:WebSocket 在连接建立之前关闭

Posted

技术标签:

【中文标题】WebSocket 连接到 \'ws://localhost:4444/subscriptions\' 失败:WebSocket 在连接建立之前关闭【英文标题】:WebSocket connection to 'ws://localhost:4444/subscriptions' failed: WebSocket is closed before the connection is establishedWebSocket 连接到 'ws://localhost:4444/subscriptions' 失败:WebSocket 在连接建立之前关闭 【发布时间】:2020-04-07 17:33:02 【问题描述】:

操作系统:Windows 10 专业版 快递:4.17.1 阿波罗服务器快递:2.9.13 阿波罗客户端:2.6.4 阿波罗链接上下文:1.0.18 阿波罗链接-http:1.5.15 阿波罗-链接-ws:1.0.18

所以,我正在从 graphql-yoga 迁移到 apollo-server 2 并且遇到 ws 连接问题(见图)。我忽略了什么?

我的代码如下:

withData.js

const endpoint = `http://localhost:4444/graphql`;
const endpointWS = `ws://localhost:4444/subscriptions`;

  const httpLink = createHttpLink(
    uri: process.env.NODE_ENV === 'development' ? endpoint : prodEndpoint,
    credentials: 'include',
  );

  const wsLink = process.browser ? new WebSocketLink(
    uri: process.env.NODE_ENV === 'development' ? endpointWS : prodEndpointWS,
    options: 
      reconnect: true,
      timeout: 3000,
    
  ) : null;

  const authLink = setContext(() => 
    return 
      headers: 
        ...headers,
      
    
  );

const link = process.browser ? split(
   ( query ) => 
    const definition = getMainDefinition(query);
    return (
      definition.kind === 'OperationDefinition' &&
      definition.operation === 'subscription'
    );
  ,
  wsLink,
  httpLink,
) : httpLink;

index.js

const PORT = '4444';
const path2 = '/graphql';

const createServer = require('./createServer');
const server = createServer();
const app = express();

app.use(cookieParser());

server.applyMiddleware(
  app, 
  path: path2,
  cors: 
    credentials: true,
    origin: process.env.FRONTEND_URL,
  ,
 );
const httpServer = http.createServer(app);
server.installSubscriptionHandlers(httpServer);

httpServer.listen(PORT, err => 
  if (err) throw err
  console.log(`???? Server ready at http://localhost:$PORT$server.graphqlPath`)
  console.log(`???? Subscriptions ready at ws://localhost:$PORT$server.subscriptionsPath`)
);

createServer.js

const Mutation = require('./resolvers/Mutation');
const Query = require('./resolvers/Query');
const Subscription = require('./resolvers/Subscription');
const db = require('./db');
const typeDefsFile = importSchema(__dirname.concat('/schema.graphql'));
const typeDefs = gql(typeDefsFile);

function createServer() 
    return new ApolloServer(
        typeDefs,
        resolvers: 
            Mutation,
            Query,
            Subscription,
        ,
        cors: 
          credentials: true,
          origin: process.env.FRONTEND_URL,
        ,
        subscriptions: 
          keepAlive: 1000,
          path: '/subscriptions',
        ,
        playground: process.env.NODE_ENV === 'production' ? false : '/',
        tracing: true,
        introspection: true,
        context: req => ( ...req, db ),
    );


module.exports = createServer;

db.js

const  Prisma  = require('prisma-binding');

const db = new Prisma(
    typeDefs: __dirname + "/schema_prep.graphql",
    endpoint: process.env.PRISMA_ENDPOINT,
    secret: process.env.PRISMA_SECRET,
    debug: false,
);

module.exports = db;

订阅.js

const Subscription =    
    item:    
        subscribe: async (parent, args, ctx, info) =>    
            const itemResult = await ctx.db.subscription   
                .item(   
                    where:    
                        mutation_in: ['CREATED', 'UPDATED'],   
                    ,   
                ,   
                info   
            );   
            return itemResult;   
        ,   
    ,   
    itemDeleted:    
        subscribe: (parent, args, ctx, info) =>    
          const selectionSet = ` previousValues  id, userIdentity  `   
          return ctx.db.subscription.item(   
               
              where:    
                mutation_in: ['DELETED'],   
              ,   
            ,   
            selectionSet,   
          );   
        ,   
        resolve: (payload, args, context, info) =>    
          return payload ? payload.item.previousValues : payload   
        ,   
    ,   
;   

module.exports = Subscription;

【问题讨论】:

【参考方案1】:

我通过将查询和突变解析器中上下文的响应和请求属性分别从 ctx.response 和 ctx.request 更改为 ctx.res 和 ctx.req 解决了这个问题。

【讨论】:

以上是关于WebSocket 连接到 'ws://localhost:4444/subscriptions' 失败:WebSocket 在连接建立之前关闭的主要内容,如果未能解决你的问题,请参考以下文章

内容安全策略拒绝连接到 Websocket 错误

actioncable 无法连接到 websocket

WebSocket 连接到自签名服务器

WCF 连接到 Websocket 服务器

在android java中连接到服务器websocket

WebSocket 连接到 'ws://localhost:4444/subscriptions' 失败:WebSocket 在连接建立之前关闭