冠军

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

统计

GraphQL Part II: 中间件

GraphQL Part II: 中间件

 如果您熟悉 ASP.NET Core 的中间件,您可能注意到在我们上一篇博客中我们已经拥有了一个中间件。在初始的空白应用中,中间件的职责是返回 hello World 响应。后来, 我们用我们的自定义代码替换了它, 以便它可以响应一些静态 GraphQL 查询的结果。

 中间件是一种可以装配到应用处理管线中的软件,以便处理请求和响应。每个组件包括:

  • 选择是否将请求传递给管线中的下一个组件
  • 可以在管线调用下一个组件之前或者之后执行任务

事实上,中间件是一个代理,或者更精确地说,他是一个请求代理。如名字所提示,它处理传入的请求并决定是否传递到管线中的下一个中间件。在我们的案例中,我们使用 IApplicationBuilder 的 run() 扩展方法来配置请求代理。在 3 个扩展方法之间 ( use, run, map ),Run() 方法在请求管线中终止了进一步的请求处理。

我们中间件中的代码非常简单,仅仅返回硬编码的静态查询,但是,在真实场景下,query 应该是动态的,我们必须从传入的请求中获取它。

每个请求代理接受一个 HttpContet 对象。如果 query 是通过 HTTP 的 Post 方式提交,您可以使用如下代码读取请求体。

string body;  
using (var streamReader = new StreamReader(httpContext.Request.Body))  
{
    body = await streamReader.ReadToEndAsync();
}

 

 在读取其内容之前做校验工作,就不会带来危害。所以,让我们放置一个 if 来检查两件事:

  • 它是 Post 请求吗?
  • 它来自特定的 URL 地址吗?

我们的代码做如下修改:

复制代码
if(context.Request.Path.StartsWithSegments("/api/graphql") && 
string.Equals(context.Request.Method, "POST", StringComparison.OrdinalIgnoreCase)) { string body; using (var streamReader = new StreamReader(context.Request.Body)) { body = await streamReader.ReadToEndAsync(); }
......
复制代码

 

请求体重可以包含大量字段,但是,我们可以说传入的 GraphQL 查询在名为 query 的字段内。所以,我们可以解析 body 的内容到一个包含 Query 属性的复杂类型示例中。

复杂类型如下所示:

public class GraphQLRequest
{
    public string Query { get; set; }
}

 

下一步要做的就是反序列化 body 内容到 GraphQLRequest 对象示例中,使用 Json.Net 的 JsonConvert.DeserializeObject 并替换前面硬编码的内容。

var request = JsonConvert.DeserializeObject<GraphQLRequest>(body);


var result = await new DocumentExecuter().ExecuteAsync(doc =>
{
    doc.Schema = schema;
    doc.Query = request.Query;
}).ConfigureAwait(false);

 

在所有的修改之后,在 Startup.cs 中的 Run 方法如下所示:

复制代码
app.Run(async (context) =>
{
    if (context.Request.Path.StartsWithSegments("/api/graphql")
   && string.Equals(context.Request.Method, "POST", StringComparison.OrdinalIgnoreCase))
    {
        string body;
        using (var streamReader = new StreamReader(context.Request.Body))
        {
            body = await streamReader.ReadToEndAsync();

            var request = JsonConvert.DeserializeObject<GraphQLRequest>(body);
            var schema = new Schema { Query = new HelloWorldQuery() };

            var result = await new DocumentExecuter().ExecuteAsync(doc =>
            {
                doc.Schema = schema;
                doc.Query = request.Query;
            }).ConfigureAwait(false);

            var json = new DocumentWriter(indent: true).Write(result);
            await context.Response.WriteAsync(json);
        }
    }
});
复制代码

 

现在,可以使用任何客户端 ( Postman 或者 Insomnia ) 发送一个包含 query 字段的 POST 请求.

我们几乎完成了工作,但是您可以看到大量的 new 代码创建对象,例如:new DocumentExecuter(),new Schema(), new DocumentWriter() 等等,下一节,我们将使用 ASP.NET Core 内置的依赖注入系统注入它们。

 

上一篇:GraphQL Part I: hello, world.

下一篇:GraphQL Part III: 依赖注入

参考资料

 

posted on   冠军  阅读(393)  评论(0编辑  收藏  举报

编辑推荐:
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
历史上的今天:
2012-03-28 window.parent ,window.top,window.self 详解
点击右上角即可分享
微信分享提示