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

如何在Resolver中拦截GraphQL Hotchocolate Banana Cake Pop查询?

问题原因

你直接通过IHttpContextAccessor读取不到查询内容,是因为HotChocolate中间件处理请求时已经提前消费了HTTP请求体,默认不会重置流位置,后续读取时流已经处于末尾,自然拿不到内容。且如果是BananaCakePop发起的GET查询请求,查询参数是放在URL中,读请求体本身也获取不到内容,这种直接读取HttpContext的方式本身也不是HotChocolate推荐的方案。

推荐实现方案

方案1:全局请求拦截器(适合统一拦截所有查询请求)

HotChocolate提供了原生的IHttpRequestInterceptor接口,可以直接拦截所有 incoming 的GraphQL请求,包括BananaCakePop传递的查询,无需自行处理HTTP流逻辑。

  1. 实现拦截器逻辑
public class GraphQLRequestInterceptor : IHttpRequestInterceptor
{
    public async ValueTask OnCreateAsync(HttpContext context, 
        IRequestExecutor requestExecutor, 
        IQueryRequestBuilder requestBuilder, 
        CancellationToken cancellationToken)
    {
        // 直接获取解析后的查询内容,自动兼容GET/POST请求、批量请求等场景
        if (requestBuilder.TryGetQuery(out var query))
        {
            string rawQuery = query.ToString();
            // 此处可实现你的拦截、读取、校验逻辑
        }
        
        // 若仍需要读取原始HTTP请求体,可通过如下方式读取,无需额外配置中间件
        context.Request.EnableBuffering();
        context.Request.Body.Position = 0;
        using var reader = new StreamReader(context.Request.Body, leaveOpen: true);
        string rawBody = await reader.ReadToEndAsync(cancellationToken);
        context.Request.Body.Position = 0;
    }
}
  1. 注册拦截器
    在你的GraphQL服务注册链式配置中添加拦截器注册即可:
services.AddGraphQLServer()
    .AddHttpRequestInterceptor<GraphQLRequestInterceptor>() // 添加这行注册拦截器
    // 保留你原有其他配置,比如AddQueryType、AddMutationType等
    ;

方案2:Resolver内直接获取当前查询

如果你只需要在特定Resolver内拿到当前查询内容,不需要全局拦截,可以直接注入HotChocolate原生的IQueryContext,无需绕IHttpContextAccessor:

public async Task<IEnumerable<Account>> MyResolver(
        [Service] IConfigService configService,
        IQueryContext queryContext) // 直接注入查询上下文
{
    // 直接读取当前请求的查询内容
    string currentQuery = queryContext.Request.Query.ToString();
    // 你的原有业务逻辑
}
硬读HttpContext的补充配置

如果你一定要坚持用IHttpContextAccessor读取原始请求体,需要在GraphQL中间件注册前添加请求体缓冲配置,允许重复读取请求流:

// 这段配置要放在app.UseGraphQL()之前
app.Use(next => context =>
{
    context.Request.EnableBuffering();
    return next(context);
});

app.UseGraphQL();

读取时需要主动重置流位置:

httpContext.HttpContext.Request.Body.Position = 0;
using var reader = new StreamReader(httpContext.HttpContext.Request.Body, leaveOpen: true);
string rawBody = await reader.ReadToEndAsync();
// 读完后记得把位置重置回0,避免影响后续中间件逻辑
httpContext.HttpContext.Request.Body.Position = 0;

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 10:21:01