Pip: Fast-deps: bad interaction with Artifactory leading to zipfile.BadZipFile

Created on 6 Aug 2020  Β·  20Comments  Β·  Source: pypa/pip

What did you want to do?
Trying to install Cython using the experimental features.

Command line:

virtualenv -p python3.7 env
source env/bin/activate
pip install -U pip
pip install --use-feature=2020-resolver --use-feature=fast-deps -v cython

This works correctly on my home linux computer, but fails at work where we have the following /etc/pip.conf:

[global]
cert = /etc/pki/tls/cert.pem
no-cache-dir = false
index-url = https://artifactory.our-organization.com/artifactory/api/pypi/python-virtual-repo/simple
index = https://artifactory.our-organization.com/artifactory/api/pypi/python-virtual-repo/simple

It also works in both places when I keep 2020-resolver but omit fast-deps.

The same problem is present on master

Output
This is the relevant part of the output from pip -v, with pip f17c1d6d3bf4b4ee8b7b0e669c449b9cd86e94f6 installed:

Given no hashes to check 141 links for project 'cython': discarding no candidates
Collecting cython
  Obtaining dependency information from cython 0.29.21
  https://artifactory.our-organization.com:443 "HEAD /artifactory/api/pypi/python-virtual-repo/packages/packages/6b/36/d6c18632a339dafa54fd128b0dd2c36c6dc4bc86b8e0d366ccd9f22b480a/Cython-0.29.21-cp37-cp37m-manylinux1_x86_64.whl HTTP/1.1" 200 0
  https://artifactory.our-organization.com:443 "GET /artifactory/api/pypi/python-virtual-repo/packages/packages/6b/36/d6c18632a339dafa54fd128b0dd2c36c6dc4bc86b8e0d366ccd9f22b480a/Cython-0.29.21-cp37-cp37m-manylinux1_x86_64.whl HTTP/1.1" 200 1969113
  https://artifactory.our-organization.com:443 "GET /artifactory/api/pypi/python-virtual-repo/packages/packages/6b/36/d6c18632a339dafa54fd128b0dd2c36c6dc4bc86b8e0d366ccd9f22b480a/Cython-0.29.21-cp37-cp37m-manylinux1_x86_64.whl HTTP/1.1" 200 1969113
  https://artifactory.our-organization.com:443 "GET /artifactory/api/pypi/python-virtual-repo/packages/packages/6b/36/d6c18632a339dafa54fd128b0dd2c36c6dc4bc86b8e0d366ccd9f22b480a/Cython-0.29.21-cp37-cp37m-manylinux1_x86_64.whl HTTP/1.1" 200 1969113
  https://artifactory.our-organization.com:443 "GET /artifactory/api/pypi/python-virtual-repo/packages/packages/6b/36/d6c18632a339dafa54fd128b0dd2c36c6dc4bc86b8e0d366ccd9f22b480a/Cython-0.29.21-cp37-cp37m-manylinux1_x86_64.whl HTTP/1.1" 200 1969113
  https://artifactory.our-organization.com:443 "GET /artifactory/api/pypi/python-virtual-repo/packages/packages/6b/36/d6c18632a339dafa54fd128b0dd2c36c6dc4bc86b8e0d366ccd9f22b480a/Cython-0.29.21-cp37-cp37m-manylinux1_x86_64.whl HTTP/1.1" 200 1969113
  https://artifactory.our-organization.com:443 "GET /artifactory/api/pypi/python-virtual-repo/packages/packages/6b/36/d6c18632a339dafa54fd128b0dd2c36c6dc4bc86b8e0d366ccd9f22b480a/Cython-0.29.21-cp37-cp37m-manylinux1_x86_64.whl HTTP/1.1" 200 1969113
  https://artifactory.our-organization.com:443 "GET /artifactory/api/pypi/python-virtual-repo/packages/packages/6b/36/d6c18632a339dafa54fd128b0dd2c36c6dc4bc86b8e0d366ccd9f22b480a/Cython-0.29.21-cp37-cp37m-manylinux1_x86_64.whl HTTP/1.1" 200 1969113

