From 6801ed0b789638a30f6707bbbed5b2fdde97d644 Mon Sep 17 00:00:00 2001 From: Wesley B <62723358+wesleyboar@users.noreply.github.com> Date: Tue, 23 Jun 2026 19:00:40 -0500 Subject: [PATCH] feat(favicon): add /favicon.ico proxy view Adds a Django view that serves /favicon.ico from either a remote CDN URL or a local static file, based on PORTAL_FAVICON["is_remote"]. - PDF renderers fetch /favicon.ico from origin and ignore tags - Caches response for 24 hours via @cache_page --- taccsite_cms/urls.py | 2 ++ taccsite_cms/views.py | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+) create mode 100644 taccsite_cms/views.py diff --git a/taccsite_cms/urls.py b/taccsite_cms/urls.py index ea475b3be..148378042 100755 --- a/taccsite_cms/urls.py +++ b/taccsite_cms/urls.py @@ -13,6 +13,7 @@ from django.views.static import serve from django.views.generic.base import TemplateView from taccsite_cms import remote_cms_auth as remote_cms_auth +from taccsite_cms.views import favicon from django.http import request @@ -25,6 +26,7 @@ url(r'^admin/', admin.site.urls), # NOQA url(r'^cms/logout/', views.LogoutView.as_view(), name='logout'), + url(r'^favicon\.ico$', favicon, name='favicon'), url(r'^', include('djangocms_forms.urls')), ] diff --git a/taccsite_cms/views.py b/taccsite_cms/views.py new file mode 100644 index 000000000..aa0935e31 --- /dev/null +++ b/taccsite_cms/views.py @@ -0,0 +1,35 @@ +import requests as http_client +from django.conf import settings +from django.contrib.staticfiles import finders +from django.http import HttpResponse +from django.views.decorators.cache import cache_page + +_24_HOURS = 86400 + + +@cache_page(_24_HOURS) +def favicon(request): + portal_favicon = getattr(settings, 'PORTAL_FAVICON', {}) + img_src = portal_favicon.get('img_file_src', '') + is_remote = portal_favicon.get('is_remote', False) + + if not img_src: + return HttpResponse(status=404) + + if is_remote: + try: + response = http_client.get(img_src, timeout=5) + return HttpResponse( + response.content, + content_type='image/x-icon', + status=response.status_code, + ) + except http_client.exceptions.RequestException: + return HttpResponse(status=502) + + path = finders.find(img_src) + if not path: + return HttpResponse(status=404) + + with open(path, 'rb') as f: + return HttpResponse(f.read(), content_type='image/x-icon')