Repository: unjs/h3
Pull request #455 (2023-07-24 16:52:12)

feat(event): support `event.url`
<!---
☝️ PR title should follow conventional commits (https://conventionalcommits.org) 
-->

### 🔗 Linked issue

Related / Needed by #454

### ❓ 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

This adds `event.url` with a lazy initializer to access the request URL. 

By default, we use `getRequestURL` with default options (trusts `x-forwarded-proto` as a boolean and ignores `x-forwarded-host`)

### 📝 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! -->

- [ ] I have linked an issue or discussion.
- [ ] I have updated the documentation accordingly.


codecov[bot]: ## [Codecov](https://app.codecov.io/gh/unjs/h3/pull/455?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=unjs) Report
> Merging [#455](https://app.codecov.io/gh/unjs/h3/pull/455?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=unjs) (f086c69) into [main](https://app.codecov.io/gh/unjs/h3/commit/27a1bd098f1a417034220301478f5c022ad47bb1?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=unjs) (27a1bd0) will **increase** coverage by `0.17%`.
> The diff coverage is `96.22%`.

```diff
@@            Coverage Diff             @@
##             main     #455      +/-   ##
==========================================
+ Coverage   77.76%   77.93%   +0.17%     
==========================================
  Files          26       26              
  Lines        2698     2724      +26     
  Branches      399      395       -4     
==========================================
+ Hits         2098     2123      +25     
- Misses        600      601       +1     
```


| [Impacted Files](https://app.codecov.io/gh/unjs/h3/pull/455?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=unjs) | Coverage Δ | |
|---|---|---|
| [src/utils/request.ts](https://app.codecov.io/gh/unjs/h3/pull/455?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=unjs#diff-c3JjL3V0aWxzL3JlcXVlc3QudHM=) | `98.44% <75.00%> (-1.56%)` | :arrow_down: |
| [src/event/event.ts](https://app.codecov.io/gh/unjs/h3/pull/455?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=unjs#diff-c3JjL2V2ZW50L2V2ZW50LnRz) | `68.12% <95.83%> (+5.80%)` | :arrow_up: |
| [src/app.ts](https://app.codecov.io/gh/unjs/h3/pull/455?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=unjs#diff-c3JjL2FwcC50cw==) | `97.68% <100.00%> (+0.05%)` | :arrow_up: |
| [src/router.ts](https://app.codecov.io/gh/unjs/h3/pull/455?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=unjs#diff-c3JjL3JvdXRlci50cw==) | `98.47% <100.00%> (-0.03%)` | :arrow_down: |
| [src/utils/route.ts](https://app.codecov.io/gh/unjs/h3/pull/455?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=unjs#diff-c3JjL3V0aWxzL3JvdXRlLnRz) | `89.47% <100.00%> (+1.97%)` | :arrow_up: |



Patch:
diff --git a/src/event/event.ts b/src/event/event.ts
index fde7c76..dc4e949 100644
--- a/src/event/event.ts
+++ b/src/event/event.ts
@@ -1,7 +1,12 @@
 import type { IncomingHttpHeaders } from "node:http";
 import type { H3EventContext, HTTPMethod } from "../types";
 import type { NodeIncomingMessage, NodeServerResponse } from "../node";
-import { MIMES, sanitizeStatusCode, sanitizeStatusMessage } from "../utils";
+import {
+  MIMES,
+  getRequestURL,
+  sanitizeStatusCode,
+  sanitizeStatusMessage,
+} from "../utils";
 import { H3Response } from "./response";
 
 const DOUBLE_SLASH_RE = /[/\\]{2,}/g; // TODO: Dedup from request.ts
@@ -22,6 +27,7 @@ export class H3Event implements Pick<FetchEvent, "respondWith"> {
   _method: HTTPMethod | undefined;
   _headers: Headers | undefined;
   _path: string | undefined;
+  _url: URL | undefined;
 
   // Response
   _handled = false;
@@ -45,6 +51,13 @@ export class H3Event implements Pick<FetchEvent, "respondWith"> {
     return this._path;
   }
 
+  get url() {
+    if (!this._url) {
+      this._url = getRequestURL(this);
+    }
+    return this._url;
+  }
+
   get handled(): boolean {
     return (
       this._handled || this.node.res.writableEnded || this.node.res.headersSent
diff --git a/src/utils/request.ts b/src/utils/request.ts
index cbeac3d..cc28186 100644
--- a/src/utils/request.ts
+++ b/src/utils/request.ts
@@ -124,6 +124,6 @@ export function getRequestURL(
 ) {
   const host = getRequestHost(event, opts);
   const protocol = getRequestProtocol(event);
-  const path = getRequestPath(event);
+  const path = event.path;
   return new URL(path, `${protocol}://${host}`);
 }


Test patch:
diff --git a/test/event.test.ts b/test/event.test.ts
index ce2bab0..ac48cdd 100644
--- a/test/event.test.ts
+++ b/test/event.test.ts
@@ -49,4 +49,15 @@ describe("Event", () => {
     expect(headers.find(([key]) => key === "x-test")[1]).toBe("works");
     expect(headers.find(([key]) => key === "cookie")[1]).toBe("a; b");
   });
+
+  it("can get request url", async () => {
+    app.use(
+      "/",
+      eventHandler((event) => {
+        return event.url;
+      })
+    );
+    const result = await request.get("/hello");
+    expect(result.text).toMatch(/http:\/\/127.0.0.1:\d+\/hello/);
+  });
 });