Apollo GraphQL客户端报错时如何获取请求头并添加客户端requestId?
解决方案:客户端生成Request ID并关联到错误对象
要在Apollo Client请求出错时获取客户端生成的Request ID,你需要通过请求链路注入ID + 错误链路重新包装错误的方式实现——直接修改原错误对象的extensions字段是只读的,无法直接修改。
步骤1:生成并注入Request ID到请求
通过自定义请求链路,在每个请求发送前生成客户端唯一Request ID,同时添加到请求头和请求上下文:
import { ApolloLink } from '@apollo/client'; // 生成唯一Request ID(可根据需求替换生成规则,比如自定义字符串生成逻辑) const generateRequestId = () => crypto.randomUUID(); const requestLink = new ApolloLink((operation, forward) => { const requestId = generateRequestId(); // 将Request ID添加到请求头 operation.setContext(({ headers }) => ({ headers: { ...headers, 'X-Client-Request-ID': requestId, }, })); // 将Request ID存入请求上下文,供后续错误链路调用 operation.context.requestId = requestId; return forward(operation); });
步骤2:在错误链路中包装错误,附加Request ID
由于原错误对象被冻结为只读状态,我们需要创建新的错误对象并注入Request ID,再重新抛出:
import { onError } from '@apollo/client/link/error'; import { Observable } from '@apollo/client/utilities'; const errorLink = onError(({ graphQLErrors, operation }) => { const requestId = operation.context.requestId; if (graphQLErrors) { // 复制原错误并添加Request ID到extensions字段 const modifiedGraphQLErrors = graphQLErrors.map(error => ({ ...error, extensions: { ...error.extensions, clientRequestId: requestId, }, })); // 返回新的Observable,抛出修改后的错误对象 return new Observable(observer => { observer.error({ graphQLErrors: modifiedGraphQLErrors, operation, }); }); } });
步骤3:组合链路并初始化Apollo Client
将自定义链路与HTTP链路组合,确保请求链路先执行,再处理错误:
import { ApolloClient, InMemoryCache, createHttpLink, from } from '@apollo/client'; const httpLink = createHttpLink({ uri: '/your-graphql-endpoint' }); const client = new ApolloClient({ link: from([requestLink, errorLink, httpLink]), cache: new InMemoryCache(), });
在组件中获取Request ID
现在在useQuery的错误处理逻辑中,就能直接拿到客户端生成的Request ID:
const { data, error } = useQuery(gql`Query ...`); if (error) { const clientRequestId = error.graphQLErrors[0].extensions.clientRequestId; // 可用于日志上报、问题定位等场景 console.log('请求失败,客户端Request ID:', clientRequestId); }
补充说明
- 如果只是需要获取请求头中的值(而非客户端生成),可以在请求链路中把请求头存入上下文,再在错误链路中取出使用。
- 不要尝试直接修改原错误对象的属性,Apollo Client会冻结错误对象以避免意外修改。
内容的提问来源于stack exchange,提问作者Alex Vasilev
相关产品推荐
相关产品推荐