[SNIP: that line repeats a total of 193 times]

ERROR: Exception:
Traceback (most recent call last):
  File "/tmp/tmp.O9hMH57Ecq/env2/lib/python3.7/site-packages/pip/_internal/cli/base_command.py", line 216, in _main
    status = self.run(options, args)
  File "/tmp/tmp.O9hMH57Ecq/env2/lib/python3.7/site-packages/pip/_internal/cli/req_command.py", line 182, in wrapper
    return func(self, options, args)
  File "/tmp/tmp.O9hMH57Ecq/env2/lib/python3.7/site-packages/pip/_internal/commands/install.py", line 324, in run
    reqs, check_supported_wheels=not options.target_dir
  File "/tmp/tmp.O9hMH57Ecq/env2/lib/python3.7/site-packages/pip/_internal/resolution/resolvelib/resolver.py", line 111, in resolve
    requirements, max_rounds=try_to_avoid_resolution_too_deep,
  File "/tmp/tmp.O9hMH57Ecq/env2/lib/python3.7/site-packages/pip/_vendor/resolvelib/resolvers.py", line 427, in resolve
    state = resolution.resolve(requirements, max_rounds=max_rounds)
  File "/tmp/tmp.O9hMH57Ecq/env2/lib/python3.7/site-packages/pip/_vendor/resolvelib/resolvers.py", line 324, in resolve
    failure_causes = self._attempt_to_pin_criterion(name, criterion)
  File "/tmp/tmp.O9hMH57Ecq/env2/lib/python3.7/site-packages/pip/_vendor/resolvelib/resolvers.py", line 224, in _attempt_to_pin_criterion
    criteria = self._get_criteria_to_update(candidate)
  File "/tmp/tmp.O9hMH57Ecq/env2/lib/python3.7/site-packages/pip/_vendor/resolvelib/resolvers.py", line 215, in _get_criteria_to_update
    for r in self._p.get_dependencies(candidate):
  File "/tmp/tmp.O9hMH57Ecq/env2/lib/python3.7/site-packages/pip/_internal/resolution/resolvelib/provider.py", line 151, in get_dependencies
    for r in candidate.iter_dependencies(with_requires)
  File "/tmp/tmp.O9hMH57Ecq/env2/lib/python3.7/site-packages/pip/_internal/resolution/resolvelib/provider.py", line 150, in <listcomp>
    r
  File "/tmp/tmp.O9hMH57Ecq/env2/lib/python3.7/site-packages/pip/_internal/resolution/resolvelib/candidates.py", line 251, in iter_dependencies
    for r in self.dist.requires():
  File "/tmp/tmp.O9hMH57Ecq/env2/lib/python3.7/site-packages/pip/_internal/resolution/resolvelib/candidates.py", line 230, in dist
    self._prepare()
  File "/tmp/tmp.O9hMH57Ecq/env2/lib/python3.7/site-packages/pip/_internal/resolution/resolvelib/candidates.py", line 217, in _prepare
    dist = self._prepare_distribution()
  File "/tmp/tmp.O9hMH57Ecq/env2/lib/python3.7/site-packages/pip/_internal/resolution/resolvelib/candidates.py", line 315, in _prepare_distribution
    self._ireq, parallel_builds=True,
  File "/tmp/tmp.O9hMH57Ecq/env2/lib/python3.7/site-packages/pip/_internal/operations/prepare.py", line 500, in prepare_linked_requirement
    wheel_dist = self._fetch_metadata_using_lazy_wheel(link)
  File "/tmp/tmp.O9hMH57Ecq/env2/lib/python3.7/site-packages/pip/_internal/operations/prepare.py", line 488, in _fetch_metadata_using_lazy_wheel
    return dist_from_wheel_url(name, url, self._session)
  File "/tmp/tmp.O9hMH57Ecq/env2/lib/python3.7/site-packages/pip/_internal/network/lazy_wheel.py", line 46, in dist_from_wheel_url
    zip_file = ZipFile(wheel)  # type: ignore
  File "/opt/python-3.7/lib/python3.7/zipfile.py", line 1222, in __init__
    self._RealGetContents()
  File "/opt/python-3.7/lib/python3.7/zipfile.py", line 1317, in _RealGetContents
    raise BadZipFile("Bad magic number for central directory")
