程序员求职经验分享与学习资料整理平台

网站首页 > 文章精选 正文

YARP HTTP 请求诊断(http状态400–错误请求错误请求怎么解决)

balukai 2025-07-27 18:37:46 文章精选 4 ℃

Inspect your YARP HTTP Request

Intro

最近有在项目里使用 yarp 做一个第三方 API 的反向代理,yarp 是微软的一个反向代理项目(Yet Another Reverse Proxy)

发现本地是好的,但是发布到测试环境之后就有问题,经过一系列排查发现是 nginx ingress 的问题,在过程中分析 yarp 转发的请求感觉可能会对大家有点帮助,所以分享一下

Setup

我们先准备一个最简单的 YARP 服务


var builder = WebApplication.CreateSlimBuilder(args);
builder.Services.AddReverseProxy()
.LoadFromConfig(builder.Configuration.GetSection("ReverseProxy"))
;
var app = builder.Build();
app.MapReverseProxy();
app.Run();

示例配置如下:

{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning",
"Microsoft.AspNetCore.HttpLogging": "Information",
"Yarp": "Debug"
}
},
"ReverseProxy": {
"Routes": {
"default" : {
"ClusterId": "default",
"Match": {
"Path": "/"
}
}
},
"Clusters": {
"default": {
"Destinations": {
"default": {
"Address": "https://reservation.weihanli.xyz/api/notice"
}
}
}
}
}
}

我们请求一下 yarp 服务,日志如下:

basic-yarp-logging

可以看到日志里只有下游的地址和下游服务返回的 response status code,有些问题需要排查的时候可能信息就不太够用了

Diagnostics

YARP 请求分成两部分,一部分是直接对 YARP 服务的 http 请求,另一部分是转发到下游的请求

针对 YARP 服务的 http 请求,我们可以使用 ASP.NET Core 自带的 Http Logging 中间件来记录

针对转发到下游的请求,我们可以通过 YARP 的扩展实现 transform 来记录转发的请求信息

Http Logging

简单的配置如下:

var builder = WebApplication.CreateSlimBuilder(args);
+ builder.Services.AddHttpLogging();
builder.Services.AddReverseProxy()
.LoadFromConfig(builder.Configuration.GetSection("ReverseProxy"))
;
var app = builder.Build();
+ app.UseHttpLogging();
app.MapReverseProxy();
app.Run();

这样我们就可以记录 HTTP 请求的信息了

http logging 日志示例如下:

http logging sample

Transform

YARP 提供了 Transform 的扩展,我们可以实现一个 transform 来记录转发的完整请求,我们可以使用 ResponseTransform 来记录转发的请求和响应,实现示例如下:

为了显式的明确约束,这里继承于 ResponseTransform 来实现的,也可以实现一个静态方法即可

public classYarpLoggingTransform : ResponseTransform
{
public override ValueTask ApplyAsync(ResponseTransformContext context)
{
var proxyResponse = context.ProxyResponse;
if (proxyResponse is)
return ValueTask.CompletedTask;

var proxyRequest = proxyResponse.RequestMessage;

var logger = context.HttpContext.RequestServices.GetRequiredService<ILogger<YarpLoggingTransform>>();
if (proxyRequest isnot)
{
logger.LogInformation("Proxy request: {Url} {Headers}",
proxyRequest.RequestUri?.AbsoluteUri, string.Join(";",
proxyRequest.Headers.Select(h =>
$"{h.Key}:{string.Join(",", h.Value)}")));
}

logger.LogInformation("Proxy response: {ResponseStatusCode} {ResponseHeaders}",
(int)proxyResponse.StatusCode, string.Join(";", proxyResponse.Headers.Select(x=> $"{x.Key}:{string.Join(",", x.Value)}")));
return ValueTask.CompletedTask;
}
}

这里的 proxyRequest/proxyResponse 就是我们转发到下游服务的 HttpClient 发起的 Http 请求和响应

之后在 YARP 服务注册的地方配置一下使用我们的 Transform

var builder = WebApplication.CreateSlimBuilder(args);
builder.Services.AddHttpLogging();
+ builder.Services.AddSingleton<YarpLoggingTransform>();
builder.Services.AddReverseProxy()
.LoadFromConfig(builder.Configuration.GetSection("ReverseProxy"))
+ .AddTransforms(transformContext =>
+ transformContext.ResponseTransforms.Add(transformContext.Services.GetRequiredService<YarpLoggingTransform>()))
;
var app = builder.Build();
app.UseHttpLogging();
app.MapReverseProxy();
app.Run();

配置之后的日志示例:

proxy-http-logging-sample

这里可以看到我们的转发的请求和响应的 HTTP header 信息都被记录下来了,也可以根据需要进行一些定制

More

Http Logging Middleware 在前面的示例只是使用了默认的配置,更多使用配置可以参考文档:https://learn.microsoft.com/en-us/aspnet/core/fundamentals/http-logging/?view=aspnetcore-9.0

YARP 也提供了一个 telemetry 的方式,可以基于 telemetry 来实现记录转发到的是哪一个下游服务以及实现一些 tracing/metrics 的需求,但是没有完整的下游转发的请求,没有 header 和 content,有需要可以根据文档自己试一下,所以自己实现了一个 ResponseTransform 来实现 logging 自己想要记录的信息

再说回我们的问题,最后查下来是因为 nginx 默认不支持下划线的 header

Tags:

最近发表
标签列表