如何获取gqlgen子图中联邦GraphQL网关传递的上下文
所有通过联邦网关传递到子图的请求信息(包括HTTP头、联邦协议扩展字段、链路追踪数据、认证信息等),都可以通过gqlgen标准的上下文链路获取,不需要做额外的黑科技改造,常用方式分三类:
从Resolver原生入参的context获取通用HTTP透传内容
gqlgen所有Resolver的第一个参数都是Go标准库的context.Context,网关转发请求时带的所有原生HTTP头、请求元信息已经被框架提前封装在这个上下文里,直接调用内置方法就能拿到原始请求:func (r *queryResolver) GetOrder(ctx context.Context, orderID string) (*Order, error) { // 提取网关转发的原生HTTP请求 httpReq := transport.GetHTTPRequest(ctx) // 读取网关透传的认证头、链路ID、自定义业务头 userRole := httpReq.Header.Get("X-User-Role") traceID := httpReq.Header.Get("X-Trace-Id") // 后续业务逻辑 return &Order{ID: orderID, BelongRole: userRole}, nil }不要自己在全局HTTP Handler里缓存请求对象做传递,这种方式很容易出现并发场景下上下文串流的问题,用框架内置方法拿是线程安全的。
获取联邦协议专属的实体解析上下文
处理_entities实体查询请求时,网关会把上游子图返回的实体标识、扩展字段存在representations结构里下发,这部分内容不需要自己解析请求体,gqlgen的联邦支持包已经把当前正在解析的实体数据注入到上下文里,直接调用方法即可读取:func (r *entityResolver) FindOrderByID(ctx context.Context, id string) (*Order, error) { // 读取当前实体对应的联邦透传representation数据 entityRep, err := federated.GetEntity(ctx) if err != nil { // 非实体解析场景调用会返回错误,按正常逻辑做错误处理即可 } // entityRep 里就是网关透传的完整实体原始字段,可直接读取跨子图传递的扩展属性 return &Order{ID: id}, nil }通过中间件全局预处理上下文
如果需要统一处理所有请求的透传内容(比如全局校验认证token、注入用户信息、打链路日志),直接注册gqlgen的全局操作中间件即可,中间件处理后的上下文会自动传递到所有后续Resolver:srv.AroundOperations(func(ctx context.Context, next graphql.OperationHandler) graphql.ResponseHandler { httpReq := transport.GetHTTPRequest(ctx) token := httpReq.Header.Get("Authorization") // 校验token、解析用户信息 ctx = context.WithValue(ctx, "current_user", parsedUser) return next(ctx) })后续所有Resolver里直接从ctx读取提前注入的自定义值即可,不用重复写解析逻辑。
避坑提示:不要自己手动反序列化GraphQL请求体提取联邦上下文,gqlgen的联邦插件已经兼容了Federation v1/v2的协议解析逻辑,手动解析很容易在协议版本升级时出现兼容故障,走标准context链路获取是官方推荐的无依赖方案。
内容的提问来源于stack exchange,提问作者hboylan

