Files
web_hgdja_h5/tests/client-headers.test.mjs
谢宇宁andClaude Opus 5.5 6bd5cc665a Initial commit
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-05 20:30:26 +07:00

85 lines
4.1 KiB
JavaScript

import assert from "node:assert/strict";
import { readFile } from "node:fs/promises";
import test from "node:test";
import ts from "typescript";
async function loadClientHeaders() {
const code = ts.transpileModule(
await readFile(new URL("../src/lib/api/client-headers.ts", import.meta.url), "utf8"),
{ compilerOptions: { module: ts.ModuleKind.ESNext, target: ts.ScriptTarget.ES2022 } },
).outputText;
return import(`data:text/javascript;base64,${Buffer.from(code).toString("base64")}`);
}
const { buildBrowserApiHeaders, clientHeaders, clientIp } = await loadClientHeaders();
test("浏览器 X-User-Agent 带上 DevID 和 SysType", () => {
const headers = buildBrowserApiHeaders("device-1");
assert.match(headers["X-User-Agent"], /DevID=device-1/);
assert.match(headers["X-User-Agent"], /SysType=h5_/);
assert.match(headers["X-User-Agent"], /BuildID=web/);
assert.match(headers["X-User-Agent"], /system_name=Other/);
});
test("服务端优先保留请求里的 X-User-Agent,并补 X-Real-IP", () => {
const xua = "DevID=client;DevType=iPhone;SysType=h5_ios;Ver=1.0.0;BuildID=web;sid=abc";
const headers = clientHeaders(
new Headers({
"User-Agent": " Mozilla/5.0 iPhone ",
"X-User-Agent": xua,
"X-Real-IP": "203.0.113.9",
"X-Forwarded-For": "203.0.113.8, 10.0.0.1",
}),
);
assert.equal(headers["User-Agent"], "Mozilla/5.0 iPhone");
assert.equal(headers["X-User-Agent"], xua);
assert.equal(headers["X-Real-IP"], "203.0.113.9");
assert.equal(headers["X-Forwarded-For"], undefined);
});
test("没有 X-Real-IP 时取 X-Forwarded-For 第一段", () => {
assert.equal(clientIp(new Headers({ "X-Forwarded-For": "198.51.100.4, 10.0.0.1" })), "198.51.100.4");
const headers = clientHeaders(new Headers({ "User-Agent": "Chrome", "X-Forwarded-For": "198.51.100.4, 10.0.0.1" }));
assert.equal(headers["X-Real-IP"], "198.51.100.4");
assert.match(headers["X-User-Agent"], /SysType=h5_pc/);
});
test("没有请求上下文时回退合成 X-User-Agent", () => {
const headers = clientHeaders(undefined, { devID: "web-ssr" });
assert.equal(headers["User-Agent"], undefined);
assert.match(headers["X-User-Agent"], /DevID=web-ssr/);
assert.match(headers["X-User-Agent"], /system_name=Other/);
});
test("服务端按 User-Agent 写入系统名称和系统版本", () => {
const iphone =
"Mozilla/5.0 (iPhone; CPU iPhone OS 17_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.2 Mobile/15E148 Safari/604.1";
const ios = clientHeaders(new Headers({ "User-Agent": iphone, Cookie: "sid=abc" }));
assert.match(ios["X-User-Agent"], /DevType=Apple iPhone mobile/);
assert.match(ios["X-User-Agent"], /SysType=h5_ios/);
assert.match(ios["X-User-Agent"], /BuildID=Safari 17\.2/);
assert.match(ios["X-User-Agent"], /device_brand=Apple/);
assert.match(ios["X-User-Agent"], /device_model=iPhone/);
assert.match(ios["X-User-Agent"], /system_name=iOS/);
assert.match(ios["X-User-Agent"], /system_version=17\.2/);
assert.match(ios["X-User-Agent"], /sid=abc/);
const android =
"Mozilla/5.0 (Linux; Android 13; Pixel 7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Mobile Safari/537.36";
const androidHeaders = clientHeaders(new Headers({ "User-Agent": android }));
assert.match(androidHeaders["X-User-Agent"], /SysType=h5_android/);
assert.match(androidHeaders["X-User-Agent"], /device_brand=Google/);
assert.match(androidHeaders["X-User-Agent"], /device_model=Pixel 7/);
assert.match(androidHeaders["X-User-Agent"], /system_name=Android/);
assert.match(androidHeaders["X-User-Agent"], /system_version=13/);
assert.match(androidHeaders["X-User-Agent"], /BuildID=Chrome 120\.0\.0\.0/);
const windows =
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36";
const pc = clientHeaders(new Headers({ "User-Agent": windows }));
assert.match(pc["X-User-Agent"], /SysType=h5_pc/);
assert.match(pc["X-User-Agent"], /system_name=Windows/);
assert.match(pc["X-User-Agent"], /system_version=10\.0/);
assert.match(pc["X-User-Agent"], /DevType=desktop/);
});