
后端前端Web框架开发工具【免费下载链接】redwoodRedwoodGraphQL项目地址https://gitcode.com/gh_mirrors/re/redwood点击查看免费下载这篇技术指南围绕 RedwoodJS 仓库中的 changeset .changesets/11744.md 展开它记录了一次针对redwoodjs/web中 Apollo Client 订阅链路的修复允许把自定义请求头custom headers传递给sseLink。sseLink是 RedwoodJS 用来承载 GraphQL Subscription以及live实时查询的 SSEServer-Sent Events终止链接。读完本文你将理解 RedwoodJS 中订阅请求头的构造与合并顺序、如何通过graphQLClientConfig注入自定义头以及这次修复背后的源码实现细节。一次修复的背景订阅请求为何缺少自定义头RedwoodJS 的 Web 端 GraphQL 客户端基于 Apollo Client 构建见 packages/web/src/apollo/index.tsx。对于普通的 Query 与 Mutation请求经由createUploadLink构造的uploadLink发送而对于 Subscription 与live实时查询则必须走一条基于 SSE 的终止链接——即SSELink见 packages/web/src/apollo/sseLink.ts 第 91-146 行。在本次修复之前SSELink在构造graphql-sse客户端时只处理认证头Authorization、auth-provider不接受任何自定义请求头。这意味着用户在graphQLClientConfig.httpLinkConfig.headers中配置的自定义头例如用于服务端校验的x-tenant-id、x-client-version之类只会作用于普通 HTTP 请求而在订阅的 SSE 请求中被静默丢弃导致订阅场景下服务端无法识别这些上下文信息。changeset 原文.changesets/11744.mdfix: add custom headers to subscription in apollo client (#11744) Allow passing custom headers tosseLink, which is used by the Apollo client for subscriptions.其核心改动就是为SSELinkOptions增加headers?: Recordstring, string选项并把它与已有头信息合并后透传给graphql-sse的createClient。源码级解读SSELink的头信息构造与合并顺序先看 packages/web/src/apollo/sseLink.ts 第 9-14 行的选项类型定义interface SSELinkOptions extends PartialClientOptions { url: string auth: { authProviderType: string; tokenFn: () Promisenull | string } httpLinkConfig?: HttpOptions headers?: Recordstring, string }构造器第 94-119 行是本次修复的核心位置constructor(options: SSELinkOptions) { super() const { url, auth, headers, httpLinkConfig } options const { credentials, referrer, referrerPolicy, ...customHeaders } httpLinkConfig?.headers || {} this.client createClient({ url, headers: async () { const token await auth.tokenFn() // Only add auth headers when theres a token. token is null when // !isAuthenticated. return { ...(token { Authorization: Bearer ${token} }), ...(token { auth-provider: auth.authProviderType }), ...headers, ...customHeaders, } }, credentials: mapCredentialsHeader(credentials), referrer, referrerPolicy: mapReferrerPolicyHeader(referrerPolicy), }) }这里有三个值得注意的细节认证头仅在存在 token 时注入。tokenFn()返回null表示未认证或使用 cookie/middleware 认证此时不会强行附加Authorization与auth-provider头。httpLinkConfig.headers中的传输相关字段被单独抽出。credentials、referrer、referrerPolicy这三个键会被解构出来分别经mapCredentialsHeader第 16-30 行与mapReferrerPolicyHeader第 32-60 行做白名单校验后作为graphql-sse客户端层级的配置使用——这两个映射函数只接受规范枚举值非法值一律回退为undefined避免传入无效选项。最终请求头的合并顺序是认证头 →headers选项 →httpLinkConfig.headers中的自定义头。这意味着显式配置的自定义头拥有更高优先级同名时可以覆盖默认的认证头。在graphql-sse中headers既可以是一个普通对象也可以是一个返回对象的异步函数packages/web/package.json 第 153 行显示依赖版本为graphql-sse2.5.3这正是为了支持异步获取 token。由于认证 token 是异步获取的这里采用async () ({...})的形式保证每次建立 SSE 连接时都能拿到最新的头信息。订阅链路如何路由到SSELink在 packages/web/src/apollo/index.tsx 第 234-252 行RedwoodJS 使用 Apollo 的split函数把操作分流const uploadOrSSELink typeof SSELink ! undefined ? split( ({ query }) { const definition getMainDefinition(query) return isSubscription(definition) || isLiveQuery(definition) }, new SSELink({ url: uri, auth: { authProviderType, tokenFn: getToken }, httpLinkConfig, headers, }), uploadLink, ) : uploadLinkisSubscription判断操作定义是否为OperationTypeNode.SUBSCRIPTIONsseLink.ts 第 68-73 行isLiveQuery则检查 Query 上是否带有live指令用于 GraphQL Live Query 场景第 77-86 行实现参考了n1ru4l/graphql-live-query的简化版本两者命中任一操作即被交给new SSELink({ url: uri, auth, httpLinkConfig, headers })。其中headers来自useFetchConfig()见 packages/web/src/components/FetchConfigProvider.tsx 第 48-50 行在用户已认证时提供{ auth-provider: type }。也就是说本次修复后订阅请求除了认证头还会把 FetchConfig 上下文中的头信息以及httpLinkConfig.headers中的自定义头一并带上与普通 HTTP 请求保持一致的语义。面向使用者如何为订阅请求注入自定义头结合 packages/web/src/apollo/index.tsx 第 90-137 行定义的GraphQLClientConfigPropRedwoodJS 允许通过RedwoodApolloProvider的graphQLClientConfig属性配置底层 Apollo Client。注入订阅自定义头的推荐方式有方式一通过httpLinkConfig.headers推荐Query/Mutation/Subscription 统一生效RedwoodApolloProvider graphQLClientConfig{{ httpLinkConfig: { headers: { x-tenant-id: my-tenant, }, }, }} {children} /RedwoodApolloProvider这类头会同时作用于普通请求与订阅的 SSE 请求且如前面源码分析所示它排在合并顺序的最后优先级最高。方式二通过link扩展 Redwood 的 Apollo Link 链GraphQLClientConfigProp.link支持传入函数形式的工厂接收 Redwood 内置的链接数组withToken、authMiddleware、updateDataApolloLink、httpLink你可以返回自定义组合。需要留意的是文档注释中的两条约束返回的必须是一个单一链接通常用ApolloLink.from组合HttpLink/SSELink这类终止链接必须放在最后index.tsx 第 281 行也有对应注释。附带机制Trusted Documents 与 SSE 的兼容packages/web/src/apollo/sseLink.ts 第 62-66 行的hasTrustedDocument会检查操作是否携带extensions.persistedQuery.sha256Hash即受信文档/持久化查询。request方法第 121-145 行据此决定发送方式if (hasTrustedDocument(operation)) { delete operation.query request { ...operation } } else { request { ...operation, query: print(operation.query), } }命中受信文档时不再发送 query 字符串只发送 hash否则把 AST 通过print序列化为字符串。随后通过this.client.subscribe(request, { next, complete, error })发起 SSE 订阅并把graphql-sse的流式结果桥接为 Apollo 的Observable。对应地服务端需在 GraphQL Yoga 上开启useTrustedDocuments才能配合参见 packages/graphql-server/src/createGraphQLYoga.ts 的相关选项这属于订阅链路中与头信息修复正交的既有能力。服务端订阅支持的前提本次修复是客户端链路的改动要使订阅真正可用服务端还需满足前置条件GraphQL 服务端配置了 realtime 插件并启用了 subscriptions存储可选用in-memory或redis见 packages/realtime/src/graphql/plugins/useRedwoodRealtime.ts 第 195-205 行的分支逻辑在api/src/subscriptions/目录下定义 RedwoodSubscription 订阅实现目录约定见 packages/project-config/src/paths.ts 第 106 行的PATH_API_DIR_SUBSCRIPTIONS。否则即使客户端能发出带自定义头的 SSE 请求服务端也不会建立实时连接。小结本次 changeset 修复补齐了 RedwoodJS 订阅链路的一个缺口SSELink现在完整透传自定义请求头。通过阅读 sseLink.ts 的构造器实现可以看到最终发送给graphql-sse的头信息由三层合并而成——异步获取的 Bearer 认证头、FetchConfig 上下文头、以及httpLinkConfig.headers中的自定义头后者优先级最高。对使用者而言只需在RedwoodApolloProvider的graphQLClientConfig.httpLinkConfig.headers中声明自定义头即可让 Subscription 与普通请求携带一致的上下文信息无需任何额外代码。赞分享后端前端Web框架开发工具【免费下载链接】redwoodRedwoodGraphQL项目地址https://gitcode.com/gh_mirrors/re/redwood点击查看免费下载相关推荐ingress-nginx 如何用 proxy-set-headers ConfigMap 向上游请求注入自定义请求头ingress nginx 如何用 proxy set headers ConfigMap 向上游请求注入自定义请求头 当多个后端服务都需要在收到请求时看到同一后端API网关负载均衡云原生if和while是如何被编译的miniC-hosting可视化JMP与JZ控制流指令if和while是如何被编译的miniC hosting可视化JMP与JZ控制流指令 你有没有好奇过 if 和 while 这样平平无奇的语句到了计算机底Rendertron请求头管理终极指南如何传递自定义HTTP头信息Rendertron请求头管理终极指南如何传递自定义HTTP头信息 Rendertron是一个强大的Headless Chrome渲染解决方案专为动态渲染和后端上一篇从毫秒到微秒Hono.js客户端组件性能优化实战指南下一篇如何用洛雪音乐助手打造你的专属音乐空间5个实用技巧分享 创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考