9
0
mirror of https://github.com/donlon/cloudflare-error-page.git synced 2025-12-19 06:49:30 +00:00

python: support type hinting for input params

This commit is contained in:
Anthony Donlon
2025-12-16 22:48:32 +08:00
parent ed711a2521
commit 58bf0d6b79
4 changed files with 71 additions and 9 deletions

View File

@@ -1,7 +1,15 @@
import html
import secrets
import sys
from datetime import datetime, timezone
from typing import Any
from typing import Any, TypedDict, Literal
if sys.version_info >= (3, 11):
from typing import NotRequired
else:
from typing import _SpecialForm
NotRequired: _SpecialForm
from jinja2 import Environment, PackageLoader, Template, select_autoescape
@@ -15,7 +23,53 @@ env = Environment(
default_template: Template = env.get_template("error.html")
def render(params: dict,
class ErrorPageParams(TypedDict):
class MoreInformation(TypedDict):
hidden: NotRequired[bool]
text: NotRequired[str]
link: NotRequired[str]
for_text: NotRequired[str] # renamed to avoid Python keyword conflict
class StatusItem(TypedDict):
status: NotRequired[Literal["ok", "error"]]
location: NotRequired[str]
name: NotRequired[str]
status_text: NotRequired[str]
status_text_color: NotRequired[str]
class PerfSecBy(TypedDict):
text: NotRequired[str]
link: NotRequired[str]
class CreatorInfo(TypedDict):
hidden: NotRequired[bool]
link: NotRequired[str]
text: NotRequired[str]
html_title: NotRequired[str]
title: NotRequired[str]
error_code: NotRequired[str]
time: NotRequired[str]
more_information: NotRequired[MoreInformation]
browser_status: NotRequired[StatusItem]
cloudflare_status: NotRequired[StatusItem]
host_status: NotRequired[StatusItem]
error_source: NotRequired[Literal["browser", "cloudflare", "host"]]
what_happened: NotRequired[str]
what_can_i_do: NotRequired[str]
ray_id: NotRequired[str]
client_ip: NotRequired[str]
perf_sec_by: NotRequired[PerfSecBy]
creator_info: NotRequired[CreatorInfo]
def render(params: ErrorPageParams,
allow_html: bool = True,
template: Template | None = None,
*args: Any,
@@ -35,6 +89,12 @@ def render(params: dict,
params = {**params}
more_information = params.get('more_information')
if more_information:
for_text = more_information.get('for_text')
if for_text is not None:
more_information['for'] = for_text
if not params.get('time'):
utc_now = datetime.now(timezone.utc)
params['time'] = utc_now.strftime("%Y-%m-%d %H:%M:%S UTC")

View File

@@ -11,6 +11,7 @@ from flask import (
redirect,
)
from cloudflare_error_page import ErrorPageParams
from cloudflare_error_page import render as render_cf_error_page
from .utils import fill_cf_template_params
@@ -22,7 +23,7 @@ bp = Blueprint('examples', __name__, url_prefix='/')
param_cache: dict[str, dict] = {}
def get_page_params(name: str) -> dict:
def get_page_params(name: str) -> ErrorPageParams:
name = re.sub(r'[^\w]', '', name)
params = param_cache.get(name)
if params is not None:

View File

@@ -1,7 +1,9 @@
import json
import os
from cloudflare_error_page import ErrorPageParams
from flask import request
from . import root_dir
@@ -31,13 +33,13 @@ def get_cf_location(loc: str):
return data.get('city')
def fill_cf_template_params(params: dict):
def fill_cf_template_params(params: ErrorPageParams):
# Get the real Ray ID / data center location from Cloudflare header
ray_id_loc = request.headers.get('Cf-Ray')
if ray_id_loc:
params['ray_id'] = ray_id_loc[:16]
cf_status: dict = params.get('cloudflare_status')
cf_status = params.get('cloudflare_status')
if cf_status is None:
cf_status = params['cloudflare_status'] = {}
if not cf_status.get('location'):
@@ -61,7 +63,7 @@ def sanitize_user_link(link: str):
return '#' + link
def sanitize_page_param_links(param: dict):
def sanitize_page_param_links(param: ErrorPageParams):
more_info = param.get('more_information')
if more_info:
link = more_info.get('link')

View File

@@ -1,19 +1,18 @@
#!/usr/bin/env python3
import os
import re
import sys
from flask import (
Flask,
request,
send_from_directory
)
# Append this directory to sys.path is not required if the package is already installed
examples_dir = os.path.dirname(os.path.abspath(__file__))
sys.path.append(os.path.dirname(examples_dir))
from cloudflare_error_page import ErrorPageParams
from cloudflare_error_page import render as render_cf_error_page
app = Flask(__name__)
@@ -21,7 +20,7 @@ app = Flask(__name__)
@app.route('/')
def index():
params = {
params: ErrorPageParams = {
"title": "Internal server error",
"error_code": 500,
"browser_status": {