在.net核心API中间件管道中,到底何时将HttpResponse发送到客户端?

时间:2019-07-05 12:33:59

标签: c# http asp.net-core .net-core asp.net-core-2.1

我对IIS何时发送响应感到非常困惑,我真的很想知道它是如何工作的,因为我正在执行响应日志记录,并且我不想破坏正文。

这是我的日志记录中间件Invoke,在MVC中间件(控制器)之前调用。控制器返回其Ok方法后,响应是立即发送还是等待中间件的其余部分?如果以这种方式记录日志,是否有可能破坏响应?

public async Task Invoke(HttpContext context)
{
    var requestResponseLog = new RequestResponseLog
    {
        RequestTime = DateTimeOffset.UtcNow,
        Request = await FormatRequest(context)
    };

    Stream originalBody = context.Response.Body;

    using (MemoryStream newResponseBody = _recyclableMemoryStreamManager.GetStream())
    {
        context.Response.Body = newResponseBody;

        await _next(context);

        newResponseBody.Seek(0, SeekOrigin.Begin);
        await newResponseBody.CopyToAsync(originalBody);

        newResponseBody.Seek(0, SeekOrigin.Begin);

        requestResponseLog.ResponseTime = DateTimeOffset.UtcNow;
        requestResponseLog.Response = await FormatResponse(context, newResponseBody);

        _requestResponseHandler(requestResponseLog);
    }
}

1 个答案:

答案 0 :(得分:2)

将每个注册的中间件视为创建请求的步骤。您的invoke方法是该路径上的“您的”步骤。 await _next(context);指示框架此时移至管道中的下一个中间件-但是-在其余中间件执行完毕后返回,以便可以再次拾取您的代码。

所以..考虑到这一点,让我们假设我们设置了3个中间件。管道的工作方式如下:

[要求输入]

Middleware-1 => Middleware-2 => Middleware-3

[已产生响应]

Middleware-3 => Middleware-2 => Middleware-1

[响应来电]

假设您将await _next(context)添加到了Middleware2的Invoke方法中。当代码到达该点时,它会跳到管道中的下一个中间件,但是它知道在响应返回时就在那里停止。这样您就可以再次拦截它。

如果您正在记录请求,则您的自定义代码将在该await _next(context)调用之前发送。如果您正在记录响应,它将在该调用之后出现。

注意:此外,中间件的排序由它们在Startup类中注册的顺序决定。