From 2574ae287e4cbe070b8471973437b0cb26074047 Mon Sep 17 00:00:00 2001
From: tsctx <91457664+tsctx@users.noreply.github.com>
Date: Fri, 3 May 2024 07:26:40 +0900
Subject: [PATCH 1/2] refactor: code cleanup

---
 docs/docs/api/Util.md     |  4 ++--
 lib/web/fetch/index.js    | 24 ++++++++++--------------
 test/client-request.js    |  8 +-------
 test/request-timeout.js   |  1 -
 test/types/util.test-d.ts | 13 -------------
 types/util.d.ts           | 21 ++++-----------------
 6 files changed, 17 insertions(+), 54 deletions(-)

diff --git a/docs/docs/api/Util.md b/docs/docs/api/Util.md
index 2393d079dfc..53b96e3ed3f 100644
--- a/docs/docs/api/Util.md
+++ b/docs/docs/api/Util.md
@@ -8,11 +8,11 @@ Receives a header object and returns the parsed value.
 
 Arguments:
 
-- **headers** `Record<string, string | string[]> | (Buffer | string | (Buffer | string)[])[]` (required) - Header object.
+- **headers** `(Buffer | string | (Buffer | string)[])[]` (required) - Header object.
 
 - **obj** `Record<string, string | string[]>` (optional) - Object to specify a proxy object. The parsed value is assigned to this object. But, if **headers** is an object, it is not used.
 
-Returns: `Record<string, string | string[]>` If **headers** is an object, it is **headers**. Otherwise, if **obj** is specified, it is equivalent to **obj**.
+Returns: `Record<string, string | string[]>` If **obj** is specified, it is equivalent to **obj**.
 
 ## `headerNameToString(value)`
 
