Skip to content

Commit ccb9c76

Browse files
committed
feat(server, html2pdf): implement better error reporting when Chrome is not found
**WHAT:** This change improves the error message when the StrictDoc web server cannot find a Chrome installation on the system it is running on. **WHY:** Before this change, the error message was a simple Internal Server Error without an explicit indication that the Chrome could not be found. A user would have to dig through the server logs to understand the issue. **HOW:** This integrates the upstream html2pdf4doc work where the error reporting was improved in the main.py driver program. In particular, the driver now exits with a specific exit code `COULD_NOT_FIND_CHROME = 5` that we can rely on in StrictDoc to identify the missing Chrome issue. strictdoc-project/html2pdf4doc_python#58 strictdoc-project/html2pdf4doc_python#70
1 parent 8f47295 commit ccb9c76

File tree

3 files changed

+56
-10
lines changed

3 files changed

+56
-10
lines changed

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ dependencies = [
9595
"WebSockets",
9696

9797
# HTML2PDF dependencies
98-
"html2pdf4doc >= 0.0.23",
98+
"html2pdf4doc >= 0.0.24",
9999

100100
# Robot Framework dependencies
101101
"robotframework >= 4.0.0",

strictdoc/export/html2pdf/pdf_print_driver.py

Lines changed: 44 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,53 @@
33
"""
44

55
import os.path
6-
from subprocess import CompletedProcess, TimeoutExpired, run
6+
from subprocess import CalledProcessError, CompletedProcess, TimeoutExpired, run
77
from typing import List, Tuple
88

9+
from html2pdf4doc.main import HPDExitCode
10+
911
from strictdoc.core.project_config import ProjectConfig
1012
from strictdoc.helpers.timing import measure_performance
1113

1214

15+
class PDFPrintDriverException(Exception):
16+
def __init__(self, exception: Exception):
17+
super().__init__()
18+
self.exception: Exception = exception
19+
20+
def get_server_user_message(self) -> str:
21+
"""
22+
Provide a user-friendly message that describes the underlying exception/error.
23+
"""
24+
25+
if self.is_could_not_detect_chrome():
26+
return "HTML2PDF could not detect an existing Chrome installation."
27+
28+
if self.is_timeout_error():
29+
return "HTML2PDF timeout error."
30+
31+
if self.is_js_success_timeout():
32+
return "HTML2PDF.js success timeout error."
33+
34+
return "HTML2PDF internal error."
35+
36+
def is_timeout_error(self) -> bool:
37+
return isinstance(self.exception, TimeoutExpired)
38+
39+
def is_could_not_detect_chrome(self) -> bool:
40+
return (
41+
isinstance(self.exception, CalledProcessError)
42+
and self.exception.returncode == HPDExitCode.COULD_NOT_FIND_CHROME
43+
)
44+
45+
def is_js_success_timeout(self) -> bool:
46+
return (
47+
isinstance(self.exception, CalledProcessError)
48+
and self.exception.returncode
49+
== HPDExitCode.DID_NOT_RECEIVE_SUCCESS_STATUS_FROM_HTML2PDF4DOC_JS
50+
)
51+
52+
1353
class PDFPrintDriver:
1454
@staticmethod
1555
def get_pdf_from_html(
@@ -52,7 +92,7 @@ def get_pdf_from_html(
5292
_: CompletedProcess[bytes] = run(
5393
cmd,
5494
capture_output=False,
55-
check=False,
95+
check=True,
5696
)
57-
except TimeoutExpired:
58-
raise TimeoutError from None
97+
except Exception as e_:
98+
raise PDFPrintDriverException(e_) from e_

strictdoc/server/routers/main_router.py

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,10 @@
113113
from strictdoc.export.html.html_templates import HTMLTemplates, JinjaEnvironment
114114
from strictdoc.export.html.renderers.link_renderer import LinkRenderer
115115
from strictdoc.export.html.renderers.markup_renderer import MarkupRenderer
116-
from strictdoc.export.html2pdf.pdf_print_driver import PDFPrintDriver
116+
from strictdoc.export.html2pdf.pdf_print_driver import (
117+
PDFPrintDriver,
118+
PDFPrintDriverException,
119+
)
117120
from strictdoc.export.json.json_generator import JSONGenerator
118121
from strictdoc.helpers.cast import assert_cast
119122
from strictdoc.helpers.file_modification_time import (
@@ -134,7 +137,7 @@
134137

135138
HTTP_STATUS_BAD_REQUEST = 400
136139
HTTP_STATUS_PRECONDITION_FAILED = 412
137-
HTTP_STATUS_GATEWAY_TIMEOUT = 504
140+
HTTP_STATUS_INTERNAL_SERVER_ERROR = 500
138141

139142
AUTOCOMPLETE_LIMIT = 50
140143

@@ -2148,6 +2151,9 @@ def get_export_html2pdf(document_mid: str) -> Response: # noqa: ARG001
21482151
path_to_output_pdf = os.path.join(
21492152
project_config.export_output_html_root, "html", "_temp.pdf"
21502153
)
2154+
2155+
# FIXME: Add this print driver to a service bus object to make it
2156+
# unit-testable.
21512157
pdf_print_driver = PDFPrintDriver()
21522158
with open(path_to_output_html, mode="w", encoding="utf8") as temp_file_:
21532159
temp_file_.write(document_content)
@@ -2158,10 +2164,10 @@ def get_export_html2pdf(document_mid: str) -> Response: # noqa: ARG001
21582164
project_config,
21592165
[(path_to_output_html, path_to_output_pdf)],
21602166
)
2161-
except TimeoutError: # pragma: no cover
2167+
except PDFPrintDriverException as e_: # pragma: no cover
21622168
return Response(
2163-
content="HTML2PDF timeout error.",
2164-
status_code=HTTP_STATUS_GATEWAY_TIMEOUT,
2169+
content=e_.get_server_user_message(),
2170+
status_code=HTTP_STATUS_INTERNAL_SERVER_ERROR,
21652171
)
21662172

21672173
return FileResponse(

0 commit comments

Comments
 (0)