zipfile.BadZipFile: Bad magic number for central directory

The same part of the output for my home machine where it works, also with f17c1d6d3bf4b4ee8b7b0e669c449b9cd86e94f6

Given no hashes to check 141 links for project 'cython': discarding no candidates
Collecting cython
  Obtaining dependency information from cython 0.29.21
  Starting new HTTPS connection (1): files.pythonhosted.org:443
  https://files.pythonhosted.org:443 "HEAD /packages/6b/36/d6c18632a339dafa54fd128b0dd2c36c6dc4bc86b8e0d366ccd9f22b480a/Cython-0.29.21-cp37-cp37m-manylinux1_x86_64.whl HTTP/1.1" 200 0
  Looking up "https://files.pythonhosted.org/packages/6b/36/d6c18632a339dafa54fd128b0dd2c36c6dc4bc86b8e0d366ccd9f22b480a/Cython-0.29.21-cp37-cp37m-manylinux1_x86_64.whl" in the cache
  Request header has "no-cache", cache bypassed
  https://files.pythonhosted.org:443 "GET /packages/6b/36/d6c18632a339dafa54fd128b0dd2c36c6dc4bc86b8e0d366ccd9f22b480a/Cython-0.29.21-cp37-cp37m-manylinux1_x86_64.whl HTTP/1.1" 206 3033
  Status code 206 not in (200, 203, 300, 301)
  Looking up "https://files.pythonhosted.org/packages/6b/36/d6c18632a339dafa54fd128b0dd2c36c6dc4bc86b8e0d366ccd9f22b480a/Cython-0.29.21-cp37-cp37m-manylinux1_x86_64.whl" in the cache
  Request header has "no-cache", cache bypassed
  https://files.pythonhosted.org:443 "GET /packages/6b/36/d6c18632a339dafa54fd128b0dd2c36c6dc4bc86b8e0d366ccd9f22b480a/Cython-0.29.21-cp37-cp37m-manylinux1_x86_64.whl HTTP/1.1" 206 7207
  Status code 206 not in (200, 203, 300, 301)
  Looking up "https://files.pythonhosted.org/packages/6b/36/d6c18632a339dafa54fd128b0dd2c36c6dc4bc86b8e0d366ccd9f22b480a/Cython-0.29.21-cp37-cp37m-manylinux1_x86_64.whl" in the cache
  Request header has "no-cache", cache bypassed
  https://files.pythonhosted.org:443 "GET /packages/6b/36/d6c18632a339dafa54fd128b0dd2c36c6dc4bc86b8e0d366ccd9f22b480a/Cython-0.29.21-cp37-cp37m-manylinux1_x86_64.whl HTTP/1.1" 206 13941
  Status code 206 not in (200, 203, 300, 301)
  Looking up "https://files.pythonhosted.org/packages/6b/36/d6c18632a339dafa54fd128b0dd2c36c6dc4bc86b8e0d366ccd9f22b480a/Cython-0.29.21-cp37-cp37m-manylinux1_x86_64.whl" in the cache
  Request header has "no-cache", cache bypassed
  https://files.pythonhosted.org:443 "GET /packages/6b/36/d6c18632a339dafa54fd128b0dd2c36c6dc4bc86b8e0d366ccd9f22b480a/Cython-0.29.21-cp37-cp37m-manylinux1_x86_64.whl HTTP/1.1" 206 166
  Status code 206 not in (200, 203, 300, 301)
  Looking up "https://files.pythonhosted.org/packages/6b/36/d6c18632a339dafa54fd128b0dd2c36c6dc4bc86b8e0d366ccd9f22b480a/Cython-0.29.21-cp37-cp37m-manylinux1_x86_64.whl" in the cache
  Request header has "no-cache", cache bypassed
  https://files.pythonhosted.org:443 "GET /packages/6b/36/d6c18632a339dafa54fd128b0dd2c36c6dc4bc86b8e0d366ccd9f22b480a/Cython-0.29.21-cp37-cp37m-manylinux1_x86_64.whl HTTP/1.1" 206 10240
  Status code 206 not in (200, 203, 300, 301)
  Looking up "https://files.pythonhosted.org/packages/6b/36/d6c18632a339dafa54fd128b0dd2c36c6dc4bc86b8e0d366ccd9f22b480a/Cython-0.29.21-cp37-cp37m-manylinux1_x86_64.whl" in the cache
  Request header has "no-cache", cache bypassed
  https://files.pythonhosted.org:443 "GET /packages/6b/36/d6c18632a339dafa54fd128b0dd2c36c6dc4bc86b8e0d366ccd9f22b480a/Cython-0.29.21-cp37-cp37m-manylinux1_x86_64.whl HTTP/1.1" 206 30
  Status code 206 not in (200, 203, 300, 301)
  Looking up "https://files.pythonhosted.org/packages/6b/36/d6c18632a339dafa54fd128b0dd2c36c6dc4bc86b8e0d366ccd9f22b480a/Cython-0.29.21-cp37-cp37m-manylinux1_x86_64.whl" in the cache
  Request header has "no-cache", cache bypassed
  https://files.pythonhosted.org:443 "GET /packages/6b/36/d6c18632a339dafa54fd128b0dd2c36c6dc4bc86b8e0d366ccd9f22b480a/Cython-0.29.21-cp37-cp37m-manylinux1_x86_64.whl HTTP/1.1" 206 41
  Status code 206 not in (200, 203, 300, 301)
  Looking up "https://files.pythonhosted.org/packages/6b/36/d6c18632a339dafa54fd128b0dd2c36c6dc4bc86b8e0d366ccd9f22b480a/Cython-0.29.21-cp37-cp37m-manylinux1_x86_64.whl" in the cache
  Request header has "no-cache", cache bypassed
  https://files.pythonhosted.org:443 "GET /packages/6b/36/d6c18632a339dafa54fd128b0dd2c36c6dc4bc86b8e0d366ccd9f22b480a/Cython-0.29.21-cp37-cp37m-manylinux1_x86_64.whl HTTP/1.1" 206 99
  Status code 206 not in (200, 203, 300, 301)
  Looking up "https://files.pythonhosted.org/packages/6b/36/d6c18632a339dafa54fd128b0dd2c36c6dc4bc86b8e0d366ccd9f22b480a/Cython-0.29.21-cp37-cp37m-manylinux1_x86_64.whl" in the cache
  Request header has "no-cache", cache bypassed
  https://files.pythonhosted.org:443 "GET /packages/6b/36/d6c18632a339dafa54fd128b0dd2c36c6dc4bc86b8e0d366ccd9f22b480a/Cython-0.29.21-cp37-cp37m-manylinux1_x86_64.whl HTTP/1.1" 206 30
  Status code 206 not in (200, 203, 300, 301)
  Looking up "https://files.pythonhosted.org/packages/6b/36/d6c18632a339dafa54fd128b0dd2c36c6dc4bc86b8e0d366ccd9f22b480a/Cython-0.29.21-cp37-cp37m-manylinux1_x86_64.whl" in the cache
  Request header has "no-cache", cache bypassed
  https://files.pythonhosted.org:443 "GET /packages/6b/36/d6c18632a339dafa54fd128b0dd2c36c6dc4bc86b8e0d366ccd9f22b480a/Cython-0.29.21-cp37-cp37m-manylinux1_x86_64.whl HTTP/1.1" 206 33
  Status code 206 not in (200, 203, 300, 301)
  Looking up "https://files.pythonhosted.org/packages/6b/36/d6c18632a339dafa54fd128b0dd2c36c6dc4bc86b8e0d366ccd9f22b480a/Cython-0.29.21-cp37-cp37m-manylinux1_x86_64.whl" in the cache
  Request header has "no-cache", cache bypassed
  https://files.pythonhosted.org:443 "GET /packages/6b/36/d6c18632a339dafa54fd128b0dd2c36c6dc4bc86b8e0d366ccd9f22b480a/Cython-0.29.21-cp37-cp37m-manylinux1_x86_64.whl HTTP/1.1" 206 1035
  Status code 206 not in (200, 203, 300, 301)
  Looking up "https://files.pythonhosted.org/packages/6b/36/d6c18632a339dafa54fd128b0dd2c36c6dc4bc86b8e0d366ccd9f22b480a/Cython-0.29.21-cp37-cp37m-manylinux1_x86_64.whl" in the cache
  Request header has "no-cache", cache bypassed
  https://files.pythonhosted.org:443 "GET /packages/6b/36/d6c18632a339dafa54fd128b0dd2c36c6dc4bc86b8e0d366ccd9f22b480a/Cython-0.29.21-cp37-cp37m-manylinux1_x86_64.whl HTTP/1.1" 206 30
  Status code 206 not in (200, 203, 300, 301)
  Looking up "https://files.pythonhosted.org/packages/6b/36/d6c18632a339dafa54fd128b0dd2c36c6dc4bc86b8e0d366ccd9f22b480a/Cython-0.29.21-cp37-cp37m-manylinux1_x86_64.whl" in the cache
  Request header has "no-cache", cache bypassed
  https://files.pythonhosted.org:443 "GET /packages/6b/36/d6c18632a339dafa54fd128b0dd2c36c6dc4bc86b8e0d366ccd9f22b480a/Cython-0.29.21-cp37-cp37m-manylinux1_x86_64.whl HTTP/1.1" 206 38
  Status code 206 not in (200, 203, 300, 301)
  Looking up "https://files.pythonhosted.org/packages/6b/36/d6c18632a339dafa54fd128b0dd2c36c6dc4bc86b8e0d366ccd9f22b480a/Cython-0.29.21-cp37-cp37m-manylinux1_x86_64.whl" in the cache
  Request header has "no-cache", cache bypassed
  https://files.pythonhosted.org:443 "GET /packages/6b/36/d6c18632a339dafa54fd128b0dd2c36c6dc4bc86b8e0d366ccd9f22b480a/Cython-0.29.21-cp37-cp37m-manylinux1_x86_64.whl HTTP/1.1" 206 21
  Status code 206 not in (200, 203, 300, 301)
  Looking up "https://files.pythonhosted.org/packages/6b/36/d6c18632a339dafa54fd128b0dd2c36c6dc4bc86b8e0d366ccd9f22b480a/Cython-0.29.21-cp37-cp37m-manylinux1_x86_64.whl" in the cache
  Request header has "no-cache", cache bypassed
  https://files.pythonhosted.org:443 "GET /packages/6b/36/d6c18632a339dafa54fd128b0dd2c36c6dc4bc86b8e0d366ccd9f22b480a/Cython-0.29.21-cp37-cp37m-manylinux1_x86_64.whl HTTP/1.1" 206 30
  Status code 206 not in (200, 203, 300, 301)
  Looking up "https://files.pythonhosted.org/packages/6b/36/d6c18632a339dafa54fd128b0dd2c36c6dc4bc86b8e0d366ccd9f22b480a/Cython-0.29.21-cp37-cp37m-manylinux1_x86_64.whl" in the cache
  Request header has "no-cache", cache bypassed
  https://files.pythonhosted.org:443 "GET /packages/6b/36/d6c18632a339dafa54fd128b0dd2c36c6dc4bc86b8e0d366ccd9f22b480a/Cython-0.29.21-cp37-cp37m-manylinux1_x86_64.whl HTTP/1.1" 206 3404
  Status code 206 not in (200, 203, 300, 301)
  Created temporary directory: /tmp/pip-unpack-xywl9x_9
  Looking up "https://files.pythonhosted.org/packages/6b/36/d6c18632a339dafa54fd128b0dd2c36c6dc4bc86b8e0d366ccd9f22b480a/Cython-0.29.21-cp37-cp37m-manylinux1_x86_64.whl" in the cache
  No cache entry available
  https://files.pythonhosted.org:443 "GET /packages/6b/36/d6c18632a339dafa54fd128b0dd2c36c6dc4bc86b8e0d366ccd9f22b480a/Cython-0.29.21-cp37-cp37m-manylinux1_x86_64.whl HTTP/1.1" 200 1969113
  Downloading Cython-0.29.21-cp37-cp37m-manylinux1_x86_64.whl (2.0 MB)
     |β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ| 2.0 MB 2.2 MB/s eta 0:00:01  Ignoring unknown cache-control directive: immutable
  Updating cache with response from "https://files.pythonhosted.org/packages/6b/36/d6c18632a339dafa54fd128b0dd2c36c6dc4bc86b8e0d366ccd9f22b480a/Cython-0.29.21-cp37-cp37m-manylinux1_x86_64.whl"
  Caching due to etag
     |β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ| 2.0 MB 2.2 MB/s 
  Added cython from https://files.pythonhosted.org/packages/6b/36/d6c18632a339dafa54fd128b0dd2c36c6dc4bc86b8e0d366ccd9f22b480a/Cython-0.29.21-cp37-cp37m-manylinux1_x86_64.whl#sha256=5e545a48f919e40079b0efe7b0e081c74b96f9ef25b9c1ff4cdbd95764426b58 to build tracker '/tmp/pip-req-tracker-a7imwe9c'
  Removed cython from https://files.pythonhosted.org/packages/6b/36/d6c18632a339dafa54fd128b0dd2c36c6dc4bc86b8e0d366ccd9f22b480a/Cython-0.29.21-cp37-cp37m-manylinux1_x86_64.whl#sha256=5e545a48f919e40079b0efe7b0e081c74b96f9ef25b9c1ff4cdbd95764426b58 from build tracker '/tmp/pip-req-tracker-a7imwe9c'
