You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Next.js服务端调用GraphQL如何获取Cookie中的Token

解决Next.js中Apollo Client服务端获取Cookie Token的问题

这个问题我之前也碰到过,核心问题是你当前的token获取逻辑是在模块初始化阶段执行的,这时候服务端还没拿到请求上下文(ctx),而且服务端没有浏览器的document对象,所以js-cookie根本拿不到服务端的Cookie。解决的关键是把token的获取和Apollo Client的初始化逻辑绑定到next-with-apollo提供的ctx参数上——它的回调函数其实是可以接收ctx的!

修改步骤和核心逻辑

  1. 把token获取逻辑移到withApollo的回调函数内:这个回调会接收包含ctxinitialState的对象,服务端渲染时ctx里的req对象包含了请求的Cookie信息。
  2. 区分服务端和客户端的Cookie获取方式
    • 服务端:从ctx.req.headers.cookie解析token(需要用cookie库来解析Cookie字符串)
    • 客户端:继续使用js-cookie获取token
  3. 动态创建Apollo Link:确保每次初始化Apollo Client时,都能根据当前环境拿到正确的token并设置请求头。

修改后的完整代码

import { ApolloClient } from 'apollo-client'
import { InMemoryCache } from 'apollo-cache-inmemory'
import withApollo from 'next-with-apollo'
import { createHttpLink } from 'apollo-link-http'
import fetch from 'isomorphic-unfetch'
import cookie from 'js-cookie'
// 服务端解析Cookie需要用到这个包,记得先安装:npm install cookie
import cookieParser from 'cookie'

const GRAPHQL_URL = 'https://myurl.com'

export default withApollo(({ ctx, initialState }) => {
  // 区分服务端和客户端获取token
  let token
  if (typeof window === 'undefined') {
    // 服务端:从req.headers.cookie解析token
    const serverCookie = ctx.req?.headers?.cookie
    if (serverCookie) {
      const parsedCookies = cookieParser.parse(serverCookie)
      token = parsedCookies.token
    }
  } else {
    // 客户端:用js-cookie获取token
    token = cookie.get('token')
  }

  // 动态创建带token的http link
  const link = createHttpLink({
    fetch,
    uri: GRAPHQL_URL,
    headers: {
      authorization: token ? `Bearer ${token}` : '',
    },
  })

  return new ApolloClient({
    link,
    cache: new InMemoryCache().restore(initialState || {}),
  })
})

关键细节解释

  • 服务端Cookie解析:服务端的Cookie是存在请求头的cookie字段里的字符串,需要用cookie库的parse方法转换成对象才能拿到token。同时要做可选链判断(ctx.req?.headers?.cookie),避免请求头没有Cookie时报错。
  • withApollo的回调参数next-with-apollo的回调函数会接收一个包含ctxinitialState的对象,服务端渲染时ctx就是Next.js的请求上下文,包含reqres等信息。
  • 动态Link创建:把Link的创建放到回调里,确保每次初始化Apollo Client时都能拿到当前请求的token,不管是服务端还是客户端渲染场景。

注意事项

  • 确保安装了cookie包:服务端解析Cookie需要用到它,执行npm install cookieyarn add cookie即可。
  • 验证token存在性:如果token不存在,请求头的authorization会是空字符串,后端需要处理未授权的情况。

内容的提问来源于stack exchange,提问作者Sooraj

火山引擎 最新活动