Среднее ПО всегда должно ссылаться на следующее?

Я пытался понять, как работают middlewares для ASP.NET 5. Средство промежуточного уровня, как я знаю, представляет собой всего лишь Func<RequestDelegate, RequestDelegate>, который является указателем на метод, который получает ссылку на следующий делегат запроса и возвращает новый, который обертывает следующий. Конечно, мы можем использовать класс для представления промежуточного программного обеспечения, например:

public class MyMiddleware
{
    private readonly _next;

    public MyMiddleware(RequestDelegate next)
    {
        if (next == null)
        {
            throw new ArgumentNullException("next");
        }

        _next = next;
    }

    public Task Invoke(HttpContext context)
    {
        // New request delegate code here which can wrap the next one on the pipeline
    }
}

Так как RequestDelegate является делегатом, который может содержать ссылки на методы, которые получают один HttpContext и возвращает Task, метод Invoke является делегатом запроса, который должен быть возвращен и который имеет доступ к следующему в трубопровод.

Тогда при кодировании промежуточного программного обеспечения мы получаем доступ к следующему компоненту конвейера, но есть сомнения. Вначале я думал, что идеал всегда должен работать следующим образом:

  • Проверьте, может ли промежуточное программное обеспечение обрабатывать запрос
  • Если это возможно, сделайте все, что нужно сделать с помощью HttpContext
  • Вызов следующего промежуточного программного обеспечения в конвейере

Итак, когда я впервые изучил это, я подумал, что каждое промежуточное ПО всегда должно вызывать следующее. Но это привело к странному поведению, как обсуждалось на этом вопросе.

Также, глядя на исходный код некоторых промежуточных продуктов, я вижу, что некоторые из них выполняют следующие шаги:

  • Проверьте, может ли промежуточное программное обеспечение обрабатывать запрос
  • Если это возможно, сделайте все, что нужно сделать с помощью HttpContext, и что все
  • Если нет, и только если не вызовите следующий

Это настоящая идея использования посредников? Каким образом это правильный подход? Каждое промежуточное программное обеспечение делает то, что должно быть сделано с запросом и всегда вызывает следующий, или если средние программы могут обрабатывать запрос, который он больше не вызывает следующего?

Я считаю, что промежуточное программное обеспечение должно вызывать следующее, только если оно не может обрабатывать запрос. Причина, по которой я думаю, состоит в том, что, если нет, будет связь между посредниками на трубопроводе. Чтобы обработать запрос, промежуточное ПО должно было знать о том, что сделал предыдущий, чтобы не испортить все. Правильно ли это заключение?

Ответ 1

Существует промежуточное ПО, чтобы сделать запрос конвейера модульным, что означает, что вы можете добавлять/удалять/заменять части от него, если вы соблюдаете контракт. Например, если ваше приложение обслуживает некоторые файлы без кэширования, вы можете добавить промежуточное программное обеспечение в начале конвейера, не изменяя остальные. Они являются строительными блоками.

Среднее ПО может:

  • Ничего не делать и передавать запрос дальше (например, промежуточное программное обеспечение, которое применимо только к запросам POST, а текущий - GET)
  • Ничего не делайте с запросом, делайте что-то другое и передавайте его дальше (например, протоколирование)
  • Сделайте что-нибудь для запроса и передайте запрос дальше (например, получите токен аутентификации и преобразуйте его в личность или удалите из запроса некоторую конфиденциальную информацию)
  • Завершить конвейер и не передавать запрос дальше (например StaticFileMiddleware, который просто возвращает файл, или MVC, когда маршрут совпадает)

Возможно, отвечая на ваш другой вопрос: существуют два типа промежуточного программного обеспечения:

  • Средство промежуточного уровня, которое предназначено для выполнения чего-либо и передает данные дальше (и т.д. auth, cookie, проверка, ведение журнала и т.д.).
  • Среднее ПО, которое завершает конвейер (статический файл, MVC и т.д.).

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

Автор промежуточного программного обеспечения должен решить, следует ли использовать следующее промежуточное программное обеспечение (если оно есть). В случае промежуточного программного обеспечения в вопросе, который возвращает сообщение, он не должен ссылаться на следующий.