미들웨어
Starlette에는 전체 응용 프로그램에 적용되는 동작을 추가하기 위한 여러 미들웨어 클래스가 포함되어 있습니다. 이들은 표준 ASGI 미들웨어 클래스로 구현되며 Starlette 또는 다른 ASGI 응용 프로그램에 적용할 수 있습니다.
미들웨어 사용
Starlette 응용 프로그램 클래스를 사용하면 ASGI 미들웨어를 항상 예외 처리기로 포장하는 방식으로 포함할 수 있습니다.
Starlette. 응용 프로그램이 Starlette에서 가져옵니다.
Starlette.middleware에서 미들웨어 가져오기
Starlette.middle.htpsreDirect 가져오기HTTPSRedirectMiddleware
Starlette.middle.dhost 가져오기에서TrustedHostMiddleware
경로 =. ..
# 모든 요청에 example.com 또는
# '*.example.com' 호스트 헤더이며 http 전용 액세스를 엄격하게 적용합니다.
미들웨어 = [
미들웨어(
TrustedHostMiddleware
허용된 _호스트 = ['example.com', '*.example.com'],
),
미들웨어(HTTPSRedirectMiddleware)
]
App = Starlette(경로 = 경로, middleware=middleware)
기본적으로 각 Starlette 애플리케이션에는 두 개의 미들웨어가 자동으로 포함됩니다.
ServerErrorMiddleware- 응용 프로그램 예외가 사용자 지정 500 페이지를 반환하거나 DEBUG 모드에서 응용 프로그램에 대한 추적 정보를 표시할 수 있도록 합니다. 이것은 항상 가장 바깥쪽에 있는 미들웨어 계층입니다.ExceptionMiddleware- 특정 유형의 예상 예외가 핸들러 기능과 연결될 수 있도록 예외 핸들러를 추가합니다. 예를 들어, 엔드포인트 내에서HTTPException(status_code=404)를 올리면 결국 사용자 지정 404 페이지가 렌더링됩니다.
미들웨어는 위에서 아래로 평가되므로 샘플 애플리케이션에서 실행 흐름은 다음과 같습니다.
- 미들웨어
ServerErrorMiddlewareTrustedHostMiddlewareHTTPSRedirectMiddlewareExceptionMiddleware
- 라우팅
- 엔드포인트
다음 미들웨어 구현은 Starlette 패키지에서 사용할 수 있습니다.
CORS 미들웨어
발신 응답에 적절한 CORS 헤더를 추가하여 브라우저에서 원점 간 요청을 허용합니다.
CORSMiddleware 구현에서 사용하는 기본 매개 변수는 기본적으로 제한적이므로 브라우저가 원본 간 컨텍스트에서 사용할 수 있도록 특정 소스, 메서드 또는 헤더를 명시적으로 활성화해야 합니다.
Starlette. 응용 프로그램이 Starlette에서 가져옵니다.
Starlette.middleware에서 미들웨어 가져오기
Starlette.middle.cors에서 CORSMiddleware 가져오기
경로 =. ..
미들웨어 = [
미들웨어(CORSMiddleware, _ins=['*'])
]
App = Starlette(경로 = 경로, 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- 원산지 간 요청에 대한 쿠키가 지원되어야 함을 나타냅니다. 기본값은False입니다. 또한 자격 증명을 허용하려면allow_origins,allow_methods및allow_headers를['*']로 설정할 수 없으므로 모두 명시적으로 지정해야 합니다.expose_headers- 브라우저에서 액세스할 수 있어야 하는 응답 헤더를 나타냅니다. 기본값은[]입니다.max_age- 브라우저가 CORS 응답을 캐시하는 최대 시간(초)을 설정합니다. 기본값은600입니다.
미들웨어는 두 가지 특정 유형의 HTTP 요청에 응답합니다. ..
CORS(크로스 오리진 리소스 공유) 사전 확인 요청
Origin 및 Access-Control-Request-Method 헤더가 있는 모든 OPTIONS 요청입니다. 이 경우 미들웨어는 수신 요청을 차단하고 적절한 CORS 헤더와 정보 목적으로 200 또는 400 응답으로 응답합니다.
간단한 요청
Origin 헤더가 있는 모든 요청. 이 경우 미들웨어는 평소와 같이 요청을 통과하지만 응답에 적절한 CORS 헤더가 포함됩니다.
대화 미들웨어
서명 쿠키를 기반으로 HTTP 세션을 추가합니다. 세션 정보는 읽을 수 있지만 수정할 수는 없습니다.
request.session 사전 인터페이스를 사용하여 세션 데이터에 액세스하거나 수정합니다.
다음 인수가 지원되었습니다.
secret_key- 임의의 문자열이어야 합니다.session_cookie기본값은 "대화"입니다.max_age- 세션 만료 시간(초)입니다. 기본값은 2 주입니다.None로 설정하면 쿠키의 유효 기간은 브라우저 세션 기간과 동일합니다.same_site- Same사이트 플래그는 사이트 간 요청 중에 브라우저가 세션 쿠키를 보낼 수 없도록 합니다. 기본값은'lax'입니다.path- 세션 쿠키에 대한 경로가 설정되었습니다. 기본값은'/'입니다.https_only- HTTPS에서만 사용할 수 있도록 보안 플래그를 설정해야 함을 나타냅니다. 기본값은False...-
domain- 하위 도메인 간 또는 여러 도메인 간에 쿠키를 공유하는 데 사용되는 쿠키 도메인. 브라우저는 기본적으로 하위 도메인(참조)을 제외하고 쿠키가 설정된 동일한 호스트로 도메인을 설정합니다.Starlette. 응용 프로그램이 Starlette에서 가져옵니다. Starlette.middleware에서 미들웨어 가져오기 Starlette.middle.에서 SessionMiddleware 가져오기
경로 =. ..
미들웨어 = [ 미들웨어(SessionMiddleware, key=. .., https 전용 = 참) ]
App = Starlette(경로 = 경로, middleware=middleware)
HTTPS 리디렉션 미들웨어
들어오는 모든 요청은 https 또는 wss 여야 합니다.http 또는 ws 에 대한 수신 요청은 보안 체계로 리디렉션됩니다.
Starlette. 응용 프로그램이 Starlette에서 가져옵니다.
Starlette.middleware에서 미들웨어 가져오기
Starlette.middle.htpsreDirect 가져오기HTTPSRedirectMiddleware
경로 =. ..
미들웨어 = [
미들웨어(HTTPSRedirectMiddleware)
]
App = Starlette(경로 = 경로, middleware=middleware)
이 미들웨어 클래스에 대한 구성 옵션이 없습니다.
신뢰할 수 있는 호스트 미들웨어
들어오는 모든 요청이 HTTP 호스트 헤더 공격으로부터 보호하기 위해 올바른 Host 헤더 집합을 갖도록 강제합니다.
Starlette. 응용 프로그램이 Starlette에서 가져옵니다.
Starlette.middleware에서 미들웨어 가져오기
Starlette.middle.dhost 가져오기에서TrustedHostMiddleware
경로 =. ..
미들웨어 = [
미들웨어(TrustedHostMiddleware, 허용됨_호스트=['example.com', '*.example.com'])
]
App = Starlette(경로 = 경로, middleware=middleware)
다음 인수가 지원되었습니다.
allowed_hosts- 호스트 이름으로 허용되어야 하는 도메인 목록입니다.*.example.com이러한 와일드 카드 도메인은 하위 도메인과 일치하는 데 사용할 수 있습니다. 호스트 이름을 허용하려면allowed_hosts=["*"]또는 미들웨어를 생략하십시오.www_redirect- True로 설정하면 허용된 호스트의 비 www 버전에 대한 요청이 www 버전으로 리디렉션됩니다.True...
수신 요청이 제대로 확인되지 않으면 400개의 응답이 전송됩니다.
GZip 미들웨어
아무거나 처리 Accept-Encoding 헤더 포함 "gzip" 요청에 대한 GZip 응답.
미들웨어는 표준 및 스트리밍 응답을 모두 처리합니다.
Starlette. 응용 프로그램이 Starlette에서 가져옵니다.
Starlette.middleware에서 미들웨어 가져오기
Starlette.middle.gzip에서 GZipMiddleware를 가져옵니다.
경로 =. ..
미들웨어 = [
미들웨어(GZipMiddleware, 최소_크기=1000, 압축 수준=9)
]
App = Starlette(경로 = 경로, middleware=middleware)
다음 인수가 지원되었습니다.
minimum_size- 이 최소 바이트 크기보다 작은 응답에는 GZip을 사용하지 마십시오. 기본값은500입니다.compresslevel- GZip 압축 중에 사용됩니다. 1에서 9까지의 정수입니다. 기본값은9입니다. 값이 낮을수록 압축 속도가 빠르지만 파일 크기가 클수록 압축 속도가 느려지지만 파일 크기는 작아집니다.
미들웨어는 두 번 인코딩되는 것을 방지하기 위해 이미 Content-Encoding 를 설정한 GZip 응답이 아닙니다.
BaseHTTP 미들웨어
요청/응답 인터페이스에 대한 ASGI 미들웨어를 작성할 수 있는 추상 클래스입니다.
사용법
BaseHTTPMiddleware 를 사용하여 미들웨어 클래스를 구현하려면 async def dispatch(request, call_next) 메서드를 재정의해야 합니다.
Starlette. 응용 프로그램이 Starlette에서 가져옵니다.
Starlette.middleware에서 미들웨어 가져오기
Starlette.middle.base 가져오기 BaseHTTPMiddleware에서
클래스CustomHeaderMiddleware(BaseHTTPMiddleware):
Aync def 디스패치(자체, 요청, 콜_다음):
응답 = 전화 대기 _ 다음 (요청)
응답.헤더 ['사용자 지정'] = '예'
응답 반환
경로 =. ..
미들웨어 = [
미들웨어(CustomHeaderMiddleware)
]
App = Starlette(경로 = 경로, middleware=middleware)
미들웨어 클래스에 대한 구성 옵션을 제공하려면 __init__ 메서드를 재정의하여 첫 번째 인수가 app 이고 나머지 인수가 선택적 키워드 인수인지 확인해야 합니다. 그렇다면 인스턴스에서 app 속성을 설정해야 합니다.
클래스CustomHeaderMiddleware(BaseHTTPMiddleware):
Def__init__ (자체, 앱, 헤더_값 = '예'):
슈퍼(). __init__ (앱)
셀프.헤더 _ 값 = 헤더 _ 값
Aync def 디스패치(자체, 요청, 콜_다음):
응답 = 전화 대기 _ 다음 (요청)
응답.헤더 ['사용자 지정'] = self.헤더 _ 값
응답 반환
미들웨어 = [
미들웨어(CustomHeaderMiddleware, 헤더_밸류='커스터마이징')
]
App = Starlette(경로 = 경로, middleware=middleware)
미들웨어 클래스는 안 됩니다. __init__ 메서드 외부에서 상태를 수정합니다. 대신 어떤 상태든 그대로 두어야 합니다. dispatch 메서드에 로컬이거나 미들웨어 인스턴스의 상태를 변경하는 대신 명시적으로 전달합니다.
제한
현재 BaseHTTPMiddleware 에는 알려진 몇 가지 제한이 있습니다.
BaseHTTPMiddleware를 사용하면contextlib.ContextVar의 변경 사항이 위로 전파되는 것을 방지합니다. 즉, 엔드포인트에서ContextVar값을 설정하고 릴레이에서 읽으려고 하면 값이 엔드포인트에서 설정한 값과 다르다는 것을 알 수 있습니다(이 동작의 예는 이 테스트 참조).
이러한 한계를 극복하려면 아래와 같이 순수 ASGI 미들웨어를 사용하십시오.
순수 ASGI 미들웨어
ASGI 사양을 사용하면 ASGI 인터페이스를 사용하여 ASGI 미들웨어를 일련의 ASGI 애플리케이션으로 직접 구현하고 다음 애플리케이션을 차례로 호출할 수 있습니다. 실제로 Starlette와 함께 제공되는 미들웨어 클래스는 이렇게 구현됩니다.
이 낮은 수준의 접근 방식은 행동에 대한 더 큰 제어를 제공하고 프레임워크와 서버 간의 상호 운용성을 향상시킵니다. BaseHTTPMiddleware 의 한계.
순수한 ASGI 미들웨어 쓰기
ASGI 미들웨어를 만드는 가장 일반적인 방법은 클래스를 사용하는 것입니다.
클래스 ASGIMiddleware:
Def__init__(자체, 앱):
self.app=앱
Aync def__Call __(자체, 범위, 수신, 전송):
대기self.app(범위, 수신, 전송)
위의 미들웨어는 가장 기본적인 ASGI 미들웨어입니다. 생성자에서 상위 ASGI 응용 프로그램을 매개 변수로 사용하고 상위 응용 프로그램을 호출하는 async __call__ 방법을 구현합니다.
asgi-cors 와 같은 일부 구현에서는 다음 기능을 사용하여 대체 스타일을 사용합니다.
기능 도구 가져오기
데프 asgi_middleware ():
Def asgi_ator(앱):
@
Aync def d_app(범위, 수신, 전송):
대기 앱(범위, 수신, 전송)
반품 포장 _ 앱
asgi_ator 반환
그러나 ASGI 미들웨어는 scope,receive 및 send 의 세 가지 매개 변수를 허용하는 호출 가능한 개체여야 합니다.
scope는 연결에 대한 정보를 담고 있는 사전입니다. 여기서scope["type"]는 다음과 같습니다."http": HTTP 요청에 사용됩니다."websocket": WebSocket 연결에 사용됩니다."lifespan": ASGI 라이프사이클 메시지의 경우.
receive및send는 ASGI 서버와 ASGI 이벤트 메시지를 교환하는 데 사용할 수 있습니다. 자세한 내용은 아래에 나와 있습니다. 이러한 메시지의 유형과 내용은 범위 유형에 따라 다릅니다. ASGI 사양에서 자세히 알아보십시오.
순수한 ASGI 미들웨어 사용
순수 ASGI 미들웨어는 다른 미들웨어와 마찬가지로 사용할 수 있습니다.
Starlette. 응용 프로그램이 Starlette에서 가져옵니다.
Starlette.middleware에서 미들웨어 가져오기
미들웨어에서 ASGIMiddleware 가져오기
경로 =. ..
미들웨어 = [
미들웨어(ASGIMiddleware),
]
앱 = Starlette (. ..middleware=middleware)
미들웨어 사용을 참조하십시오.
주석 입력
미들웨어에 주석을 다는 방법에는 두 가지가 있습니다. Starlette 자체 또는 asgiref 를 사용합니다.
-
Starlette 사용: 대부분의 일반적인 사용 사례에 적합합니다.
Starlette.type에서 ASGIApp, 메시지, 범위, 수신, 전송 가져오기
클래스 ASGIMiddleware: Def__init__ (자체, 앱: ASGIApp) -> 없음: self.app=앱
Async def__Call __ (자체, 범위: 범위, 수신: 수신, 전송: 전송) -> 없음: 범위가 ["유형"]인 경우! = "http": 반환 대기self.app(범위, 수신, 전송) Async def send_rapper (메시지: 메시지) -> 없음: #. .. 뭔가 해봐 보내기 대기 중(메시지) 대기self.app(범위, 수신, 송신_포장지) -
는
asgiref:를 사용하여 더 엄격한 유형의 힌트를 얻습니다.asgiref.type에서 ASGI3 가져오기 응용 프로그램, ASGIReceiveCallable, ASGISendCallable, 범위 asgiref.type에서 ASGIReceiveEvent, ASGISendEv
클래스 ASGIMiddleware: Def__init__ (자체, 앱: ASGI3 응용 프로그램) -> 없음: self.app=앱
Async def__Call __ (자체, 범위: 범위, 수신: ASGIReceiveCallable, 송신: ASGISendCallable) -> 없음: 범위가 ["유형"]인 경우! = "http": 대기self.app(범위, 수신, 전송) 반품 Async def send_rapper (메시지: ASGISendEvent) -> 없음: #. .. 뭔가 해봐 보내기 대기 중(메시지) 반환 대기self.app(범위, 수신, 송신 _ 포장지)
공통 패턴
특정 요청만 처리
ASGI 미들웨어는 scope 의 내용에 따라 특정 동작을 적용할 수 있습니다.
예를 들어 HTTP 요청만 처리하려면 쓰십시오. ..
클래스 ASGIMiddleware:
Def__init__(자체, 앱):
self.app=앱
Aync def__Call __(자체, 범위, 수신, 전송):
범위가 ["유형"]인 경우! = "http":
대기self.app(범위, 수신, 전송)
반품
# 여기서 뭔가를 해!
대기self.app(범위, 수신, 전송)
마찬가지로 WebSocket의 미들웨어만 사용할 수 있습니다. scope["type"] != "websocket" 보호를 위해.
미들웨어는 요청 방법, URL, 헤더 등에 따라 다르게 동작할 수도 있습니다.
멀티플렉싱 스타렛 구성 요소
Starlette는 ASGI scope,receive 및/또는 send 매개 변수를 허용하는 여러 데이터 구조를 제공하여 더 높은 수준의 추상화에서 작업할 수 있습니다. 이러한 데이터 구조에는 Request,Headers,QueryParams,URL 등이 포함됩니다.
예를 들어 Request 를 Instantiate하여 HTTP 요청을 더 쉽게 확인할 수 있습니다.
스타렛에서. 요청 가져오기 요청
클래스 ASGIMiddleware:
Def__init__(자체, 앱):
self.app=앱
Aync def__Call __(자체, 범위, 수신, 전송):
범위 ["유형"] == "http"인 경우:
요청 = 요청(범위)
... #`request.method`,`request.url`,`request.headers` 등을 사용합니다.
대기self.app(범위, 수신, 전송)
ASGI 애플리케이션인 응답을 재사용할 수도 있습니다.
열렬한 응답 보내기
연결 확인 scope 다른 ASGI 응용 프로그램을 조건부로 호출할 수 있습니다. 한 가지 사용 사례는 응용 프로그램에 전화하지 않고 응답을 보내는 것일 수 있습니다.
예를 들어, 이 미들웨어는 사전을 사용하여 요청된 경로를 기반으로 영구 리디렉션을 수행합니다. 라우팅 URL 패턴을 리팩터링해야 하는 경우 이를 사용하여 레거시 URL에 대한 지속적인 지원을 구현할 수 있습니다.
Starlette.data에서 가져온 URL
Starlette.에서 가져온 리디렉션 응답
클래스 리디렉션 미들웨어:
Def__init__(자체, 앱, pase_map: dict):
self.app=앱
셀프.경로 _ 매핑 = 경로 _ 매핑
Aync def__Call __(자체, 범위, 수신, 전송):
범위가 ["유형"]인 경우! = "http":
대기self.app(범위, 수신, 전송)
반품
URL = URL (범위 = 범위)
만약 url.path in self.
URL = url. (경로 = self.pase_ [url.경로])
응답 = 리디렉션 응답 (url, stast_code = 301)
응답 대기 중(범위, 수신, 전송)
반품
대기self.app(범위, 수신, 전송)
예제 사용은 다음과 같습니다.
Starlette. 응용 프로그램이 Starlette에서 가져옵니다.
Starlette.middleware에서 미들웨어 가져오기
경로 =. ..
리디렉션={
"/v1//": "/v2//",
# ...
}
미들웨어 = [
미들웨어(ReDirectsMiddleware, pase_mapping=redirections),
]
App = Starlette(경로 = 경로, middleware=middleware)
요청 확인 또는 수정
요청 정보는 다음을 통해 운영할 수 있습니다. scope 액세스하거나 변경합니다. 이 패턴의 전체 예는 Uvicorn's를 참조하십시오. ProxyHeadersMiddleware 프런트 엔드 프록시 뒤에서 서비스를 제공할 때 확인하고 조정합니다. scope ...
또한 receive ASGI 호출 가능 개체를 감싸면 http.request ASGI 이벤트 메시지를 조작하여 HTTP 요청 본문에 액세스하거나 수정할 수 있습니다.
예를 들어 이 미들웨어는 수신 요청 본문의 크기를 계산하고 기록합니다. ..
클래스LoggedRequestBodySizeMiddleware:
Def__init__(자체, 앱):
self.app=앱
Aync def__Call __(자체, 범위, 수신, 전송):
범위가 ["유형"]인 경우! = "http":
대기self.app(범위, 수신, 전송)
반품
몸매 _ 크기 = 0
Async def 수신 _ logging_요청 _ body _ 크기():
로컬이 아닌 바디_사이즈
메시지 = 수신 대기 ()
주장 메시지 ["유형"] == "htp.요청"
body _ 사이즈 + = len (
메시지가 아닌 경우 ("more_body", 거짓):
인쇄(f "요청 본문의 크기는:{body_size}바이트")
메시지 반환
self.app 기다리다 (범위, _ing_quest_body _ 크기, 보내기)
마찬가지로 WebSocket 미들웨어는 websocket.receive ASGI 이벤트 메시지를 조작하여 들어오는 WebSocket 데이터를 검사하거나 변경할 수 있습니다.
HTTP 요청의 본문을 변경하는 예는 msgpack-asgi 를 참조하십시오.
응답 확인 또는 수정
send ASGI 호출 가능을 감싸면 기본 응용 프로그램에서 보낸 HTTP 응답을 검사하거나 수정할 수 있습니다. 이렇게 하려면 http.response.start 또는 http.response.body ASGI 이벤트 메시지에 응답하십시오.
예를 들어 이 미들웨어는 다음과 같은 고정 추가 응답 헤더를 추가합니다.
MutableHeaders는 starlette.data에서 가져옵니다.
클래스ExtraResponseHeadersMiddleware:
def_init__(자체, 앱, 헤더):
self.app=앱
셀프 헤더 = 헤더
Aync def__Call __(자체, 범위, 수신, 전송):
범위가 ["유형"]인 경우! = "http":
반환 대기self.app(범위, 수신, 전송)
Async def send_with __headers(메시지):
메시지가 ["유형"] == "htp.se.start"인 경우:
헤더 = MutableHeaders (범위 = 메시지)
키의 경우 자체 값.헤더:
헤더. 추가(키, 값)
보내기 대기 중(메시지)
대기self.app(범위, 수신, 송신 _ with _ _ 헤더)
HTTP 응답을 확인하고 구성 가능한 HTTP 액세스 로그 라인을 기록하는 예가 있는 asgi-logger 를 참조하십시오.
마찬가지로 WebSocket 미들웨어는 websocket.send ASGI 이벤트 메시지를 조작하여 발신 WebSocket 데이터를 검사하거나 변경할 수 있습니다.
응답 본문을 변경하는 경우 새 응답 본문 길이와 일치하도록 응답 Content-Length 헤더를 업데이트해야 합니다. 전체 예는 brotli-asgi 를 참조하십시오.
엔드포인트에 정보 전달
기본 응용 프로그램 또는 엔드포인트와 정보를 공유해야 하는 경우 scope 사전에 저장할 수 있습니다. 예를 들어 Starlette는 이 방법을 사용하여 엔드포인트와 라우팅 정보를 공유하지만 ASGI 사양의 일부가 아닙니다.
그렇다면 충돌을 방지하기 위해 다른 미들웨어 또는 응용 프로그램에서 사용할 수 없는 키를 사용해야 합니다.
예를 들어 엔드포인트는 다음 미들웨어가 포함된 경우 request.scope["asgi_transaction_id"] 에 액세스할 수 있습니다.
uuid 가져오기
클래스TransactionIDMiddleware:
Def__init__(자체, 앱):
self.app=앱
Aync def__Call __(자체, 범위, 수신, 전송):
범위 ["asgi_tion_id"] = uuid.uuid4 ()
대기self.app(범위, 수신, 전송)
청소 및 오류 처리
정리 또는 오류 처리를 위해 try/except/finally 블록 또는 컨텍스트 관리자로 애플리케이션을 포장할 수 있습니다.
예를 들어 다음 미들웨어는 메트릭을 수집하고 애플리케이션 예외를 처리할 수 있습니다. ..
수입시간
클래스MonitoringMiddleware:
Def__init__(자체, 앱):
self.app=앱
Aync def__Call __(자체, 범위, 수신, 전송):
시작 = 시간.시간 ()
시도:
대기self.app(범위, 수신, 전송)
예외를 제외하고 exc:
... # 예외 처리
키우기
마지막으로:
종료 = 시간.시간 ()
경과 = 종료 - 시작
... # 모니터링 백엔드에 메트릭으로 `elapsed` 제출
이 패턴의 전체 예는 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)
```
❌ 아니.
```python hl_lines="7-8"
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 애플리케이션으로 포장하려면 애플리케이션 인스턴스를 래핑하는 데 보다 일반적인 패턴을 사용해야 합니다.
앱 = TrustedHostMiddleware(앱, 허용됨_호스트 = ['example.com'])
Starlette 응용 프로그램 인스턴스에서도 이 작업을 수행할 수 있지만 middleware=<List of Middleware instances> 스타일을 사용하는 것이 좋습니다.
- 는 모든 것이
ServerErrorMiddleware의 가장 바깥 층으로 싸여 있는지 확인합니다. - 는 최상위
app인스턴스를 유지합니다.
라우팅 그룹에 미들웨어 적용
미들웨어는 Mount 인스턴스에 추가할 수도 있으며, 이를 통해 라우팅 또는 하위 애플리케이션 집합에 미들웨어를 적용할 수 있습니다.
Starlette. 응용 프로그램이 Starlette에서 가져옵니다.
Starlette.middleware에서 미들웨어 가져오기
Starlette.middle.gzip에서 GZipMiddleware를 가져옵니다.
별자리에서. 라우팅 가져오기 마운트, 경로
경로 = [
마운트(
"/",
경로 = [
경로(
"/예",
엔드포인트 =. ..,
)
],
미들웨어=[미들웨어(GZipMiddleware)]
)
]
앱=스타렛(루트=루트)
이러한 방식으로 사용되는 미들웨어는 그다지 유용하지 않습니다. Starlette 응용 프로그램의 미들웨어는 예외 처리 미들웨어로 포장되어 있습니다. 확인 또는 수정에만 적합하기 때문에 일반적으로 문제가 되지 않습니다. Response 그럼에도 불구하고 이 논리를 오류 응답에 적용하고 싶지는 않을 것입니다. 특정 경로에서만 오류 응답에 미들웨어 논리를 적용하려면 몇 가지 옵션이 있습니다.
Mount에ExceptionMiddleware추가- 는 미들웨어에
try/except블록을 추가하고 거기에서 오류 응답을 반환합니다. - 는 태그 지정과 처리를 두 개의 미들웨어로 분할합니다. 하나는 응답을 처리가 필요한 것으로 플래그를 지정하는
Mount에 배치하고(예:scope["log-response"] = True를 설정하여) 다른 하나는Starlette응용 프로그램에 적용하여 무거운 리프팅을 수행합니다.
Route/WebSocket 클래스는 단일 경로에 미들웨어를 적용할 수 있는 middleware 매개 변수도 허용합니다.
Starlette. 응용 프로그램이 Starlette에서 가져옵니다.
Starlette.middleware에서 미들웨어 가져오기
Starlette.middle.gzip에서 GZipMiddleware를 가져옵니다.
별자리에서. 라우팅 가져오기 경로
경로 = [
경로(
"/예",
엔드포인트 =. ..,
미들웨어=[미들웨어(GZipMiddleware)]
)
]
앱=스타렛(루트=루트)
또한 미들웨어를 Router 클래스에 적용할 수 있으며, 이를 통해 미들웨어를 경로 집합에 적용할 수 있습니다.
Starlette. 응용 프로그램이 Starlette에서 가져옵니다.
Starlette.middleware에서 미들웨어 가져오기
Starlette.middle.gzip에서 GZipMiddleware를 가져옵니다.
별자리에서. 라우팅 가져오기 경로, 라우터
경로 = [
경로("/예", 끝점 =. ..),
경로("/다른", 끝점 =. ..),
]
라우터 = 라우터(경로 = 경로, 미들웨어 = [미들웨어(GZipMiddleware)])
타사 미들웨어
Asgi-auth-github
이 미들웨어는 모든 ASGI 애플리케이션에 인증을 추가하여 사용자가 OAuth를 통해 GitHub 계정으로 로그인해야 합니다. 특정 사용자 또는 특정 GitHub 조직 또는 팀의 구성원으로 액세스를 제한할 수 있습니다.
agi-csrf
CSRF 공격으로부터 보호하기 위한 미들웨어. 이 미들웨어는 쿠키를 설정한 다음 csrfktok 숨겨진 양식 필드 또는 x-csrftoken HTTP 헤더와 비교하는 이중 커밋 쿠키 모드를 구현합니다.
정품 미들웨어
저자의 JWT 모듈을 사용하여 Starlette의 세션 미들웨어에 대한 직접적인 대안입니다.
벅스내그 미들웨어
Bugsng에 대한 예외 로깅을 위한 미들웨어 클래스입니다.
CSRF 미들웨어
CSRF 공격으로부터 보호하는 미들웨어. 이 미들웨어는 쿠키를 설정한 다음 x-csrftoken HTTP 헤더와 비교하는 이중 커밋 쿠키 모드를 구현합니다.
초기 데이터 미들웨어
이전 TLSv1.3 데이터 요청을 감지하고 거부하기 위한 미들웨어 및 데코레이터.
프로메테우스 미들웨어
지속적인 요청, 시간 등을 포함하여 요청 및 응답과 관련된 Prometheus 메트릭을 캡처하기 위한 미들웨어 클래스입니다. ..
프록시 헤더 미들웨어
Uvicorn에는 프록시 서버를 사용할 때 X-Forwarded-Proto 및 X-Forwarded-For 헤더를 기반으로 클라이언트 측 IP 주소를 결정하는 미들웨어 클래스가 포함되어 있습니다. 더 복잡한 프록시 구성을 위해서는 이 미들웨어를 조정해야 할 수도 있습니다.
속도 제한 미들웨어
속도 제한 미들웨어. URL과 일치하는 일반 표현식, 유연한 규칙, 사용자 지정이 가능합니다. 사용하기 매우 쉽습니다.
요청 Id 미들웨어
요청 ID를 읽거나 생성하고 응용 프로그램 로그에 연결하기 위한 미들웨어 클래스입니다.
롤바 미들웨어
예외, 오류 및 메시지를 롤바에 기록하기 위한 미들웨어 클래스입니다.
StarletteOpentracing
OpenTracing.io 호환되는 추적기로 추적 정보를 전송하고 분산 응용 프로그램을 분석하고 모니터링하는 데 사용할 수 있는 미들웨어 클래스입니다.
보안 쿠키 미들웨어
Starlette 응용 프로그램에 자동 쿠키 암호화 및 암호 해독을 추가하여 기존 쿠키 기반 미들웨어를 추가로 지원하는 사용자 지정 가능한 미들웨어.
타이밍 미들웨어
이를 통과하는 각 요청에 대해 타이밍 정보(CPU 시간 및 벽시계 시간)를 내보내는 미들웨어 클래스입니다. 이러한 타이밍을 통계 메트릭으로 내보내는 방법에 대한 예를 포함합니다.
WSGIMiddleware
WSGI 응용 프로그램을 ASGI 응용 프로그램으로 변환하는 미들웨어 클래스입니다.