We have an internal mirror of https://pypi.python.org that stopped working as the load testing started: https://status.python.org/incidents/0gmdf90kkt8n
I am currently investigating and collecting logs to further report but would like to create an issue in case other people come across the same problem.
If this turns-out to be my internal problem (I hope so!), my apologies in advance. I will update this issue as I have more information.
@thiagofigueiro thank you for the report. this breakage is likely due to not following the redirect being served.
You should be seeing a 303 See Other from pypi.python.org/simple/ urls.
Internal mirror details
Server: Artifactory Professional 4.8.0 rev 40210
Repository type: remote
Name: pypi-mirror
Remote URL: https://pypi.python.org
Remaining configuration using defaults.
I attempted changing the remote URL to https://pypi.org/simple/ but still received the same error.
We may need to be issuing a 302... perhaps 303s aren't well supported?
Does Artificatory have a User-Agent we can filter on for now?
@ewdurbin is there something I can do on my side to avoid the redirect?
I obviously want to move to the new mirror ASAP but, more importantly, I'd like to have a working service while I figure-out the differences and reconfigure our internal mirror.
@thiagofigueiro we've disabled it for now. we're going to try to filtering on User-Agent Artifactory/.*$
@ewdurbin I can confirm it started working again. Many thanks!
If you would like me to help with tests, please reach-out to me: [email protected].
URL detail:
Downloading http://INTERNAL_HOSTNAME:80/artifactory/api/pypi/pypi-mirror/packages/c5/b8/b0a563f18548168492afa9786f2b9d26774d75b578969488effa1f4061c0/django_extensions-1.6.7-py2.py3-none-any.whl
@thiagofigueiro we've moved from a 303 to a 302 and are opting all Artifactory User-Agents out of the split.
If possible, setting a Force-Warehouse-Redirect: 1 header on requests to PyPI and seeing if it still breaks would be _much_ appreciated.
@ewdurbin No obvious way to do this with the version we're currently using in production so it will take me a little bit to set-up the test.
I'm downloading the latest available from JFrog and will update this comment once I'm done.
Instance public IP: 184.72.69.31
Update: aaaaaand Artifactory OSS doesn't have PyPi support. Pro Trial licence achieved.
@thiagofigueiro if you can provide an IP address... we could give your installation the 302 redirect.
Thanks for the quick fix. We're trying it out now. Our users were impacted today as well, and after some confusion, they finally contacted me, and then I found this thread that seems to match what we were seeing. We also use Artifactory.
Our case seems to have cleared as well now. Artifactory as caching proxy behind the firewall.
It's not clear to me what failed, though. I can't yet find errors.
@mmielke-ciena to be explicit we are currently specifically excluding Artifactory User-Agents from our load test, so the issue is likely to arise if we stop doing so.
We've moved from a 303 to a 302... and hope that Artifactory supports this status code. I'll update this issue before we remove the exception for Artifactory.
@ewdurbin test instance ready. It's currently working:
# pip install -r requirements.txt
Collecting django-extensions==1.6.7 (from -r requirements.txt (line 1))
Downloading http://ec2-184-72-69-31.compute-1.amazonaws.com:8081/artifactory/api/pypi/pypi-mirror/packages/c5/b8/b0a563f18548168492afa9786f2b9d26774d75b578969488effa1f4061c0/django_extensions-1.6.7-py2.py3-none-any.whl (206kB)
Could you please activate the redirect for 184.72.69.31?
@thiagofigueiro 184.72.69.31 should be receiving the 302 redirects now.
Excellent - thanks. Can confirm it broke on the latest version of Artifactory Pro.
[root@036f888b8772 ci]# pip install -r requirements.txt
Collecting django-extensions==1.6.7 (from -r requirements.txt (line 1))
Could not find a version that satisfies the requirement django-extensions==1.6.7 (from -r requirements.txt (line 1)) (from versions: )
No matching distribution found for django-extensions==1.6.7 (from -r requirements.txt (line 1))
2018-03-15 23:32:12,185 [http-nio-8081-exec-8] [INFO ] (o.a.r.HttpRepo :414) - pypi-mirror downloading https://pypi.python.org/simple/django-extensions Unknown content length
2018-03-15 23:32:12,188 [http-nio-8081-exec-8] [INFO ] (o.a.r.HttpRepo :427) - pypi-mirror downloaded https://pypi.python.org/simple/django-extensions 37.43 KB at 14,533.67 KB/sec
Will find-out how to set Force-Warehouse-Redirect: 1 and any other work-arounds for Artifactory.
@thiagofigueiro if you can open an issue with Artifactory, let me know where it is and I'll slide in and contribute to helping find a solution.
Artifactory issue opened: #78509
where is their tracker @thiagofigueiro ?
I didn't get a link in the email - only the number. I have pointed them to this thread - hopefully they'll chime-in.
Meanwhile, this is what I see in the logs. It seems they do follow the redirect.
2018-03-15 23:44:53,962 [http-nio-8081-exec-7] [DEBUG] (o.a.w.s.RepoFilter :100) - Entering request GET (ip-redacted) /api/pypi/pypi-mirror/simple/django-extensions/.
2018-03-15 23:44:53,963 [http-nio-8081-exec-7] [DEBUG] (o.a.a.p.r.r.PypiRemoteIndexProvider:58) - Getting remote index from pypi-mirror for django-extensions
2018-03-15 23:44:53,964 [http-nio-8081-exec-7] [DEBUG] (o.a.a.m.ModuleInfoUtils:348) - Could not transform .pypi/django-extensions.html to a valid module info.
2018-03-15 23:44:53,964 [http-nio-8081-exec-7] [DEBUG] (o.a.a.m.ModuleInfoUtils:348) - Could not transform .pypi/django-extensions.html to a valid module info.
2018-03-15 23:44:53,965 [http-nio-8081-exec-7] [DEBUG] (o.a.a.m.ModuleInfoUtils:348) - Could not transform .pypi/django-extensions.html to a valid module info.
2018-03-15 23:44:53,965 [http-nio-8081-exec-7] [DEBUG] (o.a.r.RealRepoBase :79) - pypi-mirror is not a valid module info - '.pypi/django-extensions.html': not enforcing snapshot/release policy.
2018-03-15 23:44:53,965 [http-nio-8081-exec-7] [DEBUG] (o.a.s.SecurityServiceImpl:2167) - Access granted: true. granted by access token: false for pypi-mirror-cache:.pypi/django-extensions.html
2018-03-15 23:44:53,983 [http-nio-8081-exec-7] [DEBUG] (o.a.r.JFrogRedirectStrategy:142) - Redirect requested to location 'https://pypi.org/simple/django-extensions'
2018-03-15 23:44:54,019 [http-nio-8081-exec-7] [DEBUG] (o.a.r.JFrogRedirectStrategy:142) - Redirect requested to location 'https://pypi.org/simple/django-extensions/'
2018-03-15 23:44:54,021 [http-nio-8081-exec-7] [DEBUG] (o.a.a.p.r.r.PypiRemoteIndexProvider:121) - Delegating index request in pypi-mirror for simple/django-extensions
2018-03-15 23:44:54,022 [http-nio-8081-exec-7] [DEBUG] (o.a.a.m.ModuleInfoUtils:348) - Could not transform .pypi/django-extensions.html to a valid module info.
2018-03-15 23:44:54,022 [http-nio-8081-exec-7] [DEBUG] (o.a.a.m.ModuleInfoUtils:348) - Could not transform .pypi/django-extensions.html to a valid module info.
2018-03-15 23:44:54,022 [http-nio-8081-exec-7] [DEBUG] (o.a.r.RealRepoBase :79) - pypi-mirror is not a valid module info - '.pypi/django-extensions.html': not enforcing snapshot/release policy.
2018-03-15 23:44:54,023 [http-nio-8081-exec-7] [DEBUG] (o.a.s.SecurityServiceImpl:2167) - Access granted: true. granted by access token: false for pypi-mirror-cache:.pypi/django-extensions.html
2018-03-15 23:44:54,023 [http-nio-8081-exec-7] [DEBUG] (o.a.a.m.ModuleInfoUtils:348) - Could not transform .pypi/django-extensions.html to a valid module info.
2018-03-15 23:44:54,034 [http-nio-8081-exec-7] [DEBUG] (o.a.r.JFrogRedirectStrategy:142) - Redirect requested to location 'https://pypi.org/simple/django-extensions'
2018-03-15 23:44:54,038 [http-nio-8081-exec-7] [DEBUG] (o.a.r.JFrogRedirectStrategy:142) - Redirect requested to location 'https://pypi.org/simple/django-extensions/'
2018-03-15 23:44:54,040 [http-nio-8081-exec-7] [INFO ] (o.a.r.HttpRepo :414) - pypi-mirror downloading https://pypi.python.org/simple/django-extensions Unknown content length
2018-03-15 23:44:54,046 [http-nio-8081-exec-7] [INFO ] (o.a.r.HttpRepo :427) - pypi-mirror downloaded https://pypi.python.org/simple/django-extensions 37.43 KB at 7,606.20 KB/sec
2018-03-15 23:44:54,047 [http-nio-8081-exec-7] [DEBUG] (o.a.w.s.RepoFilter :188) - Exiting request GET (ip-redacted) /api/pypi/pypi-mirror/simple/django-extensions/
i.e.:
2018-03-15 23:44:53,983 [http-nio-8081-exec-7] [DEBUG] (o.a.r.JFrogRedirectStrategy:142) - Redirect requested to location 'https://pypi.org/simple/django-extensions'
2018-03-15 23:44:54,019 [http-nio-8081-exec-7] [DEBUG] (o.a.r.JFrogRedirectStrategy:142) - Redirect requested to location 'https://pypi.org/simple/django-extensions/'
@thiagofigueiro can you configure artifactory to use https://pypi.org directly?
can you configure artifactory to use https://pypi.org directly?
I did.
/api/pypi/pypi-mirror/ -> pypi.python.org
/api/pypi/pypi-new-mirror/ -> pypi.org
[global]
index-url = http://ec2-184-72-69-31.compute-1.amazonaws.com:8081/artifactory/api/pypi/pypi-mirror/simple
#index-url = http://ec2-184-72-69-31.compute-1.amazonaws.com:8081/artifactory/api/pypi/pypi-new-mirror/simple
No record of redirect in the log when I use the new mirror:
2018-03-15 23:52:21,247 [http-nio-8081-exec-9] [DEBUG] (o.a.w.s.RepoFilter :100) - Entering request GET (ip-redacted) /api/pypi/pypi-new-mirror/simple/django-extensions/.
2018-03-15 23:52:21,248 [http-nio-8081-exec-9] [DEBUG] (o.a.a.p.r.r.PypiRemoteIndexProvider:58) - Getting remote index from pypi-new-mirror for django-extensions
2018-03-15 23:52:21,249 [http-nio-8081-exec-9] [DEBUG] (o.a.a.m.ModuleInfoUtils:348) - Could not transform .pypi/django-extensions.html to a valid module info.
2018-03-15 23:52:21,249 [http-nio-8081-exec-9] [DEBUG] (o.a.a.m.ModuleInfoUtils:348) - Could not transform .pypi/django-extensions.html to a valid module info.
2018-03-15 23:52:21,249 [http-nio-8081-exec-9] [DEBUG] (o.a.a.m.ModuleInfoUtils:348) - Could not transform .pypi/django-extensions.html to a valid module info.
2018-03-15 23:52:21,250 [http-nio-8081-exec-9] [DEBUG] (o.a.r.RealRepoBase :79) - pypi-new-mirror is not a valid module info - '.pypi/django-extensions.html': not enforcing snapshot/release policy.
2018-03-15 23:52:21,250 [http-nio-8081-exec-9] [DEBUG] (o.a.s.SecurityServiceImpl:2167) - Access granted: true. granted by access token: false for pypi-new-mirror-cache:.pypi/django-extensions.html
2018-03-15 23:52:21,335 [http-nio-8081-exec-9] [DEBUG] (o.a.r.JFrogRedirectStrategy:142) - Redirect requested to location 'https://pypi.org/simple/django-extensions/'
2018-03-15 23:52:21,337 [http-nio-8081-exec-9] [DEBUG] (o.a.a.p.r.r.PypiRemoteIndexProvider:121) - Delegating index request in pypi-new-mirror for simple/django-extensions
2018-03-15 23:52:21,338 [http-nio-8081-exec-9] [DEBUG] (o.a.a.m.ModuleInfoUtils:348) - Could not transform .pypi/django-extensions.html to a valid module info.
2018-03-15 23:52:21,338 [http-nio-8081-exec-9] [DEBUG] (o.a.a.m.ModuleInfoUtils:348) - Could not transform .pypi/django-extensions.html to a valid module info.
2018-03-15 23:52:21,338 [http-nio-8081-exec-9] [DEBUG] (o.a.r.RealRepoBase :79) - pypi-new-mirror is not a valid module info - '.pypi/django-extensions.html': not enforcing snapshot/release policy.
2018-03-15 23:52:21,338 [http-nio-8081-exec-9] [DEBUG] (o.a.s.SecurityServiceImpl:2167) - Access granted: true. granted by access token: false for pypi-new-mirror-cache:.pypi/django-extensions.html
2018-03-15 23:52:21,339 [http-nio-8081-exec-9] [DEBUG] (o.a.a.m.ModuleInfoUtils:348) - Could not transform .pypi/django-extensions.html to a valid module info.
2018-03-15 23:52:21,341 [http-nio-8081-exec-9] [DEBUG] (o.a.r.JFrogRedirectStrategy:142) - Redirect requested to location 'https://pypi.org/simple/django-extensions/'
2018-03-15 23:52:21,342 [http-nio-8081-exec-9] [INFO ] (o.a.r.HttpRepo :414) - pypi-new-mirror downloading https://pypi.org/simple/django-extensions Unknown content length
2018-03-15 23:52:21,351 [http-nio-8081-exec-9] [INFO ] (o.a.r.HttpRepo :427) - pypi-new-mirror downloaded https://pypi.org/simple/django-extensions 37.43 KB at 4,740.02 KB/sec
2018-03-15 23:52:21,352 [http-nio-8081-exec-9] [DEBUG] (o.a.w.s.RepoFilter :188) - Exiting request GET (ip-redacted) /api/pypi/pypi-new-mirror/simple/django-extensions/
If you would like access to this instance please give me an IP address.
@thiagofigueiro and things are working as expected or are you still in a broken state?
and things are working as expected or are you still in a broken state?
Still broken. Same error from pip:
[root@036f888b8772 ci]# pip install -vvv -r requirements.txt
Collecting django-extensions==1.6.7 (from -r requirements.txt (line 1))
1 location(s) to search for versions of django-extensions:
* http://ec2-184-72-69-31.compute-1.amazonaws.com:8081/artifactory/api/pypi/pypi-new-mirror/simple/django-extensions/
Getting page http://ec2-184-72-69-31.compute-1.amazonaws.com:8081/artifactory/api/pypi/pypi-new-mirror/simple/django-extensions/
Starting new HTTP connection (1): ec2-184-72-69-31.compute-1.amazonaws.com
"GET /artifactory/api/pypi/pypi-new-mirror/simple/django-extensions/ HTTP/1.1" 404 None
Could not fetch URL http://ec2-184-72-69-31.compute-1.amazonaws.com:8081/artifactory/api/pypi/pypi-new-mirror/simple/django-extensions/: 404 Client Error: Not Found for url: http://ec2-184-72-69-31.compute-1.amazonaws.com:8081/artifactory/api/pypi/pypi-new-mirror/simple/django-extensions/ - skipping
Could not find a version that satisfies the requirement django-extensions==1.6.7 (from -r requirements.txt (line 1)) (from versions: )
Cleaning up...
No matching distribution found for django-extensions==1.6.7 (from -r requirements.txt (line 1))
Exception information:
Traceback (most recent call last):
File "/usr/lib/python2.7/site-packages/pip/basecommand.py", line 215, in main
status = self.run(options, args)
File "/usr/lib/python2.7/site-packages/pip/commands/install.py", line 335, in run
wb.build(autobuilding=True)
File "/usr/lib/python2.7/site-packages/pip/wheel.py", line 749, in build
self.requirement_set.prepare_files(self.finder)
File "/usr/lib/python2.7/site-packages/pip/req/req_set.py", line 380, in prepare_files
ignore_dependencies=self.ignore_dependencies))
File "/usr/lib/python2.7/site-packages/pip/req/req_set.py", line 554, in _prepare_file
require_hashes
File "/usr/lib/python2.7/site-packages/pip/req/req_install.py", line 278, in populate_link
self.link = finder.find_requirement(self, upgrade)
File "/usr/lib/python2.7/site-packages/pip/index.py", line 514, in find_requirement
'No matching distribution found for %s' % req
DistributionNotFound: No matching distribution found for django-extensions==1.6.7 (from -r requirements.txt (line 1))
Artifactory seems to be unable to parse the HTML correctly for individual packages.
It can read the package listing on https://pypi.org/simple since I saw it download the individual package metadata, but then failed to present any packages in the listing.
(tested on my own instance)
@firon thanks for the additional information. we'll investigate that avenue.
@thiagofigueiro we've concluded load splitting for this phase. do you want to leave the supplied IP on the redirect route?
@ewdurbin Not at this stage - thanks. You know how to reach me if you want me to run other tests.
For what it's worth here's a sample diff between the old and new response for simple/:
--- /tmp/simple-new 2018-03-16 11:09:06.000000000 +1100
+++ /tmp/simple-old 2018-03-16 11:08:35.000000000 +1100
-<html>
- <head>
- <title>Simple Index</title>
- <meta name="api-version" value="2" />
- </head>
- <body>
- <a href="/simple/0/">0</a>
- <a href="/simple/0-0/">0-._.-._.-._.-._.-._.-._.-0</a>
- <a href="/simple/0-0-1/">0.0.1</a>
- <a href="/simple/00smalinux/">00SMALINUX</a>
+<html><head><title>Simple Index</title><meta name="api-version" value="2" /></head><body>
+<a href="0" rel="internal" >0</a><br/>
+<a href="0-.-.-.-.-.-.-.-.-.-.-.-.-0" rel="internal" >0-._.-._.-._.-._.-._.-._.-0</a><br/>
+<a href="0-core-client" rel="internal" >0-core-client</a><br/>
I think @firon has a point that Artifactory is trying to parse the HTML. I'm happy to follow this up with them but would appreciate if you could keep the Artifactory user-agent exclusion until they fix the issue.
Thanks again for being on top of this so quickly. You went beyond duty of care on this one.
@thiagofigueiro 184.72.69.31 is getting the same response as all the other Artifactory installations now :)

