#!/usr/bin/env python3
"""极简HTTP服务: POST /save 接收规则JSON写回gost.yaml"""
json, subprocess
http.server BaseHTTPRequestHandler, HTTPServer
H(BaseHTTPRequestHandler):
USER="admin"; PASS="oyh159159oiw.@"
_check_auth(self):
base64
a=self.headers.get("Authorization","")
a.startswith("Basic "):
:
u,p=base64.b64decode(a[:]).decode().split(":",)
u==self.USER p==self.PASS
Exception:
_cors(self):
self.send_header("Access-Control-Allow-Origin","*")
self.send_header("Access-Control-Allow-Headers","*")
self.send_header("Access-Control-Allow-Methods","POST, OPTIONS")
do_OPTIONS(self):
self.send_response(); self._cors(); self.end_headers()
do_GET(self):
self._check_auth():
self.send_response(); self._cors()
self.send_header("WWW-Authenticate","Basic realm=gost"); self.end_headers();
self.path ("/yaml","/rawyaml"):
self.send_response(); self._cors(); self.end_headers();
self.path=="/rawyaml":
open("/etc/gost/gost.yaml","rb") f: raw=f.read()
self.send_response()
self._cors(); self.send_header("Content-Type","text/plain; charset=utf-")
self.end_headers(); self.wfile.write(raw)
self.send_response(); self._cors(); self.end_headers();
:
open("/etc/gost/gost.yaml") f: txt=f.read()
yaml Y
data=Y.safe_load(txt) {}
json J
out=J.dumps({"services":data.get("services",[])}).encode()
self.send_response()
Exception e:
out=str(e).encode(); self.send_response()
self._cors(); self.send_header("Content-Type","application/json")
self.end_headers(); self.wfile.write(out)
do_POST(self):
self._check_auth():
self.send_response(); self._cors()
self.send_header("WWW-Authenticate","Basic realm=gost"); self.end_headers();
self.path != "/save":
self.send_response(); self._cors(); self.end_headers();
n = int(self.headers.get("Content-Length",""))
body = self.rfile.read(n)
:
r = subprocess.run(["python3","/usr/local/bin/gost-save.py"],
input=body, capture_output=, timeout=)
out = r.stdout.decode() r.stderr.decode()
code = r.returncode==
Exception e:
out = str(e); code =
self.send_response(code)
self._cors(); self.send_header("Content-Type","text/plain")
self.end_headers()
self.wfile.write(out.encode())
log_message(self,*a):
auto_sync():
time, urllib.request, base64, yaml Y, shutil, datetime
CONF="/etc/gost/gost.yaml"
auth="Basic "+base64.b64encode(b"admin:oyh159159oiw.@").decode()
:
time.sleep()
:
req=urllib.request.Request("http://.:/gostapi/config")
req.add_header("Authorization",auth)
urllib.request.urlopen(req,timeout=) r:
rt=json.load(r)
names_rt=sorted(s["name"] s (rt.get("services") []))
open(CONF) f: cfg=Y.safe_load(f) {}
names_yaml=sorted(s["name"] s (cfg.get("services") []))
# 提取运行时规则的纯净结构(去掉status等动态字段)
clean=[]
s (rt.get("services") []):
d={k:v k,v s.items() k ("name","addr","handler","listener","forwarder","metadata","ignoreClientVersion")}
clean.append(d)
names_rt!=names_yaml:
bak=CONF+".bak-"+datetime.datetime.now().strftime("%Y%m%d%H%M%S")
shutil.copy(CONF,bak)
cfg["services"]=clean
open(CONF,"w") f: Y.safe_dump(cfg,f,sort_keys=,allow_unicode=)
("auto-synced yaml:",names_rt,flush=)
Exception e:
("auto-sync err:",e,flush=)
threading
threading.Thread(target=auto_sync,daemon=).start()
HTTPServer((".",),H).serve_forever()