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.
This commit is contained in:
James Addison 2023-07-20 21:38:21 +01:00 committed by GitHub
parent e45fb5e61b
commit 13720de50c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 10 additions and 3 deletions

View File

@ -18,7 +18,7 @@ from urllib.parse import unquote, urlparse, urlsplit, urlunparse
from docutils import nodes
from requests import Response
from requests.exceptions import ConnectionError, HTTPError, TooManyRedirects
from requests.exceptions import ConnectionError, HTTPError, SSLError, TooManyRedirects
from sphinx.application import Sphinx
from sphinx.builders.dummy import DummyBuilder
@ -333,6 +333,10 @@ class HyperlinkAvailabilityCheckWorker(Thread):
del response
break
except SSLError as err:
# SSL failure; report that the link is broken.
return 'broken', str(err), 0
except (ConnectionError, TooManyRedirects) as err:
# Servers drop the connection on HEAD requests, causing
# ConnectionError.
@ -361,7 +365,7 @@ class HyperlinkAvailabilityCheckWorker(Thread):
continue
except Exception as err:
# Unhandled exception (intermittent or permanent); report that the
# Unhandled exception (intermittent or permanent); report that
# the link is broken.
return 'broken', str(err), 0

View File

@ -18,6 +18,7 @@ import pytest
from sphinx.builders.linkcheck import HyperlinkAvailabilityCheckWorker, RateLimit
from sphinx.testing.util import strip_escseq
from sphinx.util import requests
from sphinx.util.console import strip_colors
from .utils import CERT_FILE, http_server, https_server
@ -394,7 +395,9 @@ class OKHandler(http.server.BaseHTTPRequestHandler):
def test_invalid_ssl(app):
# Link indicates SSL should be used (https) but the server does not handle it.
with http_server(OKHandler):
with mock.patch("sphinx.builders.linkcheck.requests.get", wraps=requests.get) as get_request:
app.build()
assert not get_request.called
with open(app.outdir / 'output.json', encoding='utf-8') as fp:
content = json.load(fp)