Skip to content

Commit facdb8e

Browse files
committed
feat: 优化 Node.js 下请求头 Accept 逻辑
1 parent 3374eae commit facdb8e

3 files changed

Lines changed: 73 additions & 9 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.34.0",
3+
"version": "2.35.0",
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: 51 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ describe('open-api HTTP adapter', function () {
2121
let originalProxyAgent;
2222
let originalRequest;
2323
let agentOptions;
24+
let requestOptions;
2425

2526
beforeEach(function () {
2627
originalEnv = Object.fromEntries(
@@ -34,6 +35,7 @@ describe('open-api HTTP adapter', function () {
3435
originalProxyAgent = undici.ProxyAgent;
3536
originalRequest = undici.request;
3637
agentOptions = [];
38+
requestOptions = undefined;
3739

3840
class CapturingAgent {
3941
constructor(options) {
@@ -47,14 +49,17 @@ describe('open-api HTTP adapter', function () {
4749

4850
undici.EnvHttpProxyAgent = CapturingAgent;
4951
undici.ProxyAgent = CapturingAgent;
50-
undici.request = async () => ({
51-
statusCode: 200,
52-
headers: {},
53-
body: {
54-
text: async () => '',
55-
arrayBuffer: async () => new ArrayBuffer(0),
56-
},
57-
});
52+
undici.request = async (_url, options) => {
53+
requestOptions = options;
54+
return {
55+
statusCode: 200,
56+
headers: {},
57+
body: {
58+
text: async () => '',
59+
arrayBuffer: async () => new ArrayBuffer(0),
60+
},
61+
};
62+
};
5863
});
5964

6065
afterEach(function () {
@@ -90,4 +95,42 @@ describe('open-api HTTP adapter', function () {
9095
expect(agentOptions[0].connect.allowH2).to.equal(false);
9196
expect(agentOptions[0].requestTls.allowH2).to.equal(false);
9297
});
98+
99+
it('adds a curl-like Accept header by default in Node.js', async function () {
100+
await HTTP({
101+
headers: {
102+
'User-Agent': 'Surge',
103+
},
104+
}).get('https://example.com/subscription');
105+
106+
expect(requestOptions.headers).to.include({
107+
'User-Agent': 'Surge',
108+
Accept: '*/*',
109+
});
110+
});
111+
112+
it('keeps an explicit Accept header in Node.js', async function () {
113+
await HTTP({
114+
headers: {
115+
accept: 'application/json',
116+
},
117+
}).get('https://example.com/subscription');
118+
119+
expect(requestOptions.headers).to.deep.equal({
120+
accept: 'application/json',
121+
});
122+
});
123+
124+
it('omits Accept when callers set it to null in Node.js', async function () {
125+
await HTTP({
126+
headers: {
127+
'User-Agent': 'Surge',
128+
Accept: null,
129+
},
130+
}).get('https://example.com/subscription');
131+
132+
expect(requestOptions.headers).to.deep.equal({
133+
'User-Agent': 'Surge',
134+
});
135+
});
93136
});

backend/src/vendor/open-api.js

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,24 @@ function parseSocks5Uri(uri) {
4242
password: password != null ? decodeURIComponent(password) : undefined,
4343
};
4444
}
45+
46+
function normalizeNodeRequestHeaders(headers) {
47+
const normalized = { ...(headers || {}) };
48+
let hasAccept = false;
49+
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];
54+
}
55+
56+
if (!hasAccept) {
57+
normalized.Accept = '*/*';
58+
}
59+
60+
return normalized;
61+
}
62+
4563
export class OpenAPI {
4664
constructor(name = 'untitled', debug = false) {
4765
this.name = name;
@@ -523,6 +541,9 @@ export function HTTP(defaultOptions = { baseURL: '' }) {
523541
).toString('base64')}`,
524542
};
525543
}
544+
opts.headers = normalizeNodeRequestHeaders(
545+
opts.headers,
546+
);
526547
let dispatcher;
527548
if (!opts.proxy) {
528549
const allProxy =

0 commit comments

Comments
 (0)