Repository: unjs/h3
Pull request #427 (2023-07-06 14:13:45)

feat: add `removeResponseHeader` and `clearResponseHeaders` utils
- feat: add request and response helpers
- feat: add url utilities

<!---
☝️ PR title should follow conventional commits (https://conventionalcommits.org) 
-->

### 🔗 Linked issue

#420 
#423

<!-- Please ensure there is an open issue and mention its number as #123 -->

### ❓ Type of change

<!-- What types of changes does your code introduce? Put an `x` in all the boxes that apply. -->

- [ ] 📖 Documentation (updates to the documentation, readme, or JSdoc annotations)
- [ ] 🐞 Bug fix (a non-breaking change that fixes an issue)
- [ ] 👌 Enhancement (improving an existing functionality like performance)
- [x] ✨ New feature (a non-breaking change that adds functionality)
- [ ] 🧹 Chore (updates to the build process or auxiliary tools and libraries)
- [ ] ⚠️ Breaking change (fix or feature that would cause existing functionality to change)

### 📚 Description

<!-- Describe your changes in detail -->
<!-- Why is this change required? What problem does it solve? -->
<!-- If it resolves an open issue, please link to the issue here. For example "Resolves #1337" -->

This adds 7 new helpers. 

### 📝 Checklist

<!-- Put an `x` in all the boxes that apply. -->
<!-- If your change requires a documentation PR, please link it appropriately -->
<!-- If you're unsure about any of these, don't hesitate to ask. We're here to help! -->

- [x] I have linked an issue or discussion.
- [ ] I have updated the documentation accordingly.


codecov[bot]: ## [Codecov](https://app.codecov.io/gh/unjs/h3/pull/427?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=unjs) Report
> Merging [#427](https://app.codecov.io/gh/unjs/h3/pull/427?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=unjs) (99ece01) into [main](https://app.codecov.io/gh/unjs/h3/commit/78aec63c2823e45f28cb84c66baacff2ab299483?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=unjs) (78aec63) will **decrease** coverage by `1.33%`.
> The diff coverage is `47.36%`.

> :exclamation: Current head 99ece01 differs from pull request most recent head fbc7501. Consider uploading reports for the commit fbc7501 to get more accurate results

```diff
@@            Coverage Diff             @@
##             main     #427      +/-   ##
==========================================
- Coverage   78.37%   77.04%   -1.33%     
==========================================
  Files          26       26              
  Lines        2793     2636     -157     
  Branches      407      376      -31     
==========================================
- Hits         2189     2031     -158     
- Misses        604      605       +1     
```


| [Files Changed](https://app.codecov.io/gh/unjs/h3/pull/427?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=unjs) | Coverage Δ | |
|---|---|---|
| [src/utils/response.ts](https://app.codecov.io/gh/unjs/h3/pull/427?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=unjs#diff-c3JjL3V0aWxzL3Jlc3BvbnNlLnRz) | `67.84% <45.45%> (-1.90%)` | :arrow_down: |
| [src/utils/request.ts](https://app.codecov.io/gh/unjs/h3/pull/427?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=unjs#diff-c3JjL3V0aWxzL3JlcXVlc3QudHM=) | `97.12% <50.00%> (-1.33%)` | :arrow_down: |

... and [7 files with indirect coverage changes](https://app.codecov.io/gh/unjs/h3/pull/427/indirect-changes?src=pr&el=tree-more&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=unjs)



Patch:
diff --git a/src/utils/response.ts b/src/utils/response.ts
index b82aae2..8a0ed7f 100644
--- a/src/utils/response.ts
+++ b/src/utils/response.ts
@@ -148,6 +148,30 @@ export function appendResponseHeader(
 
 export const appendHeader = appendResponseHeader;
 
+/**
+ * Remove all response headers, or only those specified in the headerNames array.
+ * @param event H3 event
+ * @param headerNames Array of header names to remove
+ */
+export function clearResponseHeaders(
+  event: H3Event,
+  headerNames?: string[]
+): void {
+  if (headerNames && headerNames.length > 0) {
+    for (const name of headerNames) {
+      removeResponseHeader(event, name);
+    }
+  } else {
+    for (const [name] of Object.entries(getResponseHeaders(event))) {
+      removeResponseHeader(event, name);
+    }
+  }
+}
+
+export function removeResponseHeader(event: H3Event, name: string): void {
+  return event.node.res.removeHeader(name);
+}
+
 export function isStream(data: any): data is Readable | ReadableStream {
   if (!data || typeof data !== "object") {
     return false;


Test patch:
diff --git a/test/header.test.ts b/test/header.test.ts
index b78dd88..c6f31a5 100644
--- a/test/header.test.ts
+++ b/test/header.test.ts
@@ -17,6 +17,8 @@ import {
   appendHeader,
   toNodeListener,
   eventHandler,
+  removeResponseHeader,
+  clearResponseHeaders,
 } from "../src";
 
 describe("", () => {
@@ -267,4 +269,50 @@ describe("", () => {
       expect(result.headers["nuxt-http-header"]).toEqual("value 1, value 2");
     });
   });
+
+  describe("clearResponseHeaders", () => {
+    it("can remove all response headers", async () => {
+      app.use(
+        "/",
+        eventHandler((event) => {
+          appendHeader(event, "header-1", "1");
+          appendHeader(event, "header-2", "2");
+          clearResponseHeaders(event);
+        })
+      );
+      const result = await request.get("/");
+      expect(result.headers["header-1"]).toBeUndefined();
+      expect(result.headers["header-2"]).toBeUndefined();
+    });
+
+    it("can remove multiple response headers", async () => {
+      app.use(
+        "/",
+        eventHandler((event) => {
+          appendHeader(event, "header-3", "3");
+          appendHeader(event, "header-4", "4");
+          appendHeader(event, "header-5", "5");
+          clearResponseHeaders(event, ["header-3", "header-5"]);
+        })
+      );
+      const result = await request.get("/");
+      expect(result.headers["header-3"]).toBeUndefined();
+      expect(result.headers["header-4"]).toBe("4");
+      expect(result.headers["header-5"]).toBeUndefined();
+    });
+
+    it("can remove a single response header", async () => {
+      app.use(
+        "/",
+        eventHandler((event) => {
+          appendHeader(event, "header-6", "6");
+          appendHeader(event, "header-7", "7");
+          removeResponseHeader(event, "header-6");
+        })
+      );
+      const result = await request.get("/");
+      expect(result.headers["header-6"]).toBeUndefined();
+      expect(result.headers["header-7"]).toBe("7");
+    });
+  });
 });