mirror of
https://github.com/donlon/cloudflare-error-page.git
synced 2025-12-19 14:59:28 +00:00
editor/server: support external config file
This commit is contained in:
@@ -5,13 +5,14 @@ import os
|
|||||||
import secrets
|
import secrets
|
||||||
import string
|
import string
|
||||||
import sys
|
import sys
|
||||||
|
import tomllib
|
||||||
|
|
||||||
from flask import Flask, request
|
from flask import Flask, redirect, request, url_for
|
||||||
from flask_limiter import Limiter
|
from flask_limiter import Limiter
|
||||||
from flask_limiter.util import get_remote_address
|
from flask_limiter.util import get_remote_address
|
||||||
from flask_sqlalchemy import SQLAlchemy
|
from flask_sqlalchemy import SQLAlchemy
|
||||||
from sqlalchemy import event
|
|
||||||
from sqlalchemy.orm import DeclarativeBase
|
from sqlalchemy.orm import DeclarativeBase
|
||||||
|
from werkzeug.middleware.proxy_fix import ProxyFix
|
||||||
|
|
||||||
root_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), '../../')
|
root_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), '../../')
|
||||||
sys.path.append(root_dir)
|
sys.path.append(root_dir)
|
||||||
@@ -28,29 +29,46 @@ limiter: Limiter = Limiter(
|
|||||||
key_func=get_remote_address, # Uses client's IP address by default
|
key_func=get_remote_address, # Uses client's IP address by default
|
||||||
)
|
)
|
||||||
|
|
||||||
def generate_secret(length=32) -> str:
|
def _generate_secret(length=32) -> str:
|
||||||
characters = string.ascii_letters + string.digits # A-Z, a-z, 0-9
|
characters = string.ascii_letters + string.digits # A-Z, a-z, 0-9
|
||||||
return ''.join(secrets.choice(characters) for _ in range(length))
|
return ''.join(secrets.choice(characters) for _ in range(length))
|
||||||
|
|
||||||
|
|
||||||
|
def _initialize_app_config(app: Flask):
|
||||||
|
if app.config.get('BEHIND_PROXY', True):
|
||||||
|
app.wsgi_app = ProxyFix(
|
||||||
|
app.wsgi_app, x_for=1, x_proto=1
|
||||||
|
)
|
||||||
|
app.json.ensure_ascii = False
|
||||||
|
app.json.mimetype = "application/json; charset=utf-8"
|
||||||
|
secret_key = app.config.get('SECRET_KEY', '')
|
||||||
|
if secret_key:
|
||||||
|
app.secret_key = secret_key
|
||||||
|
else:
|
||||||
|
app.logger.info('Using generated secret')
|
||||||
|
app.secret_key = _generate_secret()
|
||||||
|
|
||||||
|
app.config["SQLALCHEMY_DATABASE_URI"] = app.config.get('SQLALCHEMY_DATABASE_URI', 'sqlite:///example.db')
|
||||||
|
if app.config["SQLALCHEMY_DATABASE_URI"].startswith('sqlite'):
|
||||||
|
app.config["SQLALCHEMY_ENGINE_OPTIONS"] = {
|
||||||
|
'isolation_level': 'SERIALIZABLE',
|
||||||
|
# "execution_options": {"autobegin": False}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
def create_app(test_config=None) -> Flask:
|
def create_app(test_config=None) -> Flask:
|
||||||
instance_path = os.getenv('INSTANCE_PATH', None)
|
instance_path = os.getenv('INSTANCE_PATH')
|
||||||
if instance_path is not None:
|
if instance_path is not None:
|
||||||
|
instance_path = os.path.abspath(instance_path)
|
||||||
os.makedirs(instance_path, exist_ok=True)
|
os.makedirs(instance_path, exist_ok=True)
|
||||||
|
print(f'App instance path: {instance_path}')
|
||||||
|
|
||||||
app = Flask(__name__,
|
app = Flask(__name__,
|
||||||
instance_path=instance_path,
|
instance_path=instance_path,
|
||||||
instance_relative_config=True
|
instance_relative_config=True
|
||||||
)
|
)
|
||||||
app.json.ensure_ascii = False
|
app.config.from_file("config.toml", load=tomllib.load, text=False)
|
||||||
app.json.mimetype = "application/json; charset=utf-8"
|
_initialize_app_config(app)
|
||||||
secret_key = os.getenv('SECRET_KEY', '')
|
|
||||||
if secret_key:
|
|
||||||
app.secret_key = secret_key
|
|
||||||
else:
|
|
||||||
print('Using generated secret')
|
|
||||||
app.secret_key = generate_secret()
|
|
||||||
app.config["SQLALCHEMY_DATABASE_URI"] = os.getenv('DATABASE_URI', 'sqlite:///example.db')
|
|
||||||
url_prefix = os.getenv('URL_PREFIX', '')
|
|
||||||
|
|
||||||
|
|
||||||
from . import utils
|
from . import utils
|
||||||
@@ -59,28 +77,17 @@ def create_app(test_config=None) -> Flask:
|
|||||||
from . import editor
|
from . import editor
|
||||||
from . import share
|
from . import share
|
||||||
|
|
||||||
if app.config["SQLALCHEMY_DATABASE_URI"].startswith('sqlite'):
|
|
||||||
app.config["SQLALCHEMY_ENGINE_OPTIONS"] = {
|
|
||||||
'isolation_level': 'SERIALIZABLE',
|
|
||||||
# "execution_options": {"autobegin": False}
|
|
||||||
}
|
|
||||||
db.init_app(app)
|
db.init_app(app)
|
||||||
limiter.init_app(app)
|
limiter.init_app(app)
|
||||||
|
|
||||||
|
|
||||||
with app.app_context():
|
with app.app_context():
|
||||||
db.create_all()
|
db.create_all()
|
||||||
# if db.engine.dialect.name == 'sqlite':
|
|
||||||
# @event.listens_for(db.engine, "connect")
|
|
||||||
# def enable_foreign_keys(dbapi_connection, connection_record):
|
|
||||||
# cursor = dbapi_connection.cursor()
|
|
||||||
# cursor.execute("PRAGMA foreign_keys=ON;")
|
|
||||||
# cursor.close()
|
|
||||||
|
|
||||||
@app.route('/health')
|
@app.route('/health')
|
||||||
def health():
|
def health():
|
||||||
return '', 204
|
return '', 204
|
||||||
|
|
||||||
|
url_prefix = app.config.get('URL_PREFIX', '')
|
||||||
app.register_blueprint(editor.bp, url_prefix=f'{url_prefix}/editor')
|
app.register_blueprint(editor.bp, url_prefix=f'{url_prefix}/editor')
|
||||||
app.register_blueprint(examples.bp, url_prefix=f'{url_prefix}/examples')
|
app.register_blueprint(examples.bp, url_prefix=f'{url_prefix}/examples')
|
||||||
app.register_blueprint(share.bp, url_prefix=f'{url_prefix}/s')
|
app.register_blueprint(share.bp, url_prefix=f'{url_prefix}/s')
|
||||||
@@ -88,5 +95,4 @@ def create_app(test_config=None) -> Flask:
|
|||||||
return app
|
return app
|
||||||
|
|
||||||
|
|
||||||
|
__all__ = ['create_app']
|
||||||
__all__ = ['create_app', 'db', 'get_common_cf_template_params', 'render_cf_error_page']
|
|
||||||
|
|||||||
14
editor/server/config.example.toml
Normal file
14
editor/server/config.example.toml
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
# Url prefix for app urls
|
||||||
|
URL_PREFIX = ''
|
||||||
|
|
||||||
|
# Set to true if trust X-Forwarded-For/X-Forwarded-Proto header
|
||||||
|
BEHIND_PROXY = true
|
||||||
|
|
||||||
|
# Some random secret, will be auto-generated if empty
|
||||||
|
SECRET_KEY = ''
|
||||||
|
|
||||||
|
# Main database URL
|
||||||
|
SQLALCHEMY_DATABASE_URI = 'sqlite:///database.db'
|
||||||
|
|
||||||
|
# Rate limit storage for Flask-Limiter
|
||||||
|
RATELIMIT_STORAGE_URI = 'memory://'
|
||||||
@@ -43,11 +43,10 @@ def fill_cf_template_params(params: dict):
|
|||||||
if loc:
|
if loc:
|
||||||
cf_status['location'] = loc
|
cf_status['location'] = loc
|
||||||
|
|
||||||
# Get real client ip from Cloudflare header or request.remote_addr
|
# Get real client ip from remote_addr
|
||||||
client_ip = request.headers.get('X-Forwarded-For')
|
# If this server is behind proxies (e.g CF CDN / Nginx), make sure to set 'BEHIND_PROXY'=True in app config. Then ProxyFix will fix this variable
|
||||||
if not client_ip:
|
# using X-Forwarded-For header from the proxy.
|
||||||
client_ip = request.remote_addr
|
params['client_ip'] = request.remote_addr
|
||||||
params['client_ip'] = client_ip
|
|
||||||
|
|
||||||
|
|
||||||
def sanitize_user_link(link: str):
|
def sanitize_user_link(link: str):
|
||||||
|
|||||||
Reference in New Issue
Block a user