【问题标题】:How to handle cookies inside apollo-server-lambda如何在 apollo-server-lambda 中处理 cookie
【发布时间】:2019-12-27 18:09:40
【问题描述】:

使用 apollo-server-lambda 在 lambda 无服务器中设置 cookie

我正在从 apollo-server 迁移到无服务器版本。有没有办法可以访问响应对象或其他方式来设置 cookie?

context: ({ event, context }) => ({
   headers: event.headers,
   functionName: context.functionName,
   event,
   context,
 }),

我希望在上下文中能够像在 apollo-server 中一样访问 res 对象。

【问题讨论】:

    标签: lambda graphql serverless apollo-server


    【解决方案1】:

    我找不到使用 apollo-server-lambda 的方法,所以我所做的是结合使用 apollo-server-expressserverless-http。下面的代码使用导入/导出,因为我使用的是打字稿。

    serverless-http 接受各种类似 express 的框架。

    import express from 'express'; // <-- IMPORTANT
    import serverlessHttp from 'serverless-http'; // <-- IMPORTANT
    import { ApolloServer } from 'apollo-server-express'; // <-- IMPORTANT
    import typeDef from './typeDef';
    import resolvers from './resolvers';
    
    export const server = new ApolloServer({
        typeDef,
        resolvers,
        context: async ({ req, res }) => {
            /**
             * you can do anything here like check if req has a session,
             * check if the session is valid, etc...
             */
            return {
                // things that it'll be available to the resolvers
                req,
                res,
            };
        },
    });
    
    const app = express(); // <-- IMPORTANT
    
    server.applyMiddleware({ app }); // <-- IMPORTANT
    
    // IMPORTANT
    // by the way, you can name the handler whatever you want
    export const graphqlHandler = serverlessHttp(app, {
        /** 
         * **** IMPORTANT ****
         * this request() function is important because 
         * it adds the lambda's event and context object 
         * into the express's req object so you can access
         * inside the resolvers or routes if your not using apollo
         */
        request(req, event, context) { 
            req.event = event;
            req.context = context;
        },
    });
    

    现在你可以在解析器中使用 res.cookie()

    import uuidv4 from 'uuid/v4';
    
    export default async (parent, args, context) => {
    // ... function code
    
    const sessionID = uuidv4();
    
    // a example of setting the cookie
    context.res.cookie('session', sessionID, {
            httpOnly: true,
            secure: true,
            path: '/',
            maxAge: 1000 * 60 * 60 * 24 * 7,
        });
    }
    
    

    另一个有用的resource

    【讨论】:

    • 我在尝试使用这种方法使 Express 和 Lambda 这两个服务器与 cookie 一起工作时遇到了很多问题......最好的解决方案是删除 cookie 和会话并使用 JWT
    【解决方案2】:

    您可以使用apollo-server-plugin-http-headers 包。

    在您的解析器中使用就像这样简单:

    context.setCookies.push({
        name: "cookieName",
        value: "cookieContent",
        options: {
            domain: "example.com",
            expires: new Date("2021-01-01T00:00:00"),
            httpOnly: true,
            maxAge: 3600,
            path: "/",
            sameSite: true,
            secure: true
        }
    });
    

    【讨论】:

      【解决方案3】:

      您需要一种在解析器中设置响应标头的方法。

      您可以做的是在解析器中为上下文对象设置一个值。

      const resolver = (parent, args, { context }) => {
        context.addHeaders = [{ key: 'customheader', value: 'headervalue'}]
      }
      
      

      您可以通过创建Apollo Server plugin 来捕获willSendResponse event in the server lifecycle 中的上下文。然后,您可以将 customHeaders 属性中的标头添加到 GraphQLResponse 对象。

      const customHeadersPlugin = {
        requestDidStart(requestContext) {
          return {
            willSendResponse(requestContext) {
              const {
                context: { addHeaders = [] }
              } = requestContext.context
      
              addHeaders.forEach(({ key, value }) => {
                requestContext.response.http.headers.append(key, value)
              })
      
              return requestContext
            }
          }
        }
      }
      

      您需要在 Apollo Server 中加载插件。

      const server = new ApolloServer({
        typeDefs,
        resolvers,
        plugins: [customHeadersPlugin],
        context: ({ context }) => ({
          context
        })
      })
      

      现在您可以修改解析器中的响应标头了。为了能够设置 cookie,您可以使用 cookie 字符串手动设置 Set-Cookie 标头或使用 cookie library


      感谢 Apollo GraphQL 团队的 Trevor Scheer 在我需要自己实现此功能时为我指明了正确的方向。

      【讨论】:

        猜你喜欢
        • 2020-10-21
        • 2020-03-20
        • 2020-12-27
        • 2017-05-24
        • 2022-06-30
        • 2019-06-09
        • 2020-09-03
        • 2018-12-28
        • 2021-04-09
        相关资源
        最近更新 更多