fix: recognize 'undefined' header value in ClientRequest (#41615)

Co-authored-by: zowu <luke.wu@nokia-sbell.com>
This commit is contained in:
daihere1993 2024-03-28 07:46:07 +08:00 committed by GitHub
parent 08241669bc
commit 72c2b9e862
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 37 additions and 18 deletions

View file

@ -209,6 +209,22 @@ type ExtraURLLoaderOptions = {
headers: Record<string, { name: string, value: string | string[] }>; headers: Record<string, { name: string, value: string | string[] }>;
allowNonHttpProtocols: boolean; allowNonHttpProtocols: boolean;
} }
function validateHeader (name: any, value: any): void {
if (typeof name !== 'string') {
throw new TypeError('`name` should be a string in setHeader(name, value)');
}
if (value == null) {
throw new Error('`value` required in setHeader("' + name + '", value)');
}
if (!isValidHeaderName(name)) {
throw new Error(`Invalid header name: '${name}'`);
}
if (!isValidHeaderValue(value.toString())) {
throw new Error(`Invalid value for header '${name}': '${value}'`);
}
}
function parseOptions (optionsIn: ClientRequestConstructorOptions | string): NodeJS.CreateURLLoaderOptions & ExtraURLLoaderOptions { function parseOptions (optionsIn: ClientRequestConstructorOptions | string): NodeJS.CreateURLLoaderOptions & ExtraURLLoaderOptions {
// eslint-disable-next-line node/no-deprecated-api // eslint-disable-next-line node/no-deprecated-api
const options: any = typeof optionsIn === 'string' ? url.parse(optionsIn) : { ...optionsIn }; const options: any = typeof optionsIn === 'string' ? url.parse(optionsIn) : { ...optionsIn };
@ -275,12 +291,7 @@ function parseOptions (optionsIn: ClientRequestConstructorOptions | string): Nod
}; };
const headers: Record<string, string | string[]> = options.headers || {}; const headers: Record<string, string | string[]> = options.headers || {};
for (const [name, value] of Object.entries(headers)) { for (const [name, value] of Object.entries(headers)) {
if (!isValidHeaderName(name)) { validateHeader(name, value);
throw new Error(`Invalid header name: '${name}'`);
}
if (!isValidHeaderValue(value.toString())) {
throw new Error(`Invalid value for header '${name}': '${value}'`);
}
const key = name.toLowerCase(); const key = name.toLowerCase();
urlLoaderOptions.headers[key] = { name, value }; urlLoaderOptions.headers[key] = { name, value };
} }
@ -351,21 +362,10 @@ export class ClientRequest extends Writable implements Electron.ClientRequest {
} }
setHeader (name: string, value: string) { setHeader (name: string, value: string) {
if (typeof name !== 'string') {
throw new TypeError('`name` should be a string in setHeader(name, value)');
}
if (value == null) {
throw new Error('`value` required in setHeader("' + name + '", value)');
}
if (this._started || this._firstWrite) { if (this._started || this._firstWrite) {
throw new Error('Can\'t set headers after they are sent'); throw new Error('Can\'t set headers after they are sent');
} }
if (!isValidHeaderName(name)) { validateHeader(name, value);
throw new Error(`Invalid header name: '${name}'`);
}
if (!isValidHeaderValue(value.toString())) {
throw new Error(`Invalid value for header '${name}': '${value}'`);
}
const key = name.toLowerCase(); const key = name.toLowerCase();
this._urlLoaderOptions.headers[key] = { name, value }; this._urlLoaderOptions.headers[key] = { name, value };

View file

@ -616,6 +616,25 @@ describe('net module (session)', () => {
}); });
}).to.throw('`partition` should be a string'); }).to.throw('`partition` should be a string');
}); });
it('should throw if given a header value that is empty(null/undefined)', () => {
const emptyHeaderValues = [null, undefined];
const errorMsg = '`value` required in setHeader("foo", value)';
for (const emptyValue of emptyHeaderValues) {
expect(() => {
net.request({
url: 'https://foo',
headers: { foo: emptyValue as any }
} as any);
}).to.throw(errorMsg);
const request = net.request({ url: 'https://foo' });
expect(() => {
request.setHeader('foo', emptyValue as any);
}).to.throw(errorMsg);
}
});
}); });
describe('net.fetch', () => { describe('net.fetch', () => {