You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Next.js中authLink、httpLink与GraphQL订阅集成问题求助

解决Apollo Client中authLink与splitLink协同工作的问题

我明白你遇到的困扰了——在Next.js SSR环境下配置Apollo Client时,authLink没法正常生效,还碰到了终止链接的报错。这其实是链路顺序搞反导致的,我来帮你梳理清楚:

问题根源

splitLink属于终止链接(terminating link),它的作用是直接处理请求(要么通过httpLink发送HTTP请求,要么通过wsLink建立WebSocket连接),是整个请求链路的终点。如果你把authLink放在splitLink后面,请求已经被终止链接处理完了,authLink根本没有机会修改请求头,而且还会触发那个“concat终止链接无效”的报错。

正确的逻辑应该是:先让请求经过authLink添加鉴权头,再进入splitLink选择传输方式。另外还要注意,WebSocket连接初始化时也需要携带token,不然订阅请求会鉴权失败。

修改后的完整配置

import {ApolloClient, ApolloLink, createHttpLink, InMemoryCache, split} from "@apollo/client"
import {setContext} from "@apollo/client/link/context"
import { WebSocketLink } from "@apollo/client/link/ws"
import {getMainDefinition} from "@apollo/client/utilities";

const httpLink = createHttpLink({ 
  uri: "http://localhost:4000/graphql", 
})

// 处理WebSocket链接,同时添加鉴权参数
const wsLink = process.browser ? new WebSocketLink({ 
  uri: 'ws://localhost:4000/graphql', 
  options: { 
    reconnect: true,
    // 建立WebSocket连接时携带token
    connectionParams: () => {
      const token = localStorage.getItem('token')
      return {
        authorization: token
      }
    }
  } 
}) : null

// 处理HTTP请求的鉴权头,同时兼容SSR环境(避免localStorage报错)
const authLink = setContext((_, { headers }) => {
  // 仅在浏览器环境下获取token,SSR时跳过
  const token = process.browser ? localStorage.getItem('token') : null
  return { 
    headers: { 
      ...headers, 
      authorization: token ? token : '' 
    } 
  }
})

// 创建splitLink:选择HTTP或WebSocket传输
const splitLink = process.browser ? split(
  ({ query }) => { 
    const definition = getMainDefinition(query)
    return ( 
      definition.kind === 'OperationDefinition' && 
      definition.operation === 'subscription' 
    ) 
  }, 
  wsLink, 
  httpLink
) : httpLink

// 关键:链路顺序是authLink在前,splitLink在后
const client = new ApolloClient({ 
  link: ApolloLink.from([authLink, splitLink]), 
  cache: new InMemoryCache(), 
});

export default client;

关键修改点说明

  1. 链路顺序调整:用ApolloLink.from([authLink, splitLink])让请求先经过authLink处理头信息,再进入splitLink选择传输方式,这样不管是HTTP请求还是WebSocket订阅,都能带上鉴权头。
  2. WebSocket鉴权补充:在wsLink的connectionParams里添加token,因为WebSocket是长连接,初始化时就需要传递鉴权信息,后续的订阅请求会复用这个连接的鉴权。
  3. SSR环境兼容:在获取localStorage时加上process.browser判断,避免Next.js在服务端渲染时因为没有localStorage而抛出错误。

这样配置后,authLink就能正常生效,不管是查询、突变还是订阅请求,都会正确携带你的token了。

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.27 13:42:43