summaryrefslogtreecommitdiff
path: root/venv/lib/python3.11/site-packages/litestar/config/response_cache.py
diff options
context:
space:
mode:
Diffstat (limited to 'venv/lib/python3.11/site-packages/litestar/config/response_cache.py')
-rw-r--r--venv/lib/python3.11/site-packages/litestar/config/response_cache.py81
1 files changed, 81 insertions, 0 deletions
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)