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

在AWS Lambda+Apollo Server中设置多Set-Cookie头的问题求助

在AWS Lambda + API Gateway V2 + Apollo Server中设置多Set-Cookie头的问题

问题背景

基于AWS Lambda与API Gateway V2(HTTP API),使用@as-integrations/aws-lambda包开发Apollo Server的GraphQL API。用户登录流程中需要设置三个Cookie:idToken、accessToken、refreshToken。

问题现象

Lambda返回响应时,三个Cookie被合并到单个Set-Cookie头中,以逗号分隔。浏览器仅识别第一个Cookie(idToken),忽略其余两个,导致后续请求仅携带idToken,缺失accessToken和refreshToken。测试了fetch、axios、graphql-request等多种客户端库,问题一致,确认问题出在服务端。

响应头示例:

Set-Cookie: idToken=...; Path=/; HttpOnly; Secure; SameSite=None; Max-Age=3600, accessToken=...; Path=/; HttpOnly; Secure; SameSite=None; Max-Age=3600, refreshToken=...; Path=/; HttpOnly; Secure; SameSite; Max-Age=86400

服务端相关代码

Apollo Server Cookie插件代码

const cookiePlugin: ApolloServerPlugin = {
  async requestDidStart() {
    return {
      async willSendResponse(
        requestContext: GraphQLRequestContextWillSendResponse<any>
      ) {
        const { contextValue, response } = requestContext;
        const setCookies = contextValue.setCookies || [];

        if (setCookies.length > 0) {
          response.http.headers.set(
            "Set-Cookie",
            setCookies
              .map((cookie) => {
                const parts = [`${cookie.name}=${cookie.value}`];
                parts.push(`Path=${cookie.options.path}`);
                if (cookie.options.httpOnly) {
                  parts.push("HttpOnly");
                }
                if (cookie.options.secure) {
                  parts.push("Secure");
                }
                parts.push(`SameSite=${cookie.options.sameSite}`);
                parts.push(`Max-Age=${cookie.options.maxAge}`);
                return parts.join("; ");
              })
              .join(", ")
          );
        }
      },
    };
  },
};

认证函数设置Cookie的代码

context.setCookies.push(
  {
    name: "idToken",
    value: IdToken,
    options: {
      ...cookieOptions,
      maxAge: 3600,
    },
  },
  {
    name: "accessToken",
    value: AccessToken,
    options: {
      ...cookieOptions,
      maxAge: 3600,
    },
  },
  {
    name: "refreshToken",
    value: RefreshToken,
    options: {
      ...cookieOptions,
      maxAge: 86400,
    },
  }
);

服务端配置代码

const publicServer = new ApolloServer({
  typeDefs: publicTypeDefs,
  resolvers: publicResolvers,
  csrfPrevention: false,
  plugins: [cookiePlugin],
});

export const graphqlHandler = startServerAndCreateLambdaHandler(
  publicServer,
  handlers.createAPIGatewayProxyEventV2RequestHandler(),
  {
    context: ctx,
    middleware: [
      async (event) => {
        return async (result) => {
          result.headers = {
            ...result.headers,
            "access-control-allow-headers": "content-type, authorization, recaptcha",
            "access-control-allow-methods": "*",
            "access-control-allow-origin": origin,
            "access-control-allow-credentials": "true",
          };
          return result;
        };
      },
    ],
  }
);

已尝试的解决方案

  • 将response.http.headers['Set-Cookie']设置为Cookie字符串数组:Set-Cookie头完全消失
  • 在Lambda响应中使用multiValueHeaders:API Gateway V2(HTTP API)不支持该方式
  • 调整中间件处理头信息:无法实现多个Set-Cookie头单独发送

已知认知

  • HTTP协议中,每个Cookie应单独使用一个Set-Cookie头,合并到单个头会导致浏览器仅接受第一个Cookie
  • AWS API Gateway若处理不当,可能会合并同名的多个头

问题咨询

  1. 如何在AWS Lambda(搭配API Gateway与Apollo Server)的响应中正确设置多个Set-Cookie头,让浏览器能识别所有Cookie?
  2. 是否有办法让AWS API Gateway V2正确发送Lambda返回的多个Set-Cookie头?是否需要调整响应头的设置方式?

补充信息

  • 使用AWS API Gateway V2(HTTP API)
  • 客户端fetch请求包含credentials: 'include'
  • 问题在不同客户端HTTP库中均存在,确认问题出在服务端

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 21:44:52