Перейти к содержанию

Промежуточное ПО

Starlette состоит из нескольких классов промежуточного ПО, которые добавляют поведение, применимое ко всему приложению. Все они реализуются как стандартные классы ASGI промежуточного ПО и могут быть применены к Starlette или любому другому приложению ASGI.

Использование промежуточного элемента

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

from Starlette.applications import Starlette
from Starlette.middleware import Middleware
from starlett.middleware. https redirect import HTTPS Redirect Middleware
from starlett.middleware.trustedhost import TrustedHostMiddleware

routes =…

# Ensure that all requests include an 'example.com' or
# '*.example.com' host header, and strictly enforce https-only access.
middleware =(
    Местность (
        TrustedhostMiddleware,
        allowed_hosts =['example.com','*. example.com'],
    ),
    Middleware(HTTPS Redirect Middleware)
]

app = Starlette(routes=routes, middleware=middleware)

По умолчанию каждое приложение Starlette автоматически содержит два промежуточных файла:

  • ServerErrorMiddleware-убедитесь, что исключение приложения может вернуть пользовательскую страницу 500 или отобразить информацию о отслеживании приложения в режиме DEBUG. Это всегда самый внешний слой промежуточного ПО.
  • ExceptionMiddleware-Добавлен обработчик исключений, так что определенные типы ожидаемых исключений могут быть связаны с функциями обработчика. Например, запуск HTTPException(status_code=404) в конечной точке приведет к появлению пользовательской страницы 404.

Промежуточное программное обеспечение оценивается сверху вниз, поэтому в нашем примере приложения процесс выполнения будет выглядеть следующим образом:

  • Промежуточный элемент
    • ServerErrorMiddleware
    • TrustedHostMiddleware
    • HTTPSRedirectMiddleware
    • ExceptionMiddleware
  • Выбор маршрута
  • Конечная точка

В пакетах Starlette можно использовать следующие промежуточные элементы:

Промежуточные элементы CORS

Добавьте соответствующий заголовок CORS к ответам, отправленным наружу, чтобы разрешить межисходные запросы из браузера.

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

Из Starlette.applications Import Starlette
from Starlette.middleware import Middleware
from starlette middleware.cors import CORSMiddleware

routes =…

middleware = [
    Middleware(CORSMiddleware, allow_origins =['*'])
]

app = Starlette(routes=routes, middleware=middleware)

Поддержку получили следующие аргументы:

  • allow_origins-список источников, которые должны быть разрешены для межисходных запросов. Например,['https://example.org', 'https://www.example.org']. Вы можете использовать ['*'], чтобы разрешить любой источник.
  • allow_origin_regex-строка регулярного выражения, которая соответствует источнику, которому разрешено выполнять межисходные запросы. Например,'https://.*\.example\.org'.
  • allow_methods-список методов HTTP, которые должны быть разрешены для межисходных запросов. По умолчанию используется ['GET']. Вы можете использовать ['*'], чтобы разрешить все стандартные методы.
  • allow_headers - Список заголовков HTTP-запросов, которые должны поддерживаться для межисходных запросов. По умолчанию: [] . Вы можете использовать ['*'] чтобы разрешить все заголовки. Для запроса CORS, Accept 、 Accept-Language 、 Content-Language и Content-Type Заголовок всегда допускается.
  • allow_credentials-указывает на файлы Cookie, которые должны поддерживать запросы из разных источников. По умолчанию используется False. Кроме того, для разрешения учетных данных allow_origins,allow_methods и allow_headers не могут быть установлены в ['*'], они должны быть четко указаны.
  • expose_headers-указывает любой заголовок ответа, который должен быть доступен для браузера. По умолчанию используется [].
  • max_age-устанавливает максимальное время в секундах для кэширования ответов CORS браузера. По умолчанию 600.

Промежуточные файлы отвечают на два конкретных типа HTTP-запросов...

Предварительный запрос на междоменное совместное использование ресурсов (CORS)

Это любые запросы OPTIONS с заголовками Origin и Access-Control-Request-Method. В этом случае промежуточная программа перехватит входящие запросы и ответит с помощью соответствующего заголовка CORS, а также ответ 200 или 400 для информационных целей.

