首页 > 解决方案 > asp.net Core 在 UseRouting 之后在中间件中添加响应头

问题描述

我正在尝试通过中间件添加服务器端延迟标头。我看过几个有类似问题的 SO 帖子,但他们的解决方案对我不起作用。这是我的Startup.cs

public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory factory)
{
    app.UseForwardedHeaders(new ForwardedHeadersOptions
    {
         ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto
    });

    app.UseRouting();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllers();
        endpoints.MapRazorPages();
    });

    app.MyHeaderMiddleware();
}

我必须在MyHeaderMiddleware之后注册UseRoutingUseEndpoints因为它还需要端点数据。

然后在扩展方法类中,我有以下内容。

public static void MyHeaderMiddleware(this IApplicationBuilder app)
{
    app.MyHeaderMiddleware((context, logger) =>
    {
        var actionDescriptor = endpoint.Metadata.GetMetadata<ControllerActionDescriptor>();
        int status = context.Response.StatusCode;

        if (context.Request.Host != null)
        {
            logger.PutProperty("Host", context.Request.Host.Value);
        }

        if (context.Request?.HttpContext?.Connection?.RemoteIpAddress != null)
        {
            logger.PutProperty("SourceIp", context.Request.HttpContext.Connection.RemoteIpAddress.ToString());
        }

        if (context.Request.Headers.TryGetValue("X-Forwarded-For", out StringValues value) && !String.IsNullOrEmpty(value) && value.Count > 0)
        {
            logger.PutProperty("X-Forwarded-For", value.ToArray());
        }
   
        return Task.CompletedTask;
    });
}

public static void MyHeaderMiddleware(this IApplicationBuilder app, Func<HttpContext, IMetricsLogger, Task> metricsSetup)
{
    app.Use(async (context, next) =>
    {
        Stopwatch stopWatch = new Stopwatch();
        stopWatch.Start();
                
        var logger = context.RequestServices.GetRequiredService<IMetricsLogger>();
        await metricsSetup(context, logger);

        context.Response.OnStarting(() =>
        {
            stopWatch.Stop();
            context.Response.Headers.Add("X-Server-Side-Latency", stopWatch.ElapsedMilliseconds.ToString());

            return Task.CompletedTask;
        });
                
        await next();
    });
}

如果我在之前注册了我的中间件UseRouting,则会按预期添加标头,但如果它在之后,它会执行,但在响应中看不到标头。我需要设置我的指标记录器作为其中的一部分,因为我既记录了每个 API 调用的服务器端延迟,也将其放入 http 响应中。

标签: asp.netasp.net-coremiddleware

解决方案


我改变了一些步骤的顺序,最终使它起作用。主要的变化是这样的。

await next(); // this will make the endpoints available in the logger setup
await metricsSetup(context, logger);

在较小程度上,这:

app.UseRouting();
app.UseEmfMiddleware();
app.UseEndpoints(endpoints =>
{
    endpoints.MapControllers();
    endpoints.MapRazorPages();
});

通过在设置指标记录器之前调用next(),端点可用,即使它们在启动时位于此中间件之后。


推荐阅读