Installing collected packages: cython

  changing mode of /tmp/ohoashd-env/bin/cygdb to 755
  changing mode of /tmp/ohoashd-env/bin/cython to 755
  changing mode of /tmp/ohoashd-env/bin/cythonize to 755
Successfully installed cython-0.29.21
Removed build tracker: '/tmp/pip-req-tracker-a7imwe9c'

Additional information

Happy to try versions from pull requests if that's helpful. I might also be smart enough to set up a mitmproxy to record the HTTP interaction, but I'm not completely sure.

bug

All 20 comments

Seems similar to #8701. That one is already fixed in master, it’d be nice if you can try if it fixes this as well.

I ran across that bug while I was testing for this one, and I agree that it's fixed in master. But even though the exception is the same, the cause seems to be different. Pip's caching is disabled on my work computer where this failure happens. I did reproduce this bug using master.

It seems like a different bug, then. I’m unfortunately not familiar with the part of code to offer a fix, so I’ll let those who do work on it.

Hi @tgs, thank you very much for filing this, which will give us better understanding on the current state of support for range requests on package indices in the wild.

https://artifactory.our-organization.com:443 "GET /artifactory/api/pypi/python-virtual-repo/packages/packages/6b/36/d6c18632a339dafa54fd128b0dd2c36c6dc4bc86b8e0d366ccd9f22b480a/Cython-0.29.21-cp37-cp37m-manylinux1_x86_64.whl HTTP/1.1" 200 1969113
[SNIP: that line repeats a total of 193 times]

