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

如何在Azure Functions的Apollo Server中设置Cookie?当前配置无效

Azure Functions + Apollo Server 设置Cookie无效的解决办法

问题描述

在Azure Functions中使用Apollo Server时,尝试通过Resolver设置Cookie,但操作始终无效且无任何错误抛出,目前缺少针对Apollo Server Azure Functions的相关官方文档。

原代码示例

import { ApolloServer, gql } from "apollo-server-azure-functions";
import { ApolloServerPluginLandingPageLocalDefault } from "apollo-server-core";
import { serialize, parse } from "cookie";

// 定义GraphQL Schema
const typeDefs = gql`
  type Query {
    user: User
  }

  type User {
    id: ID!
    name: String!
    email: String!
  }
`;

// 定义Resolver
const resolvers = {
  Query: {
    user: (parents, args, { request, context }, info) => {
      const cookie = serialize("token", "123", {
        expires: new Date(Date.now() + 900000),
        httpOnly: true,
      });

      context.res.setHeader("Set-Cookie", cookie);

      return {
        id: "1",
        name: "John Doe",
        email: "john@example.com",
      };
    },
  },
};

// 创建Apollo Server实例
// @ts-ignore
const server = new ApolloServer({
  typeDefs,
  resolvers,
  debug: true,
  plugins: [ApolloServerPluginLandingPageLocalDefault({ embed: true })],
  context: (context) => {
    return context;
  },
});

// 创建Azure Functions Handler
export default server.createHandler({
  cors: {
    origin: ["*", "https://studio.apollographql.com"],
    methods: ["GET", "POST", "OPTIONS"],
    allowedHeaders: [
      "access-control-allow-header",
      "access-control-allow-credentials",
      "access-control-allow-origin",
      "content-type",
    ],
  },
});

问题分析与修复方案

导致Cookie无法生效的核心原因包括:

  • CORS配置未启用凭据支持:跨域场景下,浏览器需要明确允许凭据(Cookie)传递,否则会忽略Set-Cookie头
  • Context层级混淆:原代码中context嵌套层级错误,导致操作的res对象并非Azure Functions的响应实例
  • Cookie属性不完整:缺少path等关键属性,可能导致Cookie仅在特定路径生效
  • 响应头设置方式不当:直接使用setHeader可能覆盖其他头,且不符合Azure Functions的响应处理逻辑

修正后的代码

import { ApolloServer, gql } from "apollo-server-azure-functions";
import { ApolloServerPluginLandingPageLocalDefault } from "apollo-server-core";
import { serialize, parse } from "cookie";

const typeDefs = gql`
  type Query {
    user: User
  }

  type User {
    id: ID!
    name: String!
    email: String!
  }
`;

const resolvers = {
  Query: {
    user: (parents, args, { res }, info) => {
      const cookie = serialize("token", "123", {
        expires: new Date(Date.now() + 900000),
        httpOnly: true,
        path: "/", // 确保Cookie在全站生效
        secure: process.env.NODE_ENV === "production", // 生产环境启用HTTPS-only
        sameSite: "lax" // 根据业务场景调整为strict或none
      });

      // 使用appendHeader避免覆盖已有Set-Cookie头
      res.appendHeader("Set-Cookie", cookie);

      return {
        id: "1",
        name: "John Doe",
        email: "john@example.com",
      };
    },
  },
};

const server = new ApolloServer({
  typeDefs,
  resolvers,
  debug: true,
  plugins: [ApolloServerPluginLandingPageLocalDefault({ embed: true })],
  // 直接解构传递req和res,避免层级嵌套错误
  context: ({ req, res }) => ({ req, res }),
});

export default server.createHandler({
  cors: {
    // 当credentials为true时,origin不能用通配符*,需指定具体域名
    origin: ["https://studio.apollographql.com", "你的前端域名"],
    methods: ["GET", "POST", "OPTIONS"],
    allowedHeaders: ["Content-Type"],
    credentials: true, // 关键:允许跨域传递Cookie
  },
});

关键修改说明

  1. CORS配置优化:
    • 移除*作为origin,因为credentials: true不允许通配符,需指定具体域名
    • 添加credentials: true,让浏览器允许携带Cookie进行跨域请求
  2. Context传递简化:直接解构req和res传入上下文,避免嵌套层级错误
  3. Cookie属性完善:添加path: "/"确保全站生效,生产环境启用secure,设置sameSite提升安全性
  4. 响应头设置调整:使用appendHeader代替setHeader,避免覆盖其他可能存在的Set-Cookie头

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 19:20:17