为Apollo GraphQL客户端添加请求头引发Window.fetch执行失败错误的问题求助
先看你代码里最直接的错误:你把链接组合后的结果放到了uri字段,但uri应该是字符串地址,正确的做法是把组合后的link放到link属性里,这会导致请求处理逻辑完全混乱,大概率是引发fetch错误的核心原因。
第一步:修复Apollo Client的核心配置错误
你的代码里:
const apolloClient = new ApolloClient({ //@ts-ignore uri: authLink.concat(link), cache: new InMemoryCache({...}) });
这是错误的,uri字段接收的是GraphQL服务器的字符串地址,而组合后的authLink.concat(link)应该赋值给link属性。修改后的代码应该是:
const apolloClient = new ApolloClient({ link: authLink.concat(link), // 这里用link字段而非uri cache: new InMemoryCache({ typePolicies: { Query: { fields: { token: { read() { return tokenVar(); }, }, userData: { read() { return userDataVar(); }, }, } } } }) });
注意:如果你的HttpLink已经设置了uri,这里就不需要再单独写uri字段了,link会自动处理请求地址。
第二步:修正Authorization头的生成逻辑
从你的cache配置能看出来tokenVar是Apollo的响应式变量(Reactive Variable),这类变量是函数,需要调用tokenVar()才能拿到实际值——你当前直接用tokenVar会导致Authorization头变成Bearer [object Function],这会触发请求异常。
修改后的authLink代码:
const authLink = setContext((_, { headers }) => { const token = tokenVar(); // 调用函数获取token的实际值 return { headers: { ...headers, // 没有token时设为undefined,避免发送无效空头触发不必要的预检请求 authorization: token ? `Bearer ${token}` : undefined, }, }; });
为什么用undefined而非空字符串?因为空字符串的authorization: ''会被浏览器识别为自定义头,触发OPTIONS预检请求;而不发送该头则能减少CORS相关的潜在问题。
第三步:确保后端CORS配置正确处理预检请求
当请求带有自定义头(比如Authorization)时,浏览器会先发送OPTIONS预检请求,后端必须正确响应这个请求。你的现有配置只设置了origin和credentials,还需要补充:
- 允许的自定义头:
allowedHeaders: ['Authorization', 'Content-Type'] - 允许的HTTP方法:
methods: ['GET', 'POST', 'OPTIONS'] - 可选:预检请求的缓存时间
maxAge: 86400(减少重复预检请求)
以Express的cors中间件为例,正确配置应该是:
app.use(cors({ origin: 'http://localhost:3000', credentials: true, allowedHeaders: ['Authorization', 'Content-Type'], methods: ['GET', 'POST', 'OPTIONS'], }));
另外要确认后端能正确处理OPTIONS请求,返回200状态码——部分框架可能需要单独编写OPTIONS请求的处理逻辑。
第四步:验证请求状态
修复以上问题后,重启前后端,打开浏览器开发者工具的Network标签:
- 查看GraphQL请求的Request Headers,确认
Authorization: Bearer xxx是否正确存在 - 如果有OPTIONS请求,检查响应状态码是否为200,响应头是否包含
Access-Control-Allow-Origin、Access-Control-Allow-Headers等正确字段
如果仍有问题,查看Console标签的详细错误信息,排查是否是token格式错误或后端返回了其他业务错误。
内容的提问来源于stack exchange,提问作者Sad Hope

