diff --git a/sphinx/builders/linkcheck.py b/sphinx/builders/linkcheck.py index f4299d14c..479a5b877 100644 --- a/sphinx/builders/linkcheck.py +++ b/sphinx/builders/linkcheck.py @@ -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 diff --git a/tests/test_build_linkcheck.py b/tests/test_build_linkcheck.py index f4229cccd..d7c925e7c 100644 --- a/tests/test_build_linkcheck.py +++ b/tests/test_build_linkcheck.py @@ -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): - app.build() + 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)