Files
Private-Proxy/lite/rrpp_core/pac_data.py
T

54 lines
1.7 KiB
Python

"""PAC 数据文件的网络传输与安全落盘。"""
import json
import os
import urllib.request
from pathlib import Path
def read_version(path):
"""读取 PAC JSON 的 version/date;无效文件返回空字符串。"""
try:
data = json.loads(Path(path).read_text("utf-8"))
return str(data.get("version") or ""), str(data.get("date") or "")
except Exception:
return "", ""
def no_proxy_opener():
"""创建忽略环境/系统代理的直连 HTTP opener。"""
return urllib.request.build_opener(urllib.request.ProxyHandler({}))
def fetch_json(url, timeout=15, tries=2):
"""以直连方式拉取 JSON;最后一次失败时保留原始异常。"""
opener = no_proxy_opener()
for attempt in range(tries):
try:
with opener.open(url, timeout=timeout) as response:
return json.loads(response.read().decode("utf-8"))
except Exception:
if attempt == tries - 1:
raise
def validate_document(name, data):
"""校验各 PAC 文件的最小结构,避免错误响应覆盖有效缓存。"""
if not isinstance(data, dict):
return False
if name in ("pac_domains", "pac_direct_domains"):
return isinstance(data.get("domains"), list)
if name == "pac_ip_cn":
return isinstance(data.get("cidrs"), list)
return False
def atomic_write(directory, name, data):
"""将 PAC JSON 以 tmp + replace 原子写入指定用户目录。"""
directory = Path(directory)
directory.mkdir(parents=True, exist_ok=True)
target = directory / f"{name}.json"
temporary_path = directory / f"{name}.json.tmp"
temporary_path.write_text(json.dumps(data, ensure_ascii=False), "utf-8")
os.replace(temporary_path, target)