diff --git a/docs/release-notes/version-3.5.md b/docs/release-notes/version-3.5.md index a22728b53..254cc7391 100644 --- a/docs/release-notes/version-3.5.md +++ b/docs/release-notes/version-3.5.md @@ -5,6 +5,7 @@ ### Bug Fixes * [#12380](https://github.com/netbox-community/netbox/issues/12380) - Allow selecting object change as model under object list widget configuration +* [#12384](https://github.com/netbox-community/netbox/issues/12384) - Add a three-second timeout for RSS reader widget * [#12395](https://github.com/netbox-community/netbox/issues/12395) - Fix "create & add another" action for objects with custom fields * [#12396](https://github.com/netbox-community/netbox/issues/12396) - Provider account should not be a required field in REST API serializer * [#12405](https://github.com/netbox-community/netbox/issues/12405) - Fix filtering for VLAN groups displayed under site view diff --git a/netbox/extras/dashboard/widgets.py b/netbox/extras/dashboard/widgets.py index 0018cf547..9cd53763a 100644 --- a/netbox/extras/dashboard/widgets.py +++ b/netbox/extras/dashboard/widgets.py @@ -4,6 +4,7 @@ from hashlib import sha256 from urllib.parse import urlencode import feedparser +import requests from django import forms from django.conf import settings from django.contrib.contenttypes.models import ContentType @@ -269,12 +270,9 @@ class RSSFeedWidget(DashboardWidget): ) def render(self, request): - url = self.config['feed_url'] - feed = self.get_feed() - return render_to_string(self.template_name, { - 'url': url, - 'feed': feed, + 'url': self.config['feed_url'], + **self.get_feed() }) @cached_property @@ -286,17 +284,33 @@ class RSSFeedWidget(DashboardWidget): def get_feed(self): # Fetch RSS content from cache if available if feed_content := cache.get(self.cache_key): - feed = feedparser.FeedParserDict(feed_content) - else: - feed = feedparser.parse( - self.config['feed_url'], - request_headers={'User-Agent': f'NetBox/{settings.VERSION}'} - ) - if not feed.bozo: - # Cap number of entries - max_entries = self.config.get('max_entries') - feed['entries'] = feed['entries'][:max_entries] - # Cache the feed content - cache.set(self.cache_key, dict(feed), self.config.get('cache_timeout')) + return { + 'feed': feedparser.FeedParserDict(feed_content), + } - return feed + # Fetch feed content from remote server + try: + response = requests.get( + url=self.config['feed_url'], + headers={'User-Agent': f'NetBox/{settings.VERSION}'}, + proxies=settings.HTTP_PROXIES, + timeout=3 + ) + response.raise_for_status() + except requests.exceptions.RequestException as e: + return { + 'error': e, + } + + # Parse feed content + feed = feedparser.parse(response.content) + if not feed.bozo: + # Cap number of entries + max_entries = self.config.get('max_entries') + feed['entries'] = feed['entries'][:max_entries] + # Cache the feed content + cache.set(self.cache_key, dict(feed), self.config.get('cache_timeout')) + + return { + 'feed': feed, + } diff --git a/netbox/templates/extras/dashboard/widgets/rssfeed.html b/netbox/templates/extras/dashboard/widgets/rssfeed.html index 5de3c3105..c304b7c07 100644 --- a/netbox/templates/extras/dashboard/widgets/rssfeed.html +++ b/netbox/templates/extras/dashboard/widgets/rssfeed.html @@ -1,4 +1,4 @@ -{% if not feed.bozo %} +{% if feed and not feed.bozo %}
{% for entry in feed.entries %}
@@ -16,7 +16,9 @@ There was a problem fetching the RSS feed: -
-Response status: {{ feed.status }}
-Error: {{ feed.bozo_exception|escape }}
+ {% if feed %} + {{ feed.bozo_exception|escape }} (HTTP {{ feed.status }}) + {% else %} + {{ error }} + {% endif %} {% endif %}