Proxy middleware for the Litestar web framework.
The following example will redirect all requests to /app
and nested paths to http://127.0.0.1:5173
and update the Host
header. It will proxy all cookies both sent by the client and by the target server.
The handler logic will never be executed, so it does not matter, what happens inside the handler function.
from pathlib import Path
from litestar import Litestar, Response, route
from litestar_proxy import HttpProxyConfig, create_http_proxy_middleware
proxy_config = HttpProxyConfig(url="http://127.0.0.1:5173")
proxy_middleware = create_http_proxy_middleware(proxy_config)
@route(
"/app",
http_method=["GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS", "HEAD"],
middleware=[proxy_middleware],
)
async def index() -> Response:
return Response({"message": "This will never be reached"})
@route(
"/app/{path:path}",
http_method=["GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS", "HEAD"],
middleware=[proxy_middleware],
)
async def frontend(path: Path) -> Response:
return Response({"message": "This will never be reached"})
app = Litestar(route_handlers=[frontend, index])
A class that holds the configuration for the middleware. Params:
url
- The target URL to proxy the requests to. This parameter is requiredscheme_strategy
- The strategy for resolving the proxied request schemeno-downgrade
(default) - Always use HTTPS except for when both the target and incoming request scheme is HTTPtarget
- always use the scheme of the target serverrequest
- always use the scheme of the incoming request
path_strategy
- The strategy for resolving the proxied request pathappend
(default) - append the request path to the target URLtarget
- always use the target path, discard the request pathrequest
- always use the incoming request path, discard the target path
query_strategy
- The strategy for resolving the proxied request query stringmerge
(default) - Merge the query parameters of the target URL and incoming requesttarget
- always use the target URL query params, discard the query params of the incoming requestrequest
- always use the query params of the incoming request, discard the params of the target URLrequest_header_config
- how to handle the headers for the proxied request (see below)response_header_config
- how to handle the headers for the response from the target server (see below)
A class that holds the configuration for the headers of the proxied request Params:
override_host
- whether to override the Host header to the target server location (default True)exclude_cookies
- whether to exclude cookies when proxying the incoming request (default False)exclude_headers
- a list of header names to exclude from the proxied requestheader_parser
- a callable that takes theMutableScopeHeader
class of Litestar which contains the original headers, and returns an object that can be passed into the.update()
function ofMutableMapping
- so either aMapping[str, str]
orIterable[Tuple[str, str]]
A class that holds the configuration for the headers of the response from the target URL Params:
Same as RequestHeaderConfig
except it doesn't have the override_host
option
The following example behaves similarly as the default, but it also
- Excludes cookies from both response and request
- Excludes the
Origin
header from the response - Uses a custom parsing function to remov all headers that start with
X-Secret
from both the request and the response
from litestar_proxy import HttpProxyConfig, RequestHeaderConfig, ResponseHeaderConfig
config = HttpProxyConfig(
url="http://127.0.0.1:5173",
scheme_strategy="no-downgrade",
path_strategy="append",
query_strategy="merge",
request_header_config=RequestHeaderConfig(
override_host=True,
exclude_cookies=True,
exclude_headers=["Origin"],
header_parser=lambda headers: {
k: v for k, v in headers.items() if not str(k).lower().startswith("X-Secret")
},
),
response_header_config=ResponseHeaderConfig(
exclude_cookies=True,
header_parser=lambda headers: {
k: v for k, v in headers.items() if not str(k).lower().startswith("X-Secret")
},
),
)