网页界面如果直接去请求云端,会遇到跨域限制,而且云端域名会出现在浏览器历史与代理日志里。7.1.0 的做法是全部经本机后端转发:前端只认 127.0.0.1,云端请求由后端用 WinHTTP 发出。
候选路径:子目录优先
云端可能部署在站点根目录,也可能挂在子目录下;接口可能是目录写法,也可能是 .php 文件写法。后端按命中概率排好候选顺序,逐个试探:
vector<string> tmpl;
tmpl.push_back(path + "/"); // /api/activate/ ← 命中率最高,排第一
tmpl.push_back(path); // /api/activate ← 部分服务器拒收这种 POST,兜底
if (basePath.empty()) { // 仅根目录部署才需要文件写法兜底
tmpl.push_back(path + "/index.php");
tmpl.push_back(path + ".php");
}
vector<string> bases;
if (!basePath.empty()) bases.push_back(basePath); // 子目录部署优先
bases.push_back(string("")); // 根目录兜底命中过的路径要记住
// 已经命中过的路径直接打,不再逐个探测:正常情况每次云端调用只发 1 次 HTTPS
if (!g_cloudOkPath.empty()) {
DWORD st0 = 0;
string r0 = HttpPostTo(host, port, https, g_cloudOkPath + extraQuery, body, contentType, st0);
if (st0 != 0 && LooksLikeJson(r0)) return r0;
g_cloudOkPath.clear(); // 云端换路径了,重新学习
}只有 404 / 405 才视为「这个路径不对」,继续试下一个;2xx / 5xx 会记录下来,若返回的是 JSON 就直接采用并记住路径。
日志脱敏
排障需要日志,但云端主机名与私信内容都不该落盘。于是日志只保留「路径 + 状态码 + 长度 + 是否 JSON」,主机名半掩,正文只在非 JSON(多为错误页)时才留一小段:
static string MaskHost(const string& h) {
// 保留首字母与域名后缀:s***.example.com —— 够排障,又不可直接复用
}
static string Sanitize(const string& s) {
string o;
for (char c : s) {
unsigned char u = (unsigned char)c;
o += (c == '\r' || c == '\n' || c == '\t') ? ' ' : (u < 32 ? '.' : c);
}
return o; // 控制字符替换掉,避免日志被注入换行伪造记录
}
// 只记:https / host(半掩) / port / path / status / len / json
// 非 JSON 才附加 head=<前 80 字节>(多为 404、405 错误页)