9
0
mirror of https://github.com/donlon/cloudflare-error-page.git synced 2025-12-19 14:59:28 +00:00

editor/server: support showing real Cloudflare DC city

This commit is contained in:
Anthony Donlon
2025-11-22 00:18:55 +08:00
parent 28b5ee7e69
commit 5c18dfb930
6 changed files with 2957 additions and 34 deletions

1
editor/server/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
cf-colos.json

View File

@@ -1,5 +1,6 @@
# SPDX-License-Identifier: MIT
import json
import os
import secrets
import string
@@ -52,6 +53,7 @@ def create_app(test_config=None) -> Flask:
url_prefix = os.getenv('URL_PREFIX', '')
from . import utils
from . import models
from . import examples
from . import editor
@@ -86,19 +88,5 @@ def create_app(test_config=None) -> Flask:
return app
def get_common_cf_template_params():
# Get real Ray ID from Cloudflare header
ray_id = request.headers.get('Cf-Ray')
if ray_id:
ray_id = ray_id[:16]
# Get real client ip from Cloudflare header or request.remote_addr
client_ip = request.headers.get('X-Forwarded-For')
if not client_ip:
client_ip = request.remote_addr
return {
'ray_id': ray_id,
'client_ip': client_ip,
}
__all__ = ['create_app', 'db', 'get_common_cf_template_params', 'render_cf_error_page']

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,6 @@
# SPDX-License-Identifier: MIT
import copy
import os
import re
@@ -10,8 +11,8 @@ from flask import (
redirect,
)
from . import get_common_cf_template_params
from cloudflare_error_page import render as render_cf_error_page
from .utils import fill_cf_template_params
root_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), '../../')
examples_dir = os.path.join(root_dir, 'examples')
@@ -25,12 +26,12 @@ def get_page_params(name: str) -> dict:
name = re.sub(r'[^\w]', '', name)
params = param_cache.get(name)
if params is not None:
return params
return copy.deepcopy(params)
try:
with open(os.path.join(examples_dir, f'{name}.json')) as f:
params = json.load(f)
param_cache[name] = params
return params
return copy.deepcopy(params)
except Exception as _:
return None
@@ -49,10 +50,7 @@ def index(name: str):
if params is None:
abort(404)
params = {
**params,
**get_common_cf_template_params(),
}
fill_cf_template_params(params)
# Render the error page
return render_cf_error_page(params, use_cdn=True), 500
return render_cf_error_page(params, use_cdn=True)

View File

@@ -13,12 +13,18 @@ from flask import (
)
from jinja2 import Environment, select_autoescape
from cloudflare_error_page import render as render_cf_error_page, fill_params, default_template as cf_template
from cloudflare_error_page import (
fill_params as fill_template_params,
default_template as cf_template
)
from . import get_common_cf_template_params
from . import db
from . import limiter
from . import models
from . import (
db,
limiter,
models
)
from .utils import fill_cf_template_params
# root_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), '../../')
# examples_dir = os.path.join(root_dir, 'examples')
@@ -89,7 +95,7 @@ def get(name: str):
if not item:
if is_json:
return jsonify({
'status': 'not-found'
'status': 'notfound'
})
else:
return abort(404)
@@ -104,22 +110,19 @@ def get(name: str):
'parameters': params,
})
else:
params = {
**params,
**get_common_cf_template_params(),
}
params['creator_info'] = {
'hidden': False,
'text': 'CF Error Page Editor',
'link': f'https://virt.moe/cloudflare-error-page/editor/#from={name}',
}
fill_params(params)
# 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)
return template.render(base=cf_template,
params=params,
url=request.url,
description='Cloudflare error page',
resources_use_cdn=True)
# return render_cf_error_page(params=params, allow_html=False, use_cdn=True), 200

50
editor/server/utils.py Normal file
View File

@@ -0,0 +1,50 @@
import json
import os
from flask import request
from . import root_dir
loc_data: dict = None
def read_loc_file(path: str):
try:
with open(os.path.join(root_dir, path)) as f:
return json.load(f)
except:
return
def get_cf_location(loc: str):
global loc_data
loc = loc.upper()
if loc_data is None:
loc_data = read_loc_file('editor/server/cf-colos.json')
if loc_data is None:
# From https://github.com/Netrvin/cloudflare-colo-list/blob/main/DC-Colos.json
loc_data = read_loc_file('editor/server/cf-colos.bundled.json')
if loc_data is None:
return
data: dict = loc_data.get(loc)
if not data:
return
return data.get('city')
def fill_cf_template_params(params: dict):
# Get 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', {})
if not cf_status.get('location'):
loc = get_cf_location()
if loc:
cf_status['location'] = loc
# Get real client ip from Cloudflare header or request.remote_addr
client_ip = request.headers.get('X-Forwarded-For')
if not client_ip:
client_ip = request.remote_addr
params['client_ip'] = client_ip