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

Apollo联邦网关无法获取req对象转发请求头求助

Apollo Gateway 请求头转发问题

依赖版本

  • @apollo/gateway: ^2.1.3
  • @apollo/server: ^4.0.0
  • graphql: ^16.6.0

问题描述

无法获取req对象以提取请求头并转发给子图。buildService代码可向下游服务添加请求头,但ApolloServer的context始终为空。尝试了同步/异步方式、用request替代req,甚至直接尝试获取context.req.headers,但均为null。需要实现请求头(如Authorization)的转发。

代码示例

const gateway = new ApolloGateway({
  supergraphSdl: new IntrospectAndCompose({
    subgraphs: [
      { name: "persons", url: process.env.PERSON_SERVER_URL },
    ],
  }),
  buildService({ url }) {
    return new RemoteGraphQLDataSource({
      url,
      willSendRequest: ({ request, context }) => {
        console.log(JSON.stringify(context));
        // TRYING TO INJECT AUTH HEADERS HERE
      }
    });
  }
});

const app = express();
const httpServer = http.createServer(app);

const server = new ApolloServer({
  gateway,
  context: ({ req }) => {
    console.log(JSON.stringify(req));
    // req IS NULL
  },
  plugins: [
    ApolloServerPluginLandingPageDisabled(),
    ApolloServerPluginDrainHttpServer({ httpServer })
  ]
});
await server.start();

const graphqlRoute = "/graphql";
app.use(
  graphqlRoute,
  bodyParser.json(),
  expressMiddleware(server),
);

await new Promise((resolve) => httpServer.listen(process.env.PORT, "0.0.0.0", resolve));
console.log(`🚀 Server ready at ${JSON.stringify(httpServer.address())}`);

补充说明:我也在Apollo社区提问过,认为联邦模式下应该有简单的配置项来转发Authorization头。


解决方案

核心原因

Apollo Server 4中,expressMiddleware是请求处理的入口,原ApolloServer配置里的context无法直接获取到req对象,必须在expressMiddleware的配置中传递上下文信息。

具体修正步骤

  1. 调整上下文传递逻辑
    删除ApolloServer配置里的context,转而在expressMiddleware中注入需要的请求信息:

    const graphqlRoute = "/graphql";
    app.use(
      graphqlRoute,
      bodyParser.json(),
      expressMiddleware(server, {
        // 将需要的请求头传入上下文
        context: async ({ req }) => ({
          authHeader: req.headers.authorization,
          // 也可以传入完整headers对象:headers: req.headers
        })
      }),
    );
    
  2. 在willSendRequest中转发请求头
    修改buildService中的逻辑,从上下文取出目标头并添加到子图请求中:

    buildService({ url }) {
      return new RemoteGraphQLDataSource({
        url,
        willSendRequest: ({ request, context }) => {
          // 转发Authorization头
          if (context.authHeader) {
            request.http.headers.set('Authorization', context.authHeader);
          }
          // 若传入完整headers,可按需转发其他业务头
          // if (context.headers['x-user-id']) {
          //   request.http.headers.set('X-User-ID', context.headers['x-user-id']);
          // }
        }
      });
    }
    
  3. 简化全量转发(按需使用)
    如果需要批量转发业务相关请求头,可直接传入整个req对象到上下文,再过滤设置:

    // expressMiddleware配置
    expressMiddleware(server, {
      context: ({ req }) => ({ req })
    })
    
    // willSendRequest逻辑
    willSendRequest: ({ request, context }) => {
      // 定义允许转发的头列表,避免传递host、content-length等无关头
      const allowedHeaders = ['authorization', 'x-user-id', 'x-request-id'];
      allowedHeaders.forEach(header => {
        const value = context.req.headers[header];
        if (value) {
          request.http.headers.set(header, value);
        }
      });
    }
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 17:30:51