与 Hasura 的 WebSocket 连接不适用于 Node.js 上的 ApolloClient v3

Posted

技术标签:

【中文标题】与 Hasura 的 WebSocket 连接不适用于 Node.js 上的 ApolloClient v3【英文标题】:WebSocket connection to Hasura does not work with ApolloClient v3 on Node.js 【发布时间】:2021-06-26 09:44:08 【问题描述】:

我创建了一个 Express/Node 服务,它使用 ApolloClient v3 订阅 Hasura 上的数据库(数据库是在 Hasura 平台上使用 Heroku 创建的)。我想通过 ApolloClient 订阅数据库更改。

我的 ApolloClient 设置如下所示(灵感来自 Split Communication Docs):

import express,  Request, Response  from "express";
import "cross-fetch/polyfill";
import ws from "ws";

import 
  ApolloClient,
  HttpLink,
  InMemoryCache,
  split,
  gql,
 from "@apollo/client/core";
import  WebSocketLink  from "@apollo/client/link/ws";
import  getMainDefinition  from "@apollo/client/utilities";

const app = express();
const port = 8080;

const httpLink = new HttpLink(
  uri: "https://my.hasura.app/v1/graphql",
  fetch,
);

const wsLink = new WebSocketLink(
  uri: "ws://my.hasura.app/v1/graphql",
  options: 
    reconnect: true,
  ,
  webSocketImpl: ws,
);

const splitLink = split(
  ( query ) => 
    const definition = getMainDefinition(query);
    return (
      definition.kind === "OperationDefinition" &&
      definition.operation === "subscription"
    );
  ,
  wsLink,
  httpLink
);

const client = new ApolloClient(
  link: splitLink,
  cache: new InMemoryCache(),
);

我已经发现将 ApolloClient 与 Node.js 结合使用:

使用 "@apollo/client/core" 导入而不是 "@apollo/client",因为这需要一个 react 依赖项(我不希望在我的后端服务上使用它) import ws from "ws"; 用于节点的 Web 套接字实现,因为这是一个浏览器功能 import "cross-fetch/polyfill"; 具有获取功能,供 ApolloClient 使用

现在应用程序运行没有错误,但我不知道为什么我的订阅不起作用。我在前端有相同的代码(有点不同,因为它是 React)并且在那里运行良好。

这是我的订阅逻辑:

const observable = client.subscribe(
  query: gql`
    subscription 
      payments() 
        amount
        id
        time
        userId
      
    
  `,
);

observable.subscribe((data: any) => 
  console.log("data", data);
);

我期待我的console.log 在数据库更改时记录一些数据 - 但它没有,并且我的 Hasura Dashboard 没有列出新的连接。 如何建立到我的数据库的 websocket 连接?

【问题讨论】:

【参考方案1】:

我发现,Node.js 客户端上的 WebSocket uri 必须以 http/https 而不是 ws/wws 开头。

有了这段代码,它现在可以工作了:

const wsLink = new WebSocketLink(
  uri: "https://my.hasura.app/v1/graphql",  // instead of "ws://my.hasura.app/v1/graphql"
  options: 
    reconnect: true,
  ,
  webSocketImpl: ws,
);

【讨论】:

以上是关于与 Hasura 的 WebSocket 连接不适用于 Node.js 上的 ApolloClient v3的主要内容,如果未能解决你的问题,请参考以下文章

SSL WebSocket 连接不适用于 webkit 浏览器?

WebSocket SocketIO 连接不适用于 Heroku 上的 NestJS 服务器并在 Vercel 上反应客户端

WebSocket 不适用于 https 请求,并且它与使用 PHP 棘轮库的 http 一起正常工作

PHP websocket不适用于safari,标头修改

Apollo 联合网关背后的 Hasura GraphQL 端点

SwiftyJSON 不适用于 WebSocket 消息