javascript - Next js 和 Apollo - Cookie 未被传递

标签 javascript reactjs graphql apollo next.js

我将 Next JS 与 Apollo 一起使用,并在我的数据 HOC 中使用以下配置对其进行了设置:

import { ApolloClient } from 'apollo-client';
import { InMemoryCache } from 'apollo-cache-inmemory';
import { HttpLink } from 'apollo-link-http';
import { onError } from 'apollo-link-error';
import { withClientState } from 'apollo-link-state';
import { getMainDefinition } from 'apollo-utilities';
import { ApolloLink, Observable, split  } from 'apollo-link';
import { WebSocketLink } from 'apollo-link-ws';
import withApollo from 'next-with-apollo';
import { SubscriptionClient } from 'subscriptions-transport-ws';

import { endpoint, prodEndpoint, WSendpoint, WSprodEndpoint } from '../config';

import defaults from '../apollo-state/graphql/default-state';
import Mutation from '../apollo-state/resolvers/mutation-resolvers';

const wsClient = process.browser ? new SubscriptionClient(process.env.NODE_ENV === 'development' ? WSendpoint : WSprodEndpoint, {
  reconnect: true,
}) : null;


function createClient({ headers }) {
  const wsLink = process.browser ? new WebSocketLink(wsClient) : null;
  const httpLink = new HttpLink({
    uri: process.env.NODE_ENV === 'development' ? endpoint : prodEndpoint,
    credentials: 'include',
  })

  const link = process.browser ? split(
    // split based on operation type
    ({ query }) => {
      const { kind, operation } = getMainDefinition(query);
      return kind === 'OperationDefinition' && operation === 'subscription';
    },
    wsLink,
    httpLink,
  ) : httpLink;

  const cache = new InMemoryCache();

  const request = async operation => {
    const contextObj = {
      fetchOptions: {
        credentials: 'include'
      },
      headers
    };
    operation.setContext(contextObj);
  }; 

  const requestLink = new ApolloLink((operation, forward) =>
    new Observable(observer => {
      let handle;
      Promise.resolve(operation)
        .then(oper => request(oper))
        .then(() => {
          handle = forward(operation).subscribe({
            next: observer.next.bind(observer),
            error: observer.error.bind(observer),
            complete: observer.complete.bind(observer),
          });
        })
        .catch(observer.error.bind(observer));

      return () => {
        if (handle) handle.unsubscribe();
      };
    })
  );
  // end custom config functions
  const apolloClient = new ApolloClient({
      credentials: 'include',
      ssrMode: !process.browser,
      link: ApolloLink.from([
        onError(({ graphQLErrors, networkError }) => {
          if (graphQLErrors) {
            console.log(graphQLErrors)
          }
          if (networkError) {
            console.log(networkError)
          }
        }),
        requestLink,
        withClientState({
          defaults, // default state
          resolvers: {
            Mutation // mutations
          },
          cache
        }),
        link
      ]),
      cache
  }); // end new apollo client
  return apolloClient;
}

export { wsClient };
export default withApollo(createClient);

本地一切正常。我可以登录,当我访问该站点时它会自动登录,SSR 没有问题。但是,当我部署到 Next 或 Heroku 时,SSR 不起作用。

我已经调查了这个问题,这似乎是一个常见的问题,即 cookie 没有随请求一起发送:

https://github.com/apollographql/apollo-client/issues/4455

https://github.com/apollographql/apollo-client/issues/4190

https://github.com/apollographql/apollo-client/issues/4193

问题似乎出在 Apollo 配置的这一部分,其中有时未定义 header ,因此未发送 cookie:

  const request = async operation => {
    const contextObj = {
      fetchOptions: {
        credentials: 'include'
      },
      headers
    };
    operation.setContext(contextObj);
  }; 

人们提到的一些解决方法是手动设置 cookie header (如果 header 存在):

  const request = async operation => {
    const contextObj = {
      fetchOptions: {
        credentials: 'include'
      },
      headers: {
        cookie: headers && headers.cookie
      }
    };
    operation.setContext(contextObj);
  }; 

上面对代码的修改修复了服务器端呈现,但是当我在浏览器中使用登录 cookie 访问该站点时,它将不再自动登录(它使用我的初始方法自动登录但不会这样做生产中的 SSR)

人们已经提到,这可能与 Now 或 Heroku 在部署应用程序后获得的生成的 URL 中使用子域有关,并使用自定义域来解决问题。我尝试使用自定义域,但问题仍然存在。我的域设置是这样的:

前端域:mysite.com 后台域名:api.mysite.com

这里有没有人遇到过这个问题并能够解决它?

如果您发现我的配置或我的域设置有问题,请告诉我。

最佳答案

晚了但试试这个

您应该如下添加 cookies 选项。请确保您的浏览器中有 cookie,即 csrftoken。它应该可用。希望它有效。


  const request = async operation => {
    const contextObj = {
      fetchOptions: {
        credentials: 'include'
      },
      //################ CHANGE HERE ##########
      headers: {
        ...header
      }
      cookies: {
        ...cookies
      }
      //######################################

    };
    operation.setContext(contextObj);
  };

关于javascript - Next js 和 Apollo - Cookie 未被传递,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56263624/

相关文章:

javascript - Sigma.js学习与实例

javascript - Amchart 子弹轮在股票图表中不起作用

javascript - 如何制作一个简单的 jQuery 按钮来切换元素的背景

javascript - REACT 中的 404 页面

javascript - 如何在 HTML 标签中使用 REACTJS 和 Context

graphql - 如何将嵌套变量传递给 Apollo 中的 GraphQL 查询?

go - 如何动态构建查询过滤器

javascript - Angular 2 : Form submission canceled because the form is not connected

javascript - 使用输入值提交表单后 React Router 重定向

angular - apollo.watchQuery 结果为 'ERROR TypeError: Object(...) is not a function'