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.
参考资料
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 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 详解