diff --git a/lib/web/fetch/index.js b/lib/web/fetch/index.js
index 82ccb26865c..e7e7acfb0ea 100644
--- a/lib/web/fetch/index.js
+++ b/lib/web/fetch/index.js
@@ -2102,20 +2102,16 @@ async function httpNetworkFetch (
 
           const headersList = new HeadersList()
 
-          // For H2, the rawHeaders are a plain JS object
-          // We distinguish between them and iterate accordingly
-          if (Array.isArray(rawHeaders)) {
-            for (let i = 0; i < rawHeaders.length; i += 2) {
-              headersList.append(bufferToLowerCasedHeaderName(rawHeaders[i]), rawHeaders[i + 1].toString('latin1'), true)
-            }
-            const contentEncoding = headersList.get('content-encoding', true)
-            if (contentEncoding) {
-              // https://www.rfc-editor.org/rfc/rfc7231#section-3.1.2.1
-              // "All content-coding values are case-insensitive..."
-              codings = contentEncoding.toLowerCase().split(',').map((x) => x.trim())
-            }
-            location = headersList.get('location', true)
+          for (let i = 0; i < rawHeaders.length; i += 2) {
+            headersList.append(bufferToLowerCasedHeaderName(rawHeaders[i]), rawHeaders[i + 1].toString('latin1'), true)
+          }
+          const contentEncoding = headersList.get('content-encoding', true)
+          if (contentEncoding) {
+            // https://www.rfc-editor.org/rfc/rfc7231#section-3.1.2.1
+            // "All content-coding values are case-insensitive..."
+            codings = contentEncoding.toLowerCase().split(',').map((x) => x.trim())
           }
+          location = headersList.get('location', true)
 
           this.body = new Readable({ read: resume })
 
@@ -2125,7 +2121,7 @@ async function httpNetworkFetch (
             redirectStatusSet.has(status)
 
           // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Encoding
-          if (request.method !== 'HEAD' && request.method !== 'CONNECT' && !nullBodyStatus.includes(status) && !willFollow) {
+          if (codings.length !== 0 && request.method !== 'HEAD' && request.method !== 'CONNECT' && !nullBodyStatus.includes(status) && !willFollow) {
             for (let i = 0; i < codings.length; ++i) {
               const coding = codings[i]
               // https://www.rfc-editor.org/rfc/rfc9112.html#section-7.2
diff --git a/test/client-request.js b/test/client-request.js
index 4071b484c50..2bd38201a72 100644
--- a/test/client-request.js
+++ b/test/client-request.js
@@ -98,13 +98,7 @@ test('request dump with abort signal', async (t) => {
       method: 'GET'
     }, (err, { body }) => {
       t.ifError(err)
-      let ac
-      if (!global.AbortController) {
-        const { AbortController } = require('abort-controller')
-        ac = new AbortController()
-      } else {
-        ac = new AbortController()
-      }
+      const ac = new AbortController()
       body.dump({ signal: ac.signal }).catch((err) => {
         t.strictEqual(err.name, 'AbortError')
         server.close()
diff --git a/test/request-timeout.js b/test/request-timeout.js
index 03d34c9bef5..6d90c437041 100644
--- a/test/request-timeout.js
+++ b/test/request-timeout.js
@@ -9,7 +9,6 @@ const timers = require('../lib/util/timers')
 const { createServer } = require('node:http')
 const EventEmitter = require('node:events')
 const FakeTimers = require('@sinonjs/fake-timers')
-const { AbortController } = require('abort-controller')
 const {
   pipeline,
   Readable,
diff --git a/test/types/util.test-d.ts b/test/types/util.test-d.ts
index 9879fd31507..1dd59d84108 100644
--- a/test/types/util.test-d.ts
+++ b/test/types/util.test-d.ts
@@ -1,19 +1,6 @@
 import { expectAssignable } from 'tsd';
 import { util } from '../../types/util';
 
-expectAssignable<Record<string, string | string[]>>(
-  util.parseHeaders({ 'content-type': 'text/plain' })
-);
-
-expectAssignable<Record<string, string | string[]>>(
-  //@ts-ignore
-  util.parseHeaders({ 'content-type': 'text/plain' }, {})
-);
-
-expectAssignable<Record<string, string | string[]>>(
-  util.parseHeaders({} as Record<string, string> | string[], {})
-);
-
 expectAssignable<Record<string, string | string[]>>(
   util.parseHeaders(['content-type', 'text/plain'])
 );
diff --git a/types/util.d.ts b/types/util.d.ts
index 2a604148fd8..77cf1473a24 100644
--- a/types/util.d.ts
+++ b/types/util.d.ts
@@ -8,24 +8,11 @@ export namespace util {
   /**
    * Receives a header object and returns the parsed value.
    * @param headers Header object
+   * @param obj Object to specify a proxy object. Used to assign parsed values.
+   * @returns If `obj` is specified, it is equivalent to `obj`.
    */
   export function parseHeaders(
-    headers:
-      | Record<string, string | string[]>
-      | (Buffer | string | (Buffer | string)[])[]
-  ): Record<string, string | string[]>;
-  /**
-   * Receives a header object and returns the parsed value.
-   * @param headers Header object
-   * @param obj Object to specify a proxy object. Used to assign parsed values. But, if `headers` is an object, it is not used.
-   * @returns If `headers` is an object, it is `headers`. Otherwise, if `obj` is specified, it is equivalent to `obj`.
-   */
-  export function parseHeaders<
-    H extends
-      | Record<string, string | string[]>
-      | (Buffer | string | (Buffer | string)[])[]
-  >(
-    headers: H,
-    obj?: H extends any[] ? Record<string, string | string[]> : never
+    headers: (Buffer | string | (Buffer | string)[])[],
+    obj?: Record<string, string | string[]>
   ): Record<string, string | string[]>;
 }

From cc8a875e25a5eee47cc49037c7e7c030cdcd5017 Mon Sep 17 00:00:00 2001
From: tsctx <91457664+tsctx@users.noreply.github.com>
Date: Fri, 3 May 2024 07:30:11 +0900
Subject: [PATCH 2/2] fixup

---
 test/request-timeout.js | 1 +
 1 file changed, 1 insertion(+)

diff --git a/test/request-timeout.js b/test/request-timeout.js
index 6d90c437041..03d34c9bef5 100644
--- a/test/request-timeout.js
+++ b/test/request-timeout.js
@@ -9,6 +9,7 @@ const timers = require('../lib/util/timers')
 const { createServer } = require('node:http')
 const EventEmitter = require('node:events')
 const FakeTimers = require('@sinonjs/fake-timers')
+const { AbortController } = require('abort-controller')
 const {
   pipeline,
   Readable,
