From 249cc2d6c3867d70c9911c73138ce366311b9796 Mon Sep 17 00:00:00 2001 From: Anthony Donlon Date: Tue, 16 Dec 2025 20:57:24 +0800 Subject: [PATCH] python: render extended error pages using common routine --- cloudflare_error_page/__init__.py | 40 +++++++++++++++++++++---------- editor/server/share.py | 18 +++++++------- 2 files changed, 35 insertions(+), 23 deletions(-) diff --git a/cloudflare_error_page/__init__.py b/cloudflare_error_page/__init__.py index 6f6d0c3..7fa47ed 100644 --- a/cloudflare_error_page/__init__.py +++ b/cloudflare_error_page/__init__.py @@ -1,36 +1,50 @@ import html -import os import secrets from datetime import datetime, timezone +from typing import Any, Optional from jinja2 import Environment, PackageLoader, Template, select_autoescape env = Environment( - loader=PackageLoader("cloudflare_error_page"), + loader=PackageLoader(__name__), autoescape=select_autoescape(), trim_blocks=True, lstrip_blocks=True, ) -default_template = env.get_template("error.html") +default_template: Template = env.get_template("error.html") -def fill_params(params: dict): +def render(params: dict, + allow_html: bool = True, + template: Optional[Template] = None, + *args: Any, + **kwargs: Any) -> str: + '''Render a customized Cloudflare error page. + + :param params: Parameters passed to the template. Refer to the project homepage for more information. + :param allow_html: Allow output raw HTML content from parameters. Set to False if you don't trust the source of the params. + :param template: Jinja template used to render the error page. Default template will be used if ``template`` is None. + Override this to extend or customize the base template. + :param args: Additional positional arguments passed to ``Template.render`` function. + :param kwargs: Additional keyword arguments passed to ``Template.render`` function. + :return: The rendered error page as a string. + ''' + if not template: + template = default_template + + params = {**params} + if not params.get('time'): utc_now = datetime.now(timezone.utc) params['time'] = utc_now.strftime("%Y-%m-%d %H:%M:%S UTC") if not params.get('ray_id'): params['ray_id'] = secrets.token_hex(8) - - -def render(params: dict, allow_html: bool=True) -> str: - """ - Render a customized Cloudflare error page. - """ - params = {**params} - fill_params(params) if not allow_html: params['what_happened'] = html.escape(params.get('what_happened', '')) params['what_can_i_do'] = html.escape(params.get('what_can_i_do', '')) - return default_template.render(params=params) + return template.render(params=params, *args, **kwargs) + + +__all__ = ['default_template', 'render'] diff --git a/editor/server/share.py b/editor/server/share.py index 33dd022..cda7465 100644 --- a/editor/server/share.py +++ b/editor/server/share.py @@ -14,8 +14,8 @@ from flask import ( from jinja2 import Environment, select_autoescape from cloudflare_error_page import ( - fill_params as fill_template_params, - default_template as cf_template + default_template as cf_template, + render as render_cf_error_page, ) from . import ( @@ -127,14 +127,12 @@ def get(name: str): 'text': 'CF Error Page Editor', 'link': request.host_url[:-1] + url_for('editor.index') + f'#from={name}', } - # Always escape HTML - params['what_happened'] = html.escape(params.get('what_happened', '')) # TODO: common render function? - params['what_can_i_do'] = html.escape(params.get('what_can_i_do', '')) fill_cf_template_params(params) - fill_template_params(params) sanitize_page_param_links(params) - return template.render(base=cf_template, - params=params, - url=request.url, - description='Cloudflare error page') + return render_cf_error_page(params=params, + allow_html=False, + template=template, + base=cf_template, + url=request.url, + description='Cloudflare error page')