.NET GraphQL API 作为代理转发请求并添加自定义头是否可行?
搭建.NET GraphQL转发API的简便实现思路
方案一:轻量级请求转发控制器(最快上手)
直接编写一个API控制器接收GraphQL请求,添加自定义头后转发到目标API,无需维护GraphQL Schema,完全透明转发。
步骤:
- 安装
System.Net.Http.Json、Microsoft.AspNetCore.MvcNuGet包。 - 定义极简的GraphQL请求/响应模型,用于序列化和反序列化请求体。
- 在控制器中接收请求,注入自定义请求头,转发到目标API后返回响应。
- 安装
示例代码:
[ApiController] [Route("graphql")] public class GraphqlProxyController : ControllerBase { private readonly HttpClient _httpClient; private readonly string _targetApiUrl; public GraphqlProxyController(HttpClient httpClient, IConfiguration config) { _httpClient = httpClient; _targetApiUrl = config["TargetGraphqlApi:Url"]; } [HttpPost] public async Task<IActionResult> ForwardGraphqlRequest([FromBody] GraphqlRequest request) { // 添加自定义请求头(可根据业务动态生成) _httpClient.DefaultRequestHeaders.Remove("X-Custom-Proxy-Header"); _httpClient.DefaultRequestHeaders.Add("X-Custom-Proxy-Header", "Proxy-Generated-Value"); // 转发请求到目标API var targetResponse = await _httpClient.PostAsJsonAsync(_targetApiUrl, request); targetResponse.EnsureSuccessStatusCode(); // 将目标响应原样返回 var responseContent = await targetResponse.Content.ReadFromJsonAsync<GraphqlResponse>(); return Ok(responseContent); } } // 基础模型,覆盖绝大多数GraphQL请求场景 public class GraphqlRequest { public string Query { get; set; } public Dictionary<string, object> Variables { get; set; } public string OperationName { get; set; } } public class GraphqlResponse { public object Data { get; set; } public List<GraphqlError> Errors { get; set; } } public class GraphqlError { public string Message { get; set; } public List<GraphqlErrorLocation> Locations { get; set; } } public class GraphqlErrorLocation { public int Line { get; set; } public int Column { get; set; } }
- 优点:代码量极少,无需理解复杂的GraphQL Schema规则,部署即可用;适合纯转发场景。
方案二:YARP反向代理(官方生态,性能稳定)
利用ASP.NET Core官方的反向代理组件YARP,专门处理请求转发逻辑,配合自定义中间件注入请求头,适合需要批量代理多个路径的场景。
步骤:
- 安装
Yarp.ReverseProxyNuGet包。 - 在配置文件中定义转发规则,将
/graphql路径映射到目标API。 - 添加自定义中间件,在请求转发前注入额外请求头。
- 安装
示例配置与代码:
// Program.cs var builder = WebApplication.CreateBuilder(args); // 注册YARP反向代理 builder.Services.AddReverseProxy() .LoadFromConfig(builder.Configuration.GetSection("ReverseProxy")); var app = builder.Build(); // 自定义中间件:添加转发请求头 app.Use(async (context, next) => { // 避免重复添加头,先移除再添加 context.Request.Headers.Remove("X-Custom-Proxy-Header"); context.Request.Headers.Add("X-Custom-Proxy-Header", "Proxy-Generated-Value"); await next(); }); // 启用反向代理路由 app.MapReverseProxy(); app.Run();
- appsettings.json配置:
{ "ReverseProxy": { "Routes": { "graphql-proxy-route": { "ClusterId": "target-graphql-cluster", "Match": { "Path": "/graphql" } } }, "Clusters": { "target-graphql-cluster": { "Destinations": { "primary-target": { "Address": "https://your-target-graphql-api.com/" } } } } } }
- 优点:基于ASP.NET Core官方组件,性能优异,支持负载均衡、健康检查等高级特性;适合需要长期维护的生产环境。
方案三:基于GraphQL Schema的代理(类型安全,可扩展)
如果需要对请求做校验、参数修改等扩展操作,可以先定义与目标API一致的GraphQL Schema,在Resolver中转发请求,兼顾类型安全和灵活性。
步骤:
- 安装
GraphQL、GraphQL.Server.CoreNuGet包。 - 复制目标API的Schema定义,创建对应的GraphQL类型。
- 在字段Resolver中发起HTTP请求到目标API,添加自定义头后返回结果。
- 安装
示例Resolver片段:
public class ProductQuery : ObjectGraphType { public ProductQuery(HttpClient httpClient, IConfiguration config) { Field<ProductType>("product") .Argument<IdGraphType>("productId") .ResolveAsync(async context => { var productId = context.GetArgument<string>("productId"); // 构造目标API的GraphQL查询 var query = $"{{ product(productId: \"{productId}\") {{ id name price }} }}"; var request = new GraphqlRequest { Query = query }; httpClient.DefaultRequestHeaders.Add("X-Custom-Proxy-Header", "Proxy-Generated-Value"); var response = await httpClient.PostAsJsonAsync(config["TargetGraphqlApi:Url"], request); var result = await response.Content.ReadFromJsonAsync<GraphqlResponse>(); // 将响应数据映射到本地类型 return result.Data.GetProperty("product").Deserialize<Product>(); }); } } public class ProductType : ObjectGraphType<Product> { public ProductType() { Field(x => x.Id); Field(x => x.Name); Field(x => x.Price); } } public class Product { public string Id { get; set; } public string Name { get; set; } public decimal Price { get; set; } }
- 优点:类型安全,可在转发前加入业务逻辑(如参数校验、权限验证);缺点:需要同步维护目标API的Schema,适合需要扩展功能的场景。
内容的提问来源于stack exchange,提问作者Branislav B.
相关产品推荐
相关产品推荐