The relevant parsing information is that artifactory does not permit files from outside of the source server:
// handle complete URL listings
if (href.startsWith("http:") || href.startsWith("https:")) {
try {
href = new URL(href).getPath();
if (!href.startsWith(baseUrl.getPath())) {
// ignore URLs which aren't children of the base URL
continue;
}
href = href.substring(baseUrl.getPath().length());
} catch (Exception ignore) {
// incorrect URL, ignore
continue;
}
}
Thus generating empty listings.
Ah, so it seems to be upset that we moved file hosting off of the domain and onto files.pythonhosted.org?
The move to hosting package content on files.pythonhosted.org is intentional and _will_ be happening.
We'll need Artifactory to release fixes which respect the URLs provided.
@thiagofigueiro do you have a link to the JFrog/Artifactory ticket?
Hi, @ewdurbin - I had answered this before, you probably missed it: https://github.com/pypa/warehouse/issues/3275#issuecomment-373556617 and the message right after it.
tl;dr: JFrog don't provide a link to the ticket. :(
The CSR responding to the email failed to understand what I was explaining and I don't think they will find their way to this github issue.
Hi,
@ewdurbin and @thiagofigueiro, thank you for reporting this matter we, JFrog, are aware to it.
Please find the JIRA ticket, you are more than welcome to watch it: https://www.jfrog.com/jira/browse/RTFACT-16223
Ori
@ori-yitzhaki thank you for following up, I'd like to note that this may be a higher priority issue than it is filed in JFrog-Jira. We'll be shipping the new /simple via warehouse in the next couple weeks and will not be able to guard Artifactory installations once that is complete.
Target right now is April 8th.
JFrog has made contact and I'm meeting with them to make sure they fully understand the changes that pypi.org will bring. Will update with summary of the discussion.
@ewdurbin
I would like to thank you for reaching out and agree to support Artifactory users on pypi.python.org for a while.
I would like to ask you to set the target for the migration of pypi.python.org => pypi.org to April 22nd. By that time we will have the support for pypi.org.
10x
Oh! To summarize meeting: JFrog team confirmed the changes they saw with the warehouse simple index implementation and asked for anything else to be aware of. TLS v1.0/v1.1 deprecation was all that I had to add.
They mentioned needing some more time to ship code changes and allow users to handle that. I directed them to have that conversation here and it seems they have!
I said that we can technically delay the redirects from pypi.python.org to pypi.org that are causing trouble, but only for a short time, but we need consensus on how long.
We currently exclude user agents for Artifactory from our temporary redirects and can support the same for the main rollout.
@di @dstufft I presume you are both also ok with keeping the User-Agent exclusions for the redirect up till April 22nd?
Makes sense to me.
we actually discuss that User-Agent exclusions for the redirect will last for a couple of months
@ewdurbin can you come with a date which until it you will support the User-Agent exclusions for the redirect?
@ori-yitzhaki If Artifactory can fully support using pypi.org by April 22nd, why do the User-Agent exclusions need to remain for "a couple months"?
Currently (as of today) we are planning to fully shutdown pypi.python.org on Monday April 30th.
Customers will have to coordinate such a change with their security departments (firewall) in larger organizations it might take a bit more time and we will appreciate if we can provide them sufficient notice
I don't believe we are going to be able to keep the User-Agent exclusion for a couple of months. @ewdurbin is away this week (until the 8th), but our current target (as @di mentioned) for shutting down legacy PuPI is April 30th, 2018. Once legacy PyPI is shut down, there will be nothing backing pypi.python.org for a User-Agent exclusion to help at all, since your request would have nothing there to process it.
Keeping the exclusion past April 30th, 2018 would mean having to continue to run the legacy PyPI backend, @ewdurbin would have to speak more to that, but that's a much larger ask than keeping the exclusion in place until the 22nd.
The discussion I recall didn鈥檛 include anything beyond April 30, I tried to make clear that the initially
requested April 22 date was technically straightforward, but may have misunderstood.
Indeed, holding on to the old backends after that date for a single client of the index is not something we can support.
@dstufft thanks for the information.
So just to confirm, there will be support for a User-Agent exclusion until April 30th?
@ori-yitzhaki We can keep the User-Agent exclusion until we shut down the legacy backends, that is currently scheduled for April 30th but that date is subject to change if needed (but I suspect it won't be).
@ori-yitzhaki hey! so the day is here! pypi.org has shipped and we're planning to shutdown legacy on April 30th, 2018.
Can you confirm that JFrog/Artifactory is underway with patches?
The April 10th update in the JIRA ticket by @yuvalreches says:
Starting April ~22nd PyPI will redirect all requests going to the default PyPI remote repository url (pypi.python.org) to pypi.org...
Users might experience errors even before April 22nd, as PyPI are temporarily redirecting pypi.python.org to pypi.org from time to time as part of their tests.
The redirect has already started (on Monday, April 16th), and the User-Agent exclusion will work until April 30th. Could you please update the JIRA ticket to reflect @ewdurbin's explanation above, and advise your users to update Artifactory and change their PyPI remote repo URL fields now rather than waiting till April 22nd? Thank you.
@ewdurbin Artifactory 5.10.3 and 5.9.5, 5.8.9 are available for download and supporting pypi.org 馃槂
@brainwane I've updated the JIRA comment, thanks :)
Thank you @yuvalreches!
@ori-yitzhaki @yuvalreches do you have a public support document, blog post, or similar that we can reference after the shutdown for artifactory users?
@ewdurbin you can use this one:
https://jfrog.com/knowledge-base/why-am-i-not-able-to-connect-to-pypi-python-org/
@yuvalreches excellent! thank you!
Given that Artifactory 5.10.3, 5.9.5, and 5.8.9 are released and we have the necessary reference material for users impacted on Monday, I'm going to close this issue!
Most helpful comment
@yuvalreches excellent! thank you!
Given that Artifactory 5.10.3, 5.9.5, and 5.8.9 are released and we have the necessary reference material for users impacted on Monday, I'm going to close this issue!