api docs, generator

This commit is contained in:
Mateusz Gruszczyński
2026-03-03 10:03:34 +01:00
parent b3a16303d2
commit 721ad44960
9 changed files with 1590 additions and 1004 deletions

110
app.py
View File

@@ -3,16 +3,15 @@ GeoIP Ban Generator - Web Application
"""
from flask import Flask, render_template, request, Response, jsonify
import hashlib
import os
import sqlite3
from geoip_handler import GeoIPHandler
from pathlib import Path
from functools import wraps
from datetime import datetime
import config
from api import api
from geoip_handler import GeoIPHandler
import hashlib
import os
import sqlite3
import config
app = Flask(__name__,
static_folder=str(config.STATIC_DIR),
@@ -23,6 +22,18 @@ app.register_blueprint(api)
handler = GeoIPHandler()
CACHEABLE_PAGES = {
"/api-docs",
"/generator",
}
NO_CACHE_PREFIXES = (
"/api/",
)
STATIC_PREFIX = "/static/"
redis_cache = None
if config.REDIS_ENABLED:
try:
@@ -105,6 +116,54 @@ def inject_globals():
'redis_connected': redis_cache.health_check()['connected'] if redis_cache else False,
}
from flask import jsonify, render_template, request
def _wants_json():
if request.path.startswith("/api/"):
return True
accept = (request.headers.get("Accept") or "").lower()
return "application/json" in accept
def _render_4xx(code, title, message):
payload = {
"success": False,
"error": title,
"message": message,
"path": request.path,
"status": code,
}
if _wants_json():
return jsonify(payload), code
return render_template(
"error.html",
status=code,
title=title,
message=message,
path=request.path
), code
@app.errorhandler(400)
def bad_request(e):
return _render_4xx(400, "Bad Request", "Request is invalid or missing required fields.")
@app.errorhandler(401)
def unauthorized(e):
return _render_4xx(401, "Unauthorized", "Authentication is required for this resource.")
@app.errorhandler(403)
def forbidden(e):
return _render_4xx(403, "Forbidden", "You don't have permission to access this resource.")
@app.errorhandler(404)
def not_found(e):
return _render_4xx(404, "Not Found", "The requested endpoint/page does not exist.")
@app.errorhandler(405)
def method_not_allowed(e):
return _render_4xx(405, "Method Not Allowed", "The HTTP method is not allowed for this endpoint.")
@app.route('/')
def index():
"""Main page"""
@@ -118,6 +177,11 @@ def api_docs():
"""API documentation page"""
return render_template('api.html')
@app.route("/generator")
def generator():
"""Script gwnerator"""
return render_template("generator.html")
@app.route('/favicon.ico')
def favicon():
return '', 204
@@ -217,21 +281,29 @@ def cache_control(max_age: int = None):
@app.after_request
def add_headers(response):
"""Add cache control headers based on request path"""
if request.path == '/' or request.path.startswith('/api/'):
response.headers['Cache-Control'] = 'no-cache, no-store'
elif request.path.startswith('/static/'):
if 'Content-Disposition' in response.headers:
del response.headers['Content-Disposition']
path = request.path
if path.startswith(STATIC_PREFIX):
if "Content-Disposition" in response.headers:
del response.headers["Content-Disposition"]
if config.ENABLE_CACHE_BUSTING:
response.headers['Cache-Control'] = f'public, max-age={config.CACHE_TTL_SECONDS}, immutable'
response.headers["Cache-Control"] = (
f"public, max-age={config.CACHE_TTL_SECONDS}, immutable"
)
else:
response.headers['Cache-Control'] = f'public, max-age={config.CACHE_TTL_SECONDS}'
elif request.path == '/api-docs':
response.headers['Cache-Control'] = 'public, max-age=300'
response.headers["Cache-Control"] = f"public, max-age={config.CACHE_TTL_SECONDS}"
return response
if path in CACHEABLE_PAGES:
response.headers["Cache-Control"] = "public, max-age=300"
return response
if path == "/" or any(path.startswith(p) for p in NO_CACHE_PREFIXES):
response.headers["Cache-Control"] = "no-cache, no-store"
return response
return response
if __name__ == '__main__':