From 748bcc328fc7eb21715a992d4f52e1de61431bfb Mon Sep 17 00:00:00 2001 From: Paul Selkirk Date: Wed, 27 Dec 2023 12:56:38 -0500 Subject: [PATCH] fix: Wrap weasyprint to catch exceptions (#6728) * fix: Wrap weasyprint to catch exceptions (#6324) * test: Restore socket function after test * test: Use mock instead of monkeying with sockets * refactor: Log the error * fix: Don't catch non-Exception interruptions --------- Co-authored-by: Robert Sparks --- ietf/doc/models.py | 3 +++ ietf/doc/tests.py | 8 ++++++++ ietf/doc/views_doc.py | 6 ++++-- ietf/templates/doc/weasyprint_failed.html | 17 +++++++++++++++++ 4 files changed, 32 insertions(+), 2 deletions(-) create mode 100644 ietf/templates/doc/weasyprint_failed.html diff --git a/ietf/doc/models.py b/ietf/doc/models.py index 434096929a..e53717cb7d 100644 --- a/ietf/doc/models.py +++ b/ietf/doc/models.py @@ -634,6 +634,9 @@ def pdfized(self): ) except AssertionError: pdf = None + except Exception as e: + log.log('weasyprint failed:'+str(e)) + raise if pdf: cache.set(cache_key, pdf, settings.PDFIZER_CACHE_TIME) return pdf diff --git a/ietf/doc/tests.py b/ietf/doc/tests.py index 71ec23906c..0b5a651060 100644 --- a/ietf/doc/tests.py +++ b/ietf/doc/tests.py @@ -31,6 +31,8 @@ from tastypie.test import ResourceTestCaseMixin +from weasyprint.urls import URLFetchingError + import debug # pyflakes:ignore from ietf.doc.models import ( Document, DocRelationshipName, RelatedDocument, State, @@ -2867,6 +2869,12 @@ def test_pdfized(self): self.should_succeed(dict(name=draft.name,rev=f'{r:02d}',ext=ext)) self.should_404(dict(name=draft.name,rev='02')) + with mock.patch('ietf.doc.models.DocumentInfo.pdfized', side_effect=URLFetchingError): + url = urlreverse(self.view, kwargs=dict(name=rfc.name)) + r = self.client.get(url) + self.assertEqual(r.status_code, 200) + self.assertContains(r, "Error while rendering PDF") + class NotifyValidationTests(TestCase): def test_notify_validation(self): valid_values = [ diff --git a/ietf/doc/views_doc.py b/ietf/doc/views_doc.py index e0bf328e89..293d32daff 100644 --- a/ietf/doc/views_doc.py +++ b/ietf/doc/views_doc.py @@ -51,7 +51,6 @@ from django import forms from django.contrib.staticfiles import finders - import debug # pyflakes:ignore from ietf.doc.models import ( Document, DocHistory, DocEvent, BallotDocEvent, BallotType, @@ -1064,7 +1063,10 @@ def document_pdfized(request, name, rev=None, ext=None): if not os.path.exists(doc.get_file_name()): raise Http404("File not found: %s" % doc.get_file_name()) - pdf = doc.pdfized() + try: + pdf = doc.pdfized() + except Exception: + return render(request, "doc/weasyprint_failed.html") if pdf: return HttpResponse(pdf,content_type='application/pdf') else: diff --git a/ietf/templates/doc/weasyprint_failed.html b/ietf/templates/doc/weasyprint_failed.html new file mode 100644 index 0000000000..985fe12fe1 --- /dev/null +++ b/ietf/templates/doc/weasyprint_failed.html @@ -0,0 +1,17 @@ +{# Copyright The IETF Trust 2023, All Rights Reserved #} +{% extends "base.html" %} +{% load origin %} +{% block title %}Error while rendering PDF{% endblock %} +{% block content %} + {% origin %} +

Error while rendering PDF

+

+ An error was encountered while trying to render your document as PDF. + In case this was a temporary error, you may want to try again in a + little while. +

+

+ A failure report with details about what happened has been sent to the + server administrators. +

+{% endblock %} \ No newline at end of file