""" webui/api/proxy.py - Nginx proxy domain management API blueprint. Exposed at /api/proxy/* and delegates to lib.nginx. """ from flask import Blueprint, jsonify, request from lib.nginx import ( add_domain, apply, get_config, get_domains, remove_domain, set_management_proxy, test_config, update_domain, ) bp = Blueprint("proxy", __name__) # --------------------------------------------------------------------------- # Helpers # --------------------------------------------------------------------------- def _error(msg, code=400): return jsonify({"ok": False, "error": msg}), code def _ok(data=None): body = {"ok": True} if data is not None: body["data"] = data return jsonify(body) # --------------------------------------------------------------------------- # Domains # --------------------------------------------------------------------------- @bp.route("/domains", methods=["GET"]) def list_domains(): try: return _ok(get_domains()) except RuntimeError as exc: return _error(str(exc), 500) @bp.route("/domains", methods=["POST"]) def add_domain_bp(): body = request.get_json(silent=True) or {} domain = body.get("domain", "").strip() backend_host = body.get("backend_host", "").strip() backend_port = body.get("backend_port") backend_proto = body.get("backend_proto", "http").strip() or "http" cert = body.get("cert") extra_headers = body.get("extra_headers") if not domain: return _error("'domain' is required", 400) if not backend_host: return _error("'backend_host' is required", 400) if backend_port is None: return _error("'backend_port' is required", 400) try: add_domain( domain, backend_host, int(backend_port), backend_proto, cert, extra_headers ) return _ok({"domain": domain}) except (ValueError, RuntimeError) as exc: return _error(str(exc), 500) @bp.route("/domains/", methods=["GET"]) def domain_details(domain): try: cfg = get_config() entry = cfg.get("domains", {}).get(domain) if entry is None: return _error(f"Domain '{domain}' not found", 404) return _ok({"domain": domain, **entry}) except RuntimeError as exc: return _error(str(exc), 500) @bp.route("/domains/", methods=["PUT"]) def update_domain_bp(domain): body = request.get_json(silent=True) or {} if not body: return _error("Request body must be a JSON object with fields to update", 400) try: update_domain(domain, **body) return _ok({"domain": domain}) except KeyError as exc: return _error(str(exc), 404) except RuntimeError as exc: return _error(str(exc), 500) @bp.route("/domains/", methods=["DELETE"]) def remove_domain_bp(domain): try: cfg = get_config() if domain not in cfg.get("domains", {}): return _error(f"Domain '{domain}' not found", 404) remove_domain(domain) return _ok({"domain": domain}) except RuntimeError as exc: return _error(str(exc), 500) # --------------------------------------------------------------------------- # Apply / test # --------------------------------------------------------------------------- @bp.route("/apply", methods=["POST"]) def apply_bp(): try: apply() return _ok({"message": "nginx configuration applied and reloaded"}) except RuntimeError as exc: return _error(str(exc), 500) @bp.route("/test", methods=["POST"]) def test_bp(): try: ok, message = test_config() if ok: return _ok({"passed": True, "message": message}) return jsonify({"ok": False, "error": message, "passed": False}), 400 except RuntimeError as exc: return _error(str(exc), 500) # --------------------------------------------------------------------------- # Management proxy # --------------------------------------------------------------------------- @bp.route("/management", methods=["POST"]) def management_bp(): body = request.get_json(silent=True) or {} domain = body.get("domain", "").strip() if not domain: return _error("'domain' is required", 400) flask_host = body.get("flask_host", "127.0.0.1").strip() or "127.0.0.1" flask_port = body.get("flask_port", 9090) auth_user = body.get("auth_user") auth_pass = body.get("auth_pass") try: set_management_proxy(domain, flask_host, int(flask_port), auth_user, auth_pass) return _ok({"domain": domain}) except (ValueError, RuntimeError) as exc: code = 400 if isinstance(exc, ValueError) else 500 return _error(str(exc), code)