Skip to content

Commit 6385f02

Browse files
author
Alexander Mancevice
committed
Allow override of Cache-Control header
See pypa#8109
1 parent 2062cb1 commit 6385f02

File tree

2 files changed

+61
-1
lines changed

2 files changed

+61
-1
lines changed

src/pip/_internal/index/collector.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,9 @@ def _get_html_response(url, session):
163163
# trip for the conditional GET now instead of only
164164
# once per 10 minutes.
165165
# For more information, please see pypa/pip#5670.
166-
"Cache-Control": "max-age=0",
166+
# However if we want to override Cache-Control, e.g. via CLI,
167+
# we can still do so.
168+
"Cache-Control": session.headers.get('Cache-Control', 'max-age=0'),
167169
},
168170
)
169171
resp.raise_for_status()

tests/unit/test_collector.py

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ def test_get_html_response_archive_to_http_scheme(url, content_type):
6060
if the scheme supports it, and raise `_NotHTML` if the response isn't HTML.
6161
"""
6262
session = mock.Mock(PipSession)
63+
session.headers = {}
6364
session.head.return_value = mock.Mock(**{
6465
"request.method": "HEAD",
6566
"headers": {"Content-Type": content_type},
@@ -87,6 +88,7 @@ def test_get_html_response_archive_to_http_scheme_is_html(url):
8788
request is responded with text/html.
8889
"""
8990
session = mock.Mock(PipSession)
91+
session.headers = {}
9092
session.head.return_value = mock.Mock(**{
9193
"request.method": "HEAD",
9294
"headers": {"Content-Type": "text/html"},
@@ -120,6 +122,7 @@ def test_get_html_response_no_head(url):
120122
look like an archive, only the GET request that retrieves data.
121123
"""
122124
session = mock.Mock(PipSession)
125+
session.headers = {}
123126

124127
# Mock the headers dict to ensure it is accessed.
125128
session.get.return_value = mock.Mock(headers=mock.Mock(**{
@@ -145,6 +148,7 @@ def test_get_html_response_dont_log_clear_text_password(caplog):
145148
in its DEBUG log message.
146149
"""
147150
session = mock.Mock(PipSession)
151+
session.headers = {}
148152

149153
# Mock the headers dict to ensure it is accessed.
150154
session.get.return_value = mock.Mock(headers=mock.Mock(**{
@@ -167,6 +171,57 @@ def test_get_html_response_dont_log_clear_text_password(caplog):
167171
]
168172

169173

174+
@pytest.mark.parametrize(
175+
("url", "headers", "cache_control"),
176+
[
177+
(
178+
"http://python.org/python-3.7.1.zip",
179+
{},
180+
"max-age=0",
181+
),
182+
(
183+
"https://pypi.org/pip-18.0.tar.gz",
184+
{},
185+
"max-age=0",
186+
),
187+
(
188+
"http://python.org/python-3.7.1.zip",
189+
{"Cache-Control": "max-age=1"},
190+
"max-age=1",
191+
),
192+
(
193+
"https://pypi.org/pip-18.0.tar.gz",
194+
{"Cache-Control": "max-age=1"},
195+
"max-age=1",
196+
),
197+
],
198+
)
199+
def test_get_html_response_override_cache_control(url, headers, cache_control):
200+
"""
201+
`_get_html_response()` should use the session's default value for the
202+
Cache-Control header if provided.
203+
"""
204+
session = mock.Mock(PipSession)
205+
session.headers = headers
206+
session.head.return_value = mock.Mock(**{
207+
"request.method": "HEAD",
208+
"headers": {"Content-Type": "text/html"},
209+
})
210+
session.get.return_value = mock.Mock(headers={"Content-Type": "text/html"})
211+
212+
resp = _get_html_response(url, session=session)
213+
214+
assert resp is not None
215+
assert session.mock_calls == [
216+
mock.call.head(url, allow_redirects=True),
217+
mock.call.head().raise_for_status(),
218+
mock.call.get(url, headers={
219+
"Accept": "text/html", "Cache-Control": cache_control,
220+
}),
221+
mock.call.get().raise_for_status(),
222+
]
223+
224+
170225
@pytest.mark.parametrize(
171226
("html", "url", "expected"),
172227
[
@@ -416,6 +471,7 @@ def test_request_http_error(caplog):
416471
caplog.set_level(logging.DEBUG)
417472
link = Link('http://localhost')
418473
session = Mock(PipSession)
474+
session.headers = {}
419475
session.get.return_value = resp = Mock()
420476
resp.raise_for_status.side_effect = requests.HTTPError('Http error')
421477
assert _get_html_page(link, session=session) is None
@@ -429,6 +485,7 @@ def test_request_retries(caplog):
429485
caplog.set_level(logging.DEBUG)
430486
link = Link('http://localhost')
431487
session = Mock(PipSession)
488+
session.headers = {}
432489
session.get.side_effect = requests.exceptions.RetryError('Retry error')
433490
assert _get_html_page(link, session=session) is None
434491
assert (
@@ -501,6 +558,7 @@ def test_get_html_page_directory_append_index(tmpdir):
501558
expected_url = "{}/index.html".format(dir_url.rstrip("/"))
502559

503560
session = mock.Mock(PipSession)
561+
session.headers = {}
504562
fake_response = make_fake_html_response(expected_url)
505563
mock_func = mock.patch("pip._internal.index.collector._get_html_response")
506564
with mock_func as mock_func:

0 commit comments

Comments
 (0)