Когда именно HttpResponse отправляется клиенту в конвейер промежуточного программного обеспечения API ядра .net? - PullRequest
1 голос
/ 05 июля 2019

Я так растерялся, когда 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 Ответ

2 голосов
/ 05 июля 2019

Думайте о каждом зарегистрированном промежуточном программном обеспечении как о шаге по пути создания запроса.Ваш метод вызова является «вашим» шагом на этом пути.await _next(context); указывает платформе перейти к следующему промежуточному программному обеспечению в конвейере в этот момент - но - вернуться после выполнения остальных промежуточных программ, чтобы ваш код мог быть снова загружен.

Итак ... Имея это в виду, давайте предположим, что у нас установлено 3 промежуточных программного обеспечения.Конвейер работает следующим образом:

[ЗАПРОС НАЧИНАЕТСЯ]

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

[ОТВЕТ ПРОИЗВОДИТСЯ]

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

[ОТВЕТ ВЫХОДИТ ЗВОНОК]

Допустим, вы добавили await _next(context) в метод вызова Middleware2.Когда код достигает этой точки, он переходит к следующему промежуточному программному обеспечению в конвейере, но он знает, где остановиться, когда возвращается ответ.Таким образом, вы можете перехватить это снова.

Если вы регистрируете запрос, ваш пользовательский код будет идти до этого await _next(context) вызова.Если вы регистрируете ответ, он приходит после этого вызова.

Примечание. Кроме того, порядок промежуточного программного обеспечения определяется порядком, который они зарегистрированы в вашем классе запуска.

...