diff --git a/CHANGES/2947.feature b/CHANGES/2947.feature new file mode 100644 index 000000000..99189a898 --- /dev/null +++ b/CHANGES/2947.feature @@ -0,0 +1,4 @@ +Added NOCACHE_LIST config to enable specifying files to be served with a no-cache header. + +By default, repomd.xml, repomd.key, and repomd.key.asc are served with +Cache-control: no-cache. diff --git a/pulp_rpm/app/models/repository.py b/pulp_rpm/app/models/repository.py index 4985d3e37..d377c2211 100644 --- a/pulp_rpm/app/models/repository.py +++ b/pulp_rpm/app/models/repository.py @@ -1,4 +1,5 @@ import re +import os import textwrap from gettext import gettext as _ @@ -492,6 +493,14 @@ def content_handler(self, path): return Response(body=val) + def content_headers_for(self, path): + """Return per-file http-headers.""" + headers = super().content_headers_for(path) + base = os.path.basename(path) # path.strip("/").split("/")[-1] + if base in settings.NOCACHE_LIST: + headers.update({"Cache-Control": "no-cache"}) + return headers + def content_handler_list_directory(self, rel_path): """Return the extra dir entries.""" retval = set() diff --git a/pulp_rpm/app/settings.py b/pulp_rpm/app/settings.py index 63bb67928..02186b359 100644 --- a/pulp_rpm/app/settings.py +++ b/pulp_rpm/app/settings.py @@ -15,3 +15,4 @@ KEEP_CHANGELOG_LIMIT = 10 SOLVER_DEBUG_LOGS = True RPM_METADATA_USE_REPO_PACKAGE_TIME = False +NOCACHE_LIST = ["repomd.xml", "repomd.xml.asc", "repomd.xml.key"] diff --git a/pulp_rpm/tests/functional/api/test_consume_content.py b/pulp_rpm/tests/functional/api/test_consume_content.py index 9096302f3..762708b99 100644 --- a/pulp_rpm/tests/functional/api/test_consume_content.py +++ b/pulp_rpm/tests/functional/api/test_consume_content.py @@ -207,3 +207,24 @@ def test_config_dot_repo( if has_signing_service: assert f"gpgkey={distribution.base_url}repodata/repomd.xml.key" in content + + +@pytest.mark.parallel +def test_repomd_headers( + create_distribution, + http_get_headers, +): + """Test if repomd.xml is returned with Cache-control: no-cache header.""" + distribution = create_distribution(gpgcheck=1, repo_gpgcheck=1, has_signing_service=True) + assert ( + http_get_headers(f"{distribution.base_url}repodata/repomd.xml").get("Cache-control", "") + == "no-cache" + ) + assert ( + not http_get_headers(f"{distribution.base_url}config.repo").get("Cache-control", "") + == "no-cache" + ) + assert ( + http_get_headers(f"{distribution.base_url}repodata/repomd.xml.key").get("Cache-control", "") + == "no-cache" + ) diff --git a/pulp_rpm/tests/functional/conftest.py b/pulp_rpm/tests/functional/conftest.py index 6d8c4d8fb..2f66d3d20 100644 --- a/pulp_rpm/tests/functional/conftest.py +++ b/pulp_rpm/tests/functional/conftest.py @@ -1,7 +1,9 @@ +import asyncio import json import uuid from tempfile import NamedTemporaryFile +import aiohttp import pytest from pulpcore.client.pulp_rpm import ( @@ -342,3 +344,17 @@ def _cleanup_domains( assert content_api_client.list(pulp_domain=domain.name).count == 0 return _cleanup_domains + + +@pytest.fixture(scope="session") +def http_get_headers(): + def _http_get_headers(url, **kwargs): + async def _send_request(): + async with aiohttp.ClientSession(raise_for_status=True) as session: + async with session.get(url) as response: + return response.headers + + headers = asyncio.run(_send_request()) + return headers + + return _http_get_headers diff --git a/requirements.txt b/requirements.txt index ba0985ede..04679490b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,6 +3,6 @@ django_readonly_field~=1.1.1 jsonschema>=4.6,<5.0 libcomps>=0.1.15.post1,<0.2 productmd~=1.33.0 -pulpcore>=3.25.0,<3.40 +pulpcore>=3.28.0,<3.40 solv~=0.7.21 aiohttp_xmlrpc~=1.5.0