如何通过Java DataFetcher环境在GraphQL查询中获取请求头?
GraphQL中读取HTTP请求头的实现方案
默认GraphQLContext没有提供getHeader()方法,本质是框架初始化上下文时没有自动携带HTTP请求的元数据,不需要修改现有解析器的调用逻辑,只需要在请求入口层把请求头信息提前注入上下文,后续就可以在任意DataFetcher中直接读取,效果和REST场景下的HttpServletRequest.getHeader()完全一致。
Spring for GraphQL 场景配置(最常用)
如果你用的是Spring生态的GraphQL组件,只需要新增一个全局拦截器,在请求进入GraphQL执行引擎前把请求头存入上下文即可:
import org.springframework.graphql.server.WebGraphQlInterceptor; import org.springframework.graphql.server.WebGraphQlRequest; import org.springframework.graphql.server.WebGraphQlResponse; import org.springframework.http.HttpHeaders; import org.springframework.stereotype.Component; import reactor.core.publisher.Mono; import java.util.Collections; @Component public class HeaderInjectInterceptor implements WebGraphQlInterceptor { @Override public Mono<WebGraphQlResponse> intercept(WebGraphQlRequest request, Chain chain) { request.configureExecutionInput((executionInput, builder) -> builder.graphQLContext(Collections.singletonMap("REQ_HEADERS", request.getHeaders())) .build() ); return chain.next(request); } }
解析器中读取请求头
注入完成后,在任意解析器中都可以通过DataFetchingEnvironment拿到上下文,直接读取目标请求头:
GraphQLContext context = env.getGraphQlContext(); HttpHeaders headers = context.get("REQ_HEADERS"); // 读取指定头的值,和预期的getHeader效果一致 String ipassId = headers.getFirst("headerkeyIpass");
如果想要更贴近你预期的context.getHeader()调用形式,可以写一个公共工具类做轻量封装,不需要修改框架源码:
// 公共工具类方法 public static String getHeader(GraphQLContext context, String headerKey) { HttpHeaders headers = context.get("REQ_HEADERS"); return headers == null ? null : headers.getFirst(headerKey); } // 调用方式和你预期的写法几乎无差别 String Id = GraphQlUtil.getHeader(context, "headerkeyIpass");
原生graphql-java场景配置
如果没有集成Spring,直接使用原生graphql-java,只需要在构建ExecutionInput的请求入口处,把请求头存入上下文即可:
// 在接收GraphQL请求的Servlet/Controller入口构建ExecutionInput时注入 Map<String, String> headerMap = new HashMap<>(); Enumeration<String> headerNames = httpServletRequest.getHeaderNames(); while (headerNames.hasMoreElements()) { String key = headerNames.nextElement(); headerMap.put(key, httpServletRequest.getHeader(key)); } ExecutionInput executionInput = ExecutionInput.newExecutionInput() .query(queryBody) .variables(variables) .graphQLContext(contextBuilder -> contextBuilder.put("REQ_HEADERS", headerMap)) .build(); // 解析器中读取逻辑 Map<String, String> headers = env.getGraphQlContext().get("REQ_HEADERS"); String ipassId = headers.get("headerkeyIpass");
该方案无代码侵入,不需要修改现有解析器的方法签名和调用逻辑。后续如果需要在上下文中注入鉴权信息、请求追踪ID等通用请求元数据,也可以在同一个拦截器中统一处理,避免每个解析器重复写参数解析逻辑。
内容的提问来源于stack exchange,提问作者Chaithra Rai
相关产品推荐
相关产品推荐

