Browse Source

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

Co-authored-by: zowu <[email protected]>
daihere1993 1 year ago
parent
commit
72c2b9e862
2 changed files with 37 additions and 18 deletions
  1. 18 18
      lib/common/api/net-client-request.ts
  2. 19 0
      spec/api-net-session-spec.ts

+ 18 - 18
lib/common/api/net-client-request.ts

@@ -209,6 +209,22 @@ type ExtraURLLoaderOptions = {
    headers: Record<string, { name: string, value: string | string[] }>;
    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 {
   // eslint-disable-next-line node/no-deprecated-api
   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 || {};
   for (const [name, value] of Object.entries(headers)) {
-    if (!isValidHeaderName(name)) {
-      throw new Error(`Invalid header name: '${name}'`);
-    }
-    if (!isValidHeaderValue(value.toString())) {
-      throw new Error(`Invalid value for header '${name}': '${value}'`);
-    }
+    validateHeader(name, value);
     const key = name.toLowerCase();
     urlLoaderOptions.headers[key] = { name, value };
   }
@@ -351,21 +362,10 @@ export class ClientRequest extends Writable implements Electron.ClientRequest {
   }
 
   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) {
       throw new Error('Can\'t set headers after they are sent');
     }
-    if (!isValidHeaderName(name)) {
-      throw new Error(`Invalid header name: '${name}'`);
-    }
-    if (!isValidHeaderValue(value.toString())) {
-      throw new Error(`Invalid value for header '${name}': '${value}'`);
-    }
+    validateHeader(name, value);
 
     const key = name.toLowerCase();
     this._urlLoaderOptions.headers[key] = { name, value };

+ 19 - 0
spec/api-net-session-spec.ts

@@ -616,6 +616,25 @@ describe('net module (session)', () => {
         });
       }).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', () => {