veryfront 0.1.121 → 0.1.124

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/esm/deno.js CHANGED
@@ -1,6 +1,6 @@
1
1
  export default {
2
2
  "name": "veryfront",
3
- "version": "0.1.121",
3
+ "version": "0.1.124",
4
4
  "license": "Apache-2.0",
5
5
  "nodeModulesDir": "auto",
6
6
  "exclude": [
@@ -12,8 +12,8 @@ export function generateNonce() {
12
12
  /**
13
13
  * Build a default CSP that works for typical veryfront apps.
14
14
  *
15
- * - Scripts: nonce-based + cdn.jsdelivr.net (Scalar API docs, html2canvas,
16
- * React UMD, browser inference)
15
+ * - Scripts: nonce-based + cdn.jsdelivr.net + esm.sh (Scalar API docs,
16
+ * html2canvas, legacy/browser ESM hydration)
17
17
  * - Styles: 'self' + 'unsafe-inline' + nonce + Google Fonts + cdn.veryfront.com
18
18
  * plus style-src-attr 'unsafe-inline' so React style="" attributes remain
19
19
  * compatible while inline <style> tags continue to use the nonce
@@ -28,7 +28,7 @@ export function generateNonce() {
28
28
  function buildDefaultCSP(nonce) {
29
29
  return [
30
30
  `default-src 'self'`,
31
- `script-src 'self' 'nonce-${nonce}' https://cdn.jsdelivr.net`,
31
+ `script-src 'self' 'nonce-${nonce}' https://cdn.jsdelivr.net https://esm.sh`,
32
32
  `style-src 'self' 'unsafe-inline' 'nonce-${nonce}' https://fonts.googleapis.com https://cdn.veryfront.com`,
33
33
  `style-src-attr 'unsafe-inline'`,
34
34
  `img-src 'self' data: https:`,
@@ -1 +1 @@
1
- {"version":3,"file":"request-context.d.ts","sourceRoot":"","sources":["../../../../src/src/server/context/request-context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,OAAO,MAAM,wBAAwB,CAAC;AAIlD,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,IAAI,EAAE,SAAS,GAAG,YAAY,CAAC;CAChC;AAED,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,OAAO,CAAC,OAAO,GAAG,cAAc,CA+BzE;AAED,wBAAgB,gBAAgB,CAC9B,GAAG,EAAE,cAAc,EACnB,cAAc,CAAC,EAAE,OAAO,GACvB,MAAM,GAAG,YAAY,GAAG,WAAW,CAIrC;AAED,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,cAAc,EAAE,cAAc,CAAC,EAAE,OAAO,GAAG,OAAO,CAExF;AAED,wBAAgB,uBAAuB,CAAC,GAAG,CAAC,EAAE,cAAc,EAAE,cAAc,CAAC,EAAE,OAAO,GAAG,OAAO,CAG/F"}
1
+ {"version":3,"file":"request-context.d.ts","sourceRoot":"","sources":["../../../../src/src/server/context/request-context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,OAAO,MAAM,wBAAwB,CAAC;AAKlD,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,IAAI,EAAE,SAAS,GAAG,YAAY,CAAC;CAChC;AAED,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,OAAO,CAAC,OAAO,GAAG,cAAc,CAqBzE;AAED,wBAAgB,gBAAgB,CAC9B,GAAG,EAAE,cAAc,EACnB,cAAc,CAAC,EAAE,OAAO,GACvB,MAAM,GAAG,YAAY,GAAG,WAAW,CAIrC;AAED,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,cAAc,EAAE,cAAc,CAAC,EAAE,OAAO,GAAG,OAAO,CAExF;AAED,wBAAgB,uBAAuB,CAAC,GAAG,CAAC,EAAE,cAAc,EAAE,cAAc,CAAC,EAAE,OAAO,GAAG,OAAO,CAG/F"}
@@ -1,16 +1,8 @@
1
1
  import { getHostEnv } from "../../platform/compat/process.js";
2
2
  import { parseProjectDomain } from "../utils/domain-parser.js";
3
+ import { getEffectiveRequestHost } from "../utils/request-host.js";
3
4
  export function createRequestContext(req) {
4
- const { hostname } = new URL(req.url);
5
- const rawForwardedHost = req.headers.get("x-forwarded-host");
6
- // x-forwarded-host can be comma-separated (multiple proxies); take the first entry.
7
- const forwardedHost = rawForwardedHost
8
- ? (rawForwardedHost.split(",")[0]?.trim() || undefined)
9
- : undefined;
10
- const hostHeader = req.headers.get("host");
11
- // In proxy mode, req.url hostname may be 127.0.0.1 while the real domain
12
- // is in the Host header (e.g., "flow-ops.lvh.me:3010"). Prefer Host header.
13
- const effectiveHost = forwardedHost ?? hostHeader ?? hostname;
5
+ const effectiveHost = getEffectiveRequestHost(req);
14
6
  const parsed = parseProjectDomain(effectiveHost);
15
7
  const headerProjectSlug = req.headers.get("x-project-slug")?.trim() || undefined;
16
8
  const xEnvironment = req.headers.get("x-environment");
@@ -1 +1 @@
1
- {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../../../../../src/src/server/handlers/dev/projects/api.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,OAAO,MAAM,8BAA8B,CAAC;AACxD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAWrD,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,OAAO,CAAC,OAAO,EAAE,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAOpG"}
1
+ {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../../../../../src/src/server/handlers/dev/projects/api.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,OAAO,MAAM,8BAA8B,CAAC;AACxD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAYrD,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,OAAO,CAAC,OAAO,EAAE,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAOpG"}
@@ -1,4 +1,5 @@
1
1
  import * as dntShim from "../../../../../_dnt.shims.js";
2
+ import { getEffectiveRequestHost } from "../../../utils/request-host.js";
2
3
  const JSON_HEADERS = {
3
4
  "Content-Type": "application/json",
4
5
  "Cache-Control": "no-cache",
@@ -16,10 +17,7 @@ export function handleProjectsAPI(req, ctx) {
16
17
  }
17
18
  function handleGetConfig(req, ctx) {
18
19
  const url = new URL(req.url);
19
- const host = req.headers.get("x-forwarded-host") ??
20
- req.headers.get("host") ??
21
- url.host ??
22
- "lvh.me";
20
+ const host = getEffectiveRequestHost(req, url) || "lvh.me";
23
21
  const hostWithoutPort = host.replace(/:\d+$/, "") || "lvh.me";
24
22
  const port = host.includes(":") ? host.split(":")[1] ?? "" : "";
25
23
  return jsonResponse({
@@ -1 +1 @@
1
- {"version":3,"file":"hmr.handler.d.ts","sourceRoot":"","sources":["../../../../../src/src/server/handlers/preview/hmr.handler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,OAAO,MAAM,2BAA2B,CAAC;AASrD,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,EACL,KAAK,cAAc,EACnB,KAAK,eAAe,EAEpB,KAAK,aAAa,EACnB,MAAM,aAAa,CAAC;AAmBrB,YAAY,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAK7D,qBAAa,UAAW,SAAQ,WAAW;IACzC,OAAO,CAAC,MAAM,CAAC,WAAW,CAAgD;IAC1E,OAAO,CAAC,MAAM,CAAC,iBAAiB,CAA6B;IAC7D,OAAO,CAAC,MAAM,CAAC,4BAA4B,CAAK;IAChD,OAAO,CAAC,MAAM,CAAC,WAAW,CAAS;IAEnC,QAAQ,EAAE,eAAe,CAKvB;IAEF,OAAO,CAAC,MAAM,CAAC,UAAU;IAsCzB,MAAM,CAAC,GAAG,EAAE,OAAO,CAAC,OAAO,EAAE,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC;IA0JzE;;;;;OAKG;YACW,wBAAwB;IAuCtC,MAAM,CAAC,cAAc,IAAI,MAAM;IAI/B,MAAM,CAAC,UAAU,IAAI;QACnB,OAAO,EAAE,MAAM,CAAC;QAChB,cAAc,EAAE,MAAM,CAAC;QACvB,iBAAiB,EAAE,MAAM,CAAC;QAC1B,iBAAiB,EAAE,MAAM,CAAC;KAC3B;IAID,MAAM,CAAC,+BAA+B,IAAI,MAAM,IAAI;IAWpD,MAAM,CAAC,QAAQ,IAAI,IAAI;IAcvB,OAAO,CAAC,MAAM,CAAC,cAAc;CAO9B"}
1
+ {"version":3,"file":"hmr.handler.d.ts","sourceRoot":"","sources":["../../../../../src/src/server/handlers/preview/hmr.handler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,OAAO,MAAM,2BAA2B,CAAC;AASrD,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,EACL,KAAK,cAAc,EACnB,KAAK,eAAe,EAEpB,KAAK,aAAa,EACnB,MAAM,aAAa,CAAC;AAoBrB,YAAY,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAK7D,qBAAa,UAAW,SAAQ,WAAW;IACzC,OAAO,CAAC,MAAM,CAAC,WAAW,CAAgD;IAC1E,OAAO,CAAC,MAAM,CAAC,iBAAiB,CAA6B;IAC7D,OAAO,CAAC,MAAM,CAAC,4BAA4B,CAAK;IAChD,OAAO,CAAC,MAAM,CAAC,WAAW,CAAS;IAEnC,QAAQ,EAAE,eAAe,CAKvB;IAEF,OAAO,CAAC,MAAM,CAAC,UAAU;IAsCzB,MAAM,CAAC,GAAG,EAAE,OAAO,CAAC,OAAO,EAAE,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC;IA0JzE;;;;;OAKG;YACW,wBAAwB;IAuCtC,MAAM,CAAC,cAAc,IAAI,MAAM;IAI/B,MAAM,CAAC,UAAU,IAAI;QACnB,OAAO,EAAE,MAAM,CAAC;QAChB,cAAc,EAAE,MAAM,CAAC;QACvB,iBAAiB,EAAE,MAAM,CAAC;QAC1B,iBAAiB,EAAE,MAAM,CAAC;KAC3B;IAID,MAAM,CAAC,+BAA+B,IAAI,MAAM,IAAI;IAWpD,MAAM,CAAC,QAAQ,IAAI,IAAI;IAcvB,OAAO,CAAC,MAAM,CAAC,cAAc;CAO9B"}
@@ -10,6 +10,7 @@ import { isLocalDevHost } from "../../utils/domain-parser.js";
10
10
  import { addClient, clearAll, getClient, getClientCount, getClientDetails, removeClient, } from "./hmr-client-manager.js";
11
11
  import { getPingIntervalMs, startPingInterval, stopPingInterval } from "./hmr-ping-keepalive.js";
12
12
  import { broadcastUpdate, getMetrics } from "./hmr-message-router.js";
13
+ import { getEffectiveRequestHost } from "../../utils/request-host.js";
13
14
  const logger = serverLogger.component("hmr-handler");
14
15
  // Priority between auth (0) and high (100)
15
16
  const PRIORITY_HMR = HandlerPriority.EARLY;
@@ -62,7 +63,7 @@ export class HMRHandler extends BaseHandler {
62
63
  const queryEnv = url.searchParams.get("x-environment");
63
64
  const isPreviewMode = ctx.requestContext?.mode === "preview" || queryEnv === "preview";
64
65
  const isLocal = !!ctx.isLocalProject;
65
- const host = req.headers.get("host") ?? "";
66
+ const host = getEffectiveRequestHost(req, url);
66
67
  const isLocalhost = isLocalDevHost(host);
67
68
  if (!isPreviewMode && !isLocal && !isLocalhost) {
68
69
  logger.warn("Skipping /_ws - not preview, local dev, or localhost", {
@@ -1 +1 @@
1
- {"version":3,"file":"project-resolution.d.ts","sourceRoot":"","sources":["../../../../src/src/server/runtime-handler/project-resolution.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"project-resolution.d.ts","sourceRoot":"","sources":["../../../../src/src/server/runtime-handler/project-resolution.ts"],"names":[],"mappings":"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"}
@@ -4,6 +4,7 @@ import { getEnvironmentType, lookupProjectByDomain } from "../utils/domain-looku
4
4
  import { parseProxyEnvironment } from "./proxy-environment.js";
5
5
  import { SpanNames, withSpan } from "./tracing.js";
6
6
  import { isInternalHost } from "./request-utils.js";
7
+ import { getEffectiveRequestHost } from "../utils/request-host.js";
7
8
  const baseLogger = getBaseLogger("SERVER");
8
9
  const logger = baseLogger.component("project-resolution");
9
10
  let injectedDeps = null;
@@ -20,17 +21,8 @@ function getDeps() {
20
21
  getEnvironmentType: injectedDeps?.getEnvironmentType ?? getEnvironmentType,
21
22
  };
22
23
  }
23
- function parseForwardedHost(raw) {
24
- if (!raw)
25
- return undefined;
26
- // x-forwarded-host can be a comma-separated list when multiple proxies
27
- // are chained. Take the first (client-facing) entry and trim whitespace.
28
- const first = raw.split(",")[0]?.trim();
29
- return first || undefined;
30
- }
31
24
  function getEffectiveHost(req, url) {
32
- const forwardedHost = parseForwardedHost(req.headers.get("x-forwarded-host"));
33
- return forwardedHost ?? req.headers.get("host") ?? url.host;
25
+ return getEffectiveRequestHost(req, url);
34
26
  }
35
27
  /**
36
28
  * Extract project-related headers from a request.
@@ -0,0 +1,4 @@
1
+ import * as dntShim from "../../../_dnt.shims.js";
2
+ export declare function parseForwardedHost(raw: string | null): string | undefined;
3
+ export declare function getEffectiveRequestHost(req: dntShim.Request, url?: URL): string;
4
+ //# sourceMappingURL=request-host.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"request-host.d.ts","sourceRoot":"","sources":["../../../../src/src/server/utils/request-host.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,OAAO,MAAM,wBAAwB,CAAC;AAClD,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,GAAG,SAAS,CAKzE;AAED,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,EAAE,GAAG,GAAG,MAAM,CAI/E"}
@@ -0,0 +1,11 @@
1
+ export function parseForwardedHost(raw) {
2
+ if (!raw)
3
+ return undefined;
4
+ const first = raw.split(",")[0]?.trim();
5
+ return first || undefined;
6
+ }
7
+ export function getEffectiveRequestHost(req, url) {
8
+ return parseForwardedHost(req.headers.get("x-forwarded-host")) ??
9
+ req.headers.get("host") ??
10
+ (url ?? new URL(req.url)).host;
11
+ }
@@ -1,2 +1,2 @@
1
- export declare const VERSION = "0.1.121";
1
+ export declare const VERSION = "0.1.124";
2
2
  //# sourceMappingURL=version-constant.d.ts.map
@@ -1,3 +1,3 @@
1
1
  // Keep in sync with deno.json version.
2
2
  // scripts/release.ts updates this constant during releases.
3
- export const VERSION = "0.1.121";
3
+ export const VERSION = "0.1.124";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "veryfront",
3
- "version": "0.1.121",
3
+ "version": "0.1.124",
4
4
  "description": "The simplest way to build AI-powered apps",
5
5
  "keywords": [
6
6
  "react",
package/src/deno.js CHANGED
@@ -1,6 +1,6 @@
1
1
  export default {
2
2
  "name": "veryfront",
3
- "version": "0.1.121",
3
+ "version": "0.1.124",
4
4
  "license": "Apache-2.0",
5
5
  "nodeModulesDir": "auto",
6
6
  "exclude": [
@@ -18,8 +18,8 @@ export function generateNonce(): string {
18
18
  /**
19
19
  * Build a default CSP that works for typical veryfront apps.
20
20
  *
21
- * - Scripts: nonce-based + cdn.jsdelivr.net (Scalar API docs, html2canvas,
22
- * React UMD, browser inference)
21
+ * - Scripts: nonce-based + cdn.jsdelivr.net + esm.sh (Scalar API docs,
22
+ * html2canvas, legacy/browser ESM hydration)
23
23
  * - Styles: 'self' + 'unsafe-inline' + nonce + Google Fonts + cdn.veryfront.com
24
24
  * plus style-src-attr 'unsafe-inline' so React style="" attributes remain
25
25
  * compatible while inline <style> tags continue to use the nonce
@@ -34,7 +34,7 @@ export function generateNonce(): string {
34
34
  function buildDefaultCSP(nonce: string): string {
35
35
  return [
36
36
  `default-src 'self'`,
37
- `script-src 'self' 'nonce-${nonce}' https://cdn.jsdelivr.net`,
37
+ `script-src 'self' 'nonce-${nonce}' https://cdn.jsdelivr.net https://esm.sh`,
38
38
  `style-src 'self' 'unsafe-inline' 'nonce-${nonce}' https://fonts.googleapis.com https://cdn.veryfront.com`,
39
39
  `style-src-attr 'unsafe-inline'`,
40
40
  `img-src 'self' data: https:`,
@@ -1,6 +1,7 @@
1
1
  import * as dntShim from "../../../_dnt.shims.js";
2
2
  import { getHostEnv } from "../../platform/compat/process.js";
3
3
  import { parseProjectDomain } from "../utils/domain-parser.js";
4
+ import { getEffectiveRequestHost } from "../utils/request-host.js";
4
5
 
5
6
  export interface RequestContext {
6
7
  token: string;
@@ -10,17 +11,7 @@ export interface RequestContext {
10
11
  }
11
12
 
12
13
  export function createRequestContext(req: dntShim.Request): RequestContext {
13
- const { hostname } = new URL(req.url);
14
- const rawForwardedHost = req.headers.get("x-forwarded-host");
15
- // x-forwarded-host can be comma-separated (multiple proxies); take the first entry.
16
- const forwardedHost = rawForwardedHost
17
- ? (rawForwardedHost.split(",")[0]?.trim() || undefined)
18
- : undefined;
19
- const hostHeader = req.headers.get("host");
20
-
21
- // In proxy mode, req.url hostname may be 127.0.0.1 while the real domain
22
- // is in the Host header (e.g., "flow-ops.lvh.me:3010"). Prefer Host header.
23
- const effectiveHost = forwardedHost ?? hostHeader ?? hostname;
14
+ const effectiveHost = getEffectiveRequestHost(req);
24
15
  const parsed = parseProjectDomain(effectiveHost);
25
16
  const headerProjectSlug = req.headers.get("x-project-slug")?.trim() || undefined;
26
17
 
@@ -1,5 +1,6 @@
1
1
  import * as dntShim from "../../../../../_dnt.shims.js";
2
2
  import type { HandlerContext } from "../../types.js";
3
+ import { getEffectiveRequestHost } from "../../../utils/request-host.js";
3
4
 
4
5
  const JSON_HEADERS = {
5
6
  "Content-Type": "application/json",
@@ -21,11 +22,7 @@ export function handleProjectsAPI(req: dntShim.Request, ctx: HandlerContext): dn
21
22
 
22
23
  function handleGetConfig(req: dntShim.Request, ctx: HandlerContext): dntShim.Response {
23
24
  const url = new URL(req.url);
24
-
25
- const host = req.headers.get("x-forwarded-host") ??
26
- req.headers.get("host") ??
27
- url.host ??
28
- "lvh.me";
25
+ const host = getEffectiveRequestHost(req, url) || "lvh.me";
29
26
 
30
27
  const hostWithoutPort = host.replace(/:\d+$/, "") || "lvh.me";
31
28
  const port = host.includes(":") ? host.split(":")[1] ?? "" : "";
@@ -28,6 +28,7 @@ import {
28
28
  } from "./hmr-client-manager.js";
29
29
  import { getPingIntervalMs, startPingInterval, stopPingInterval } from "./hmr-ping-keepalive.js";
30
30
  import { broadcastUpdate, getMetrics } from "./hmr-message-router.js";
31
+ import { getEffectiveRequestHost } from "../../utils/request-host.js";
31
32
 
32
33
  const logger = serverLogger.component("hmr-handler");
33
34
 
@@ -95,7 +96,7 @@ export class HMRHandler extends BaseHandler {
95
96
  const queryEnv = url.searchParams.get("x-environment");
96
97
  const isPreviewMode = ctx.requestContext?.mode === "preview" || queryEnv === "preview";
97
98
  const isLocal = !!ctx.isLocalProject;
98
- const host = req.headers.get("host") ?? "";
99
+ const host = getEffectiveRequestHost(req, url);
99
100
  const isLocalhost = isLocalDevHost(host);
100
101
 
101
102
  if (!isPreviewMode && !isLocal && !isLocalhost) {
@@ -19,6 +19,7 @@ import { getEnvironmentType, lookupProjectByDomain } from "../utils/domain-looku
19
19
  import { parseProxyEnvironment, type ProxyEnvironment } from "./proxy-environment.js";
20
20
  import { SpanNames, withSpan } from "./tracing.js";
21
21
  import { isInternalHost } from "./request-utils.js";
22
+ import { getEffectiveRequestHost } from "../utils/request-host.js";
22
23
 
23
24
  const baseLogger = getBaseLogger("SERVER");
24
25
 
@@ -73,17 +74,8 @@ interface RequestHeaders {
73
74
  projectPath: string | undefined;
74
75
  }
75
76
 
76
- function parseForwardedHost(raw: string | null): string | undefined {
77
- if (!raw) return undefined;
78
- // x-forwarded-host can be a comma-separated list when multiple proxies
79
- // are chained. Take the first (client-facing) entry and trim whitespace.
80
- const first = raw.split(",")[0]?.trim();
81
- return first || undefined;
82
- }
83
-
84
77
  function getEffectiveHost(req: dntShim.Request, url: URL): string {
85
- const forwardedHost = parseForwardedHost(req.headers.get("x-forwarded-host"));
86
- return forwardedHost ?? req.headers.get("host") ?? url.host;
78
+ return getEffectiveRequestHost(req, url);
87
79
  }
88
80
 
89
81
  /**
@@ -0,0 +1,13 @@
1
+ import * as dntShim from "../../../_dnt.shims.js";
2
+ export function parseForwardedHost(raw: string | null): string | undefined {
3
+ if (!raw) return undefined;
4
+
5
+ const first = raw.split(",")[0]?.trim();
6
+ return first || undefined;
7
+ }
8
+
9
+ export function getEffectiveRequestHost(req: dntShim.Request, url?: URL): string {
10
+ return parseForwardedHost(req.headers.get("x-forwarded-host")) ??
11
+ req.headers.get("host") ??
12
+ (url ?? new URL(req.url)).host;
13
+ }
@@ -1,3 +1,3 @@
1
1
  // Keep in sync with deno.json version.
2
2
  // scripts/release.ts updates this constant during releases.
3
- export const VERSION = "0.1.121";
3
+ export const VERSION = "0.1.124";