2

我们在 Web API 中有中间件,我们用它来过滤来自控制器的响应主体在将我们的服务更新到 .net 5 后,替换输出失败为

System.InvalidOperationException: Headers already sent.
         at Microsoft.AspNetCore.Server.HttpSys.Response.CheckResponseStarted()
         at Microsoft.AspNetCore.Server.HttpSys.FeatureContext.ConsiderEnablingResponseCache()
         at Microsoft.AspNetCore.Server.HttpSys.FeatureContext.OnResponseStart()
         at Microsoft.AspNetCore.Server.HttpSys.FeatureContext.CompleteAsync()
         at Microsoft.AspNetCore.Server.HttpSys.RequestContext.Execute()
         at Microsoft.AspNetCore.Server.HttpSys.RequestContext.Execute()

我们过滤输出的中间件看起来像这样

internal class FilterOutput : IMiddleware
{
    public async Task InvokeAsync(HttpContext context, RequestDelegate next)
    {
        var originalBodyStream = context.Response.Body;
        var tempResponseBody = new MemoryStream();
        context.Response.Body = tempResponseBody;
        context.Response.OnStarting(async state =>
        {
            await FilterResponse(context, tempResponseBody, originalBodyStream);
        }, context);
        await next(context);
    }

    private async Task FilterResponse(HttpContext context, MemoryStream tempResponseBody, Stream originalBodyStream)
    {
        if (context.Response.StatusCode == 200)
        {
            var output = Encoding.UTF8.GetString(tempResponseBody.GetBuffer());
            var newOutput = output.Filter(null);

            var updatedStream = GenerateStreamFromString(newOutput);
            await updatedStream.CopyToAsync(originalBodyStream);
            context.Response.Body = originalBodyStream;
            return;
        }
        await tempResponseBody.CopyToAsync(originalBodyStream);
    }

    public static Stream GenerateStreamFromString(string s)
    {
        var stream = new MemoryStream();
        var writer = new StreamWriter(stream);
        writer.Write(s);
        writer.Flush();
        stream.Position = 0;
        return stream;
    }
}

我意识到 net 5 可能更异步并且更早发送标头有没有办法阻止它,所以我可以修改中间件中的输出主体?

4

0 回答 0