我有一个 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 */
我假设这段代码位于组件内部,因为你有一个钩子:
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.
我只是手写的,所以如果语法不正确,请道歉,但它应该说明这一点。
在您的 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,
},
});