This commit is contained in:
Mateusz Gruszczyński
2025-08-29 22:04:29 +02:00
parent eac2002f56
commit 0d35b3e654
4 changed files with 205 additions and 57 deletions

64
app.py
View File

@@ -73,20 +73,7 @@ def track_request_data():
@app.after_request
def add_cache_headers(response):
if request.path.startswith("/static/"):
response.headers.pop("Content-Disposition", None)
if request.path.endswith((".css", ".js")):
response.headers["Cache-Control"] = "public, max-age=31536000, immutable"
else:
response.headers["Cache-Control"] = "public, max-age=86400"
return response
@app.after_request
def after_request(response):
def finalize_response(response):
elapsed = time.perf_counter() - g.start_time
redis_client.incrbyfloat("stats:processing_time_total", elapsed)
redis_client.incr("stats:processing_time_count")
@@ -102,6 +89,29 @@ def after_request(response):
redis_client.set("stats:processing_time_max", elapsed)
except Exception:
redis_client.set("stats:processing_time_max", elapsed)
path = request.path or "/"
if response.status_code >= 400:
response.headers["Cache-Control"] = "no-store"
response.headers["Pragma"] = "no-cache"
response.headers["Expires"] = "0"
return response
if path.startswith("/static/"):
response.headers.pop("Content-Disposition", None)
if path.endswith((".css", ".js")):
response.headers["Cache-Control"] = "public, max-age=31536000, immutable"
else:
response.headers["Cache-Control"] = "public, max-age=86400"
return response
if path == "/":
response.headers["Cache-Control"] = "private, no-store"
response.headers["Pragma"] = "no-cache"
response.headers["Expires"] = "0"
return response
return response
@@ -319,6 +329,14 @@ def add_recent_convert():
redis_client.ltrim("recent_converts", 0, 99)
def validate_ip(value: str) -> str:
v = (value or "").strip()
try:
return str(ipaddress.ip_address(v))
except Exception:
raise ValueError("Invalid IP address")
@app.route("/favicon.ico", methods=["GET"])
def favicon():
return Response(status=204)
@@ -329,7 +347,11 @@ def index():
generated_link = None
recent_links = get_recent_links()
url_param = request.args.get("url", config.DEFAULT_SOURCE_URL)
target_ip = request.args.get("ip", "127.0.0.1")
raw_ip = request.args.get("ip", "127.0.0.1")
try:
target_ip = validate_ip(raw_ip)
except ValueError:
target_ip = "127.0.0.1"
if url_param:
try:
@@ -437,7 +459,15 @@ def convert():
redis_client.incr("stats:errors_400")
abort(400)
target_ip = request.args.get("ip", "127.0.0.1")
try:
target_ip = validate_ip(request.args.get("ip", "127.0.0.1"))
except ValueError:
if debug_mode:
d("Bad parametr ?ip")
return debug_response(status=400)
redis_client.incr("stats:errors_400")
abort(400, description="Invalid IP")
if debug_mode:
d(f"URL (encoded): {encoded_url}")
d(f"URL (decoded): {decoded_url}")
@@ -561,7 +591,7 @@ def convert_head():
abort(400)
decoded_url = unquote(encoded_url)
validate_and_normalize_url(decoded_url)
target_ip = request.args.get("ip", "127.0.0.1")
target_ip = validate_ip(request.args.get("ip", "127.0.0.1"))
etag = build_etag(None, None, target_ip)
resp = Response(status=200)
resp.headers.update(cache_headers(etag, None))