vinext 0.0.16 → 0.0.17

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.
@@ -73,10 +73,11 @@ export declare function matchConfigPattern(pathname: string, pattern: string): R
73
73
  * Apply redirect rules from next.config.js.
74
74
  * Returns the redirect info if a redirect was matched, or null.
75
75
  *
76
- * When `ctx` is provided, has/missing conditions on the redirect rules
77
- * are evaluated against the request context (cookies, headers, query, host).
76
+ * `ctx` provides the request context (cookies, headers, query, host) used
77
+ * to evaluate has/missing conditions. Next.js always has request context
78
+ * when evaluating redirects, so this parameter is required.
78
79
  */
79
- export declare function matchRedirect(pathname: string, redirects: NextRedirect[], ctx?: RequestContext): {
80
+ export declare function matchRedirect(pathname: string, redirects: NextRedirect[], ctx: RequestContext): {
80
81
  destination: string;
81
82
  permanent: boolean;
82
83
  } | null;
@@ -84,10 +85,11 @@ export declare function matchRedirect(pathname: string, redirects: NextRedirect[
84
85
  * Apply rewrite rules from next.config.js.
85
86
  * Returns the rewritten URL or null if no rewrite matched.
86
87
  *
87
- * When `ctx` is provided, has/missing conditions on the rewrite rules
88
- * are evaluated against the request context (cookies, headers, query, host).
88
+ * `ctx` provides the request context (cookies, headers, query, host) used
89
+ * to evaluate has/missing conditions. Next.js always has request context
90
+ * when evaluating rewrites, so this parameter is required.
89
91
  */
90
- export declare function matchRewrite(pathname: string, rewrites: NextRewrite[], ctx?: RequestContext): string | null;
92
+ export declare function matchRewrite(pathname: string, rewrites: NextRewrite[], ctx: RequestContext): string | null;
91
93
  /**
92
94
  * Sanitize a redirect/rewrite destination to collapse protocol-relative URLs.
93
95
  *
@@ -120,10 +122,11 @@ export declare function proxyExternalRequest(request: Request, externalUrl: stri
120
122
  * Apply custom header rules from next.config.js.
121
123
  * Returns an array of { key, value } pairs to set on the response.
122
124
  *
123
- * `ctx` is optional for backward compatibility with existing callers.
124
- * When omitted, `has`/`missing` conditions are not evaluated.
125
+ * `ctx` provides the request context (cookies, headers, query, host) used
126
+ * to evaluate has/missing conditions. Next.js always has request context
127
+ * when evaluating headers, so this parameter is required.
125
128
  */
126
- export declare function matchHeaders(pathname: string, headers: NextHeader[], ctx?: RequestContext): Array<{
129
+ export declare function matchHeaders(pathname: string, headers: NextHeader[], ctx: RequestContext): Array<{
127
130
  key: string;
128
131
  value: string;
129
132
  }>;
@@ -1 +1 @@
1
- {"version":3,"file":"config-matchers.d.ts","sourceRoot":"","sources":["../../src/config/config-matchers.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAc5F;;;;;;;;;GASG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAsGpD;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAczE;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAsDzD;AAED;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,KAAK,EAAE,eAAe,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAWhF;AAED;;GAEG;AACH,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,OAAO,GAAG,cAAc,CAQ1E;AAmDD;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAChC,GAAG,EAAE,YAAY,EAAE,GAAG,SAAS,EAC/B,OAAO,EAAE,YAAY,EAAE,GAAG,SAAS,EACnC,GAAG,EAAE,cAAc,GAClB,OAAO,CAYT;AAsBD;;;;;;;;;;GAUG;AACH,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,GACd,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CA+F/B;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAC3B,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,YAAY,EAAE,EACzB,GAAG,CAAC,EAAE,cAAc,GACnB;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,OAAO,CAAA;CAAE,GAAG,IAAI,CAwBpD;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAC1B,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,WAAW,EAAE,EACvB,GAAG,CAAC,EAAE,cAAc,GACnB,MAAM,GAAG,IAAI,CAwBf;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAWxD;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAElD;AAED;;;;;;;;GAQG;AACH,wBAAsB,oBAAoB,CACxC,OAAO,EAAE,OAAO,EAChB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,QAAQ,CAAC,CAkFnB;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAC1B,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,UAAU,EAAE,EACrB,GAAG,CAAC,EAAE,cAAc,GACnB,KAAK,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CAiBvC"}
1
+ {"version":3,"file":"config-matchers.d.ts","sourceRoot":"","sources":["../../src/config/config-matchers.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAc5F;;;;;;;;;GASG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAsGpD;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAczE;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAsDzD;AAED;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,KAAK,EAAE,eAAe,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAWhF;AAED;;GAEG;AACH,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,OAAO,GAAG,cAAc,CAQ1E;AAmDD;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAChC,GAAG,EAAE,YAAY,EAAE,GAAG,SAAS,EAC/B,OAAO,EAAE,YAAY,EAAE,GAAG,SAAS,EACnC,GAAG,EAAE,cAAc,GAClB,OAAO,CAYT;AAsBD;;;;;;;;;;GAUG;AACH,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,GACd,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CA+F/B;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAC3B,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,YAAY,EAAE,EACzB,GAAG,EAAE,cAAc,GAClB;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,OAAO,CAAA;CAAE,GAAG,IAAI,CAuBpD;AAED;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAC1B,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,WAAW,EAAE,EACvB,GAAG,EAAE,cAAc,GAClB,MAAM,GAAG,IAAI,CAuBf;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAWxD;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAElD;AAED;;;;;;;;GAQG;AACH,wBAAsB,oBAAoB,CACxC,OAAO,EAAE,OAAO,EAChB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,QAAQ,CAAC,CAkFnB;AAED;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAC1B,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,UAAU,EAAE,EACrB,GAAG,EAAE,cAAc,GAClB,KAAK,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CAevC"}
@@ -455,15 +455,15 @@ export function matchConfigPattern(pathname, pattern) {
455
455
  * Apply redirect rules from next.config.js.
456
456
  * Returns the redirect info if a redirect was matched, or null.
457
457
  *
458
- * When `ctx` is provided, has/missing conditions on the redirect rules
459
- * are evaluated against the request context (cookies, headers, query, host).
458
+ * `ctx` provides the request context (cookies, headers, query, host) used
459
+ * to evaluate has/missing conditions. Next.js always has request context
460
+ * when evaluating redirects, so this parameter is required.
460
461
  */
461
462
  export function matchRedirect(pathname, redirects, ctx) {
462
463
  for (const redirect of redirects) {
463
464
  const params = matchConfigPattern(pathname, redirect.source);
464
465
  if (params) {
465
- // Check has/missing conditions if present and context is available
466
- if (ctx && (redirect.has || redirect.missing)) {
466
+ if (redirect.has || redirect.missing) {
467
467
  if (!checkHasConditions(redirect.has, redirect.missing, ctx)) {
468
468
  continue;
469
469
  }
@@ -487,15 +487,15 @@ export function matchRedirect(pathname, redirects, ctx) {
487
487
  * Apply rewrite rules from next.config.js.
488
488
  * Returns the rewritten URL or null if no rewrite matched.
489
489
  *
490
- * When `ctx` is provided, has/missing conditions on the rewrite rules
491
- * are evaluated against the request context (cookies, headers, query, host).
490
+ * `ctx` provides the request context (cookies, headers, query, host) used
491
+ * to evaluate has/missing conditions. Next.js always has request context
492
+ * when evaluating rewrites, so this parameter is required.
492
493
  */
493
494
  export function matchRewrite(pathname, rewrites, ctx) {
494
495
  for (const rewrite of rewrites) {
495
496
  const params = matchConfigPattern(pathname, rewrite.source);
496
497
  if (params) {
497
- // Check has/missing conditions if present and context is available
498
- if (ctx && (rewrite.has || rewrite.missing)) {
498
+ if (rewrite.has || rewrite.missing) {
499
499
  if (!checkHasConditions(rewrite.has, rewrite.missing, ctx)) {
500
500
  continue;
501
501
  }
@@ -636,8 +636,9 @@ export async function proxyExternalRequest(request, externalUrl) {
636
636
  * Apply custom header rules from next.config.js.
637
637
  * Returns an array of { key, value } pairs to set on the response.
638
638
  *
639
- * `ctx` is optional for backward compatibility with existing callers.
640
- * When omitted, `has`/`missing` conditions are not evaluated.
639
+ * `ctx` provides the request context (cookies, headers, query, host) used
640
+ * to evaluate has/missing conditions. Next.js always has request context
641
+ * when evaluating headers, so this parameter is required.
641
642
  */
642
643
  export function matchHeaders(pathname, headers, ctx) {
643
644
  const result = [];
@@ -645,9 +646,7 @@ export function matchHeaders(pathname, headers, ctx) {
645
646
  const escaped = escapeHeaderSource(rule.source);
646
647
  const sourceRegex = safeRegExp("^" + escaped + "$");
647
648
  if (sourceRegex && sourceRegex.test(pathname)) {
648
- // When no request context is available, skip has/missing checks
649
- // and apply all path-matched rules unconditionally (backward compat).
650
- if (ctx && (rule.has || rule.missing)) {
649
+ if (rule.has || rule.missing) {
651
650
  if (!checkHasConditions(rule.has, rule.missing, ctx)) {
652
651
  continue;
653
652
  }
@@ -1 +1 @@
1
- {"version":3,"file":"config-matchers.js","sourceRoot":"","sources":["../../src/config/config-matchers.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Config pattern matching and rule application utilities.\n *\n * Shared between the dev server (index.ts) and the production server\n * (prod-server.ts) so both apply next.config.js rules identically.\n */\n\nimport type { NextRedirect, NextRewrite, NextHeader, HasCondition } from \"./next-config.js\";\n\n/** Hop-by-hop headers that should not be forwarded through a proxy. */\nconst HOP_BY_HOP_HEADERS = new Set([\n \"connection\",\n \"keep-alive\",\n \"proxy-authenticate\",\n \"proxy-authorization\",\n \"te\",\n \"trailers\",\n \"transfer-encoding\",\n \"upgrade\",\n]);\n\n/**\n * Detect regex patterns vulnerable to catastrophic backtracking (ReDoS).\n *\n * Uses a lightweight heuristic: scans the pattern string for nested quantifiers\n * (a quantifier applied to a group that itself contains a quantifier). This\n * catches the most common pathological patterns like `(a+)+`, `(.*)*`,\n * `([^/]+)+`, `(a|a+)+` without needing a full regex parser.\n *\n * Returns true if the pattern appears safe, false if it's potentially dangerous.\n */\nexport function isSafeRegex(pattern: string): boolean {\n // Track parenthesis nesting depth and whether we've seen a quantifier\n // at each depth level.\n const quantifierAtDepth: boolean[] = [];\n let depth = 0;\n let i = 0;\n\n while (i < pattern.length) {\n const ch = pattern[i];\n\n // Skip escaped characters\n if (ch === \"\\\\\") {\n i += 2;\n continue;\n }\n\n // Skip character classes [...] — quantifiers inside them are literal\n if (ch === \"[\") {\n i++;\n while (i < pattern.length && pattern[i] !== \"]\") {\n if (pattern[i] === \"\\\\\") i++; // skip escaped char in class\n i++;\n }\n i++; // skip closing ]\n continue;\n }\n\n if (ch === \"(\") {\n depth++;\n // Initialize: no quantifier seen yet at this new depth\n if (quantifierAtDepth.length <= depth) {\n quantifierAtDepth.push(false);\n } else {\n quantifierAtDepth[depth] = false;\n }\n i++;\n continue;\n }\n\n if (ch === \")\") {\n const hadQuantifier = depth > 0 && quantifierAtDepth[depth];\n if (depth > 0) depth--;\n\n // Look ahead for a quantifier on this group: +, *, {n,m}\n // Note: '?' after ')' means \"zero or one\" which does NOT cause catastrophic\n // backtracking — it only allows 2 paths (match/skip), not exponential.\n // Only unbounded repetition (+, *, {n,}) on a group with inner quantifiers is dangerous.\n const next = pattern[i + 1];\n if (next === \"+\" || next === \"*\" || next === \"{\") {\n if (hadQuantifier) {\n // Nested quantifier detected: quantifier on a group that contains a quantifier\n return false;\n }\n // Mark the enclosing depth as having a quantifier\n if (depth >= 0 && depth < quantifierAtDepth.length) {\n quantifierAtDepth[depth] = true;\n }\n }\n i++;\n continue;\n }\n\n // Detect quantifiers: +, *, ?, {n,m}\n // '?' is a quantifier (optional) unless it follows another quantifier (+, *, ?, })\n // in which case it's a non-greedy modifier.\n if (ch === \"+\" || ch === \"*\") {\n if (depth > 0) {\n quantifierAtDepth[depth] = true;\n }\n i++;\n continue;\n }\n\n if (ch === \"?\") {\n // '?' after +, *, ?, or } is a non-greedy modifier, not a quantifier\n const prev = i > 0 ? pattern[i - 1] : \"\";\n if (prev !== \"+\" && prev !== \"*\" && prev !== \"?\" && prev !== \"}\") {\n if (depth > 0) {\n quantifierAtDepth[depth] = true;\n }\n }\n i++;\n continue;\n }\n\n if (ch === \"{\") {\n // Check if this is a quantifier {n}, {n,}, {n,m}\n let j = i + 1;\n while (j < pattern.length && /[\\d,]/.test(pattern[j])) j++;\n if (j < pattern.length && pattern[j] === \"}\" && j > i + 1) {\n if (depth > 0) {\n quantifierAtDepth[depth] = true;\n }\n i = j + 1;\n continue;\n }\n }\n\n i++;\n }\n\n return true;\n}\n\n/**\n * Compile a regex pattern safely. Returns the compiled RegExp or null if the\n * pattern is invalid or vulnerable to ReDoS.\n *\n * Logs a warning when a pattern is rejected so developers can fix their config.\n */\nexport function safeRegExp(pattern: string, flags?: string): RegExp | null {\n if (!isSafeRegex(pattern)) {\n console.warn(\n `[vinext] Ignoring potentially unsafe regex pattern (ReDoS risk): ${pattern}\\n` +\n ` Patterns with nested quantifiers (e.g. (a+)+) can cause catastrophic backtracking.\\n` +\n ` Simplify the pattern to avoid nested repetition.`,\n );\n return null;\n }\n try {\n return new RegExp(pattern, flags);\n } catch {\n return null;\n }\n}\n\n/**\n * Convert a Next.js header/rewrite/redirect source pattern into a regex string.\n *\n * Regex groups in the source (e.g. `(\\d+)`) are extracted first, the remaining\n * text is escaped/converted in a **single pass** (avoiding chained `.replace()`\n * which CodeQL flags as incomplete sanitization), then groups are restored.\n */\nexport function escapeHeaderSource(source: string): string {\n // Sentinel character for group placeholders. Uses a Unicode private-use-area\n // codepoint that will never appear in real source patterns.\n const S = \"\\uE000\";\n\n // Step 1: extract regex groups and replace with numbered placeholders.\n const groups: string[] = [];\n const withPlaceholders = source.replace(/\\(([^)]+)\\)/g, (_m, inner) => {\n groups.push(inner);\n return `${S}G${groups.length - 1}${S}`;\n });\n\n // Step 2: single-pass conversion of the placeholder-bearing string.\n // Match named params (:[\\w-]+), sentinel group placeholders, metacharacters, and literal text.\n // The regex uses non-overlapping alternatives to avoid backtracking:\n // :[\\w-]+ — named parameter (constraint sentinel is checked procedurally;\n // param names may contain hyphens, e.g. :auth-method)\n // sentinel group — standalone regex group placeholder\n // [.+?*] — single metachar to escape/convert\n // [^.+?*:\\uE000]+ — literal text (excludes all chars that start other alternatives)\n let result = \"\";\n const re = new RegExp(\n `${S}G(\\\\d+)${S}|:[\\\\w-]+|[.+?*]|[^.+?*:\\\\uE000]+`, // lgtm[js/redos] — alternatives are non-overlapping\n \"g\",\n );\n let m: RegExpExecArray | null;\n while ((m = re.exec(withPlaceholders)) !== null) {\n if (m[1] !== undefined) {\n // Standalone regex group — restore as-is\n result += `(${groups[Number(m[1])]})`;\n } else if (m[0].startsWith(\":\")) {\n // Named parameter — check if followed by a constraint group placeholder\n const afterParam = withPlaceholders.slice(re.lastIndex);\n const constraintMatch = afterParam.match(new RegExp(`^${S}G(\\\\d+)${S}`));\n if (constraintMatch) {\n // :param(constraint) — use the constraint as the capture group\n re.lastIndex += constraintMatch[0].length;\n result += `(${groups[Number(constraintMatch[1])]})`;\n } else {\n // Plain named parameter → match one segment\n result += \"[^/]+\";\n }\n } else {\n switch (m[0]) {\n case \".\": result += \"\\\\.\"; break;\n case \"+\": result += \"\\\\+\"; break;\n case \"?\": result += \"\\\\?\"; break;\n case \"*\": result += \".*\"; break;\n default: result += m[0]; break;\n }\n }\n }\n\n return result;\n}\n\n/**\n * Request context needed for evaluating has/missing conditions.\n * Callers extract the relevant parts from the incoming Request.\n */\nexport interface RequestContext {\n headers: Headers;\n cookies: Record<string, string>;\n query: URLSearchParams;\n host: string;\n}\n\n/**\n * Parse a Cookie header string into a key-value record.\n */\nexport function parseCookies(cookieHeader: string | null): Record<string, string> {\n if (!cookieHeader) return {};\n const cookies: Record<string, string> = {};\n for (const part of cookieHeader.split(\";\")) {\n const eq = part.indexOf(\"=\");\n if (eq === -1) continue;\n const key = part.slice(0, eq).trim();\n const value = part.slice(eq + 1).trim();\n if (key) cookies[key] = value;\n }\n return cookies;\n}\n\n/**\n * Build a RequestContext from a Web Request object.\n */\nexport function requestContextFromRequest(request: Request): RequestContext {\n const url = new URL(request.url);\n return {\n headers: request.headers,\n cookies: parseCookies(request.headers.get(\"cookie\")),\n query: url.searchParams,\n host: request.headers.get(\"host\") ?? url.host,\n };\n}\n\n/**\n * Check a single has/missing condition against request context.\n * Returns true if the condition is satisfied.\n */\nfunction checkSingleCondition(condition: HasCondition, ctx: RequestContext): boolean {\n switch (condition.type) {\n case \"header\": {\n const headerValue = ctx.headers.get(condition.key);\n if (headerValue === null) return false;\n if (condition.value !== undefined) {\n const re = safeRegExp(condition.value);\n if (re) return re.test(headerValue);\n return headerValue === condition.value;\n }\n return true; // Key exists, no value constraint\n }\n case \"cookie\": {\n const cookieValue = ctx.cookies[condition.key];\n if (cookieValue === undefined) return false;\n if (condition.value !== undefined) {\n const re = safeRegExp(condition.value);\n if (re) return re.test(cookieValue);\n return cookieValue === condition.value;\n }\n return true;\n }\n case \"query\": {\n const queryValue = ctx.query.get(condition.key);\n if (queryValue === null) return false;\n if (condition.value !== undefined) {\n const re = safeRegExp(condition.value);\n if (re) return re.test(queryValue);\n return queryValue === condition.value;\n }\n return true;\n }\n case \"host\": {\n if (condition.value !== undefined) {\n const re = safeRegExp(condition.value);\n if (re) return re.test(ctx.host);\n return ctx.host === condition.value;\n }\n return ctx.host === condition.key;\n }\n default:\n return false;\n }\n}\n\n/**\n * Check all has/missing conditions for a config rule.\n * Returns true if the rule should be applied (all has conditions pass, all missing conditions pass).\n *\n * - has: every condition must match (the request must have it)\n * - missing: every condition must NOT match (the request must not have it)\n */\nexport function checkHasConditions(\n has: HasCondition[] | undefined,\n missing: HasCondition[] | undefined,\n ctx: RequestContext,\n): boolean {\n if (has) {\n for (const condition of has) {\n if (!checkSingleCondition(condition, ctx)) return false;\n }\n }\n if (missing) {\n for (const condition of missing) {\n if (checkSingleCondition(condition, ctx)) return false;\n }\n }\n return true;\n}\n\n/**\n * If the current position in `str` starts with a parenthesized group, consume\n * it and advance `re.lastIndex` past the closing `)`. Returns the group\n * contents or null if no group is present.\n */\nfunction extractConstraint(str: string, re: RegExp): string | null {\n if (str[re.lastIndex] !== \"(\") return null;\n const start = re.lastIndex + 1;\n let depth = 1;\n let i = start;\n while (i < str.length && depth > 0) {\n if (str[i] === \"(\") depth++;\n else if (str[i] === \")\") depth--;\n i++;\n }\n if (depth !== 0) return null;\n re.lastIndex = i;\n return str.slice(start, i - 1);\n}\n\n/**\n * Match a Next.js config pattern (from redirects/rewrites sources) against a pathname.\n * Returns matched params or null.\n *\n * Supports:\n * :param - matches a single path segment\n * :param* - matches zero or more segments (catch-all)\n * :param+ - matches one or more segments\n * (regex) - inline regex patterns in the source\n * :param(constraint) - named param with inline regex constraint\n */\nexport function matchConfigPattern(\n pathname: string,\n pattern: string,\n): Record<string, string> | null {\n // If the pattern contains regex groups like (\\d+) or (.*), use regex matching.\n // Also enter this branch when a catch-all parameter (:param* or :param+) is\n // followed by a literal suffix (e.g. \"/:path*.md\"). Without this, the suffix\n // pattern falls through to the simple segment matcher which incorrectly treats\n // the whole segment (\":path*.md\") as a named parameter and matches everything.\n if (\n pattern.includes(\"(\") ||\n pattern.includes(\"\\\\\") ||\n /:[\\w-]+[*+][^/]/.test(pattern)\n ) {\n try {\n // Param names may contain hyphens (e.g. :auth-method, :sign-in).\n const paramNames: string[] = [];\n // Single-pass conversion with procedural suffix handling. The tokenizer\n // matches only simple, non-overlapping tokens; quantifier/constraint\n // suffixes after :param are consumed procedurally to avoid polynomial\n // backtracking in the regex engine.\n let regexStr = \"\";\n const tokenRe = /:([\\w-]+)|[.]|[^:.]+/g; // lgtm[js/redos] — alternatives are non-overlapping (`:` and `.` excluded from `[^:.]+`)\n let tok: RegExpExecArray | null;\n while ((tok = tokenRe.exec(pattern)) !== null) {\n if (tok[1] !== undefined) {\n const name = tok[1];\n const rest = pattern.slice(tokenRe.lastIndex);\n // Check for quantifier (* or +) with optional constraint\n if (rest.startsWith(\"*\") || rest.startsWith(\"+\")) {\n const quantifier = rest[0];\n tokenRe.lastIndex += 1;\n const constraint = extractConstraint(pattern, tokenRe);\n paramNames.push(name);\n if (constraint !== null) {\n regexStr += `(${constraint})`;\n } else {\n regexStr += quantifier === \"*\" ? \"(.*)\" : \"(.+)\";\n }\n } else {\n // Check for inline constraint without quantifier\n const constraint = extractConstraint(pattern, tokenRe);\n paramNames.push(name);\n regexStr += constraint !== null ? `(${constraint})` : \"([^/]+)\";\n }\n } else if (tok[0] === \".\") {\n regexStr += \"\\\\.\";\n } else {\n regexStr += tok[0];\n }\n }\n const re = safeRegExp(\"^\" + regexStr + \"$\");\n if (!re) return null;\n const match = re.exec(pathname);\n if (!match) return null;\n const params: Record<string, string> = Object.create(null);\n for (let i = 0; i < paramNames.length; i++) {\n params[paramNames[i]] = match[i + 1] ?? \"\";\n }\n return params;\n } catch {\n // Fall through to segment-based matching\n }\n }\n\n // Check for catch-all patterns (:param* or :param+) without regex groups\n // Param names may contain hyphens (e.g. :sign-in*, :sign-up+).\n const catchAllMatch = pattern.match(/:([\\w-]+)(\\*|\\+)$/);\n if (catchAllMatch) {\n const prefix = pattern.slice(0, pattern.lastIndexOf(\":\"));\n const paramName = catchAllMatch[1];\n const isPlus = catchAllMatch[2] === \"+\";\n\n if (!pathname.startsWith(prefix.replace(/\\/$/, \"\"))) return null;\n\n const rest = pathname.slice(prefix.replace(/\\/$/, \"\").length);\n if (isPlus && (!rest || rest === \"/\")) return null;\n let restValue = rest.startsWith(\"/\") ? rest.slice(1) : rest;\n // NOTE: Do NOT decodeURIComponent here. The pathname is already decoded at\n // the request entry point. Decoding again would produce incorrect param values.\n return { [paramName]: restValue };\n }\n\n // Simple segment-based matching for exact patterns and :param\n const parts = pattern.split(\"/\");\n const pathParts = pathname.split(\"/\");\n\n if (parts.length !== pathParts.length) return null;\n\n const params: Record<string, string> = Object.create(null);\n for (let i = 0; i < parts.length; i++) {\n if (parts[i].startsWith(\":\")) {\n params[parts[i].slice(1)] = pathParts[i];\n } else if (parts[i] !== pathParts[i]) {\n return null;\n }\n }\n return params;\n}\n\n/**\n * Apply redirect rules from next.config.js.\n * Returns the redirect info if a redirect was matched, or null.\n *\n * When `ctx` is provided, has/missing conditions on the redirect rules\n * are evaluated against the request context (cookies, headers, query, host).\n */\nexport function matchRedirect(\n pathname: string,\n redirects: NextRedirect[],\n ctx?: RequestContext,\n): { destination: string; permanent: boolean } | null {\n for (const redirect of redirects) {\n const params = matchConfigPattern(pathname, redirect.source);\n if (params) {\n // Check has/missing conditions if present and context is available\n if (ctx && (redirect.has || redirect.missing)) {\n if (!checkHasConditions(redirect.has, redirect.missing, ctx)) {\n continue;\n }\n }\n let dest = redirect.destination;\n for (const [key, value] of Object.entries(params)) {\n // Replace :param*, :param+, and :param forms in the destination.\n // The catch-all suffixes (* and +) must be stripped along with the param name.\n dest = dest.replace(`:${key}*`, value);\n dest = dest.replace(`:${key}+`, value);\n dest = dest.replace(`:${key}`, value);\n }\n // Collapse protocol-relative URLs (e.g. //evil.com from decoded %2F in catch-all params).\n dest = sanitizeDestination(dest);\n return { destination: dest, permanent: redirect.permanent };\n }\n }\n return null;\n}\n\n/**\n * Apply rewrite rules from next.config.js.\n * Returns the rewritten URL or null if no rewrite matched.\n *\n * When `ctx` is provided, has/missing conditions on the rewrite rules\n * are evaluated against the request context (cookies, headers, query, host).\n */\nexport function matchRewrite(\n pathname: string,\n rewrites: NextRewrite[],\n ctx?: RequestContext,\n): string | null {\n for (const rewrite of rewrites) {\n const params = matchConfigPattern(pathname, rewrite.source);\n if (params) {\n // Check has/missing conditions if present and context is available\n if (ctx && (rewrite.has || rewrite.missing)) {\n if (!checkHasConditions(rewrite.has, rewrite.missing, ctx)) {\n continue;\n }\n }\n let dest = rewrite.destination;\n for (const [key, value] of Object.entries(params)) {\n // Replace :param*, :param+, and :param forms in the destination.\n // The catch-all suffixes (* and +) must be stripped along with the param name.\n dest = dest.replace(`:${key}*`, value);\n dest = dest.replace(`:${key}+`, value);\n dest = dest.replace(`:${key}`, value);\n }\n // Collapse protocol-relative URLs (e.g. //evil.com from decoded %2F in catch-all params).\n dest = sanitizeDestination(dest);\n return dest;\n }\n }\n return null;\n}\n\n/**\n * Sanitize a redirect/rewrite destination to collapse protocol-relative URLs.\n *\n * After parameter substitution, a destination like `/:path*` can become\n * `//evil.com` if the catch-all captured a decoded `%2F` (`/evil.com`).\n * Browsers interpret `//evil.com` as a protocol-relative URL, redirecting\n * users off-site.\n *\n * This function collapses any leading double (or more) slashes to a single\n * slash for non-external (relative) destinations.\n */\nexport function sanitizeDestination(dest: string): string {\n // External URLs (http://, https://) are intentional — don't touch them\n if (dest.startsWith(\"http://\") || dest.startsWith(\"https://\")) {\n return dest;\n }\n // Normalize leading backslashes to forward slashes. Browsers interpret\n // backslash as forward slash in URL contexts, so \"\\/evil.com\" becomes\n // \"//evil.com\" (protocol-relative redirect). Replace any mix of leading\n // slashes and backslashes with a single forward slash.\n dest = dest.replace(/^[\\\\/]+/, \"/\");\n return dest;\n}\n\n/**\n * Check if a URL is external (absolute URL or protocol-relative).\n * Detects any URL scheme (http:, https:, data:, javascript:, blob:, etc.)\n * per RFC 3986, plus protocol-relative URLs (//).\n */\nexport function isExternalUrl(url: string): boolean {\n return /^[a-z][a-z0-9+.-]*:/i.test(url) || url.startsWith(\"//\");\n}\n\n/**\n * Proxy an incoming request to an external URL and return the upstream response.\n *\n * Used for external rewrites (e.g. `/ph/:path*` → `https://us.i.posthog.com/:path*`).\n * Next.js handles these as server-side reverse proxies, forwarding the request\n * method, headers, and body to the external destination.\n *\n * Works in all runtimes (Node.js, Cloudflare Workers) via the standard fetch() API.\n */\nexport async function proxyExternalRequest(\n request: Request,\n externalUrl: string,\n): Promise<Response> {\n // Build the full external URL, preserving query parameters from the original request\n const originalUrl = new URL(request.url);\n const targetUrl = new URL(externalUrl);\n\n // If the rewrite destination already has query params, merge them.\n // Destination params take precedence — original request params are only added\n // when the destination doesn't already specify that key.\n for (const [key, value] of originalUrl.searchParams) {\n if (!targetUrl.searchParams.has(key)) {\n targetUrl.searchParams.set(key, value);\n }\n }\n\n // Forward the request with appropriate headers\n const headers = new Headers(request.headers);\n // Set Host to the external target (required for correct routing)\n headers.set(\"host\", targetUrl.host);\n // Remove headers that should not be forwarded to external services\n headers.delete(\"connection\");\n // Strip credentials and internal headers to prevent leaking auth tokens,\n // session cookies, and middleware internals to third-party origins.\n headers.delete(\"cookie\");\n headers.delete(\"authorization\");\n headers.delete(\"x-api-key\");\n headers.delete(\"proxy-authorization\");\n const keysToDelete: string[] = [];\n for (const key of headers.keys()) {\n if (key.startsWith(\"x-middleware-\")) {\n keysToDelete.push(key);\n }\n }\n for (const key of keysToDelete) {\n headers.delete(key);\n }\n\n const method = request.method;\n const hasBody = method !== \"GET\" && method !== \"HEAD\";\n\n const init: RequestInit & { duplex?: string } = {\n method,\n headers,\n redirect: \"manual\", // Don't follow redirects — pass them through to the client\n };\n\n if (hasBody && request.body) {\n init.body = request.body;\n init.duplex = \"half\";\n }\n\n // Enforce a timeout so slow/unresponsive upstreams don't hold connections\n // open indefinitely (DoS amplification risk on Node.js dev/prod servers).\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), 30_000);\n let upstreamResponse: Response;\n try {\n upstreamResponse = await fetch(targetUrl.href, { ...init, signal: controller.signal });\n } catch (e: any) {\n if (e?.name === \"AbortError\") {\n console.error(\"[vinext] External rewrite proxy timeout:\", targetUrl.href);\n return new Response(\"Gateway Timeout\", { status: 504 });\n }\n console.error(\"[vinext] External rewrite proxy error:\", e);\n return new Response(\"Bad Gateway\", { status: 502 });\n } finally {\n clearTimeout(timeout);\n }\n\n // Build the response to return to the client.\n // Copy all upstream headers except hop-by-hop headers.\n const responseHeaders = new Headers();\n upstreamResponse.headers.forEach((value, key) => {\n if (!HOP_BY_HOP_HEADERS.has(key.toLowerCase())) {\n responseHeaders.append(key, value);\n }\n });\n\n return new Response(upstreamResponse.body, {\n status: upstreamResponse.status,\n statusText: upstreamResponse.statusText,\n headers: responseHeaders,\n });\n}\n\n/**\n * Apply custom header rules from next.config.js.\n * Returns an array of { key, value } pairs to set on the response.\n *\n * `ctx` is optional for backward compatibility with existing callers.\n * When omitted, `has`/`missing` conditions are not evaluated.\n */\nexport function matchHeaders(\n pathname: string,\n headers: NextHeader[],\n ctx?: RequestContext,\n): Array<{ key: string; value: string }> {\n const result: Array<{ key: string; value: string }> = [];\n for (const rule of headers) {\n const escaped = escapeHeaderSource(rule.source);\n const sourceRegex = safeRegExp(\"^\" + escaped + \"$\");\n if (sourceRegex && sourceRegex.test(pathname)) {\n // When no request context is available, skip has/missing checks\n // and apply all path-matched rules unconditionally (backward compat).\n if (ctx && (rule.has || rule.missing)) {\n if (!checkHasConditions(rule.has, rule.missing, ctx)) {\n continue;\n }\n }\n result.push(...rule.headers);\n }\n }\n return result;\n}\n"]}
1
+ {"version":3,"file":"config-matchers.js","sourceRoot":"","sources":["../../src/config/config-matchers.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Config pattern matching and rule application utilities.\n *\n * Shared between the dev server (index.ts) and the production server\n * (prod-server.ts) so both apply next.config.js rules identically.\n */\n\nimport type { NextRedirect, NextRewrite, NextHeader, HasCondition } from \"./next-config.js\";\n\n/** Hop-by-hop headers that should not be forwarded through a proxy. */\nconst HOP_BY_HOP_HEADERS = new Set([\n \"connection\",\n \"keep-alive\",\n \"proxy-authenticate\",\n \"proxy-authorization\",\n \"te\",\n \"trailers\",\n \"transfer-encoding\",\n \"upgrade\",\n]);\n\n/**\n * Detect regex patterns vulnerable to catastrophic backtracking (ReDoS).\n *\n * Uses a lightweight heuristic: scans the pattern string for nested quantifiers\n * (a quantifier applied to a group that itself contains a quantifier). This\n * catches the most common pathological patterns like `(a+)+`, `(.*)*`,\n * `([^/]+)+`, `(a|a+)+` without needing a full regex parser.\n *\n * Returns true if the pattern appears safe, false if it's potentially dangerous.\n */\nexport function isSafeRegex(pattern: string): boolean {\n // Track parenthesis nesting depth and whether we've seen a quantifier\n // at each depth level.\n const quantifierAtDepth: boolean[] = [];\n let depth = 0;\n let i = 0;\n\n while (i < pattern.length) {\n const ch = pattern[i];\n\n // Skip escaped characters\n if (ch === \"\\\\\") {\n i += 2;\n continue;\n }\n\n // Skip character classes [...] — quantifiers inside them are literal\n if (ch === \"[\") {\n i++;\n while (i < pattern.length && pattern[i] !== \"]\") {\n if (pattern[i] === \"\\\\\") i++; // skip escaped char in class\n i++;\n }\n i++; // skip closing ]\n continue;\n }\n\n if (ch === \"(\") {\n depth++;\n // Initialize: no quantifier seen yet at this new depth\n if (quantifierAtDepth.length <= depth) {\n quantifierAtDepth.push(false);\n } else {\n quantifierAtDepth[depth] = false;\n }\n i++;\n continue;\n }\n\n if (ch === \")\") {\n const hadQuantifier = depth > 0 && quantifierAtDepth[depth];\n if (depth > 0) depth--;\n\n // Look ahead for a quantifier on this group: +, *, {n,m}\n // Note: '?' after ')' means \"zero or one\" which does NOT cause catastrophic\n // backtracking — it only allows 2 paths (match/skip), not exponential.\n // Only unbounded repetition (+, *, {n,}) on a group with inner quantifiers is dangerous.\n const next = pattern[i + 1];\n if (next === \"+\" || next === \"*\" || next === \"{\") {\n if (hadQuantifier) {\n // Nested quantifier detected: quantifier on a group that contains a quantifier\n return false;\n }\n // Mark the enclosing depth as having a quantifier\n if (depth >= 0 && depth < quantifierAtDepth.length) {\n quantifierAtDepth[depth] = true;\n }\n }\n i++;\n continue;\n }\n\n // Detect quantifiers: +, *, ?, {n,m}\n // '?' is a quantifier (optional) unless it follows another quantifier (+, *, ?, })\n // in which case it's a non-greedy modifier.\n if (ch === \"+\" || ch === \"*\") {\n if (depth > 0) {\n quantifierAtDepth[depth] = true;\n }\n i++;\n continue;\n }\n\n if (ch === \"?\") {\n // '?' after +, *, ?, or } is a non-greedy modifier, not a quantifier\n const prev = i > 0 ? pattern[i - 1] : \"\";\n if (prev !== \"+\" && prev !== \"*\" && prev !== \"?\" && prev !== \"}\") {\n if (depth > 0) {\n quantifierAtDepth[depth] = true;\n }\n }\n i++;\n continue;\n }\n\n if (ch === \"{\") {\n // Check if this is a quantifier {n}, {n,}, {n,m}\n let j = i + 1;\n while (j < pattern.length && /[\\d,]/.test(pattern[j])) j++;\n if (j < pattern.length && pattern[j] === \"}\" && j > i + 1) {\n if (depth > 0) {\n quantifierAtDepth[depth] = true;\n }\n i = j + 1;\n continue;\n }\n }\n\n i++;\n }\n\n return true;\n}\n\n/**\n * Compile a regex pattern safely. Returns the compiled RegExp or null if the\n * pattern is invalid or vulnerable to ReDoS.\n *\n * Logs a warning when a pattern is rejected so developers can fix their config.\n */\nexport function safeRegExp(pattern: string, flags?: string): RegExp | null {\n if (!isSafeRegex(pattern)) {\n console.warn(\n `[vinext] Ignoring potentially unsafe regex pattern (ReDoS risk): ${pattern}\\n` +\n ` Patterns with nested quantifiers (e.g. (a+)+) can cause catastrophic backtracking.\\n` +\n ` Simplify the pattern to avoid nested repetition.`,\n );\n return null;\n }\n try {\n return new RegExp(pattern, flags);\n } catch {\n return null;\n }\n}\n\n/**\n * Convert a Next.js header/rewrite/redirect source pattern into a regex string.\n *\n * Regex groups in the source (e.g. `(\\d+)`) are extracted first, the remaining\n * text is escaped/converted in a **single pass** (avoiding chained `.replace()`\n * which CodeQL flags as incomplete sanitization), then groups are restored.\n */\nexport function escapeHeaderSource(source: string): string {\n // Sentinel character for group placeholders. Uses a Unicode private-use-area\n // codepoint that will never appear in real source patterns.\n const S = \"\\uE000\";\n\n // Step 1: extract regex groups and replace with numbered placeholders.\n const groups: string[] = [];\n const withPlaceholders = source.replace(/\\(([^)]+)\\)/g, (_m, inner) => {\n groups.push(inner);\n return `${S}G${groups.length - 1}${S}`;\n });\n\n // Step 2: single-pass conversion of the placeholder-bearing string.\n // Match named params (:[\\w-]+), sentinel group placeholders, metacharacters, and literal text.\n // The regex uses non-overlapping alternatives to avoid backtracking:\n // :[\\w-]+ — named parameter (constraint sentinel is checked procedurally;\n // param names may contain hyphens, e.g. :auth-method)\n // sentinel group — standalone regex group placeholder\n // [.+?*] — single metachar to escape/convert\n // [^.+?*:\\uE000]+ — literal text (excludes all chars that start other alternatives)\n let result = \"\";\n const re = new RegExp(\n `${S}G(\\\\d+)${S}|:[\\\\w-]+|[.+?*]|[^.+?*:\\\\uE000]+`, // lgtm[js/redos] — alternatives are non-overlapping\n \"g\",\n );\n let m: RegExpExecArray | null;\n while ((m = re.exec(withPlaceholders)) !== null) {\n if (m[1] !== undefined) {\n // Standalone regex group — restore as-is\n result += `(${groups[Number(m[1])]})`;\n } else if (m[0].startsWith(\":\")) {\n // Named parameter — check if followed by a constraint group placeholder\n const afterParam = withPlaceholders.slice(re.lastIndex);\n const constraintMatch = afterParam.match(new RegExp(`^${S}G(\\\\d+)${S}`));\n if (constraintMatch) {\n // :param(constraint) — use the constraint as the capture group\n re.lastIndex += constraintMatch[0].length;\n result += `(${groups[Number(constraintMatch[1])]})`;\n } else {\n // Plain named parameter → match one segment\n result += \"[^/]+\";\n }\n } else {\n switch (m[0]) {\n case \".\": result += \"\\\\.\"; break;\n case \"+\": result += \"\\\\+\"; break;\n case \"?\": result += \"\\\\?\"; break;\n case \"*\": result += \".*\"; break;\n default: result += m[0]; break;\n }\n }\n }\n\n return result;\n}\n\n/**\n * Request context needed for evaluating has/missing conditions.\n * Callers extract the relevant parts from the incoming Request.\n */\nexport interface RequestContext {\n headers: Headers;\n cookies: Record<string, string>;\n query: URLSearchParams;\n host: string;\n}\n\n/**\n * Parse a Cookie header string into a key-value record.\n */\nexport function parseCookies(cookieHeader: string | null): Record<string, string> {\n if (!cookieHeader) return {};\n const cookies: Record<string, string> = {};\n for (const part of cookieHeader.split(\";\")) {\n const eq = part.indexOf(\"=\");\n if (eq === -1) continue;\n const key = part.slice(0, eq).trim();\n const value = part.slice(eq + 1).trim();\n if (key) cookies[key] = value;\n }\n return cookies;\n}\n\n/**\n * Build a RequestContext from a Web Request object.\n */\nexport function requestContextFromRequest(request: Request): RequestContext {\n const url = new URL(request.url);\n return {\n headers: request.headers,\n cookies: parseCookies(request.headers.get(\"cookie\")),\n query: url.searchParams,\n host: request.headers.get(\"host\") ?? url.host,\n };\n}\n\n/**\n * Check a single has/missing condition against request context.\n * Returns true if the condition is satisfied.\n */\nfunction checkSingleCondition(condition: HasCondition, ctx: RequestContext): boolean {\n switch (condition.type) {\n case \"header\": {\n const headerValue = ctx.headers.get(condition.key);\n if (headerValue === null) return false;\n if (condition.value !== undefined) {\n const re = safeRegExp(condition.value);\n if (re) return re.test(headerValue);\n return headerValue === condition.value;\n }\n return true; // Key exists, no value constraint\n }\n case \"cookie\": {\n const cookieValue = ctx.cookies[condition.key];\n if (cookieValue === undefined) return false;\n if (condition.value !== undefined) {\n const re = safeRegExp(condition.value);\n if (re) return re.test(cookieValue);\n return cookieValue === condition.value;\n }\n return true;\n }\n case \"query\": {\n const queryValue = ctx.query.get(condition.key);\n if (queryValue === null) return false;\n if (condition.value !== undefined) {\n const re = safeRegExp(condition.value);\n if (re) return re.test(queryValue);\n return queryValue === condition.value;\n }\n return true;\n }\n case \"host\": {\n if (condition.value !== undefined) {\n const re = safeRegExp(condition.value);\n if (re) return re.test(ctx.host);\n return ctx.host === condition.value;\n }\n return ctx.host === condition.key;\n }\n default:\n return false;\n }\n}\n\n/**\n * Check all has/missing conditions for a config rule.\n * Returns true if the rule should be applied (all has conditions pass, all missing conditions pass).\n *\n * - has: every condition must match (the request must have it)\n * - missing: every condition must NOT match (the request must not have it)\n */\nexport function checkHasConditions(\n has: HasCondition[] | undefined,\n missing: HasCondition[] | undefined,\n ctx: RequestContext,\n): boolean {\n if (has) {\n for (const condition of has) {\n if (!checkSingleCondition(condition, ctx)) return false;\n }\n }\n if (missing) {\n for (const condition of missing) {\n if (checkSingleCondition(condition, ctx)) return false;\n }\n }\n return true;\n}\n\n/**\n * If the current position in `str` starts with a parenthesized group, consume\n * it and advance `re.lastIndex` past the closing `)`. Returns the group\n * contents or null if no group is present.\n */\nfunction extractConstraint(str: string, re: RegExp): string | null {\n if (str[re.lastIndex] !== \"(\") return null;\n const start = re.lastIndex + 1;\n let depth = 1;\n let i = start;\n while (i < str.length && depth > 0) {\n if (str[i] === \"(\") depth++;\n else if (str[i] === \")\") depth--;\n i++;\n }\n if (depth !== 0) return null;\n re.lastIndex = i;\n return str.slice(start, i - 1);\n}\n\n/**\n * Match a Next.js config pattern (from redirects/rewrites sources) against a pathname.\n * Returns matched params or null.\n *\n * Supports:\n * :param - matches a single path segment\n * :param* - matches zero or more segments (catch-all)\n * :param+ - matches one or more segments\n * (regex) - inline regex patterns in the source\n * :param(constraint) - named param with inline regex constraint\n */\nexport function matchConfigPattern(\n pathname: string,\n pattern: string,\n): Record<string, string> | null {\n // If the pattern contains regex groups like (\\d+) or (.*), use regex matching.\n // Also enter this branch when a catch-all parameter (:param* or :param+) is\n // followed by a literal suffix (e.g. \"/:path*.md\"). Without this, the suffix\n // pattern falls through to the simple segment matcher which incorrectly treats\n // the whole segment (\":path*.md\") as a named parameter and matches everything.\n if (\n pattern.includes(\"(\") ||\n pattern.includes(\"\\\\\") ||\n /:[\\w-]+[*+][^/]/.test(pattern)\n ) {\n try {\n // Param names may contain hyphens (e.g. :auth-method, :sign-in).\n const paramNames: string[] = [];\n // Single-pass conversion with procedural suffix handling. The tokenizer\n // matches only simple, non-overlapping tokens; quantifier/constraint\n // suffixes after :param are consumed procedurally to avoid polynomial\n // backtracking in the regex engine.\n let regexStr = \"\";\n const tokenRe = /:([\\w-]+)|[.]|[^:.]+/g; // lgtm[js/redos] — alternatives are non-overlapping (`:` and `.` excluded from `[^:.]+`)\n let tok: RegExpExecArray | null;\n while ((tok = tokenRe.exec(pattern)) !== null) {\n if (tok[1] !== undefined) {\n const name = tok[1];\n const rest = pattern.slice(tokenRe.lastIndex);\n // Check for quantifier (* or +) with optional constraint\n if (rest.startsWith(\"*\") || rest.startsWith(\"+\")) {\n const quantifier = rest[0];\n tokenRe.lastIndex += 1;\n const constraint = extractConstraint(pattern, tokenRe);\n paramNames.push(name);\n if (constraint !== null) {\n regexStr += `(${constraint})`;\n } else {\n regexStr += quantifier === \"*\" ? \"(.*)\" : \"(.+)\";\n }\n } else {\n // Check for inline constraint without quantifier\n const constraint = extractConstraint(pattern, tokenRe);\n paramNames.push(name);\n regexStr += constraint !== null ? `(${constraint})` : \"([^/]+)\";\n }\n } else if (tok[0] === \".\") {\n regexStr += \"\\\\.\";\n } else {\n regexStr += tok[0];\n }\n }\n const re = safeRegExp(\"^\" + regexStr + \"$\");\n if (!re) return null;\n const match = re.exec(pathname);\n if (!match) return null;\n const params: Record<string, string> = Object.create(null);\n for (let i = 0; i < paramNames.length; i++) {\n params[paramNames[i]] = match[i + 1] ?? \"\";\n }\n return params;\n } catch {\n // Fall through to segment-based matching\n }\n }\n\n // Check for catch-all patterns (:param* or :param+) without regex groups\n // Param names may contain hyphens (e.g. :sign-in*, :sign-up+).\n const catchAllMatch = pattern.match(/:([\\w-]+)(\\*|\\+)$/);\n if (catchAllMatch) {\n const prefix = pattern.slice(0, pattern.lastIndexOf(\":\"));\n const paramName = catchAllMatch[1];\n const isPlus = catchAllMatch[2] === \"+\";\n\n if (!pathname.startsWith(prefix.replace(/\\/$/, \"\"))) return null;\n\n const rest = pathname.slice(prefix.replace(/\\/$/, \"\").length);\n if (isPlus && (!rest || rest === \"/\")) return null;\n let restValue = rest.startsWith(\"/\") ? rest.slice(1) : rest;\n // NOTE: Do NOT decodeURIComponent here. The pathname is already decoded at\n // the request entry point. Decoding again would produce incorrect param values.\n return { [paramName]: restValue };\n }\n\n // Simple segment-based matching for exact patterns and :param\n const parts = pattern.split(\"/\");\n const pathParts = pathname.split(\"/\");\n\n if (parts.length !== pathParts.length) return null;\n\n const params: Record<string, string> = Object.create(null);\n for (let i = 0; i < parts.length; i++) {\n if (parts[i].startsWith(\":\")) {\n params[parts[i].slice(1)] = pathParts[i];\n } else if (parts[i] !== pathParts[i]) {\n return null;\n }\n }\n return params;\n}\n\n/**\n * Apply redirect rules from next.config.js.\n * Returns the redirect info if a redirect was matched, or null.\n *\n * `ctx` provides the request context (cookies, headers, query, host) used\n * to evaluate has/missing conditions. Next.js always has request context\n * when evaluating redirects, so this parameter is required.\n */\nexport function matchRedirect(\n pathname: string,\n redirects: NextRedirect[],\n ctx: RequestContext,\n): { destination: string; permanent: boolean } | null {\n for (const redirect of redirects) {\n const params = matchConfigPattern(pathname, redirect.source);\n if (params) {\n if (redirect.has || redirect.missing) {\n if (!checkHasConditions(redirect.has, redirect.missing, ctx)) {\n continue;\n }\n }\n let dest = redirect.destination;\n for (const [key, value] of Object.entries(params)) {\n // Replace :param*, :param+, and :param forms in the destination.\n // The catch-all suffixes (* and +) must be stripped along with the param name.\n dest = dest.replace(`:${key}*`, value);\n dest = dest.replace(`:${key}+`, value);\n dest = dest.replace(`:${key}`, value);\n }\n // Collapse protocol-relative URLs (e.g. //evil.com from decoded %2F in catch-all params).\n dest = sanitizeDestination(dest);\n return { destination: dest, permanent: redirect.permanent };\n }\n }\n return null;\n}\n\n/**\n * Apply rewrite rules from next.config.js.\n * Returns the rewritten URL or null if no rewrite matched.\n *\n * `ctx` provides the request context (cookies, headers, query, host) used\n * to evaluate has/missing conditions. Next.js always has request context\n * when evaluating rewrites, so this parameter is required.\n */\nexport function matchRewrite(\n pathname: string,\n rewrites: NextRewrite[],\n ctx: RequestContext,\n): string | null {\n for (const rewrite of rewrites) {\n const params = matchConfigPattern(pathname, rewrite.source);\n if (params) {\n if (rewrite.has || rewrite.missing) {\n if (!checkHasConditions(rewrite.has, rewrite.missing, ctx)) {\n continue;\n }\n }\n let dest = rewrite.destination;\n for (const [key, value] of Object.entries(params)) {\n // Replace :param*, :param+, and :param forms in the destination.\n // The catch-all suffixes (* and +) must be stripped along with the param name.\n dest = dest.replace(`:${key}*`, value);\n dest = dest.replace(`:${key}+`, value);\n dest = dest.replace(`:${key}`, value);\n }\n // Collapse protocol-relative URLs (e.g. //evil.com from decoded %2F in catch-all params).\n dest = sanitizeDestination(dest);\n return dest;\n }\n }\n return null;\n}\n\n/**\n * Sanitize a redirect/rewrite destination to collapse protocol-relative URLs.\n *\n * After parameter substitution, a destination like `/:path*` can become\n * `//evil.com` if the catch-all captured a decoded `%2F` (`/evil.com`).\n * Browsers interpret `//evil.com` as a protocol-relative URL, redirecting\n * users off-site.\n *\n * This function collapses any leading double (or more) slashes to a single\n * slash for non-external (relative) destinations.\n */\nexport function sanitizeDestination(dest: string): string {\n // External URLs (http://, https://) are intentional — don't touch them\n if (dest.startsWith(\"http://\") || dest.startsWith(\"https://\")) {\n return dest;\n }\n // Normalize leading backslashes to forward slashes. Browsers interpret\n // backslash as forward slash in URL contexts, so \"\\/evil.com\" becomes\n // \"//evil.com\" (protocol-relative redirect). Replace any mix of leading\n // slashes and backslashes with a single forward slash.\n dest = dest.replace(/^[\\\\/]+/, \"/\");\n return dest;\n}\n\n/**\n * Check if a URL is external (absolute URL or protocol-relative).\n * Detects any URL scheme (http:, https:, data:, javascript:, blob:, etc.)\n * per RFC 3986, plus protocol-relative URLs (//).\n */\nexport function isExternalUrl(url: string): boolean {\n return /^[a-z][a-z0-9+.-]*:/i.test(url) || url.startsWith(\"//\");\n}\n\n/**\n * Proxy an incoming request to an external URL and return the upstream response.\n *\n * Used for external rewrites (e.g. `/ph/:path*` → `https://us.i.posthog.com/:path*`).\n * Next.js handles these as server-side reverse proxies, forwarding the request\n * method, headers, and body to the external destination.\n *\n * Works in all runtimes (Node.js, Cloudflare Workers) via the standard fetch() API.\n */\nexport async function proxyExternalRequest(\n request: Request,\n externalUrl: string,\n): Promise<Response> {\n // Build the full external URL, preserving query parameters from the original request\n const originalUrl = new URL(request.url);\n const targetUrl = new URL(externalUrl);\n\n // If the rewrite destination already has query params, merge them.\n // Destination params take precedence — original request params are only added\n // when the destination doesn't already specify that key.\n for (const [key, value] of originalUrl.searchParams) {\n if (!targetUrl.searchParams.has(key)) {\n targetUrl.searchParams.set(key, value);\n }\n }\n\n // Forward the request with appropriate headers\n const headers = new Headers(request.headers);\n // Set Host to the external target (required for correct routing)\n headers.set(\"host\", targetUrl.host);\n // Remove headers that should not be forwarded to external services\n headers.delete(\"connection\");\n // Strip credentials and internal headers to prevent leaking auth tokens,\n // session cookies, and middleware internals to third-party origins.\n headers.delete(\"cookie\");\n headers.delete(\"authorization\");\n headers.delete(\"x-api-key\");\n headers.delete(\"proxy-authorization\");\n const keysToDelete: string[] = [];\n for (const key of headers.keys()) {\n if (key.startsWith(\"x-middleware-\")) {\n keysToDelete.push(key);\n }\n }\n for (const key of keysToDelete) {\n headers.delete(key);\n }\n\n const method = request.method;\n const hasBody = method !== \"GET\" && method !== \"HEAD\";\n\n const init: RequestInit & { duplex?: string } = {\n method,\n headers,\n redirect: \"manual\", // Don't follow redirects — pass them through to the client\n };\n\n if (hasBody && request.body) {\n init.body = request.body;\n init.duplex = \"half\";\n }\n\n // Enforce a timeout so slow/unresponsive upstreams don't hold connections\n // open indefinitely (DoS amplification risk on Node.js dev/prod servers).\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), 30_000);\n let upstreamResponse: Response;\n try {\n upstreamResponse = await fetch(targetUrl.href, { ...init, signal: controller.signal });\n } catch (e: any) {\n if (e?.name === \"AbortError\") {\n console.error(\"[vinext] External rewrite proxy timeout:\", targetUrl.href);\n return new Response(\"Gateway Timeout\", { status: 504 });\n }\n console.error(\"[vinext] External rewrite proxy error:\", e);\n return new Response(\"Bad Gateway\", { status: 502 });\n } finally {\n clearTimeout(timeout);\n }\n\n // Build the response to return to the client.\n // Copy all upstream headers except hop-by-hop headers.\n const responseHeaders = new Headers();\n upstreamResponse.headers.forEach((value, key) => {\n if (!HOP_BY_HOP_HEADERS.has(key.toLowerCase())) {\n responseHeaders.append(key, value);\n }\n });\n\n return new Response(upstreamResponse.body, {\n status: upstreamResponse.status,\n statusText: upstreamResponse.statusText,\n headers: responseHeaders,\n });\n}\n\n/**\n * Apply custom header rules from next.config.js.\n * Returns an array of { key, value } pairs to set on the response.\n *\n * `ctx` provides the request context (cookies, headers, query, host) used\n * to evaluate has/missing conditions. Next.js always has request context\n * when evaluating headers, so this parameter is required.\n */\nexport function matchHeaders(\n pathname: string,\n headers: NextHeader[],\n ctx: RequestContext,\n): Array<{ key: string; value: string }> {\n const result: Array<{ key: string; value: string }> = [];\n for (const rule of headers) {\n const escaped = escapeHeaderSource(rule.source);\n const sourceRegex = safeRegExp(\"^\" + escaped + \"$\");\n if (sourceRegex && sourceRegex.test(pathname)) {\n if (rule.has || rule.missing) {\n if (!checkHasConditions(rule.has, rule.missing, ctx)) {\n continue;\n }\n }\n result.push(...rule.headers);\n }\n }\n return result;\n}\n"]}
package/dist/deploy.js CHANGED
@@ -512,7 +512,7 @@ export default {
512
512
 
513
513
  // ── 4. Apply custom headers from next.config.js ───────────────
514
514
  if (configHeaders.length) {
515
- const matched = matchHeaders(resolvedPathname, configHeaders);
515
+ const matched = matchHeaders(resolvedPathname, configHeaders, reqCtx);
516
516
  for (const h of matched) {
517
517
  middlewareHeaders[h.key.toLowerCase()] = h.value;
518
518
  }