Skip to content

Commit b21faf5

Browse files
committed
feat: 规范化请求头 防止某些严格的风控拦截
1 parent fbadd7e commit b21faf5

3 files changed

Lines changed: 30 additions & 13 deletions

File tree

backend/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "sub-store",
3-
"version": "2.36.14",
3+
"version": "2.36.15",
44
"description": "Advanced Subscription Manager for QX, Loon, Surge, Stash and Shadowrocket.",
55
"main": "src/main.js",
66
"packageManager": "pnpm@11.0.9",

backend/src/test/vendor/open-api.spec.js

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -96,23 +96,23 @@ describe('open-api HTTP adapter', function () {
9696
expect(agentOptions[0].requestTls.allowH2).to.equal(false);
9797
});
9898

99-
it('adds a curl-like Accept header by default in Node.js', async function () {
99+
it('normalizes Node.js request header names to lowercase', async function () {
100100
await HTTP({
101101
headers: {
102102
'User-Agent': 'Surge',
103103
},
104104
}).get('https://example.com/subscription');
105105

106106
expect(requestOptions.headers).to.include({
107-
'User-Agent': 'Surge',
108-
Accept: '*/*',
107+
'user-agent': 'Surge',
108+
accept: '*/*',
109109
});
110110
});
111111

112112
it('keeps an explicit Accept header in Node.js', async function () {
113113
await HTTP({
114114
headers: {
115-
accept: 'application/json',
115+
Accept: 'application/json',
116116
},
117117
}).get('https://example.com/subscription');
118118

@@ -121,6 +121,20 @@ describe('open-api HTTP adapter', function () {
121121
});
122122
});
123123

124+
it('preserves __proto__ headers when normalizing names', async function () {
125+
await HTTP({
126+
headers: Object.fromEntries([['__proto__', 'sent']]),
127+
}).get('https://example.com/subscription');
128+
129+
expect(
130+
Object.prototype.hasOwnProperty.call(
131+
requestOptions.headers,
132+
'__proto__',
133+
),
134+
).to.equal(true);
135+
expect(requestOptions.headers.__proto__).to.equal('sent');
136+
});
137+
124138
it('omits Accept when callers set it to null in Node.js', async function () {
125139
await HTTP({
126140
headers: {
@@ -130,7 +144,7 @@ describe('open-api HTTP adapter', function () {
130144
}).get('https://example.com/subscription');
131145

132146
expect(requestOptions.headers).to.deep.equal({
133-
'User-Agent': 'Surge',
147+
'user-agent': 'Surge',
134148
});
135149
});
136150
});

backend/src/vendor/open-api.js

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -44,20 +44,23 @@ function parseSocks5Uri(uri) {
4444
}
4545

4646
function normalizeNodeRequestHeaders(headers) {
47-
const normalized = { ...(headers || {}) };
47+
const normalized = [];
4848
let hasAccept = false;
4949

50-
for (const key of Object.keys(normalized)) {
51-
if (key.toLowerCase() !== 'accept') continue;
52-
hasAccept = true;
53-
if (normalized[key] == null) delete normalized[key];
50+
for (const [key, value] of Object.entries(headers || {})) {
51+
const normalizedKey = key.toLowerCase();
52+
if (normalizedKey === 'accept') {
53+
hasAccept = true;
54+
if (value == null) continue;
55+
}
56+
normalized.push([normalizedKey, value]);
5457
}
5558

5659
if (!hasAccept) {
57-
normalized.Accept = '*/*';
60+
normalized.push(['accept', '*/*']);
5861
}
5962

60-
return normalized;
63+
return Object.fromEntries(normalized);
6164
}
6265

6366
export class OpenAPI {

0 commit comments

Comments
 (0)