Apollo 和 Hasura - 订阅缺少身份验证标头

问题描述 投票:0回答:2

我有一个 React 应用程序,我正在尝试使用 Hasura 实现订阅,但遇到了一些困难。我的查询正常工作,但在尝试执行订阅时出现以下错误:

“无法启动,因为 connection_init 失败:Miss…g JWT 身份验证模式下的授权标头”

当我将令牌记录到控制台时,它会按预期显示。我尝试过不拆分链接,但得到了相同的结果。

  /* Graphql Start */
  const {
    isLoading,
    error,
    getAccessTokenSilently
  } = useAuth0();

  /* HTTP Link Start */
  const authLink = setContext(async () => {
    const token = await getAccessTokenSilently();
    return {
      headers: {
        Authorization: `Bearer ${token}`
      }
    };
  });

  const httpLink = createHttpLink({
    uri: 'https://####.hasura.app/v1/graphql', 
  });

  const newHttpLink = authLink.concat(httpLink);
  /* HTTP Link End */

  /* Websocket Start */
  const wsAuthLink = setContext(async () => {
    const token = await getAccessTokenSilently();
    return {
      options: {
        reconnect: true,
        timeout: 30000,
        connectionParams: {
          headers: {
            Authorization: `Bearer ${token}`
          } 
        }
      }
    };
  });

  const wsLink = new WebSocketLink({
    uri: 'wss://####.hasura.app/v1/graphql',
  });

  const newWSLink = wsAuthLink.concat(wsLink);
  /* Websocket End */

  const splitLink = split(
    ({ query }) => {
      const definition = getMainDefinition(query);
      return (
        definition.kind === 'OperationDefinition' &&
        definition.operation === 'subscription'
      );
    },
    newWSLink,
    newHttpLink,
  );

  const client = new ApolloClient({
    link: splitLink,
    cache: new InMemoryCache(),
    connectToDevTools: true
  });
  /* Graphql End */
reactjs apollo subscription hasura
2个回答
0
投票

我假设这段代码位于组件内部,因为你有一个钩子:

  const {
    isLoading,
    error,
    getAccessTokenSilently
  } = useAuth0();

当组件首次呈现时,isLoading 可能为 true,并且 getAccessTokenSilently() 将解析为 false。

我认为您可能需要从该组件返回 null,直到 isLoading 为 false,并且只有在 getAccessTokenSilently() 返回某些内容后,您才需要设置链接。

您可以通过将 apollo 的设置(从 createHttpLink 到实例化 ApolloClient 的所有内容)包装在一个

中来完成此操作
const [client, setClient] = useState<ApolloClient|null>(null)
useEffect(()=>{

  if (isLoading) return;

  ...all your setup code...
  ...replace client=new ApolloClient(...) with:
  setClient(new ApolloClient({
    link: splitLink,
    cache: new InMemoryCache(),
    connectToDevTools: true
  });)
 },[isLoading])

return client;// This returns null until isLoading is false, then returns the client.

我只是手写的,所以如果语法不正确,请道歉,但它应该说明这一点。


-1
投票

在您的 wsLink 中进行以下修复:

const wsLink = new WebSocketLink({
  uri: "wss://####",
  options: {
    connectionParams: {
      headers: {
        Authorization: `Bearer ${token}`,
        "content-type": "application/json",
        "x-hasura-admin-secret": ####,
        "x-hasura-role": "###",
      },
    },
    reconnect: true,
  },
});
最新问题
© www.soinside.com 2019 - 2025. All rights reserved.