Простые просьбы

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

Промежуточный файл сеанса

Добавлена HTTP-сессия на основе файлов Cookie подписи. Информация сеанса читается, но не может быть изменена.

Используйте интерфейс словаря request.session для доступа к данным сеанса или изменения.

Поддержку получили следующие аргументы:

  • secret_key - Это должна быть случайная строка.
  • session_cookie - Значение по умолчанию-Сеанс.
  • max_age-время истечения сеанса в секундах. По умолчанию 2 недели. Если установить None, то срок действия файлов Cookie будет таким же, как продолжительность сеанса браузера.
  • same_site-логотип SameSite предотвращает отправку браузерами сессионных файлов при межсайтовых запросах. По умолчанию используется 'lax'.
  • path-путь к файлам Cookie сеанса. По умолчанию используется '/'.
  • https_only-означает, что флаг безопасности должен быть установлен (только с HTTPS). По умолчанию используется False.
  • domain-домен Cookie, используемый для совместного использования файлов Cookie между поддоменами или между доменами. Браузер устанавливает домен по умолчанию в качестве того же хоста, который устанавливает файлы Cookie, за исключением субдоменов (ссылка).

    from Starlette.applications import Starlette from Starlette.middleware import Middleware from Starlette. middleware.sessions import SessionMiddleware

    routes =..

    middleware =( Middleware(SessionMiddleware, secret_key =..., https_only =True) ]

    app = Starlette(routes=routes, middleware=middleware)

Перенаправление промежуточного файла HTTPS

Все входящие запросы должны быть https или wss. Любой запрос, входящий в http или ws, будет перенаправлен на безопасный план.

from Starlette.applications import Starlette
from Starlette.middleware import Middleware
from starlett.middleware. https redirect import HTTPS Redirect Middleware

routes =…

middleware = [
    Middleware(HTTPS Redirect Middleware)
]

app = Starlette(routes=routes, middleware=middleware)

Для этого класса промежуточных элементов параметры настройки отсутствуют.

Проверенное промежуточное программное обеспечение

Все входящие запросы должны иметь правильно настроенный заголовок Host для защиты от HTTP-атак.

Из Starlette.applications Import Starlette
from Starlette.middleware import Middleware
from starlett.middleware.trustedhost import TrustedHostMiddleware

routes =..

middleware =(
    Middleware(TrustedHostMiddleware, allowed_hosts =['example.com','*. example.com'])
]

app = Starlette(routes=routes, middleware=middleware)

Поддержку получили следующие аргументы:

  • allowed_hosts-список доменов, которые должны быть разрешены в качестве имен хостов. Домены, такие как *.example.com, могут быть использованы для соответствия поддоменов. Чтобы разрешить любое имя хоста, используйте allowed_hosts=["*"] или опустите промежуточные элементы.
  • www_redirect-Если установлено значение True, запрос на разрешенную версию хоста без ww будет перенаправлен на его www соответствующую версию. По умолчанию используется True.

Если входящий запрос не проверен должным образом, будет отправлен ответ 400.

Промежуточный файл GZip

Ответ GZip, который обрабатывает любой запрос, содержащий Accept-Encoding в заголовке "gzip".

Промежуточное ПО обрабатывает стандартные ответы и ответы потока.

Из Starlette.applications Import Starlette
from Starlette.middleware import Middleware
from starlett.middleware.gzip import GZipMiddleware


routes =…

middleware =(
    Middleware(GZipMiddleware, minimum_size =1000, compresslevel=9)
]

app = Starlette(routes=routes, middleware=middleware)

Поддержку получили следующие аргументы:

  • minimum_size-не сжигайте GZip для ответов, которые меньше этого минимального размера байта. По умолчанию используется 500.
  • compresslevel-используется во время сжатия GZip. Это целое число от 1 до 9. Значение по умолчанию-9. Чем ниже значение, тем быстрее сжатие, но тем больше размер файла; чем выше значение, тем медленнее сжатие, но тем меньше размер файла.

Промежуточные компоненты не сжимают GZip ответы, которые уже настроены Content-Encoding, чтобы предотвратить их кодирование дважды.

BaseHTTP промежуточный элемент

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

Использование

Чтобы реализовать класс промежуточного ПО с BaseHTTPMiddleware, вам придется переписать метод async def dispatch(request, call_next).

Из Starlette.applications Import Starlette
from Starlette.middleware import Middleware
from starlette. middleware.base import BaseHTTPMiddleware


Customclass HeaderMiddleware (BaseHTTPMiddleware):
    async def dispatch(self, request, call_next):
        Ответ: await call_next (request)
        response.headers ['Custom'] = 'Example'
        Возвращение ответа

routes =..

middleware = [
    Middleware(CustomHeaderMiddleware)
]

app = Starlette(routes=routes, middleware=middleware)

Если вы хотите предоставить параметры настройки для класса промежуточного продукта, вы должны переписать метод __init__, чтобы убедиться, что первый аргумент является app, а любой другой-необязательный параметр ключевого слова. Если вы это сделаете, убедитесь, что вы установили свойство app на экземпляре.

Customclass HeaderMiddleware (BaseHTTPMiddleware):
    def_init_(self, приложение, header_value ='Example'):
        super()._init__(приложение)
        self.header_value = header_value

    async def dispatch(self, request, call_next):
        Ответ: await call_next (request)
        response.headers ['Custom'] = self.header_value
        Возвращение ответа


middleware =(
    Middleware(CustomHeaderMiddleware, header_value ='Customized')
]

app = Starlette(routes=routes, middleware=middleware)

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

Ограничения.

В настоящее время у BaseHTTPMiddleware есть некоторые известные ограничения:

  • использует BaseHTTPMiddleware, чтобы предотвратить распространение изменений в contextlib.ContextVar вверх. То есть, если вы установите значение для ContextVar в конечной точке и попытаетесь прочитать его из ретранслятора, вы обнаружите, что значение отличается от того, которое вы установили в конечной точке (пример этого поведения см. в этом тесте).

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

Чистые промежуточные детали ASGI

Спецификация ASGI позволяет реализовать промежуточное ПО ASGI непосредственно с помощью интерфейса ASGI, а затем в качестве серии приложений ASGI вызывает следующее. Фактически, класс промежуточного ПО, входящий в состав Starlette, является именно таким.

Этот более низкий уровень обеспечивает больший контроль над поведением и улучшает взаимодействие между фреймворками и серверами. Он также позволяет преодолеть ограничения BaseHTTPMiddleware.

Составление простых промежуточных деталей ASGI

Наиболее распространенный способ создания промежуточного элемента ASGI-использовать класс.

class ASGIMiddleware:
    def_init__(self, app):
        self.app = app

    async def_call__(self, scope, receive, send):
        self.app (scope, receive, send)

Вышеуказанное промежуточное ПО является самым базовым промежуточным ПО ASGI. Он принимает родительское приложение ASGI в качестве аргумента в своей конструкторе и реализует метод async __call__, который вызывает родительское приложение.

Некоторые реализационные варианты, такие как asgi-cors, используют альтернативный стиль, используя функции:

Import Functools

def asgi_middleware ():
    def asgi_decorator (app):

        functools wraps(приложение)
        async def wrapped_app (scope, proceive, send):
            Приложение await App(scope, receive, send)

        Return wrapped_app

    Return Asgi_Decorator

В любом случае, промежуточное решение ASGI должно быть вызываемым объектом, который должен принимать три параметра:scope,receive и send.

  • scope-это словарь, в котором хранится информация о подключении, где scope["type"] может быть:
    • "http" Используется для HTTP-запросов;
    • "websocket" : Для подключения WebSocket.
    • "lifespan" Для сообщений ASGI жизненного цикла.
  • receive и send Может использоваться для обмена сообщениями о событиях ASGI с сервером ASGI, о чем подробнее говорится ниже. Тип и содержание этих сообщений зависят от типа области. Подробнее см. в спецификации ASGI.

Использование простых промежуточных элементов ASGI

Промежуточные компоненты ASGI можно использовать так же, как и любые другие промежуточные компоненты:

Из Starlette.applications Import Starlette
from Starlette.middleware import Middleware

middleware import ASGIMiddleware

routes =..

middleware =(
    Middleware(ASGIMiddleware),
]

app = Starlette(…, middleware=middleware)

См. также Использование промежуточных элементов.

Примечания типа

Существует два способа добавления комментариев к промежуточным элементам: используйте сам Starlette или asgiref.

  • Использование Starlette: подходит для большинства распространенных случаев использования.

    from starlette.types import ASGIApp, Message, Scope, Receive, Send

    class ASGIMIDDleware: def_init__(self, приложение: ASGIApp) -> None: self.app = app

    async def_call__(self, scope: Scope, receive: Receive, send: Send) -> None:
        if scope["type"] != "http":
            Return await self.app (scope, receive, send)
    
        async def send_wrapper (message: Message) -> None:
            ##…Do Something
            AWAIT Send(message)
    
        self.app (scope, receive, send_wrapper)
    
  • использует asgiref: для более строгих подсказок типов.

    Из asgiref.typing import ASGI3 Application, ASGIReceeeCallable, ASGISendCallable, Scope from asgiref.typing import ASGIReceeiveEvent, ASGISendEvent

    class ASGIMiddleware: def_init__(self, приложение: ASGI3Application) -> None: self.app = app

    async def_call__(self, scope: Scope, receive: ASGIReceeeeCallable, send: ASGISendCallable) -> None:
        if scope["type"] != "http":
            self.app (scope, receive, send)
            Возврат
    
        async def send_wrapper (message: ASGISendEvent) -> None:
            #…Do Something
            AWAIT Send(message)
    
        return await self.app (scope, receive, send_wrapper)
    

Обычные модели

Обработка только определенных запросов

ASGI промежуточного ПО может применять определенные действия в зависимости от содержания scope.

Например, если вы работаете только с HTTP-запросом, вы можете написать...

class ASGIMiddleware:
    def_init__(self, app):
        self.app = app

    async def_call__(self, scope, receive, send):
        if scope["type"] != "http":
            self.app (scope, receive, send)
            Возврат

        # Do Something here!

        self.app (scope, requeive, send)

Аналогичным образом, только промежуточное программное обеспечение WebSocket будет защищено от scope["type"] != "websocket".

Промежуточные файлы могут также работать по-разному в зависимости от способа запроса, URL и первого класса.

Переплетение компонентов Starlette

Starlette предлагает несколько структур данных, которые принимают параметры ASGI scope,receive и/или send, что позволяет работать на более высоком уровне абстракции. К таким структурам относятся Request,Headers,QueryParams,URL и т. д.

Например, можно создать экземпляр Request, чтобы упростить проверку HTTP-запросов:

Из starlette, requests import Request

Класс ASGIMIDDleware:
    def_init__(self, app):
        self.app = приложение

    async def_call__(self, scope, receive, send):
        if scope["type"] = "http":
            Request = Request(scope)
            ... # Use `request.method`,`request.url`,`request.headers`, etc.

        self.app (scope, requeive, send)

Вы также можете повторно использовать ответы, которые также являются приложениями ASGI.

Отправить горячий ответ

Проверка подключения к scope позволяет вам с определенными условиями вызывать различные приложения ASGI. Одним из вариантов использования может быть отправка ответа без вызова приложения.

Например, в этом промежуточном файле используется словарь для постоянного перенаправления на основе запрошенного пути. Если вам нужно перестроить шаблон URL-адреса, это может быть использовано для обеспечения постоянной поддержки старых URL-адресов.

from Starlette.datastructures import URL
from starlet.responses import RedirectResponse

class RedirectsMiddleware:
    def_init_(self, приложение, path_mapping: dict):
        self.app = приложение
        self.path_mapping = path_mapping

    async def_call__(self, scope, receive, send):
        if scope["type"] != "http":
            self.app (scope, receive, send)
            Возвращение

        url = URL(scope=scope)

        if url.path in self.path_mapping:
            url = url.replace (путь = self.path_mapping [url.path])
            Response = RedirectResponse(url, status_code =301)
            await response(scope, receive, send)
            Возвращение

        self.app (scope, requeive, send)

Пример использования выглядит следующим образом:

from Starlette.applications import Starlette
from Starlette.middleware import Middleware

routes =..

redirections = {
    "/v1/resource/": "/v2/resource/",
    # ...
}

middleware =(
    Middleware(RedirectsMiddleware, path_mapping =redirections),
]

app = Starlette(routes=routes, middleware=middleware)

Проверка или изменение запросов

Запрашиваемая информация может быть получена или изменена с помощью scope. Полный пример этого режима см. в разделе ProxyHeadersMiddleware Uvicorn, который проверяет и настраивает scope, когда предоставляет услуги за фронт-агентом.

Кроме того, упаковка вызываемых объектов receive ASGI позволяет вам получить доступ к телу HTTP-запроса или изменить его, используя сообщение о событиях http.request ASGI.

Например, это промежуточное решение вычисляет и фиксирует размер входящего субъекта запроса...

class LoggedRequestBodySizeMiddleware:
    def_init__(self, app):
        self.app = приложение

    async def_call__(self, scope, receive, send):
        if scope["type"] != "http":
            self.app (scope, requeive, send)
            Возвращение

        body_size = 0

        async def receive_logging_request_body_size ():
            nonlocal body_size

            message = await receive(
            assert message["type"] = "http.request"

            body_size += len(message.get ("body", b""))

            if not message.get ("more_body", False):
                (f"Size of request body was:{body_size}bytes")

            Возврат сообщения

        self.app (scope, receive_logging_request_body_size, send)

Аналогичным образом, промежуточный модуль WebSocket может работать с сообщениями о событиях websocket.receive ASGI для проверки или изменения входящих данных WebSocket.

Пример изменения тела HTTP-запроса см. в msgpack-asgi.

Проверка или изменение ответов

Упаковка вызываемых объектов send ASGI позволяет вам проверить или изменить ответы HTTP, отправленные базовыми приложениями. Для этого реагируйте на сообщения о событиях http.response.start или http.response.body ASGI.

Например, этот промежуточный элемент добавляет несколько фиксированных дополнительных заголовков ответа:

Из Starlette.datastructures import MutableHeaders

class ExtraResponseHeadersMiddleware:
    def_init__(self, app, headers):
        self.app = app
        self.headers = headers

    async def_call__(self, scope, receive, send):
        if scope["type"] != "http":
            Return await self.app (scope, receive, send)

        async def send_with_extra_headers (message):
            if message["type"] = "http. response.start":
                headers = MutableHeaders(scope=message)
                Для ключа, значения в self.headers:
                    headers append(ключ, значение)

            AWAIT Send(Message)

        self.app (scope, receive, send_with_extra_headers)

См. также asgi-logger, где есть пример проверки ответов HTTP и записи настраиваемых строк журнала доступа HTTP.

Аналогичным образом, промежуточный продукт WebSocket может манипулировать сообщениями о событиях websocket.send ASGI для проверки или изменения исходящих данных WebSocket.

Обратите внимание, что если вы измените текст ответа, вам нужно обновить заголовок ответа Content-Length, чтобы соответствовать новой длине тела ответа. Полный пример см. в brotli-asgi.

Перенос информации в конечные точки

Если вам нужно поделиться информацией с базовым приложением или конечным пунктом, вы можете сохранить ее в словаре scope. Имейте в виду, что это соглашение-например, Starlette использует этот метод для обмена информацией о маршруте с конечной точкой, но это не является частью спецификации ASGI. Если вы это сделаете, убедитесь, что используйте клавиши, которые вряд ли будут использоваться другими промежуточными приложениями или приложениями, чтобы избежать конфликтов.

Например, при включении следующего промежуточного компонента конечные точки будут иметь доступ к request.scope["asgi_transaction_id"].

Импортированные uid

class TransactionТрентированная iddleware:
    def_init__(self, app):
        self.app = app

    async def_call__(self, scope, receive, send):
        scope["asgi_transaction_id"] = uuid.uuuid4 ()
        self.app (scope, receive, send)

Удаление и обработка ошибок

Вы можете упаковать приложение в блок try/except/finally или в контекстный менеджер для выполнения операций очистки или обработки ошибок.

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

Импортное время

class MonitoringMiddleware:
    def_init__(self, app):
        self.app = приложение

    async def_call__(self, scope, receive, send):
        start = time (()
        try:
            self.app (scope, requeive, send)
        Вычисление исключений как exc
            # Process the exception
            Rise
        finally: .
            Время (время))
            elapsed = end - start
            ... # Submit `elapsed` as a metric to a monitoring backend

См. также timing-asgi для получения полного примера этого режима.

Потенциальные проблемы

Промежуточные элементы ASGI должны быть недействующими.

Поскольку ASGI предназначен для обработки одновременных запросов, любое состояние соединения должно быть ограничено реализацией __call__. В противном случае часто возникают конфликты чтения и записи между запросами переменных, что может привести к ошибкам.

Например, если в ответе присутствует заголовок X-Mock, то это действие будет условно заменять текст ответа…

…Делать

```python
from starlette.datastructures import Headers

class MockResponseBodyMiddleware:
    def __init__(self, app, content):
        self.app = app
        self.content = content

    async def __call__(self, scope, receive, send):
        if scope["type"] != "http":
            await self.app(scope, receive, send)
            return

        # A flag that we will turn `True` if the HTTP response
        # has the 'X-Mock' header.
        # ✅: Scoped to this function.
        should_mock = False

        async def maybe_send_with_mock_content(message):
            nonlocal should_mock

            if message["type"] == "http.response.start":
                headers = Headers(raw=message["headers"])
                should_mock = headers.get("X-Mock") == "1"
                await send(message)

            elif message["type"] == "http.response.body":
                if should_mock:
                    message = {"type": "http.response.body", "body": self.content}
                await send(message)

        await self.app(scope, receive, maybe_send_with_mock_content)
```
  • Не надо

    from starlette.datastructures import Headers
    
    class MockResponseBodyMiddleware:
        def __init__(self, app, content):
            self.app = app
            self.content = content
            # ❌: This variable would be read and written across requests!
            self.should_mock = False
    
        async def __call__(self, scope, receive, send):
            if scope["type"] != "http":
                await self.app(scope, receive, send)
                return
    
            async def maybe_send_with_mock_content(message):
                if message["type"] == "http.response.start":
                    headers = Headers(raw=message["headers"])
                    self.should_mock = headers.get("X-Mock") == "1"
                    await send(message)
    
                elif message["type"] == "http.response.body":
                    if self.should_mock:
                        message = {"type": "http.response.body", "body": self.content}
                    await send(message)
    
            await self.app(scope, receive, maybe_send_with_mock_content)
    

См. также приложение GZipMiddleware, чтобы получить полный пример реализации, которая решает эту потенциальную проблему.

Читать дальше

Этот документ должен служить хорошей основой для создания промежуточного ПО ASGI.

Тем не менее, есть много хороших статей на эту тему:

Использование промежуточных элементов в других рамах

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

app = TrustedHostMiddleware(app, allowed_hosts =['example.com'])

Вы также можете сделать это с экземпляром приложения Starlette, но лучше использовать стиль middleware=<List of Middleware instances>, так как он будет:

  • гарантирует, что все находится в одном из самых внешних ServerErrorMiddleware.
  • сохраняет верхний экземпляр app.

Применение промежуточного компонента к группе маршрутизации

Промежуточные компоненты также могут быть добавлены в экземпляр Mount, что позволяет применять их к набору маршрутизации или подприложений:

Из Starlette.applications Import Starlette
from Starlette.middleware import Middleware
from starlett.middleware.gzip import GZipMiddleware
from starlette routing import Mount, Route


routes =]
    Марина (
        "/",
        routes=[
            Маршрут (
                /example,
                endpoint=…,
            )
        ],
        middleware=[Middleware(GZipMiddleware)]
    )
]

app = Starlette(routes=routes)

Обратите внимание, что промежуточное ПО, используемое таким образом, не упаковано в промежуточное ПО, как это было сделано для приложений Starlette. Обычно это не проблема, так как оно подходит только для проверки или изменения промежуточного ПО Response, и даже в этом случае вы можете не использовать эту логику для ответа на ошибку. Если вы действительно хотите применить логику промежуточного ПО только к некоторым маршрутам, есть несколько вариантов:

  • добавляет ExceptionMiddleware на Mount
  • добавляет блок try/except в ваш промежуточный продукт и возвращает ответ на ошибку.
  • разделяет маркировку и обработку на два промежуточных продукта, один из которых размещается на Mount, помечая ответ как требуемый для обработки (например, путем настройки scope["log-response"] = True), а другой применяется к приложению Starlette для выполнения тяжелой работы.

Класс Route/WebSocket также принимает параметр middleware, который позволяет применять промежуточное программное обеспечение к одному маршруту:

from Starlette.applications import Starlette
from Starlette.middleware import Middleware
from starlett.middleware.gzip import GZipMiddleware
От Starlet.routing Import Route


routes = [
    Маршрут (
        /example,
        endpoint=…,
        middleware=[Middleware(GZipMiddleware)]
    )
]

app = Starlette(routes=routes)

Вы также можете применить промежуточное ПО к классу Router, что позволяет применить промежуточное ПО к набору маршрутов:

from Starlette.applications import Starlette
from Starlette.middleware import Middleware
from starlett.middleware.gzip import GZipMiddleware
from starlette routing import Route, Router


routes = [
    Route("/example", endpoint=...),
    Route("/another", endpoint=...),
]

router = Router(routes=routes, middleware=[Middleware(GZipMiddleware)])

Промежуточная информация от третьих сторон

asgi-auth-github)

Это промежуточное ПО добавляет проверку подлинности для любого приложения ASGI, требуя от пользователей войти в систему с помощью своей учетной записи GitHub (через OAuth). Доступ может быть ограничен определенными пользователями или членами определенной организации или группы GitHub.

ASGI-CSRF

Промежуточный продукт для защиты от атак CSRF. Этот промежуточный продукт реализует режим двойного представления файлов Cookie, в котором устанавливается файл Cookie, а затем скрываются поля формы с csrftoken или x-csrftoken Сравнение заголовков HTTP.

Authlib промежуточная часть

Прямая замена промежуточного ПО сеанса Starlette с использованием модуля jwt authlib.

Bugsnag промежуточное

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

Средство CSRF

Средство для защиты от атак CSRF. Это промежуточное ПО реализует режим двойного представления файлов Cookie, в котором устанавливается файл Cookie, который затем сравнивается с HTTP-заголовком x-csrftoken.

Ранние промежуточные элементы данных

Промежуточные и декоративные устройства для обнаружения и отклонения ранних запросов на данные TLSv1.3.

Прометея Промежуточная

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

Промежуточная деталь заголовка агента

Uvicorn содержит класс промежуточного программного обеспечения для определения IP-адреса клиента по заголовкам X-Forwarded-Proto и X-Forwarded-For при использовании прокси-сервера. Возможно, вам потребуется настроить этот промежуточный для более сложных конфигураций прокси-сервера.

Ограничение скорости промежуточного устройства

Одна скорость ограничивает промежуточную часть. Регулярные выражения соответствуют URL-адресу; гибкие правила; высокая настраиваемость. Очень просто в использовании.

RequestId промежуточный

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

Промежуточный элемент Rollbar

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

StarletteOpentracing

Класс промежуточного программного обеспечения, который отправляет информацию о отслеживании на трекер, совместимыйс OpenTracing.io, и может использоваться для анализа и мониторинга распределенных приложений.

Безопасные Cookies промежуточное

Настраиваемый промежуточный продукт для добавления автоматического шифрования и дешифрования файлов Cookie в приложение Starlette, а также дополнительная поддержка существующих промежуточных файлов на основе файлов Cookie.

Промежуточные элементы времени

Класс промежуточного программного обеспечения для отправки информации о времени (CPU и настенного времени) для каждого запроса, который проходит через него. Включает примеры того, как эти часы могут быть отправлены как индикатор statsd.

WSGIMiddleware

Класс промежуточного ПО, отвечающий за преобразование приложений WSGI в приложения ASGI.