Skip to content

Commit c1e2270

Browse files
authored
Handle HTTP errors when fetching revisions (#5234)
This PR adds exception handling to `_get_url_content` in `revisions.py` to prevent the testcase detail page from crashing with a 500 error when external requests to Gitiles (`chromium.googlesource.com`) fail with HTTP errors (such as 429, 403, or 503). This was caused by Gitiles throttling anonymous traffic due to an outage (see b/499989694 for context). This fix allows the UI to degrade gracefully, displaying 'No component revisions found' instead of crashing.
1 parent ef4af5d commit c1e2270

2 files changed

Lines changed: 12 additions & 1 deletion

File tree

src/clusterfuzz/_internal/build_management/revisions.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,11 @@ def _get_url_content(url):
182182
url_content = url_data.decode('utf-8')
183183
else:
184184
# Fetch a regular url without authentication.
185-
url_content = utils.fetch_url(url)
185+
try:
186+
url_content = utils.fetch_url(url)
187+
except Exception:
188+
logs.error(f'Failed to fetch URL {url}')
189+
return None
186190

187191
# Urls on googlesource.com return file data as base64 encoded to avoid
188192
# cross-site scripting attacks. If the requested url contains |format=text|,

src/clusterfuzz/_internal/tests/core/build_management/revisions_test.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,13 @@ def test_convert_revision_to_integer_version_string(self, _):
177177
with self.assertRaises(ValueError):
178178
revisions.convert_revision_to_integer('...')
179179

180+
@mock.patch('clusterfuzz._internal.base.utils.fetch_url')
181+
def test_get_url_content_exception(self, mock_fetch_url):
182+
"""Test that _get_url_content returns None when fetch_url raises an exception."""
183+
mock_fetch_url.side_effect = Exception('Network error')
184+
result = revisions._get_url_content('https://example.com/api') # pylint: disable=protected-access
185+
self.assertIsNone(result)
186+
180187
@mock.patch('clusterfuzz._internal.config.db_config.get')
181188
@mock.patch(
182189
'clusterfuzz._internal.build_management.revisions._get_url_content')

0 commit comments

Comments
 (0)