An interface to see if request should cached or not.
| 48 | |
| 49 | |
| 50 | class CacheController: |
| 51 | """An interface to see if request should cached or not.""" |
| 52 | |
| 53 | def __init__( |
| 54 | self, |
| 55 | cache: BaseCache | None = None, |
| 56 | cache_etags: bool = True, |
| 57 | serializer: Serializer | None = None, |
| 58 | status_codes: Collection[int] | None = None, |
| 59 | ): |
| 60 | self.cache = DictCache() if cache is None else cache |
| 61 | self.cache_etags = cache_etags |
| 62 | self.serializer = serializer or Serializer() |
| 63 | self.cacheable_status_codes = status_codes or (200, 203, 300, 301, 308) |
| 64 | |
| 65 | @classmethod |
| 66 | def _urlnorm(cls, uri: str) -> str: |
| 67 | """Normalize the URL to create a safe key for the cache""" |
| 68 | (scheme, authority, path, query, fragment) = parse_uri(uri) |
| 69 | if not scheme or not authority: |
| 70 | raise Exception("Only absolute URIs are allowed. uri = %s" % uri) |
| 71 | |
| 72 | scheme = scheme.lower() |
| 73 | authority = authority.lower() |
| 74 | |
| 75 | if not path: |
| 76 | path = "/" |
| 77 | |
| 78 | # Could do syntax based normalization of the URI before |
| 79 | # computing the digest. See Section 6.2.2 of Std 66. |
| 80 | request_uri = query and "?".join([path, query]) or path |
| 81 | defrag_uri = scheme + "://" + authority + request_uri |
| 82 | |
| 83 | return defrag_uri |
| 84 | |
| 85 | @classmethod |
| 86 | def cache_url(cls, uri: str) -> str: |
| 87 | return cls._urlnorm(uri) |
| 88 | |
| 89 | def parse_cache_control(self, headers: Mapping[str, str]) -> dict[str, int | None]: |
| 90 | known_directives = { |
| 91 | # https://tools.ietf.org/html/rfc7234#section-5.2 |
| 92 | "max-age": (int, True), |
| 93 | "max-stale": (int, False), |
| 94 | "min-fresh": (int, True), |
| 95 | "no-cache": (None, False), |
| 96 | "no-store": (None, False), |
| 97 | "no-transform": (None, False), |
| 98 | "only-if-cached": (None, False), |
| 99 | "must-revalidate": (None, False), |
| 100 | "public": (None, False), |
| 101 | "private": (None, False), |
| 102 | "proxy-revalidate": (None, False), |
| 103 | "s-maxage": (int, True), |
| 104 | } |
| 105 | |
| 106 | cc_headers = headers.get("cache-control", headers.get("Cache-Control", "")) |
| 107 |
no outgoing calls
searching dependent graphs…