add URL_PREFIX config for reverse proxy path support
All checks were successful
CI / test (push) Successful in 38s

This commit is contained in:
Username
2025-12-20 04:43:36 +01:00
parent c76a158c18
commit 5770698847
2 changed files with 24 additions and 12 deletions

View File

@@ -17,6 +17,12 @@ from app.database import check_content_hash, get_db
# Valid paste ID pattern (hexadecimal only) # Valid paste ID pattern (hexadecimal only)
PASTE_ID_PATTERN = re.compile(r"^[a-f0-9]+$") PASTE_ID_PATTERN = re.compile(r"^[a-f0-9]+$")
def _url(path: str) -> str:
"""Generate URL with configured prefix for reverse proxy deployments."""
prefix = current_app.config.get("URL_PREFIX", "")
return f"{prefix}{path}"
# Runtime-generated PoW secret (used if not configured) # Runtime-generated PoW secret (used if not configured)
_pow_secret_cache = None _pow_secret_cache = None
@@ -273,22 +279,25 @@ def index():
if request.method == "POST": if request.method == "POST":
return create_paste() return create_paste()
prefix = current_app.config.get("URL_PREFIX", "")
return _json_response( return _json_response(
{ {
"name": "FlaskPaste", "name": "FlaskPaste",
"version": VERSION, "version": VERSION,
"prefix": prefix or "/",
"endpoints": { "endpoints": {
"GET /": "API information", f"GET {_url('/')}": "API information",
"GET /health": "Health check", f"GET {_url('/health')}": "Health check",
"POST /": "Create paste", f"GET {_url('/challenge')}": "Get PoW challenge",
"GET /<id>": "Retrieve paste metadata", f"POST {_url('/')}": "Create paste",
"GET /<id>/raw": "Retrieve raw paste content", f"GET {_url('/<id>')}": "Retrieve paste metadata",
"DELETE /<id>": "Delete paste", f"GET {_url('/<id>/raw')}": "Retrieve raw paste content",
f"DELETE {_url('/<id>')}": "Delete paste",
}, },
"usage": { "usage": {
"raw": "curl --data-binary @file.txt http://host/", "raw": f"curl --data-binary @file.txt http://host{_url('/')}",
"pipe": "cat file.txt | curl --data-binary @- http://host/", "pipe": f"cat file.txt | curl --data-binary @- http://host{_url('/')}",
"json": "curl -H 'Content-Type: application/json' -d '{\"content\":\"...\"}' http://host/", "json": f"curl -H 'Content-Type: application/json' -d '{{\"content\":\"...\"}}' http://host{_url('/')}",
}, },
"note": "Use --data-binary (not -d) to preserve newlines", "note": "Use --data-binary (not -d) to preserve newlines",
} }
@@ -382,8 +391,8 @@ def create_paste():
response_data = { response_data = {
"id": paste_id, "id": paste_id,
"url": f"/{paste_id}", "url": _url(f"/{paste_id}"),
"raw": f"/{paste_id}/raw", "raw": _url(f"/{paste_id}/raw"),
"mime_type": mime_type, "mime_type": mime_type,
"created_at": now, "created_at": now,
} }
@@ -420,7 +429,7 @@ def get_paste(paste_id: str):
"mime_type": row["mime_type"], "mime_type": row["mime_type"],
"size": row["size"], "size": row["size"],
"created_at": row["created_at"], "created_at": row["created_at"],
"raw": f"/{paste_id}/raw", "raw": _url(f"/{paste_id}/raw"),
}) })

View File

@@ -44,6 +44,9 @@ class Config:
# Secret key for signing challenges (auto-generated if not set) # Secret key for signing challenges (auto-generated if not set)
POW_SECRET = os.environ.get("FLASKPASTE_POW_SECRET", "") POW_SECRET = os.environ.get("FLASKPASTE_POW_SECRET", "")
# URL prefix for reverse proxy deployments (e.g., "/paste" for mymx.me/paste)
URL_PREFIX = os.environ.get("FLASKPASTE_URL_PREFIX", "").rstrip("/")
class DevelopmentConfig(Config): class DevelopmentConfig(Config):
"""Development configuration.""" """Development configuration."""