Skip to content

Commit 00af5f4

Browse files
committed
Add env-var to force binary content-type for files
Fixes EpicWink#9
1 parent e33d32e commit 00af5f4

File tree

3 files changed

+31
-1
lines changed

3 files changed

+31
-1
lines changed

README.md

+3
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,9 @@ change in a package index.
7070
Disable files-cache by setting this to 0
7171
* `PROXPI_CACHE_DIR`: downloaded project files cache directory path, default: a new
7272
temporary directory
73+
* `PROXPI_BINARY_FILE_MIME_TYPE=1`: force file-response content-type to
74+
`"application/octet-stream"` instead of letting Flask guess it. This may be needed
75+
if your package installer (eg Poetry) mishandles responses with declared encoding.
7376

7477
### Considerations with CI
7578
`proxpi` was designed with three goals (particularly for continuous integration (CI)):

src/proxpi/server.py

+6-1
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,11 @@ def _set_handler(self, *_, **__):
6565
handler.level = logging.DEBUG
6666
logger.info("Cache: %r", cache)
6767

68+
BINARY_FILE_MIME_TYPE = (
69+
os.environ.get("PROXPI_BINARY_FILE_MIME_TYPE", "")
70+
).lower() not in ("", "0", "no", "off", "false")
71+
_file_mime_type = "application/octet-stream" if BINARY_FILE_MIME_TYPE else None
72+
6873

6974
def _compress(response: t.Union[str, flask.Response]) -> flask.Response:
7075
response = flask.make_response(response)
@@ -123,7 +128,7 @@ def get_file(package_name: str, file_name: str):
123128
scheme = urllib.parse.urlparse(path).scheme
124129
if scheme and scheme != "file":
125130
return flask.redirect(path)
126-
return flask.send_file(path)
131+
return flask.send_file(path, mimetype=_file_mime_type)
127132

128133

129134
@app.route("/cache/list", methods=["DELETE"])

tests/test_integration.py

+22
Original file line numberDiff line numberDiff line change
@@ -238,3 +238,25 @@ def test_download_file_failed(server, tmp_path):
238238
url_parsed = urllib_parse.urlsplit(response.headers["location"])
239239
assert url_parsed.netloc == "files.pythonhosted.org"
240240
assert posixpath.split(url_parsed.path)[1] == "Jinja2-2.11.1-py2.py3-none-any.whl"
241+
242+
243+
@pytest.mark.parametrize("file_mime_type", ["application/octet-stream", None])
244+
def test_download_file_representation(server, tmp_path, file_mime_type):
245+
"""Test package file content type and encoding."""
246+
(tmp_path / "packages").mkdir()
247+
file_mime_type_patch = mock.patch.object(
248+
proxpi_server, "_file_mime_type", file_mime_type
249+
)
250+
with file_mime_type_patch:
251+
response = requests.get(
252+
"http://127.0.0.1:5042/index/proxpi/proxpi-1.0.0.tar.gz",
253+
allow_redirects=False,
254+
)
255+
assert response.status_code == 200
256+
if file_mime_type:
257+
assert response.headers["Content-Type"] == "application/octet-stream"
258+
assert not response.headers.get("Content-Encoding")
259+
else:
260+
assert response.headers["Content-Type"] == "application/x-tar"
261+
assert response.headers["Content-Encoding"] == "gzip"
262+
response.close()

0 commit comments

Comments
 (0)