Skip to content

Commit 13720de

Browse files
authored
Treat SSL failures as broken links in the linkcheck builder (#11431)
TLS operates at a lower layer than HTTP, and so if there is a TLS-related error from a host, it seems unlikely that retrying with a different higher-layer protocol request (HTTP GET instead of HTTP HEAD) could succeed. We should not make additional HTTP requests that we do not believe will succeed.
1 parent e45fb5e commit 13720de

File tree

2 files changed

+10
-3
lines changed

2 files changed

+10
-3
lines changed

sphinx/builders/linkcheck.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818

1919
from docutils import nodes
2020
from requests import Response
21-
from requests.exceptions import ConnectionError, HTTPError, TooManyRedirects
21+
from requests.exceptions import ConnectionError, HTTPError, SSLError, TooManyRedirects
2222

2323
from sphinx.application import Sphinx
2424
from sphinx.builders.dummy import DummyBuilder
@@ -333,6 +333,10 @@ def check_uri() -> tuple[str, str, int]:
333333
del response
334334
break
335335

336+
except SSLError as err:
337+
# SSL failure; report that the link is broken.
338+
return 'broken', str(err), 0
339+
336340
except (ConnectionError, TooManyRedirects) as err:
337341
# Servers drop the connection on HEAD requests, causing
338342
# ConnectionError.
@@ -361,7 +365,7 @@ def check_uri() -> tuple[str, str, int]:
361365
continue
362366

363367
except Exception as err:
364-
# Unhandled exception (intermittent or permanent); report that the
368+
# Unhandled exception (intermittent or permanent); report that
365369
# the link is broken.
366370
return 'broken', str(err), 0
367371

tests/test_build_linkcheck.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
from sphinx.builders.linkcheck import HyperlinkAvailabilityCheckWorker, RateLimit
2020
from sphinx.testing.util import strip_escseq
21+
from sphinx.util import requests
2122
from sphinx.util.console import strip_colors
2223

2324
from .utils import CERT_FILE, http_server, https_server
@@ -394,7 +395,9 @@ def do_GET(self):
394395
def test_invalid_ssl(app):
395396
# Link indicates SSL should be used (https) but the server does not handle it.
396397
with http_server(OKHandler):
397-
app.build()
398+
with mock.patch("sphinx.builders.linkcheck.requests.get", wraps=requests.get) as get_request:
399+
app.build()
400+
assert not get_request.called
398401

399402
with open(app.outdir / 'output.json', encoding='utf-8') as fp:
400403
content = json.load(fp)

0 commit comments

Comments
 (0)