mirror of https://github.com/encode/starlette.git
190 lines
7.2 KiB
Markdown
190 lines
7.2 KiB
Markdown
|
|
Starlette includes several middleware classes for adding behaviour that is applied across your entire application. These are all implemented as standard ASGI
|
|
middleware classes, and can be applied either to Starlette or to any other ASGI application.
|
|
|
|
The Starlette application class allows you to include the ASGI middleware
|
|
in a way that ensures that it remains wrapped by the exception handler.
|
|
|
|
```python
|
|
from starlette.applications import Starlette
|
|
from starlette.middleware.httpsredirect import HTTPSRedirectMiddleware
|
|
from starlette.middleware.trustedhost import TrustedHostMiddleware
|
|
|
|
|
|
app = Starlette()
|
|
|
|
# Ensure that all requests include an 'example.com' or '*.example.com' host header,
|
|
# and strictly enforce https-only access.
|
|
app.add_middleware(TrustedHostMiddleware, allowed_hosts=['example.com', '*.example.com'])
|
|
app.add_middleware(HTTPSRedirectMiddleware)
|
|
```
|
|
|
|
The following middleware implementations are available in the Starlette package:
|
|
|
|
## CORSMiddleware
|
|
|
|
Adds appropriate [CORS headers](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) to outgoing responses in order to allow cross-origin requests from browsers.
|
|
|
|
The default parameters used by the CORSMiddleware implementation are restrictive by default,
|
|
so you'll need to explicitly enable particular origins, methods, or headers, in order
|
|
for browsers to be permitted to use them in a Cross-Domain context.
|
|
|
|
```python
|
|
from starlette.applications import Starlette
|
|
from starlette.middleware.cors import CORSMiddleware
|
|
|
|
|
|
app = Starlette()
|
|
app.add_middleware(CORSMiddleware, allow_origins=['*'])
|
|
```
|
|
|
|
The following arguments are supported:
|
|
|
|
* `allow_origins` - A list of origins that should be permitted to make cross-origin requests. eg. `['https://example.org', 'https://www.example.org']`. You can use `['*']` to allow any origin.
|
|
* `allow_origin_regex` - A regex string to match against origins that should be permitted to make cross-origin requests. eg. `'https://.*\.example\.org'`.
|
|
* `allow_methods` - A list of HTTP methods that should be allowed for cross-origin requests. Defaults to `['GET']`. You can use `['*']` to allow all standard methods.
|
|
* `allow_headers` - A list of HTTP request headers that should be supported for cross-origin requests. Defaults to `[]`. You can use `['*']` to allow all headers. The `Accept`, `Accept-Language`, `Content-Language` and `Content-Type` headers are always allowed for CORS requests.
|
|
* `allow_credentials` - Indicate that cookies should be supported for cross-origin requests. Defaults to `False`.
|
|
* `expose_headers` - Indicate any response headers that should be made accessible to the browser. Defaults to `[]`.
|
|
* `max_age` - Sets a maximum time in seconds for browsers to cache CORS responses. Defaults to `60`.
|
|
|
|
The middleware responds to two particular types of HTTP request...
|
|
|
|
#### CORS preflight requests
|
|
|
|
These are any `OPTION` request with `Origin` and `Access-Control-Request-Method` headers.
|
|
In this case the middleware will intercept the incoming request and respond with
|
|
appropriate CORS headers, and either a 200 or 400 response for informational purposes.
|
|
|
|
#### Simple requests
|
|
|
|
Any request with an `Origin` header. In this case the middleware will pass the
|
|
request through as normal, but will include appropriate CORS headers on the response.
|
|
|
|
## SessionMiddleware
|
|
|
|
Adds signed cookie-based HTTP sessions. Session information is readable but not modifiable.
|
|
|
|
Access or modify the session data using the `request.session` dictionary interface.
|
|
|
|
The following arguments are supported:
|
|
|
|
* `secret_key` - Should be a random string.
|
|
* `session_cookie` - Defaults to "session".
|
|
|
|
## HTTPSRedirectMiddleware
|
|
|
|
Enforces that all incoming requests must either be `https` or `wss`. Any incoming
|
|
requests to `http` or `ws` will be redirected to the secure scheme instead.
|
|
|
|
```python
|
|
from starlette.applications import Starlette
|
|
from starlette.middleware.httpsredirect import HTTPSRedirectMiddleware
|
|
|
|
|
|
app = Starlette()
|
|
app.add_middleware(HTTPSRedirectMiddleware)
|
|
```
|
|
|
|
There are no configuration options for this middleware class.
|
|
|
|
## TrustedHostMiddleware
|
|
|
|
Enforces that all incoming requests have a correctly set `Host` header, in order
|
|
to guard against HTTP Host Header attacks.
|
|
|
|
```python
|
|
from starlette.applications import Starlette
|
|
from starlette.middleware.trustedhost import TrustedHostMiddleware
|
|
|
|
|
|
app = Starlette()
|
|
app.add_middleware(TrustedHostMiddleware, allowed_hosts=['example.com', '*.example.com'])
|
|
```
|
|
|
|
The following arguments are supported:
|
|
|
|
* `allowed_hosts` - A list of domain names that should be allowed as hostnames. Wildcard
|
|
domains such as `*.example.com` are supported for matching subdomains. To allow any
|
|
hostname either use `allowed_hosts=["*"]` or omit the middleware.
|
|
|
|
If an incoming request does not validate correctly then a 400 response will be sent.
|
|
|
|
## GZipMiddleware
|
|
|
|
Handles GZip responses for any request that includes `"gzip"` in the `Accept-Encoding` header.
|
|
|
|
The middleware will handle both standard and streaming responses.
|
|
|
|
```python
|
|
from starlette.applications import Starlette
|
|
from starlette.middleware.gzip import GZipMiddleware
|
|
|
|
|
|
app = Starlette()
|
|
app.add_middleware(GZipMiddleware, minimum_size=1000)
|
|
```
|
|
|
|
The following arguments are supported:
|
|
|
|
* `minimum_size` - Do not GZip responses that are smaller than this minimum size in bytes. Defaults to `500`.
|
|
|
|
## Using ASGI middleware without Starlette
|
|
|
|
To wrap ASGI middleware around other ASGI applications, you should use the
|
|
more general pattern of wrapping the application instance:
|
|
|
|
```python
|
|
app = TrustedHostMiddleware(app, allowed_hosts=['example.com'])
|
|
```
|
|
|
|
You can do this with a Starlette application instance too, but it is preferable
|
|
to use `.add_middleware`, as it'll ensure that you don't lose the reference
|
|
to the application object, and that the exception handling always wraps around
|
|
any other behaviour.
|
|
|
|
## BaseHTTPMiddleware
|
|
|
|
An abstract class that allows you to write ASGI middleware against a request/response
|
|
interface, rather than dealing with ASGI messages directly.
|
|
|
|
To implement a middleware class using `BaseHTTPMiddleware`, you must override the
|
|
`async def dispatch(request, call_next)` method.
|
|
|
|
```python
|
|
class CustomHeaderMiddleware(BaseHTTPMiddleware):
|
|
async def dispatch(self, request, call_next):
|
|
response = await call_next(request)
|
|
response.headers['Custom'] = 'Example'
|
|
return response
|
|
|
|
|
|
app = Starlette()
|
|
app.add_middleware(CustomHeaderMiddleware)
|
|
```
|
|
|
|
If you want to provide configuration options to the middleware class you should
|
|
override the `__init__` method, ensuring that the first argument is `app`, and
|
|
any remaining arguments are optional keyword arguments. Make sure to set the `app`
|
|
attribute on the class if you do this.
|
|
|
|
```python
|
|
class CustomHeaderMiddleware(BaseHTTPMiddleware):
|
|
def __init__(self, app, header_value='Example'):
|
|
self.app = app
|
|
self.header_value
|
|
|
|
async def dispatch(self, request, call_next):
|
|
response = await call_next(request)
|
|
response.headers['Custom'] = self.header_value
|
|
return response
|
|
|
|
|
|
app = Starlette()
|
|
app.add_middleware(CustomHeaderMiddleware, header_value='Customized')
|
|
```
|
|
|
|
Middleware classes should not modify their state outside of the `__init__` method.
|
|
Instead you should keep any state local to the `dispatch` method, or pass it
|
|
around explicitly, rather than mutating the middleware instance.
|