At first glance, it seems that fast-deps is mistaking for range request support when it's actually unavailable. Could you please give us the output of the following command?

curl -I https://artifactory.our-organization.com:443 "GET /artifactory/api/pypi/python-virtual-repo/packages/packages/6b/36/d6c18632a339dafa54fd128b0dd2c36c6dc4bc86b8e0d366ccd9f22b480a/Cython-0.29.21-cp37-cp37m-manylinux1_x86_64.whl

I suspect that the index is internal so I'm not likely to be able to get my hands on, but my guess is that the bus has something to do with this part of the code https://github.com/pypa/pip/blob/e8f52198a94f9f8203afcfe34111f3c21dd1bf35/src/pip/_internal/network/lazy_wheel.py#L63-L73 which somehow did not raise HTTPRangeRequestUnsupported.

The command line didn't quite work, I changed it to omit the GET:

$ curl -I "https://artifactory.our-organization.com:443/artifactory/api/pypi/python-virtual-repo/packages/packages/6b/36/d6c18632a339dafa54fd128b0dd2c36c6dc4bc86b8e0d366ccd9f22b480a/Cython-0.29.21-cp37-cp37m-manylinux1_x86_64.whl"
HTTP/1.1 200 OK
Date: Fri, 07 Aug 2020 17:41:20 GMT
Server: Artifactory/6.18.1
X-Artifactory-Id: 58b6d1fd8d039ec1:-18e585a9:17378973c9c:-8000
Cache-Control: public, max-age=31536000
Last-Modified: Wed, 08 Jul 2020 21:56:33 GMT
ETag: 5c7486cdb788792dfb0ea3928e075a2df9960578
X-Checksum-Sha1: 5c7486cdb788792dfb0ea3928e075a2df9960578
X-Checksum-Sha256: 5e545a48f919e40079b0efe7b0e081c74b96f9ef25b9c1ff4cdbd95764426b58
X-Checksum-Md5: e244967a4c60b39072d30485df45fd90
Accept-Ranges: bytes
X-Artifactory-Filename: Cython-0.29.21-cp37-cp37m-manylinux1_x86_64.whl
Content-Disposition: attachment; filename="Cython-0.29.21-cp37-cp37m-manylinux1_x86_64.whl"; filename*=UTF-8''Cython-0.29.21-cp37-cp37m-manylinux1_x86_64.whl
Content-Type: application/octet-stream
Content-Length: 1969113
Via: 1.1 artifactory.our-organization.com

