|
| 1 | +import json |
| 2 | +import time |
| 3 | + |
1 | 4 | from django.core.exceptions import ObjectDoesNotExist |
2 | 5 | from django.db.models import F, Value |
| 6 | +from django.http import HttpResponseRedirect, HttpResponse, FileResponse as ApiFileResponse |
| 7 | +from rest_framework.response import Response |
| 8 | +from rest_framework.renderers import JSONRenderer |
3 | 9 |
|
| 10 | +from pulpcore.app.settings import settings |
4 | 11 | from pulpcore.plugin.cache import CacheKeys, AsyncContentCache, SyncContentCache |
5 | 12 |
|
6 | 13 | from pulp_container.app.models import ContainerDistribution, ContainerPullThroughDistribution |
7 | 14 | from pulp_container.app.exceptions import RepositoryNotFound |
8 | 15 |
|
9 | 16 | ACCEPT_HEADER_KEY = "accept_header" |
| 17 | +DEFAULT_EXPIRES_TTL = settings.CACHE_SETTINGS["EXPIRES_TTL"] |
10 | 18 | QUERY_KEY = "query" |
11 | 19 |
|
12 | 20 |
|
@@ -52,6 +60,43 @@ def make_key(self, request): |
52 | 60 | return key |
53 | 61 |
|
54 | 62 |
|
| 63 | + def make_entry(self, key, base_key, handler, args, kwargs, expires=DEFAULT_EXPIRES_TTL): |
| 64 | + """Gets the response for the request and try to turn it into a cacheable entry""" |
| 65 | + response = handler(*args, **kwargs) |
| 66 | + entry = {"headers": dict(response.headers), "status": response.status_code} |
| 67 | + if expires is not None: |
| 68 | + # Redis TTL is not sufficient: https://github.com/pulp/pulpcore/issues/4845 |
| 69 | + entry["expires"] = expires + time.time() |
| 70 | + else: |
| 71 | + # Settings allow you to set None to mean "does not expire". Persist. |
| 72 | + entry["expires"] = None |
| 73 | + response.headers["X-PULP-CACHE"] = "MISS" |
| 74 | + if isinstance(response, HttpResponseRedirect): |
| 75 | + entry["redirect_to"] = str(response.headers["Location"]) |
| 76 | + entry["type"] = "Redirect" |
| 77 | + elif isinstance(response, ApiFileResponse): |
| 78 | + entry["path"] = str(response.filename) |
| 79 | + entry["type"] = "FileResponse" |
| 80 | + elif isinstance(response,Response): |
| 81 | + response.accepted_renderer = JSONRenderer() |
| 82 | + response.accepted_media_type = "application/json" |
| 83 | + response.content_type = response.headers['Content-Type'] |
| 84 | + response.renderer_context = {} |
| 85 | + response.render() |
| 86 | + entry["content"] = response.content.decode("utf-8") |
| 87 | + entry["type"] = "Response" |
| 88 | + elif isinstance(response, HttpResponse): |
| 89 | + entry["content"] = response.content.decode("utf-8") |
| 90 | + entry["type"] = "Response" |
| 91 | + else: |
| 92 | + # We don't cache StreamResponses or errors |
| 93 | + return response |
| 94 | + |
| 95 | + # TODO look into smaller format, maybe some compression on the text |
| 96 | + self.set(key, json.dumps(entry), expires, base_key=base_key) |
| 97 | + return response |
| 98 | + |
| 99 | + |
55 | 100 | def find_base_path_cached(request, cached): |
56 | 101 | """ |
57 | 102 | Returns the base-path to use for the base-key in the cache |
|
0 commit comments