summaryrefslogtreecommitdiff
path: root/venv/lib/python3.11/site-packages/litestar/config
diff options
context:
space:
mode:
Diffstat (limited to 'venv/lib/python3.11/site-packages/litestar/config')
-rw-r--r--venv/lib/python3.11/site-packages/litestar/config/__init__.py0
-rw-r--r--venv/lib/python3.11/site-packages/litestar/config/__pycache__/__init__.cpython-311.pycbin0 -> 199 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/config/__pycache__/allowed_hosts.cpython-311.pycbin0 -> 2360 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/config/__pycache__/app.cpython-311.pycbin0 -> 10063 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/config/__pycache__/compression.cpython-311.pycbin0 -> 3757 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/config/__pycache__/cors.cpython-311.pycbin0 -> 7425 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/config/__pycache__/csrf.cpython-311.pycbin0 -> 2257 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/config/__pycache__/response_cache.cpython-311.pycbin0 -> 4460 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/config/allowed_hosts.py43
-rw-r--r--venv/lib/python3.11/site-packages/litestar/config/app.py223
-rw-r--r--venv/lib/python3.11/site-packages/litestar/config/compression.py83
-rw-r--r--venv/lib/python3.11/site-packages/litestar/config/cors.py147
-rw-r--r--venv/lib/python3.11/site-packages/litestar/config/csrf.py42
-rw-r--r--venv/lib/python3.11/site-packages/litestar/config/response_cache.py81
14 files changed, 619 insertions, 0 deletions
diff --git a/venv/lib/python3.11/site-packages/litestar/config/__init__.py b/venv/lib/python3.11/site-packages/litestar/config/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/config/__init__.py
diff --git a/venv/lib/python3.11/site-packages/litestar/config/__pycache__/__init__.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/config/__pycache__/__init__.cpython-311.pyc
new file mode 100644
index 0000000..c6ef8a3
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/config/__pycache__/__init__.cpython-311.pyc
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/config/__pycache__/allowed_hosts.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/config/__pycache__/allowed_hosts.cpython-311.pyc
new file mode 100644
index 0000000..f340305
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/config/__pycache__/allowed_hosts.cpython-311.pyc
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/config/__pycache__/app.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/config/__pycache__/app.cpython-311.pyc
new file mode 100644
index 0000000..a84a2f7
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/config/__pycache__/app.cpython-311.pyc
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/config/__pycache__/compression.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/config/__pycache__/compression.cpython-311.pyc
new file mode 100644
index 0000000..b6d9382
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/config/__pycache__/compression.cpython-311.pyc
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/config/__pycache__/cors.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/config/__pycache__/cors.cpython-311.pyc
new file mode 100644
index 0000000..9965625
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/config/__pycache__/cors.cpython-311.pyc
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/config/__pycache__/csrf.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/config/__pycache__/csrf.cpython-311.pyc
new file mode 100644
index 0000000..5056590
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/config/__pycache__/csrf.cpython-311.pyc
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/config/__pycache__/response_cache.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/config/__pycache__/response_cache.cpython-311.pyc
new file mode 100644
index 0000000..0ca0cf9
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/config/__pycache__/response_cache.cpython-311.pyc
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/config/allowed_hosts.py b/venv/lib/python3.11/site-packages/litestar/config/allowed_hosts.py
new file mode 100644
index 0000000..4c8e6ac
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/config/allowed_hosts.py
@@ -0,0 +1,43 @@
+from __future__ import annotations
+
+from dataclasses import dataclass, field
+from typing import TYPE_CHECKING
+
+from litestar.exceptions import ImproperlyConfiguredException
+
+__all__ = ("AllowedHostsConfig",)
+
+
+if TYPE_CHECKING:
+ from litestar.types import Scopes
+
+
+@dataclass
+class AllowedHostsConfig:
+ """Configuration for allowed hosts protection.
+
+ To enable allowed hosts protection, pass an instance of this class to the :class:`Litestar <litestar.app.Litestar>`
+ constructor using the ``allowed_hosts`` key.
+ """
+
+ allowed_hosts: list[str] = field(default_factory=lambda: ["*"])
+ """A list of trusted hosts.
+
+ Use ``*.`` to allow all hosts, or prefix domains with ``*.`` to allow all sub domains.
+ """
+ exclude: str | list[str] | None = field(default=None)
+ """A pattern or list of patterns to skip in the Allowed Hosts middleware."""
+ exclude_opt_key: str | None = field(default=None)
+ """An identifier to use on routes to disable hosts check for a particular route."""
+ scopes: Scopes | None = field(default=None)
+ """ASGI scopes processed by the middleware, if None both ``http`` and ``websocket`` will be processed."""
+ www_redirect: bool = field(default=True)
+ """A boolean dictating whether to redirect requests that start with ``www.`` and otherwise match a trusted host."""
+
+ def __post_init__(self) -> None:
+ """Ensure that the trusted hosts have correct domain wildcards."""
+ for host in self.allowed_hosts:
+ if host != "*" and "*" in host and not host.startswith("*."):
+ raise ImproperlyConfiguredException(
+ "domain wildcards can only appear in the beginning of the domain, e.g. ``*.example.com``"
+ )
diff --git a/venv/lib/python3.11/site-packages/litestar/config/app.py b/venv/lib/python3.11/site-packages/litestar/config/app.py
new file mode 100644
index 0000000..0acefb1
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/config/app.py
@@ -0,0 +1,223 @@
+from __future__ import annotations
+
+import enum
+from dataclasses import dataclass, field
+from typing import TYPE_CHECKING, Any, Callable
+
+from litestar.config.allowed_hosts import AllowedHostsConfig
+from litestar.config.response_cache import ResponseCacheConfig
+from litestar.datastructures import State
+from litestar.events.emitter import SimpleEventEmitter
+from litestar.types.empty import Empty
+
+if TYPE_CHECKING:
+ from contextlib import AbstractAsyncContextManager
+
+ from litestar import Litestar, Response
+ from litestar.config.compression import CompressionConfig
+ from litestar.config.cors import CORSConfig
+ from litestar.config.csrf import CSRFConfig
+ from litestar.connection import Request, WebSocket
+ from litestar.datastructures import CacheControlHeader, ETag
+ from litestar.di import Provide
+ from litestar.dto import AbstractDTO
+ from litestar.events.emitter import BaseEventEmitterBackend
+ from litestar.events.listener import EventListener
+ from litestar.logging.config import BaseLoggingConfig
+ from litestar.openapi.config import OpenAPIConfig
+ from litestar.openapi.spec import SecurityRequirement
+ from litestar.plugins import PluginProtocol
+ from litestar.static_files.config import StaticFilesConfig
+ from litestar.stores.base import Store
+ from litestar.stores.registry import StoreRegistry
+ from litestar.types import (
+ AfterExceptionHookHandler,
+ AfterRequestHookHandler,
+ AfterResponseHookHandler,
+ AnyCallable,
+ BeforeMessageSendHookHandler,
+ BeforeRequestHookHandler,
+ ControllerRouterHandler,
+ ExceptionHandlersMap,
+ Guard,
+ Middleware,
+ ParametersMap,
+ ResponseCookies,
+ ResponseHeaders,
+ TypeEncodersMap,
+ )
+ from litestar.types.callable_types import LifespanHook
+ from litestar.types.composite_types import TypeDecodersSequence
+ from litestar.types.empty import EmptyType
+ from litestar.types.internal_types import TemplateConfigType
+
+
+__all__ = (
+ "AppConfig",
+ "ExperimentalFeatures",
+)
+
+
+@dataclass
+class AppConfig:
+ """The parameters provided to the ``Litestar`` app are used to instantiate an instance, and then the instance is
+ passed to any callbacks registered to ``on_app_init`` in the order they are provided.
+
+ The final attribute values are used to instantiate the application object.
+ """
+
+ after_exception: list[AfterExceptionHookHandler] = field(default_factory=list)
+ """An application level :class:`exception hook handler <.types.AfterExceptionHookHandler>` or list thereof.
+
+ This hook is called after an exception occurs. In difference to exception handlers, it is not meant to return a
+ response - only to process the exception (e.g. log it, send it to Sentry etc.).
+ """
+ after_request: AfterRequestHookHandler | None = field(default=None)
+ """A sync or async function executed after the route handler function returned and the response object has been
+ resolved.
+
+ Receives the response object which may be any subclass of :class:`Response <.response.Response>`.
+ """
+ after_response: AfterResponseHookHandler | None = field(default=None)
+ """A sync or async function called after the response has been awaited. It receives the
+ :class:`Request <.connection.Request>` object and should not return any values.
+ """
+ allowed_hosts: list[str] | AllowedHostsConfig | None = field(default=None)
+ """If set enables the builtin allowed hosts middleware."""
+ before_request: BeforeRequestHookHandler | None = field(default=None)
+ """A sync or async function called immediately before calling the route handler. Receives the
+ :class:`Request <.connection.Request>` instance and any non-``None`` return value is used for the response,
+ bypassing the route handler.
+ """
+ before_send: list[BeforeMessageSendHookHandler] = field(default_factory=list)
+ """An application level :class:`before send hook handler <.types.BeforeMessageSendHookHandler>` or list thereof.
+
+ This hook is called when the ASGI send function is called.
+ """
+ cache_control: CacheControlHeader | None = field(default=None)
+ """A ``cache-control`` header of type :class:`CacheControlHeader <.datastructures.CacheControlHeader>` to add to
+ route handlers of this app.
+
+ Can be overridden by route handlers.
+ """
+ compression_config: CompressionConfig | None = field(default=None)
+ """Configures compression behaviour of the application, this enabled a builtin or user defined Compression
+ middleware.
+ """
+ cors_config: CORSConfig | None = field(default=None)
+ """If set this enables the builtin CORS middleware."""
+ csrf_config: CSRFConfig | None = field(default=None)
+ """If set this enables the builtin CSRF middleware."""
+ debug: bool = field(default=False)
+ """If ``True``, app errors rendered as HTML with a stack trace."""
+ dependencies: dict[str, Provide | AnyCallable] = field(default_factory=dict)
+ """A string keyed dictionary of dependency :class:`Provider <.di.Provide>` instances."""
+ dto: type[AbstractDTO] | None | EmptyType = field(default=Empty)
+ """:class:`AbstractDTO <.dto.base_dto.AbstractDTO>` to use for (de)serializing and validation of request data."""
+ etag: ETag | None = field(default=None)
+ """An ``etag`` header of type :class:`ETag <.datastructures.ETag>` to add to route handlers of this app.
+
+ Can be overridden by route handlers.
+ """
+ event_emitter_backend: type[BaseEventEmitterBackend] = field(default=SimpleEventEmitter)
+ """A subclass of :class:`BaseEventEmitterBackend <.events.emitter.BaseEventEmitterBackend>`."""
+ exception_handlers: ExceptionHandlersMap = field(default_factory=dict)
+ """A dictionary that maps handler functions to status codes and/or exception types."""
+ guards: list[Guard] = field(default_factory=list)
+ """A list of :class:`Guard <.types.Guard>` callables."""
+ include_in_schema: bool | EmptyType = field(default=Empty)
+ """A boolean flag dictating whether the route handler should be documented in the OpenAPI schema"""
+ lifespan: list[Callable[[Litestar], AbstractAsyncContextManager] | AbstractAsyncContextManager] = field(
+ default_factory=list
+ )
+ """A list of callables returning async context managers, wrapping the lifespan of the ASGI application"""
+ listeners: list[EventListener] = field(default_factory=list)
+ """A list of :class:`EventListener <.events.listener.EventListener>`."""
+ logging_config: BaseLoggingConfig | None = field(default=None)
+ """An instance of :class:`BaseLoggingConfig <.logging.config.BaseLoggingConfig>` subclass."""
+ middleware: list[Middleware] = field(default_factory=list)
+ """A list of :class:`Middleware <.types.Middleware>`."""
+ on_shutdown: list[LifespanHook] = field(default_factory=list)
+ """A list of :class:`LifespanHook <.types.LifespanHook>` called during application shutdown."""
+ on_startup: list[LifespanHook] = field(default_factory=list)
+ """A list of :class:`LifespanHook <.types.LifespanHook>` called during application startup."""
+ openapi_config: OpenAPIConfig | None = field(default=None)
+ """Defaults to :data:`DEFAULT_OPENAPI_CONFIG <litestar.app.DEFAULT_OPENAPI_CONFIG>`"""
+ opt: dict[str, Any] = field(default_factory=dict)
+ """A string keyed dictionary of arbitrary values that can be accessed in :class:`Guards <.types.Guard>` or
+ wherever you have access to :class:`Request <.connection.Request>` or :class:`ASGI Scope <litestar.types.Scope>`.
+
+ Can be overridden by routers and router handlers.
+ """
+ parameters: ParametersMap = field(default_factory=dict)
+ """A mapping of :class:`Parameter <.params.Parameter>` definitions available to all application paths."""
+ pdb_on_exception: bool = field(default=False)
+ """Drop into the PDB on an exception"""
+ plugins: list[PluginProtocol] = field(default_factory=list)
+ """List of :class:`SerializationPluginProtocol <.plugins.SerializationPluginProtocol>`."""
+ request_class: type[Request] | None = field(default=None)
+ """An optional subclass of :class:`Request <.connection.Request>` to use for http connections."""
+ response_class: type[Response] | None = field(default=None)
+ """A custom subclass of :class:`Response <.response.Response>` to be used as the app's default response."""
+ response_cookies: ResponseCookies = field(default_factory=list)
+ """A list of :class:`Cookie <.datastructures.Cookie>`."""
+ response_headers: ResponseHeaders = field(default_factory=list)
+ """A string keyed dictionary mapping :class:`ResponseHeader <.datastructures.ResponseHeader>`."""
+ response_cache_config: ResponseCacheConfig = field(default_factory=ResponseCacheConfig)
+ """Configures caching behavior of the application."""
+ return_dto: type[AbstractDTO] | None | EmptyType = field(default=Empty)
+ """:class:`AbstractDTO <.dto.base_dto.AbstractDTO>` to use for serializing outbound response
+ data.
+ """
+ route_handlers: list[ControllerRouterHandler] = field(default_factory=list)
+ """A required list of route handlers, which can include instances of :class:`Router <.router.Router>`,
+ subclasses of :class:`Controller <.controller.Controller>` or any function decorated by the route handler
+ decorators.
+ """
+ security: list[SecurityRequirement] = field(default_factory=list)
+ """A list of dictionaries that will be added to the schema of all route handlers in the application. See
+ :data:`SecurityRequirement <.openapi.spec.SecurityRequirement>` for details.
+ """
+ signature_namespace: dict[str, Any] = field(default_factory=dict)
+ """A mapping of names to types for use in forward reference resolution during signature modeling."""
+ signature_types: list[Any] = field(default_factory=list)
+ """A sequence of types for use in forward reference resolution during signature modeling.
+
+ These types will be added to the signature namespace using their ``__name__`` attribute.
+ """
+ state: State = field(default_factory=State)
+ """A :class:`State` <.datastructures.State>` instance holding application state."""
+ static_files_config: list[StaticFilesConfig] = field(default_factory=list)
+ """An instance or list of :class:`StaticFilesConfig <.static_files.StaticFilesConfig>`."""
+ stores: StoreRegistry | dict[str, Store] | None = None
+ """Central registry of :class:`Store <.stores.base.Store>` to be made available and be used throughout the
+ application. Can be either a dictionary mapping strings to :class:`Store <.stores.base.Store>` instances, or an
+ instance of :class:`StoreRegistry <.stores.registry.StoreRegistry>`.
+ """
+ tags: list[str] = field(default_factory=list)
+ """A list of string tags that will be appended to the schema of all route handlers under the application."""
+ template_config: TemplateConfigType | None = field(default=None)
+ """An instance of :class:`TemplateConfig <.template.TemplateConfig>`."""
+ type_decoders: TypeDecodersSequence | None = field(default=None)
+ """A sequence of tuples, each composed of a predicate testing for type identity and a msgspec hook for deserialization."""
+ type_encoders: TypeEncodersMap | None = field(default=None)
+ """A mapping of types to callables that transform them into types supported for serialization."""
+ websocket_class: type[WebSocket] | None = field(default=None)
+ """An optional subclass of :class:`WebSocket <.connection.WebSocket>` to use for websocket connections."""
+ multipart_form_part_limit: int = field(default=1000)
+ """The maximal number of allowed parts in a multipart/formdata request. This limit is intended to protect from
+ DoS attacks."""
+ experimental_features: list[ExperimentalFeatures] | None = None
+
+ def __post_init__(self) -> None:
+ """Normalize the allowed hosts to be a config or None.
+
+ Returns:
+ Optional config.
+ """
+ if self.allowed_hosts and isinstance(self.allowed_hosts, list):
+ self.allowed_hosts = AllowedHostsConfig(allowed_hosts=self.allowed_hosts)
+
+
+class ExperimentalFeatures(str, enum.Enum):
+ DTO_CODEGEN = "DTO_CODEGEN"
diff --git a/venv/lib/python3.11/site-packages/litestar/config/compression.py b/venv/lib/python3.11/site-packages/litestar/config/compression.py
new file mode 100644
index 0000000..c339329
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/config/compression.py
@@ -0,0 +1,83 @@
+from __future__ import annotations
+
+from dataclasses import dataclass, field
+from typing import TYPE_CHECKING, Any, Literal
+
+from litestar.exceptions import ImproperlyConfiguredException
+from litestar.middleware.compression import CompressionMiddleware
+from litestar.middleware.compression.gzip_facade import GzipCompression
+
+if TYPE_CHECKING:
+ from litestar.middleware.compression.facade import CompressionFacade
+
+__all__ = ("CompressionConfig",)
+
+
+@dataclass
+class CompressionConfig:
+ """Configuration for response compression.
+
+ To enable response compression, pass an instance of this class to the :class:`Litestar <.app.Litestar>` constructor
+ using the ``compression_config`` key.
+ """
+
+ backend: Literal["gzip", "brotli"] | str
+ """The backend to use.
+
+ If the value given is `gzip` or `brotli`, then the builtin gzip and brotli compression is used.
+ """
+ minimum_size: int = field(default=500)
+ """Minimum response size (bytes) to enable compression, affects all backends."""
+ gzip_compress_level: int = field(default=9)
+ """Range ``[0-9]``, see :doc:`python:library/gzip`."""
+ brotli_quality: int = field(default=5)
+ """Range ``[0-11]``, Controls the compression-speed vs compression-density tradeoff.
+
+ The higher the quality, the slower the compression.
+ """
+ brotli_mode: Literal["generic", "text", "font"] = "text"
+ """``MODE_GENERIC``, ``MODE_TEXT`` (for UTF-8 format text input, default) or ``MODE_FONT`` (for WOFF 2.0)."""
+ brotli_lgwin: int = field(default=22)
+ """Base 2 logarithm of size.
+
+ Range is 10 to 24. Defaults to 22.
+ """
+ brotli_lgblock: Literal[0, 16, 17, 18, 19, 20, 21, 22, 23, 24] = 0
+ """Base 2 logarithm of the maximum input block size.
+
+ Range is ``16`` to ``24``. If set to ``0``, the value will be set based on the quality. Defaults to ``0``.
+ """
+ brotli_gzip_fallback: bool = True
+ """Use GZIP if Brotli is not supported."""
+ middleware_class: type[CompressionMiddleware] = CompressionMiddleware
+ """Middleware class to use, should be a subclass of :class:`CompressionMiddleware`."""
+ exclude: str | list[str] | None = None
+ """A pattern or list of patterns to skip in the compression middleware."""
+ exclude_opt_key: str | None = None
+ """An identifier to use on routes to disable compression for a particular route."""
+ compression_facade: type[CompressionFacade] = GzipCompression
+ """The compression facade to use for the actual compression."""
+ backend_config: Any = None
+ """Configuration specific to the backend."""
+ gzip_fallback: bool = True
+ """Use GZIP as a fallback if the provided backend is not supported by the client."""
+
+ def __post_init__(self) -> None:
+ if self.minimum_size <= 0:
+ raise ImproperlyConfiguredException("minimum_size must be greater than 0")
+
+ if self.backend == "gzip":
+ if self.gzip_compress_level < 0 or self.gzip_compress_level > 9:
+ raise ImproperlyConfiguredException("gzip_compress_level must be a value between 0 and 9")
+ elif self.backend == "brotli":
+ # Brotli is not guaranteed to be installed.
+ from litestar.middleware.compression.brotli_facade import BrotliCompression
+
+ if self.brotli_quality < 0 or self.brotli_quality > 11:
+ raise ImproperlyConfiguredException("brotli_quality must be a value between 0 and 11")
+
+ if self.brotli_lgwin < 10 or self.brotli_lgwin > 24:
+ raise ImproperlyConfiguredException("brotli_lgwin must be a value between 10 and 24")
+
+ self.gzip_fallback = self.brotli_gzip_fallback
+ self.compression_facade = BrotliCompression
diff --git a/venv/lib/python3.11/site-packages/litestar/config/cors.py b/venv/lib/python3.11/site-packages/litestar/config/cors.py
new file mode 100644
index 0000000..d3e2ccf
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/config/cors.py
@@ -0,0 +1,147 @@
+from __future__ import annotations
+
+import re
+from dataclasses import dataclass, field
+from functools import cached_property
+from typing import TYPE_CHECKING, Literal, Pattern
+
+from litestar.constants import DEFAULT_ALLOWED_CORS_HEADERS
+
+__all__ = ("CORSConfig",)
+
+
+if TYPE_CHECKING:
+ from litestar.types import Method
+
+
+@dataclass
+class CORSConfig:
+ """Configuration for CORS (Cross-Origin Resource Sharing).
+
+ To enable CORS, pass an instance of this class to the :class:`Litestar <litestar.app.Litestar>` constructor using the
+ 'cors_config' key.
+ """
+
+ allow_origins: list[str] = field(default_factory=lambda: ["*"])
+ """List of origins that are allowed.
+
+ Can use '*' in any component of the path, e.g. 'domain.*'. Sets the 'Access-Control-Allow-Origin' header.
+ """
+ allow_methods: list[Literal["*"] | Method] = field(default_factory=lambda: ["*"])
+ """List of allowed HTTP methods.
+
+ Sets the 'Access-Control-Allow-Methods' header.
+ """
+ allow_headers: list[str] = field(default_factory=lambda: ["*"])
+ """List of allowed headers.
+
+ Sets the 'Access-Control-Allow-Headers' header.
+ """
+ allow_credentials: bool = field(default=False)
+ """Boolean dictating whether or not to set the 'Access-Control-Allow-Credentials' header."""
+ allow_origin_regex: str | None = field(default=None)
+ """Regex to match origins against."""
+ expose_headers: list[str] = field(default_factory=list)
+ """List of headers that are exposed via the 'Access-Control-Expose-Headers' header."""
+ max_age: int = field(default=600)
+ """Response caching TTL in seconds, defaults to 600.
+
+ Sets the 'Access-Control-Max-Age' header.
+ """
+
+ def __post_init__(self) -> None:
+ self.allow_headers = [v.lower() for v in self.allow_headers]
+
+ @cached_property
+ def allowed_origins_regex(self) -> Pattern[str]:
+ """Get or create a compiled regex for allowed origins.
+
+ Returns:
+ A compiled regex of the allowed path.
+ """
+ origins = self.allow_origins
+ if self.allow_origin_regex:
+ origins.append(self.allow_origin_regex)
+ return re.compile("|".join([origin.replace("*.", r".*\.") for origin in origins]))
+
+ @cached_property
+ def is_allow_all_origins(self) -> bool:
+ """Get a cached boolean flag dictating whether all origins are allowed.
+
+ Returns:
+ Boolean dictating whether all origins are allowed.
+ """
+ return "*" in self.allow_origins
+
+ @cached_property
+ def is_allow_all_methods(self) -> bool:
+ """Get a cached boolean flag dictating whether all methods are allowed.
+
+ Returns:
+ Boolean dictating whether all methods are allowed.
+ """
+ return "*" in self.allow_methods
+
+ @cached_property
+ def is_allow_all_headers(self) -> bool:
+ """Get a cached boolean flag dictating whether all headers are allowed.
+
+ Returns:
+ Boolean dictating whether all headers are allowed.
+ """
+ return "*" in self.allow_headers
+
+ @cached_property
+ def preflight_headers(self) -> dict[str, str]:
+ """Get cached pre-flight headers.
+
+ Returns:
+ A dictionary of headers to set on the response object.
+ """
+ headers: dict[str, str] = {"Access-Control-Max-Age": str(self.max_age)}
+ if self.is_allow_all_origins:
+ headers["Access-Control-Allow-Origin"] = "*"
+ else:
+ headers["Vary"] = "Origin"
+ if self.allow_credentials:
+ headers["Access-Control-Allow-Credentials"] = str(self.allow_credentials).lower()
+ if not self.is_allow_all_headers:
+ headers["Access-Control-Allow-Headers"] = ", ".join(
+ sorted(set(self.allow_headers) | DEFAULT_ALLOWED_CORS_HEADERS) # pyright: ignore
+ )
+ if self.allow_methods:
+ headers["Access-Control-Allow-Methods"] = ", ".join(
+ sorted(
+ {"DELETE", "GET", "HEAD", "OPTIONS", "PATCH", "POST", "PUT"}
+ if self.is_allow_all_methods
+ else set(self.allow_methods)
+ )
+ )
+ return headers
+
+ @cached_property
+ def simple_headers(self) -> dict[str, str]:
+ """Get cached simple headers.
+
+ Returns:
+ A dictionary of headers to set on the response object.
+ """
+ simple_headers = {}
+ if self.is_allow_all_origins:
+ simple_headers["Access-Control-Allow-Origin"] = "*"
+ if self.allow_credentials:
+ simple_headers["Access-Control-Allow-Credentials"] = "true"
+ if self.expose_headers:
+ simple_headers["Access-Control-Expose-Headers"] = ", ".join(sorted(set(self.expose_headers)))
+ return simple_headers
+
+ def is_origin_allowed(self, origin: str) -> bool:
+ """Check whether a given origin is allowed.
+
+ Args:
+ origin: An origin header value.
+
+ Returns:
+ Boolean determining whether an origin is allowed.
+ """
+ return bool(self.is_allow_all_origins or self.allowed_origins_regex.fullmatch(origin))
diff --git a/venv/lib/python3.11/site-packages/litestar/config/csrf.py b/venv/lib/python3.11/site-packages/litestar/config/csrf.py
new file mode 100644
index 0000000..5094a5b
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/config/csrf.py
@@ -0,0 +1,42 @@
+from __future__ import annotations
+
+from dataclasses import dataclass, field
+from typing import TYPE_CHECKING, Literal
+
+__all__ = ("CSRFConfig",)
+
+
+if TYPE_CHECKING:
+ from litestar.types import Method
+
+
+@dataclass
+class CSRFConfig:
+ """Configuration for CSRF (Cross Site Request Forgery) protection.
+
+ To enable CSRF protection, pass an instance of this class to the :class:`Litestar <litestar.app.Litestar>` constructor using
+ the 'csrf_config' key.
+ """
+
+ secret: str
+ """A string that is used to create an HMAC to sign the CSRF token."""
+ cookie_name: str = field(default="csrftoken")
+ """The CSRF cookie name."""
+ cookie_path: str = field(default="/")
+ """The CSRF cookie path."""
+ header_name: str = field(default="x-csrftoken")
+ """The header that will be expected in each request."""
+ cookie_secure: bool = field(default=False)
+ """A boolean value indicating whether to set the ``Secure`` attribute on the cookie."""
+ cookie_httponly: bool = field(default=False)
+ """A boolean value indicating whether to set the ``HttpOnly`` attribute on the cookie."""
+ cookie_samesite: Literal["lax", "strict", "none"] = field(default="lax")
+ """The value to set in the ``SameSite`` attribute of the cookie."""
+ cookie_domain: str | None = field(default=None)
+ """Specifies which hosts can receive the cookie."""
+ safe_methods: set[Method] = field(default_factory=lambda: {"GET", "HEAD"})
+ """A set of "safe methods" that can set the cookie."""
+ exclude: str | list[str] | None = field(default=None)
+ """A pattern or list of patterns to skip in the CSRF middleware."""
+ exclude_from_csrf_key: str = "exclude_from_csrf"
+ """An identifier to use on routes to disable CSRF for a particular route."""
diff --git a/venv/lib/python3.11/site-packages/litestar/config/response_cache.py b/venv/lib/python3.11/site-packages/litestar/config/response_cache.py
new file mode 100644
index 0000000..4f1dfe9
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/config/response_cache.py
@@ -0,0 +1,81 @@
+from __future__ import annotations
+
+from dataclasses import dataclass, field
+from typing import TYPE_CHECKING, Any, Callable, final
+from urllib.parse import urlencode
+
+from litestar.status_codes import (
+ HTTP_200_OK,
+ HTTP_300_MULTIPLE_CHOICES,
+ HTTP_301_MOVED_PERMANENTLY,
+ HTTP_308_PERMANENT_REDIRECT,
+)
+
+if TYPE_CHECKING:
+ from litestar import Litestar
+ from litestar.connection import Request
+ from litestar.stores.base import Store
+ from litestar.types import CacheKeyBuilder, HTTPScope
+
+__all__ = ("ResponseCacheConfig", "default_cache_key_builder", "CACHE_FOREVER")
+
+
+@final
+class CACHE_FOREVER: # noqa: N801
+ """Sentinel value indicating that a cached response should be stored without an expiration, explicitly skipping the
+ default expiration
+ """
+
+
+def default_cache_key_builder(request: Request[Any, Any, Any]) -> str:
+ """Given a request object, returns a cache key by combining
+ the request method and path with the sorted query params.
+
+ Args:
+ request: request used to generate cache key.
+
+ Returns:
+ A combination of url path and query parameters
+ """
+ query_params: list[tuple[str, Any]] = list(request.query_params.dict().items())
+ query_params.sort(key=lambda x: x[0])
+ return request.method + request.url.path + urlencode(query_params, doseq=True)
+
+
+def default_do_cache_predicate(_: HTTPScope, status_code: int) -> bool:
+ """Given a status code, returns a boolean indicating whether the response should be cached.
+
+ Args:
+ _: ASGI scope.
+ status_code: status code of the response.
+
+ Returns:
+ A boolean indicating whether the response should be cached.
+ """
+ return HTTP_200_OK <= status_code < HTTP_300_MULTIPLE_CHOICES or status_code in (
+ HTTP_301_MOVED_PERMANENTLY,
+ HTTP_308_PERMANENT_REDIRECT,
+ )
+
+
+@dataclass
+class ResponseCacheConfig:
+ """Configuration for response caching.
+
+ To enable response caching, pass an instance of this class to :class:`Litestar <.app.Litestar>` using the
+ ``response_cache_config`` key.
+ """
+
+ default_expiration: int | None = 60
+ """Default cache expiration in seconds used when a route handler is configured with ``cache=True``."""
+ key_builder: CacheKeyBuilder = field(default=default_cache_key_builder)
+ """:class:`CacheKeyBuilder <.types.CacheKeyBuilder>`. Defaults to :func:`default_cache_key_builder`."""
+ store: str = "response_cache"
+ """Name of the :class:`Store <.stores.base.Store>` to use."""
+ cache_response_filter: Callable[[HTTPScope, int], bool] = field(default=default_do_cache_predicate)
+ """A callable that receives connection scope and a status code, and returns a boolean indicating whether the
+ response should be cached."""
+
+ def get_store_from_app(self, app: Litestar) -> Store:
+ """Get the store defined in :attr:`store` from an :class:`Litestar <.app.Litestar>` instance."""
+ return app.stores.get(self.store)