So it does claim to accept byte ranges... weird! I'll see if I can figure out the curl command line for ranges and see if it works.

The command line didn't quite work, I changed it to omit the GET

Oops, I'm sorry for that.

I'll see if I can figure out the curl command line for ranges and see if it works.

According to MDN, something like this may give some insight:

curl -I -H "Range: bytes=0-1023" "https://artifactory.our-organization.com:443/artifactory/api/pypi/python-virtual-repo/packages/packages/6b/36/d6c18632a339dafa54fd128b0dd2c36c6dc4bc86b8e0d366ccd9f22b480a/Cython-0.29.21-cp37-cp37m-manylinux1_x86_64.whl"
> GET /artifactory/api/pypi/python-virtual-repo/packages/packages/6b/36/d6c18632a339dafa54fd128b0dd2c36c6dc4bc86b8e0d366ccd9f22b480a/Cython-0.29.21-cp37-cp37m-manylinux1_x86_64.whl HTTP/1.1
> User-Agent: curl/7.29.0
> Host: artifactory.our-organization.com
> Accept: */*
> Range: bytes=0-1023
> 
< HTTP/1.1 200 OK
< Date: Thu, 13 Aug 2020 19:57:32 GMT
< Server: Artifactory/6.18.1
< X-Artifactory-Id: 58b6d1fd8d039ec1:-18e585a9:17378973c9c:-8000
< Cache-Control: public, max-age=31536000
< Last-Modified: Wed, 08 Jul 2020 21:56:33 GMT
< ETag: 5c7486cdb788792dfb0ea3928e075a2df9960578
< X-Checksum-Sha1: 5c7486cdb788792dfb0ea3928e075a2df9960578
< X-Checksum-Sha256: 5e545a48f919e40079b0efe7b0e081c74b96f9ef25b9c1ff4cdbd95764426b58
< X-Checksum-Md5: e244967a4c60b39072d30485df45fd90
< Accept-Ranges: bytes
< X-Artifactory-Filename: Cython-0.29.21-cp37-cp37m-manylinux1_x86_64.whl
< Content-Disposition: attachment; filename="Cython-0.29.21-cp37-cp37m-manylinux1_x86_64.whl"; filename*=UTF-8''Cython-0.29.21-cp37-cp37m-manylinux1_x86_64.whl
< Content-Type: application/octet-stream
< Content-Length: 1969113
< Via: 1.1 artifactory.our-organization.com
< 

I piped it through wc -c, it did indeed return the whole file. Huh!

Maybe I should also open a ticket on the Artifactory public JIRA.

Thanks for your input @tgs! FYI range responses have the status code of 206 but I don't know enough to tell if the behavior above is acceptable by the web standards.

@dholth, is it legal for servers to advertise for Accept-Ranges but in fact responses to range requests with status 200? Should pip works around this by checking every response, or expects the servers to keep their promises?

I've reported the bug to Artifactory - https://www.jfrog.com/jira/browse/RTFACT-23108

Regardless of whether they fix it, there will probably be old versions of Artifactory still installed for some time, so maybe there will need to be a server version cutoff or something? If that's how the condition is detected - maybe that's too brittle.

Looks like we'd best parse the range from the response and write to disk accordingly.

@tgs, thank you for linking the Artifactory ticket.

@dholth, the response from Artifactory is not a range one (@tgs included the request in the output above). Considering

Regardless of whether they fix it, there will probably be old versions of Artifactory still installed for some time

I'll make a work around to fallback to whole wheel downloading if a server lies about range request support. I think you might mean to write the content of non-range response to disk, but currently we have to disable caching for range responses so probably it is not the best choice right now.

@cosmicexplorer, I saw in GH-7819 that you're using Artifactory as well. Does this problem affect you?

Will report back!

JFTR I have the exact same problem with devpi. Disabling either fast-deps or 2020-resolver fixes it.

This would likely be an interaction of fast-deps (which uses the Range header for partial downloads to handle zip files), with Artifactory/devpi/something!? Does this occur with only the 2020-resolver enabled?

Just fast-deps: βœ…
Just 2020-resolver: βœ…
Both together: ❌

fast-deps is no-op w/o 2020-resolver enabled, so that makes sense. @hynek, what would you get if you run curl -I -H "Range: bytes=0-1023" <link to a wheel on the devpi instance>? Also does anyone has an opinion about

I'll make a work around to fallback to whole wheel downloading if a server lies about range request support.

curl -I -H "Range: bytes=0-1023" "https://pypi.vm.ag/root/pypi/+f/fce/7fc47dfc97615/attrs-20.2.0-py2.py3-none-any.whl#sha256=fce7fc47dfc976152e82d53ff92fa0407700c21acd20886a13777a0d20e655dc"
HTTP/2 206
server: nginx
date: Wed, 21 Oct 2020 11:53:45 GMT
content-type: application/octet-stream
content-length: 1024
last-modified: Sat, 05 Sep 2020 10:27:32 GMT
etag: "5f536814-bc0c"
expires: Thu, 31 Dec 2037 23:55:55 GMT
cache-control: max-age=315360000
strict-transport-security: max-age=63072000
x-content-type-options: nosniff
x-xss-protection: 1; mode=block
x-frame-options: SAMEORIGIN
content-range: bytes 0-1023/48140


Thanks, and that looks like a valid partial response. In other news, files.pythonhosted.org doesn't seem to be supporting partial download anymore and I'm feeling really bad for the effort everyone spent during the summer getting fast-deps implemented. If I have to guess, there might be some issue with caching so the reverse of GH-8701 happened, perhaps. I'll try to investigate a bit deeper later this weekend.

Was this page helpful?
0 / 5 - 0 ratings