如何在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 }, });
关键修改说明
- CORS配置优化:
- 移除
*作为origin,因为credentials: true不允许通配符,需指定具体域名 - 添加
credentials: true,让浏览器允许携带Cookie进行跨域请求
- 移除
- Context传递简化:直接解构
req和res传入上下文,避免嵌套层级错误 - Cookie属性完善:添加
path: "/"确保全站生效,生产环境启用secure,设置sameSite提升安全性 - 响应头设置调整:使用
appendHeader代替setHeader,避免覆盖其他可能存在的Set-Cookie头
内容的提问来源于stack exchange,提问作者Sadman Sakib
相关产品推荐
相关产品推荐

