Skip to content

Commit fda06ee

Browse files
authored
[Console] Fix overriding of host header name (#59143) (#59269)
* fix: only override hostname if none was provided Copy the behaviour or Wreck.request from 7.4. This is a regression for setting the Host header value. * Refactor variable name * [skip ci] Fix comment
1 parent 617c874 commit fda06ee

File tree

2 files changed

+64
-8
lines changed

2 files changed

+64
-8
lines changed

src/plugins/console/server/lib/proxy_request.test.ts

Lines changed: 56 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,6 @@ describe(`Console's send request`, () => {
3030
beforeEach(() => {
3131
sandbox = sinon.createSandbox();
3232
stub = sandbox.stub(http, 'request').callsFake(() => {
33-
fakeRequest = {
34-
abort: sinon.stub(),
35-
on() {},
36-
once() {},
37-
} as any;
3833
return fakeRequest;
3934
});
4035
});
@@ -45,6 +40,11 @@ describe(`Console's send request`, () => {
4540
});
4641

4742
it('correctly implements timeout and abort mechanism', async () => {
43+
fakeRequest = {
44+
abort: sinon.stub(),
45+
on() {},
46+
once() {},
47+
} as any;
4848
try {
4949
await proxyRequest({
5050
agent: null as any,
@@ -60,4 +60,55 @@ describe(`Console's send request`, () => {
6060
expect((fakeRequest.abort as sinon.SinonStub).calledOnce).toBe(true);
6161
}
6262
});
63+
64+
it('correctly sets the "host" header entry', async () => {
65+
fakeRequest = {
66+
abort: sinon.stub(),
67+
on() {},
68+
once(event: string, fn: any) {
69+
if (event === 'response') {
70+
return fn('done');
71+
}
72+
},
73+
} as any;
74+
75+
// Don't set a host header this time
76+
const result1 = await proxyRequest({
77+
agent: null as any,
78+
headers: {},
79+
method: 'get',
80+
payload: null as any,
81+
timeout: 30000,
82+
uri: new URL('http://noone.nowhere.none'),
83+
});
84+
85+
expect(result1).toEqual('done');
86+
87+
const [httpRequestOptions1] = stub.firstCall.args;
88+
89+
expect((httpRequestOptions1 as any).headers).toEqual({
90+
'content-type': 'application/json',
91+
host: 'noone.nowhere.none', // Defaults to the provided host name
92+
'transfer-encoding': 'chunked',
93+
});
94+
95+
// Set a host header
96+
const result2 = await proxyRequest({
97+
agent: null as any,
98+
headers: { Host: 'myhost' },
99+
method: 'get',
100+
payload: null as any,
101+
timeout: 30000,
102+
uri: new URL('http://noone.nowhere.none'),
103+
});
104+
105+
expect(result2).toEqual('done');
106+
107+
const [httpRequestOptions2] = stub.secondCall.args;
108+
expect((httpRequestOptions2 as any).headers).toEqual({
109+
'content-type': 'application/json',
110+
Host: 'myhost', // Uses provided host name
111+
'transfer-encoding': 'chunked',
112+
});
113+
});
63114
});

src/plugins/console/server/lib/proxy_request.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,19 +57,24 @@ export const proxyRequest = ({
5757
reject = rej;
5858
});
5959

60+
const finalUserHeaders = { ...headers };
61+
const hasHostHeader = Object.keys(finalUserHeaders).some(key => key.toLowerCase() === 'host');
62+
if (!hasHostHeader) {
63+
finalUserHeaders.host = hostname;
64+
}
65+
6066
const req = client.request({
6167
method: method.toUpperCase(),
6268
// We support overriding this on a per request basis to support legacy proxy config. See ./proxy_config.
6369
rejectUnauthorized: typeof rejectUnauthorized === 'boolean' ? rejectUnauthorized : undefined,
6470
host: hostname,
65-
port: port === '' ? undefined : Number(port),
71+
port: port === '' ? undefined : parseInt(port, 10),
6672
protocol,
6773
path: `${pathname}${search || ''}`,
6874
headers: {
69-
...headers,
75+
...finalUserHeaders,
7076
'content-type': 'application/json',
7177
'transfer-encoding': 'chunked',
72-
host: hostname,
7378
},
7479
agent,
7580
});

0 commit comments

Comments
 (0)