首页 > 解决方案 > 通过 GraphQL 应用从 REST api 调用返回的 cookie

问题描述

在实现 auth GraphQL 模块时,解析器通过 RESTDataSource 调用外部 API。

async logout() {
 return await this.post('/logout', { credentials: 'include' })
}

这将返回一个空的主体对象(预期)和包含的标头* Set-Cookie: access_token=; Path=/; Expires=Thu, 01 Jan 1970 00:00:00 GMT

预期的结果是access_tokencookie 从浏览器中删除。如果这是直接使用 fetch 调用的,那么它会发生,但在通过 GraphQL 完成时不会发生。

这是设置:

# Resolver
Mutation: {
    logout: async (_parent, _args, context) => {
      const api = context.injector.get(UserAPI);
      const response = await api.logout();
      return response;
    },
  },

和服务器...

# Apollo Server
function apolloGraphqlServer(app: Express) {
  const server = new ApolloServer({
    schema,
    context: ({ req }): { token: string } => {
      return {
        token: req.headers.authorization,
      };
    },
    introspection: true,
  });

  server.applyMiddleware({ app });
}

和客户(在 Express 上)

const apolloClient = new ApolloClient({
      cache: new InMemoryCache(),
      link: new SchemaLink({
        schema,
        context: {
          session: req,
          token: authCookie ? `Bearer ${authCookie}` : null,
        },
      }),
      credentials: 'include',
      ssrMode: true,
    });

给定响应,我如何让 cookie 删除

标签: graphqlapollo-clientapollo-serverexpress-graphql

解决方案


通过将响应传递到上下文中解决了这个问题......

const server = new ApolloServer({
    schema,
    context: ({ req, res }): { token: string; res: Response } => {
      return {
        token: req.headers.authorization,
        res,
      };
    },
  });

然后在数据源中,拦截接收到的响应并设置标头(如果可用)。

# datasource

didReceiveResponse(response: Response, request: Request) {
    if (response.headers.get('set-cookie')) {
      this.context.res.set('set-cookie', response.headers.get('set-cookie'));
    }

    return super.didReceiveResponse(response, request);
  }

不确定这是否是最优雅的解决方案,但现在可以使用


推荐阅读