feat: server.py 迁移部署到 NGCQ(1Panel Nginx 反代 eink.njcqit.com)+境内可达 BTC 行情源+页面访问令牌
- btc_api:新增 gateio/huobi_aws/binance_vision 三源,config 增 BTC_SOURCES 控制尝试顺序(境内 okx/coinbase/huobi 主域名不通) - server:IMAGE_TOKEN 非空时三个渲染端点须带 ?token=…,否则与未知路径同样 404(防爬虫扫描);推送令牌改常量时间比较 - 文档:CLAUDE.md/README/.env.example 记录 NGCQ 部署(systemd eink-server、1Panel API 建站坑)、本机 server/cloudflared 已卸载 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
17
server.py
17
server.py
@@ -20,14 +20,17 @@ HTML 控件填同一个 URL 则**每个刷新周期都重抓**。所以对外只
|
||||
- 三路上游过期时**并行**实拉,整体最多等 FETCH_BUDGET 秒(默认 5),超预算的一路本次用旧值、后台拉完更新缓存(见 build_data);
|
||||
所以推送时机与设备抓取时机不必对齐。未推送过:Claude 显示 "--",ChatGPT 用 mock 并标「示例数据」。
|
||||
- 推送鉴权:请求头 X-Push-Token 必须等于 PUSH_TOKEN;PUSH_TOKEN 为空时拒绝一切推送(服务在公网,务必配置)。
|
||||
- 页面鉴权:IMAGE_TOKEN 非空时,三个渲染端点必须带 ?token=<IMAGE_TOKEN>,否则返回与未知路径一样的 404(防爬虫扫描)。
|
||||
其他端点:GET /health → JSON 运行状态;GET /push/usage、/push/usage_gpt → 查看暂存的原始快照(需同样令牌)。
|
||||
部署:python3 server.py(监听 SERVER_HOST:SERVER_PORT),前置 Caddy/Nginx 做 HTTPS,或 cloudflared tunnel。
|
||||
"""
|
||||
import hmac
|
||||
import io
|
||||
import json
|
||||
import os
|
||||
import threading
|
||||
import time
|
||||
import urllib.parse
|
||||
from concurrent.futures import ThreadPoolExecutor, wait
|
||||
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
|
||||
|
||||
@@ -221,12 +224,24 @@ class Handler(BaseHTTPRequestHandler):
|
||||
|
||||
def _authed(self):
|
||||
tok = config.PUSH_TOKEN
|
||||
return bool(tok) and self.headers.get("X-Push-Token", "") == tok
|
||||
return bool(tok) and hmac.compare_digest(self.headers.get("X-Push-Token", ""), tok)
|
||||
|
||||
def _page_authed(self):
|
||||
"""页面令牌:IMAGE_TOKEN 为空则放行;否则查询串里 token 必须相等(常量时间比较)。"""
|
||||
tok = config.IMAGE_TOKEN
|
||||
if not tok:
|
||||
return True
|
||||
qs = urllib.parse.parse_qs(urllib.parse.urlsplit(self.path).query)
|
||||
return any(hmac.compare_digest(v, tok) for v in qs.get("token", []))
|
||||
|
||||
# ---------- GET ----------
|
||||
def do_GET(self):
|
||||
path = self.path.split("?", 1)[0]
|
||||
try:
|
||||
if path in (config.IMAGE_PATH, config.HTML_PATH, config.HTML_PNG_PATH) and not self._page_authed():
|
||||
# 令牌不对与路径不存在返回完全一样的 404,不暴露端点存在
|
||||
self._log(404, "bad page token")
|
||||
return self._json(404, {"ok": False, "error": "not found"})
|
||||
if path == config.IMAGE_PATH:
|
||||
t0 = time.time()
|
||||
d, st = build_data()
|
||||
|
||||
Reference in New Issue
Block a user