You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为所有GraphQL请求的请求头注入Id(示例:Id:1234)

在Apollo GraphQL中全局注入请求头Id的实现方案

刚好之前做过类似的需求,给你整理几个不同场景下的可行方案,都是经过实践验证的:

Web端(React/Vue等基于Apollo Client的项目)

Apollo Client的核心是通过Link机制来拦截并修改请求,这是全局注入请求头最直接的方式。

基础实现(固定或可获取的Id)

先创建一个自定义Link,在每个请求发送前注入Id头:

import { ApolloClient, InMemoryCache, createHttpLink, ApolloLink } from '@apollo/client';

// 1. 创建基础的HTTP链接
const httpLink = createHttpLink({
  uri: '你的GraphQL服务端点URL',
});

// 2. 自定义拦截Link,注入请求头
const idInjectLink = new ApolloLink((operation, forward) => {
  // 这里替换成你实际获取Id的逻辑:比如从localStorage、全局状态或接口返回
  const targetId = '1234'; 

  // 修改请求上下文,添加Id头
  operation.setContext(({ headers = {} }) => ({
    headers: {
      ...headers, // 保留原有请求头
      Id: targetId,
    },
  }));

  // 继续执行请求链
  return forward(operation);
});

// 3. 组合Link并创建Apollo Client
const client = new ApolloClient({
  link: idInjectLink.concat(httpLink), // 先执行自定义Link,再走HTTP请求
  cache: new InMemoryCache(),
});

动态更新Id的场景

如果Id是动态变化的(比如用户登录后才生成),可以用一个全局可修改的变量存储Id,配合更新函数:

// 全局存储当前Id,初始值可设为默认值或空
let currentUserId = '';

// 提供更新Id的方法,比如用户登录后调用
export const updateRequestId = (newId) => {
  currentUserId = newId;
};

// 自定义Link逻辑调整为读取全局变量
const idInjectLink = new ApolloLink((operation, forward) => {
  operation.setContext(({ headers = {} }) => ({
    headers: {
      ...headers,
      Id: currentUserId || '默认兜底Id',
    },
  }));
  return forward(operation);
});

服务端渲染(SSR)场景(比如Next.js)

在SSR环境下,Id可能需要从请求的Cookie或Header中获取,要在服务端初始化Apollo Client时注入:

import { ApolloProvider, ApolloClient, InMemoryCache, createHttpLink } from '@apollo/client';
import { setContext } from '@apollo/client/link/context';

function MyApp({ Component, pageProps, apolloClient }) {
  return (
    <ApolloProvider client={apolloClient}>
      <Component {...pageProps} />
    </ApolloProvider>
  );
}

MyApp.getInitialProps = async ({ ctx }) => {
  // 从服务端请求的Cookie中获取Id(根据你的存储方式调整)
  const serverSideId = ctx.req?.cookies?.userId;

  const httpLink = createHttpLink({
    uri: '你的GraphQL服务端点URL',
  });

  const authLink = setContext((_, { headers }) => ({
    headers: {
      ...headers,
      Id: serverSideId || '默认Id',
    },
  }));

  const apolloClient = new ApolloClient({
    ssrMode: true,
    link: authLink.concat(httpLink),
    cache: new InMemoryCache(),
  });

  return { apolloClient };
};

export default MyApp;

移动端场景

Android(Apollo Android)

通过添加自定义Interceptor来拦截请求并注入头:

import com.apollographql.apollo3.ApolloClient
import com.apollographql.apollo3.interceptor.ApolloInterceptor
import com.apollographql.apollo3.api.ApolloRequest
import com.apollographql.apollo3.api.ApolloResponse
import kotlinx.coroutines.flow.Flow

val apolloClient = ApolloClient.builder()
    .serverUrl("你的GraphQL服务端点URL")
    .addInterceptor(object : ApolloInterceptor {
      override fun intercept(
          request: ApolloRequest<*>,
          chain: ApolloInterceptorChain
      ): Flow<ApolloResponse<*>> {
        // 修改请求,添加Id头(从SharedPreferences或其他存储获取)
        val modifiedRequest = request.newBuilder()
            .addHeader("Id", "1234")
            .build()
        return chain.proceed(modifiedRequest)
      }
    })
    .build()

iOS(Apollo iOS)

通过自定义Interceptor插入到请求链中:

import Apollo

// 1. 创建自定义拦截器
class IdHeaderInterceptor: ApolloInterceptor {
    func interceptAsync<Operation: GraphQLOperation>(
        chain: RequestChain,
        request: HTTPRequest<Operation>,
        response: HTTPResponse<Operation>?,
        completion: @escaping (Result<GraphQLResult<Operation.Data>, Error>) -> Void
    ) {
        // 注入Id头(从UserDefaults或其他存储获取)
        request.addHeader(name: "Id", value: "1234")
        // 继续执行请求链
        chain.proceedAsync(request: request, response: response, completion: completion)
    }
}

// 2. 初始化Apollo Client时添加拦截器
let endpointURL = URL(string: "你的GraphQL服务端点URL")!
let networkTransport = RequestChainNetworkTransport(
    interceptorProvider: DefaultInterceptorProvider(client: ApolloClient()),
    endpointURL: endpointURL
)
// 将自定义拦截器插入到请求链最前面
networkTransport.interceptors.insert(IdHeaderInterceptor(), at: 0)

let apolloClient = ApolloClient(networkTransport: networkTransport)

注意事项

  • 如果Id是敏感信息,避免用localStorage这类易被XSS攻击的存储方式,优先考虑HttpOnly Cookie或安全的状态管理方案。
  • 若某些请求不需要注入Id,可以在自定义Link/Interceptor中添加判断逻辑(比如根据operation.operationName过滤)。
  • 确保后端服务已经配置允许接收Id请求头(避免CORS问题)。

内容的提问来源于stack exchange,提问作者coder94

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:44:54