Javascript 下一个js和Apollo-Cookie未被传递
我正在Apollo上使用Next JS,并在我的with data HOC中使用以下配置进行了设置:Javascript 下一个js和Apollo-Cookie未被传递,javascript,reactjs,graphql,apollo,next.js,Javascript,Reactjs,Graphql,Apollo,Next.js,我正在Apollo上使用Next JS,并在我的with data 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 {
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不起作用
我已经调查了这个问题,似乎这是cookies未随请求一起发送的常见问题:
Apollo配置的这一部分似乎存在问题,其中有时未定义标头,因此未发送cookie:
const request = async operation => {
const contextObj = {
fetchOptions: {
credentials: 'include'
},
headers
};
operation.setContext(contextObj);
};
人们提到的一些解决方法是,如果存在cookie头,则手动设置cookie头:
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);
};
常量请求=异步操作=>{
const contextObj={
获取选项:{
凭据:“包括”
},
//################在这里换车##########
标题:{
…标题
}
曲奇饼:{
…饼干
}
//######################################
};
operation.setContext(contextObj);
};
这名官员有问题或缺乏能力 这是本报报道的 我将把那些让我能够解决这个问题的评论拼凑在一起 这里是对官方示例的一个修改,由发布,源于发布示例的前一个版本
从“apollo客户端”导入{apollo客户端};
从'apollo cache inmemory'导入{InMemoryCache};
从“阿波罗链接http”导入{HttpLink};
从“同构取消蚀刻”导入提取;
从“../config”导入{endpoint};
导出默认函数createApollopClient(initialState,ctx){
//“ctx”(NextPageContext)将仅出现在服务器上。
//使用它来提取身份验证头(ctx.req)或类似文件。
const enchancedFetch=(url,init)=>
获取(url{
…初始化,
标题:{
…init.headers,
Cookie:ctx.req.headers.Cookie,
},
}).然后(响应=>响应);
返回新客户端({
ssrMode:布尔值(ctx),
链接:新的HttpLink({
uri:endpoint,//服务器URL(必须是绝对的)
凭据:'相同来源',//附加的fetch()选项,如'credentials'或'headers'`
fetch:ctx?enchancedFetch:fetch,
}),
缓存:新建InMemoryCache().restore(初始状态),
});
}
为了让它工作,我还更改了后端的CORS选项
//graphql瑜伽+prisma 1后端(Wes Boss的高级反应课程)
...
const cors=要求(“cors”);
const server=createServer();
var公司={
来源:process.env.FRONTEND_URL,
凭据:正确
};
server.express.use(cors(corsOptions));
...
我还更新了依赖项,直到达到“无纱线警告”状态
"dependencies": {
"@apollo/react-hooks": "^3.1.5",
"@apollo/react-ssr": "^3.1.5",
"@babel/core": "^7.1.2",
"@types/react": "^16.8.0",
"apollo-cache-inmemory": "^1.6.6",
"apollo-client": "^2.6.9",
"apollo-link-http": "^1.5.17",
"apollo-utilities": "^1.3.2",
"graphql": "14.3.1",
"graphql-tag": "^2.10.3",
"isomorphic-unfetch": "^3.0.0",
"next": "latest",
"prop-types": "^15.6.2",
"react": "^16.13.1",
"react-dom": "^16.13.1"
},
"devDependencies": {
"babel-plugin-graphql-tag": "^2.5.0"
}
如果你有任何其他的解决方案,请与我们分享,它真的是注释。如果你没有其他解决方案,@Ngatia Frankline提出的解决方案对我来说真的很有效。我最终在下一个JS服务器上设置了cookie。以下是我为此方法复制的存储库: