Middleware
Starlette contient plusieurs classes middleware pour ajouter des comportements qui s'appliquent à l'ensemble de l'application. ceux-ci sont implémentés en tant que classes middleware ASGI standard et peuvent être appliqués à Starlette ou à toute autre application ASGI.
Utilisation du middleware
La classe d'application Starlette vous permet d'inclure le middleware ASGI d'une manière qui garantit qu 'il est toujours enveloppé dans un gestionnaire d'exception.
de starlette.applications import Starlette
de starlette.middleware import Middleware
de starlette.middleware.httpsredirect import HTTPSRedirectMiddleware
de starlette.middleware.trustedhost import TrustedHostMiddleware
routes = ...
# Ensure que toutes les demandes incluent un 'example.com' ou
# '*.example.com' host header, et strictement enforce https-only access.
middleware = [
Middleware(
TrustedHostMiddleware,
allowed_hosts=['example.com','*.example.com'],
),
Middleware(HTTPSRedirectMiddleware)
]
app = Starlette(routes=routes, middleware=middleware)
Par défaut, chaque application Starlette inclut automatiquement deux segments de middleware:
ServerErrorMiddleware-Assurez-vous que les exceptions d'application peuvent renvoyer une page 500 personnalisée ou afficher les informations de suivi de l'application en mode DEBUG.ExceptionMiddleware-Ajoute un gestionnaire d'exception afin qu 'un type particulier de situation d'exception attendue puisse être associé à une fonction de gestionnaire, par exemple, le déclenchement d'unHTTPException(status_code=404)à l'intérieur d'un point de terminaison finira par rendre une page 404 personnalisée.
Le middleware est évalué de haut en bas, donc dans notre exemple d'application, le processus d'exécution ressemblerait à ceci:
- Le middleware
ServerErrorMiddlewareTrustedHostMiddlewareHTTPSRedirectMiddlewareExceptionMiddleware
- Sélection de route
- Endpoint à
Les middlewares suivants peuvent être implémentés dans le pack Starlette:
Le middleware de CORS
Ajoutez un en-tête CORS approprié aux réponses envoyées vers l'extérieur pour permettre les demandes inter-sources des navigateurs.
Les paramètres par défaut utilisés par l'implémentation CORSMiddleware sont restrictifs par défaut, vous devez donc activer explicitement des sources, des méthodes ou des en-têtes spécifiques afin que les navigateurs soient autorisés à les utiliser dans un contexte inter-domaines.
de starlette.applications import Starlette
de starlette.middleware import Middleware
de starlette.middleware.cors import CORSMiddleware
routes = ...
middleware = [
Middleware(CORSMiddleware, allow_origins=['*'])
]
app = Starlette(routes=routes, middleware=middleware)
Les arguments suivants ont été soutenus:
allow_origins-Liste des sources qui devraient être autorisées à faire des demandes inter-sources. par exemple['https://example.org', 'https://www.example.org']. vous pouvez utiliser['*']pour autoriser n'importe quelle source.allow_origin_regex-Une chaîne d'expression régulière utilisée pour faire correspondre les sources qui devraient être autorisées à faire des demandes inter-sources. exemple:'https://.*\.example\.org'.allow_methods- Une liste des méthodes HTTP qui devraient être autorisées pour les requêtes inter-sources. par défaut['GET']Vous pouvez utiliser le['*']pour permettre toutes les méthodes standard.allow_headers- Une liste des en-têtes de requête HTTP qui devraient être pris en charge pour les requêtes inter-sources.[]Vous pouvez utiliser le['*']pour permettre tous les en-têtes. pour les demandes CORS,Accept、Accept-Language、Content-LanguageetContent-TypeLes en-têtes sont toujours autorisés.allow_credentials- Cookie indiquant que les demandes inter-sources doivent être prises en charge. par défautFalseEn outre, pour permettre le certificat,allow_origins、allow_methodset deallow_headersne peut être fixé à['*']Ils doivent tous être explicitement désignés.expose_headers-Indique tout en-tête de réponse qui devrait être rendu accessible au navigateur.[]est par défaut.max_age- Définit le temps maximum en secondes pour que le navigateur cache la réponse CORS.600。
Le middleware répond à deux types spécifiques de requêtes HTTP:
Requêtes de pré-contrôle pour le partage des ressources interdomaines (CORS)
Il s'agit de toute demande OPTIONS avec les en-têtes Origin et Access-Control-Request-Method. Dans ce cas, le middleware interceptera la demande entrante et répondra avec l'en-tête CORS approprié, ainsi qu 'une réponse 200 ou 400 à des fins d'information.
Une simple demande
Toute demande avec un en-tête Origin. Dans ce cas, le middleware passera la demande comme d'habitude, mais inclura l'en-tête CORS approprié dans la réponse.
Le middleware sessionnel
Ajout d'une session HTTP basée sur un Cookie signé Les informations de session sont lisibles mais non modifiables.
Utilisez l'interface du dictionnaire request.session pour accéder aux données de session ou les modifier.
Les arguments suivants sont soutenus:
secret_key- Ce devrait être une chaîne aléatoire.session_cookie- La valeur par défaut est "Session".max_age-Durée d'expiration de la session en secondes. par défaut 2 semaines. si elle est définie surNone, le Cookie aura la même durée de vie que la session du navigateur.same_site-Le drapeau SameSite empêche les navigateurs d'envoyer des cookies de session lors de demandes intersites.'lax'est la valeur par défaut.path-chemin défini pour les cookies de session.'/'est par défaut.https_only-Indique que le drapeau de sécurité doit être défini (utilisable uniquement avec HTTPS).Falseest par défaut.-
domain- Cookie Domaine utilisé pour partager des cookies entre sous-domaines ou entre domaines. le navigateur définit le domaine par défaut sur le même hôte qui a défini le Cookie, à l'exclusion des sous-domaines (références).de starlette.applications import Starlette de starlette.middleware import Middleware de starlette.middleware.sessions import SessionMiddleware
routes = ...
middleware = [ Middleware(SessionMiddleware, secret_key=..., https_only=True) ]
app = Starlette(routes=routes, middleware=middleware)
Redirection du middleware HTTPS
Impose que toutes les requêtes entrantes soient https ou wss Toute requête entrante vers http ou ws sera redirigée vers le schéma de sécurité.
de starlette.applications import Starlette
de starlette.middleware import Middleware
de starlette.middleware.httpsredirect import HTTPSRedirectMiddleware
Routes = ...
middleware = [
Middleware(HTTPSRedirectMiddleware)
]
app = Starlette(routes=routes, middleware=middleware)
Pour cette classe middleware, il n'y a pas d'option de configuration.
Middleware pour Trusted Host
Impose que toutes les requêtes entrantes aient un en-tête Host correctement configuré pour se protéger contre les attaques d'en-tête hôte HTTP.
de starlette.applications import Starlette
de starlette.middleware import Middleware
de starlette.middleware.trustedhost import TrustedHostMiddleware
Routes = ...
middleware = [
Middleware(TrustedHostMiddleware, allowed_hosts=['example.com','*.example.com'])
]
app = Starlette(routes=routes, middleware=middleware)
Les arguments suivants ont été soutenus:
allowed_hosts-Une liste de noms de domaine qui devraient être autorisés comme noms d'hôte. les noms de domaine génériques tels que*.example.compeuvent être utilisés pour correspondre aux sous-domaines. pour autoriser tout nom d'hôte, utilisezallowed_hosts=["*"]ou omettez le middleware.www_redirect-Si elle est définie sur True, les requêtes pour autoriser une version non www d'un hôte seront redirigées vers sa version www correspondante.Truepar défaut.
Si la demande entrante n'est pas correctement validée, une réponse 400 sera envoyée.
GZip Middleware pour GZip
Gérer les réponses GZip pour toute demande contenant "gzip" dans l'en-tête Accept-Encoding.
Le middleware traitera les réponses standard et les réponses de flux.
de starlette.applications import Starlette
de starlette.middleware import Middleware
from starlette.middleware.gzip import GZipMiddleware
Routes = ...
middleware = [
Middleware(GZipMiddleware, minimum_size=1000, compresslevel=9)
]
app = Starlette(routes=routes, middleware=middleware)
Les arguments suivants ont été soutenus:
minimum_size-Ne pas compresser GZip pour les réponses inférieures à cette taille minimale d'octets.500est la valeur par défaut.compresslevel-Utilisé pendant la compression GZip. c'est un entier de 1 à 9. la valeur par défaut est9. plus la valeur est basse, plus la compression est rapide, mais plus la taille du fichier est grande; plus la valeur est élevée, plus la compression est lente, mais la taille du fichier est petite.
Le middleware n'effectue pas de compression GZip sur les réponses pour lesquelles Content-Encoding a été configuré, afin d'éviter qu 'elles ne soient encodées deux fois.
Le middleware BaseHTTP
Une classe abstraite qui vous permet d'écrire un middleware ASGI pour une interface requête/réponse.
Utilisation de la situation
Pour implémenter une classe middleware avec BaseHTTPMiddleware, vous devez réécrire la méthode async def dispatch(request, call_next).
de starlette.applications import Starlette
de starlette.middleware import Middleware
de starlette.middleware.base import BaseHTTPMiddleware
Classe CustomHeaderMiddleware(BaseHTTPMidleware):
async def dispatch(self, request, call_next):
response = await call_next(demande)
response.headers ['Custom'] = 'Exemple'
Retour Réponse
Routes = ...
middleware = [
Middleware(CustomHeaderMiddleware)
]
app = Starlette(routes=routes, middleware=middleware)
Si vous souhaitez donner des options de configuration à une classe middleware, vous devez réécrire __init__ méthode, en s'assurant que le premier paramètre est app , tous les autres paramètres sont des paramètres de mots-clés facultatifs. si vous le faites, assurez-vous de les définir sur votre instance. app propriétés.
Classe CustomHeaderMiddleware(BaseHTTPMidleware):
def __init__(self, app, header_value ='Exemple'):
super().__init__(app)
self.header_value = header_value
async def dispatch(self, request, call_next):
response = await call_next(demande)
response.headers [`Custom '] = self.header_value
Retour Réponse
middleware = [
Middleware(CustomHeaderMiddleware, header_value ="Customized")
]
app = Starlette(routes=routes, middleware=middleware)
Une classe middleware ne devrait pas modifier son état en dehors de la méthode __init__. au lieu de cela, vous devriez laisser tout état local à la méthode dispatch ou le passer explicitement, plutôt que de modifier l'état de l'instance middleware.
Limitation de la
Actuellement,BaseHTTPMiddleware a quelques limitations connues:
- L'utilisation de
BaseHTTPMiddlewareempêchera les modifications apportées àcontextlib.ContextVarde se propager vers le haut. c'est-à-dire que si vous définissez une valeur pourContextVardans un point final et que vous essayez de la lire à partir d'un métaware, vous constaterez que la valeur est différente de celle que vous avez définie dans le point final (voir ce test pour un exemple de ce comportement).
Pour surmonter ces limitations, utilisez un middleware ASGI pur, comme indiqué ci-dessous.
Le middleware ASGI pur
La spécification ASGI permet d'implémenter directement un middleware ASGI en utilisant l'interface ASGI, comme une série d'applications ASGI qui appellent successivement la suivante-en fait, la classe middleware fournie avec Starlette est implémentée de cette façon.
Cette approche de niveau inférieur offre un plus grand contrôle sur le comportement et améliore l'interopérabilité entre les frameworks et les serveurs. il surmonte également les limites de BaseHTTPMiddleware.
Écrire du middleware ASGI pur
La façon la plus courante de créer un middleware ASGI consiste à utiliser une classe.
Classe ASGIMiddleware:
def __init__(self, app):
self.app = application
async def __call__(self, scope, receive, send):
await self.app (scope, receive, send)
Le middleware ci-dessus est le middleware ASGI le plus basique. il reçoit une application ASGI parente comme argument dans son constructeur et implémente une méthode async __call__ qui appelle cette application parente.
Certaines implémentations, telles que asgi-cors, utilisent un style alternatif qui utilise des fonctions:
Importer des functools
def asgi_middleware():
def asgi_deciator (app):
@functools.wraps(app)
async def wrapped_app(scope, receive, send):
Await App(scope, receive, send)
return wrapped_app
return asgi_decoreur
Quoi qu 'il en soit, le middleware ASGI doit être un objet appelable qui accepte trois paramètres:scope,receive et send.
scopeest un dictionnaire qui contient des informations sur les connexions, oùscope["type"]peut être"http": Utilisé pour les requêtes HTTP."websocket": pour les connexions WebSocket."lifespan": Utilisé pour les messages ASGI Lifecycle.
receiveetsendpeuvent être utilisés pour échanger des messages d'événement ASGI avec un serveur ASGI-plus d'informations à ce sujet ci-dessous. le type et le contenu de ces messages dépendent du type de portée. en savoir plus dans la spécification ASGI.
Utilisation d'un middleware ASGI pur
Le middleware ASGI pur peut être utilisé comme tout autre middleware:
de starlette.applications import Starlette
de starlette.middleware import Middleware
de.middleware import ASGIMiddleware
Routes = ...
middleware = [
Middleware(ASGIMiddleware),
]
app = Starlette(…, middleware=middleware)
Voir aussi Utilisation du middleware.
Type de commentaire
Il existe deux façons d'ajouter des annotations à un middleware: en utilisant Starlette elle-même ou asgiref.
-
Utilisation de Starlette: pour la plupart des cas d'utilisation courants.
de starlette.types import ASGIApp, Message, Scope, Receive, Send
Classe ASGIMiddleware: def init(self, app: ASGIApp) -> None: self.app = application
async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None: Si scope["type"] != "http": retour await self.app (scope, receive, send) async def send_wrapper(message: Message) -> None: #Faites quelque chose await send(message) await self.app (scope, receive, send_wrapper) -
utilise
asgiref: pour obtenir des types plus stricts.de asgiref.typing import ASGI3Application, ASGIReceiveCallable, ASGISendCallable, Scope asgiref.typing import ASGIReceiveEvent, ASGISendEvent
Classe ASGIMiddleware: def init(self, app: ASGI3Application) -> None: self.app = application
async def __call__(self, scope: Scope, receive: ASGIReceiveCallable, send: ASGISendCallable) -> None: Si scope["type"] != "http": await self.app (scope, receive, send) Retour à async def send_wrapper(message: ASGISendEvent) -> None: #Faites quelque chose await send(message) return await self.app (scope, receive, send_wrapper)
Modèles communs
Traitement de certaines demandes uniquement
Le middleware ASGI peut appliquer des comportements spécifiques en fonction du contenu de scope.
Par exemple, si seules les requêtes HTTP sont traitées, écrivez «…»
Classe ASGIMidleware:
def __init__(self, app):
self.app = application
async def __call__(soi, scope, receive, send):
Si scope["type"] != "http":
await self.app (scope, receive, send)
Retour à
#Faites-en quelque chose!
await self.app (scope, receive, send)
De même, seul le middleware de WebSocket est protégé sur scope["type"] != "websocket".
Le middleware peut également se comporter différemment en fonction de la méthode de demande, de l'URL, du premier critère.
Multiplexage de composants Starlette
Starlette fournit plusieurs structures de données qui acceptent les paramètres ASGI scope,receive et/ou send, ce qui vous permet de travailler à un niveau d'abstraction plus élevé. ces structures de données incluent Request,Headers,QueryParams,URL, etc.
Par exemple, vous pouvez instancier un Request pour vérifier plus facilement les requêtes HTTP:
de starlette.requests Demande d'importation
Classe ASGIMidleware:
def __init__(self, app):
self.app = application
async def __call__(self, scope, receive, send):
Si scope["type"] == "http":
demande = demande (scope)
... # Use `request.method`,`request.url`,`request.headers`, etc.
await self.app (scope, receive, send)
Vous pouvez également réutiliser les réponses, qui sont également des applications ASGI.
Envoyer une réponse fervente
La vérification de la connexion scope vous permet d'appeler conditionnellement à différentes applications ASGI. un cas d'utilisation pourrait être d'envoyer une réponse sans appeler l'application.
Par exemple, ce middleware utilise un dictionnaire pour effectuer une redirection permanente en fonction du chemin demandé. si vous devez reconstruire le schéma d'URL de routage, cela peut être utilisé pour implémenter un support continu pour les URL héritées.
de starlette.datastructures import URL
de starlette.responses à import RedirectResponse
Classe RedirectsMiddleware:
def __init__(self, app, path_mapping: dict):
self.app = application
self.path_mapping = path_mapping
async def __call__(self, scope, receive, send):
Si scope["type"] != "http":
await self.app (scope, receive, send)
Retour sur
url = URL(scope=scope)
if url.path in self.path_mapping:
url = url.replace(path=self.path_mapping[url.path])
response = RedirectResponse(URL, status_code=301)
Await Response(scope, receive, send)
Retour sur
await self.app (scope, receive, send)
Un exemple d'utilisation ressemblerait à ceci:
de starlette.applications import Starlette
de starlette.middleware import Middleware
Routes = ...
Redirections = {
"/v1/ressource/": "/v2/ressource/",
# ...
}
middleware = [
Middleware(RedirectsMiddleware, path_mapping=redirections),
]
app = Starlette(routes=routes, middleware=middleware)
Demande de vérification ou de modification
Les informations de demande peuvent être consultées ou modifiées en manipulant scope. pour un exemple complet de ce mode, consultez ProxyHeadersMiddleware d'Uvicorn, qui vérifie et ajuste scope lorsqu 'il fournit des services derrière un proxy frontal.
En outre, l'enveloppement d'un objet appelable ASGI receive vous permet d'accéder ou de modifier le corps d'une requête HTTP en manipulant un message d'événement ASGI http.request.
Par exemple, ce middleware calcule et enregistre la taille du corps de la requête entrante…»
Classe LoggedRequestBodySizeMiddleware:
def __init__(self, app):
self.app = application
async def __call__(soi, scope, receive, send):
Si scope["type"] != "http":
await self.app (scope, receive, send)
Retour sur
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"))
Si ce n'est pas message.get("more_body", False):
print(f"Taille du corps demandé était:{body_size}octets").
Retour message
await self.app (scope, receive_logging_request_body_size, send)
De même, le middleware WebSocket peut manipuler le message d'événement ASGI websocket.receive pour vérifier ou modifier les données WebSocket entrantes.
Pour un exemple de modification du corps d'une requête HTTP, consultez msgpack-asgi.
Vérifier ou modifier les réponses
serait send Les objets appelables ASGI sont encapsulés et vous permettent d'examiner ou de modifier les réponses HTTP envoyées par l'application sous-jacente. http.response.start ou bien http.response.body Les messages d'événement ASGI réagissent.
Par exemple, ce middleware ajoute quelques en-têtes de réponse supplémentaires fixes:
de starlette.datastructures import MutableHeaders
Classe ExtraResponseHeadersMiddleware:
def __init__(self, app, headers):
self.app = application
Self.headers = headers
async def __call__(soi, scope, receive, send):
Si 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)
pour la clé, valeur en soi-même.headers:
headers.append(clé, valeur)
await send(message)
await self.app (scope, receive, send_with_extra_headers)
Voir également asgi-logger, qui a un exemple de vérification d'une réponse HTTP et d'enregistrement d'une ligne configurable du journal d'accès HTTP.
De même, le middleware WebSocket peut manipuler les messages d'événement ASGI websocket.send pour vérifier ou modifier les données WebSocket sortantes.
Notez que si vous modifiez le corps de la réponse, vous devrez mettre à jour l'en-tête Content-Length de la réponse pour correspondre à la nouvelle longueur du corps de la réponse. voir brotli-asgi pour un exemple complet.
Transmettre des informations aux points finaux
Si vous avez besoin de partager des informations avec l'application sous-jacente ou le point de terminaison, vous pouvez les stocker dans le dictionnaire scope. Notez qu 'il s'agit d'une convention-par exemple, Starlette utilise cette méthode pour partager des informations de routage avec le point de terminaison-mais cela ne fait pas partie de la spécification ASGI. Si vous le faites, assurez-vous d'utiliser des clés qui ne sont pas susceptibles d'être utilisées par d'autres middlewares ou applications pour éviter les conflits.
Par exemple, lorsque le middleware suivant est inclus, les points de terminaison seront en mesure d'accéder à request.scope["asgi_transaction_id"].
Import uuid
Classe TransactionIDMiddleware:
def__init__(self, app):
self.app
async def__call__(self, scope, receive, send):
scope ["asgi_transaction_id"]= uuid.uuid4 ()
await www.example.com (scope, receive, send)
Nettoyage et gestion des erreurs
Vous pouvez envelopper votre application dans un bloc try/except/finally ou dans un gestionnaire de contexte pour effectuer des opérations de nettoyage ou de gestion des erreurs.
Par exemple, le middleware suivant peut collecter des métriques et gérer les exceptions d'application...
Importer le temps
Classe MonitoringMiddleware:
def__init__(self, app):
self.app
async def__call__(soi, scope, receive, send):
start = temps. temps ()
Essayez:
await www.example.com (scope, receive, send)
Exception comme exc:
#Procéder à l'exception
raise
Finalement:
Fin = temps. temps ()
elapsed = fin-début
... # Submit `elapsed` comme métrique pour un backend de surveillance
Voir aussi timing-asgi pour un exemple complet de ce mode.
Problèmes potentiels
Le middleware ASGI devrait être apatride
Parce que ASGI est destiné à traiter les demandes concurrentes, tout état spécifique à la connexion devrait être limité à l'intérieur de l'implémentation __call__. ne pas le faire entraîne généralement des conflits de lecture/écriture variables entre les demandes, et des erreurs sont susceptibles de survenir.
Par exemple, si un en-tête X-Mock est présent dans la réponse, cette action remplacera conditionnellement le corps de la réponse.
-
Faites le
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) -
Ne pas
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)
Voir aussi GZipMiddleware pour un exemple complet d'implémentation qui résout ce problème potentiel.
Read more about Lire plus
Cette documentation devrait être suffisante pour servir de base solide sur la façon de créer un middleware ASGI.
Cependant, il existe de nombreux excellents articles sur le sujet:
- Introduction à ASGI: l'émergence d'un écosystème réseau Python asynchrone
- Comment écrire le middleware ASGI
Utilisation du middleware dans d'autres frameworks
Pour envelopper un middleware ASGI autour d'autres applications ASGI, vous devez envelopper les instances d'application en utilisant un modèle plus générique:
app = TrustedHostMiddleware(app, allowed_hosts=['example.com'])
Vous pouvez également le faire avec une instance de l'application Starlette, mais il est préférable d'utiliser le style middleware=<List of Middleware instances>, car il:
- s'assure que tout est enveloppé dans une couche externe de
ServerErrorMiddleware. - réserve les instances
appde premier niveau.
Appliquer un middleware à un groupe de routage
Le middleware peut également être ajouté à une instance Mount, ce qui vous permet d'appliquer le middleware à un ensemble de routes ou de sous-applications:
de starlette.applications import Starlette
de starlette.middleware import Middleware
from starlette.middleware.gzip import GZipMiddleware
depuis starlette.routing import Mount, Route
Routes = [
Le mont (
"/",
Routes=[
La Route(
"/exemple",
endpoint=…,
)
],
Middleware=[Middleware(GZipMiddleware)]
)
]
app = Starlette(routes=routes)
Notez que le middleware utilisé de cette façon n'est pas enveloppé dans un middleware de gestion des exceptions comme celui appliqué à une application Starlette. cela ne pose généralement pas de problème car il ne s'applique qu'à la vérification ou à la modification du middleware de Response, et même dans ce cas, vous ne voudrez probablement pas appliquer cette logique aux réponses d'erreur.
- Ajouter une
ExceptionMiddlewaresurMount - ajoute un bloc
try/exceptà votre middleware et renvoie une réponse d'erreur à partir de là. - divise le marquage et le traitement en deux middlewares, l'un placé sur
Mountqui marque la réponse comme nécessitant un traitement (par exemple en configurantscope["log-response"] = True) et l'autre appliqué à l'applicationStarlettepour faire le gros du travail.
La classe Route/WebSocket accepte également un paramètre middleware qui vous permet d'appliquer le middleware à une seule route:
de starlette.applications import Starlette
de starlette.middleware import Middleware
from starlette.middleware.gzip import GZipMiddleware
de starlette.routing Route d'importation
Routes = [
La Route(
"/exemple",
endpoint=…,
Middleware=[Middleware(GZipMiddleware)]
)
]
app = Starlette(routes=routes)
Vous pouvez également appliquer le middleware à la classe Router, ce qui vous permet d'appliquer le middleware à un ensemble de routes:
de starlette.applications import Starlette
de starlette.middleware import Middleware
de starlette.middleware.gzip import GZipMiddleware
de starlette.routing import Route, Router
Routes = [
Route("/example", endpoint=...),
Route("/another", endpoint=...),
]
Router = Router(routes=routes, middleware=[Middleware(GZipMiddleware)])
Middleware par des tiers
asgi-auth-github)
Ce middleware ajoute une authentification à toute application ASGI, obligeant les utilisateurs à se connecter à l'aide de leur compte GitHub (via OAuth). L'accès peut être limité à un utilisateur spécifique ou aux membres d'une organisation ou d'une équipe GitHub spécifique.
asgi-csrf
Middleware utilisé pour se protéger contre les attaques CSRF. Ce middleware implémente un mode de Cookie à double soumission, dans lequel un Cookie est défini, puis placé avec csrftoken pour masquer les champs de formulaire ou x-csrftoken Les en-têtes HTTP sont comparés.
Le middleware Authlib
Une alternative directe au middleware conversationnel Starlette, en utilisant le module jwt d'authlib.
Le middleware de Bugsnag
Une classe middleware pour enregistrer les exceptions dans Bugsnag.
Le middleware CSRF
Middleware utilisé pour se protéger contre les attaques CSRF. Ce middleware implémente un mode de Cookie à double soumission, dans lequel un Cookie est défini, puis comparé à un en-tête HTTP x-csrftoken.
Le middleware des premières données
Middleware et décorateur pour détecter et rejeter les demandes de données antérieures TLSv1.3.
Le middleware de Prometheus
Une classe de middleware pour capturer les métriques Prometheus liées aux demandes et aux réponses, y compris les demandes en cours, le temps, etc.
Proxy Header Middleware (en anglais)
Uvicorn contient une classe middleware pour déterminer l'adresse IP du client en fonction des en-têtes X-Forwarded-Proto et X-Forwarded-For lorsque vous utilisez un serveur proxy.
Intergiciel de limitation de débit
Une sorte de middleware limitant le taux. expressions régulières correspondant aux URL; règles flexibles; hautement personnalisable. très facile à utiliser.
RequestId middleware
Une classe middleware utilisée pour lire/générer un ID de requête et l'attacher au journal de l'application.
Le middleware Rollbar
Une classe middleware pour enregistrer les exceptions, les erreurs et les messages de journal dans Rollbar.
StarletteOpentracing
Une classe de middleware qui envoie des informations de suivi aux trackers compatibles avec OpenTracing.io et peut être utilisée pour analyser et surveiller des applications distribuées.
Cookie de sécurité Middleware
Un middleware personnalisable pour ajouter un cryptage et un déchiffrement automatiques des cookies à l'application Starlette, offrant un support supplémentaire aux middlewares existants basés sur les cookies.
Timing middleware pour
Une classe middleware qui émet des informations de chronométrage (temps CPU et temps horloge murale) pour chaque requête qui la traverse. inclut un exemple de la façon dont ces chronométrages sont émis en tant que métriques statsd.
par WSGIMiddleware
Une classe de middleware responsable de la conversion des applications WSGI en applications ASGI.