Verify our vary headers match and construct a real urllib3 HTTPResponse object.
(
self,
request: PreparedRequest,
cached: Mapping[str, Any],
body_file: IO[bytes] | None = None,
)
| 81 | return self._loads_v4(request, data, body_file) |
| 82 | |
| 83 | def prepare_response( |
| 84 | self, |
| 85 | request: PreparedRequest, |
| 86 | cached: Mapping[str, Any], |
| 87 | body_file: IO[bytes] | None = None, |
| 88 | ) -> HTTPResponse | None: |
| 89 | """Verify our vary headers match and construct a real urllib3 |
| 90 | HTTPResponse object. |
| 91 | """ |
| 92 | # Special case the '*' Vary value as it means we cannot actually |
| 93 | # determine if the cached response is suitable for this request. |
| 94 | # This case is also handled in the controller code when creating |
| 95 | # a cache entry, but is left here for backwards compatibility. |
| 96 | if "*" in cached.get("vary", {}): |
| 97 | return None |
| 98 | |
| 99 | # Ensure that the Vary headers for the cached response match our |
| 100 | # request |
| 101 | for header, value in cached.get("vary", {}).items(): |
| 102 | if request.headers.get(header, None) != value: |
| 103 | return None |
| 104 | |
| 105 | body_raw = cached["response"].pop("body") |
| 106 | |
| 107 | headers: CaseInsensitiveDict[str] = CaseInsensitiveDict( |
| 108 | data=cached["response"]["headers"] |
| 109 | ) |
| 110 | if headers.get("transfer-encoding", "") == "chunked": |
| 111 | headers.pop("transfer-encoding") |
| 112 | |
| 113 | cached["response"]["headers"] = headers |
| 114 | |
| 115 | try: |
| 116 | body: IO[bytes] |
| 117 | if body_file is None: |
| 118 | body = io.BytesIO(body_raw) |
| 119 | else: |
| 120 | body = body_file |
| 121 | except TypeError: |
| 122 | # This can happen if cachecontrol serialized to v1 format (pickle) |
| 123 | # using Python 2. A Python 2 str(byte string) will be unpickled as |
| 124 | # a Python 3 str (unicode string), which will cause the above to |
| 125 | # fail with: |
| 126 | # |
| 127 | # TypeError: 'str' does not support the buffer interface |
| 128 | body = io.BytesIO(body_raw.encode("utf8")) |
| 129 | |
| 130 | # Discard any `strict` parameter serialized by older version of cachecontrol. |
| 131 | cached["response"].pop("strict", None) |
| 132 | |
| 133 | return HTTPResponse(body=body, preload_content=False, **cached["response"]) |
| 134 | |
| 135 | def _loads_v4( |
| 136 | self, |