@timber-js/app 0.2.0-alpha.133 → 0.2.0-alpha.135

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.
Files changed (177) hide show
  1. package/dist/_chunks/{actions-BNhpxrnV.js → actions-CHFblsdT.js} +62 -19
  2. package/dist/_chunks/actions-CHFblsdT.js.map +1 -0
  3. package/dist/_chunks/{build-output-helper-K7oUCRqU.js → build-output-helper-CfBfOU9m.js} +1 -1
  4. package/dist/_chunks/{build-output-helper-K7oUCRqU.js.map → build-output-helper-CfBfOU9m.js.map} +1 -1
  5. package/dist/_chunks/cli-schema-sync-q-Ce6-iG.js.map +1 -1
  6. package/dist/_chunks/{codec-registry-DqkeAydt.js → codec-registry-G9hD5LOq.js} +1 -1
  7. package/dist/_chunks/{codec-registry-DqkeAydt.js.map → codec-registry-G9hD5LOq.js.map} +1 -1
  8. package/dist/_chunks/{define-jeHDXZGq.js → define-DXWUJb-K.js} +3 -3
  9. package/dist/_chunks/{define-jeHDXZGq.js.map → define-DXWUJb-K.js.map} +1 -1
  10. package/dist/_chunks/{define-DMq-Yjp7.js → define-Dp-qu3ql.js} +3 -3
  11. package/dist/_chunks/{define-DMq-Yjp7.js.map → define-Dp-qu3ql.js.map} +1 -1
  12. package/dist/_chunks/fast-hash-DXZ7S2D5.js +36 -0
  13. package/dist/_chunks/fast-hash-DXZ7S2D5.js.map +1 -0
  14. package/dist/_chunks/{format-BjN9HLu9.js → format-CR6v1pWE.js} +1 -1
  15. package/dist/_chunks/{format-BjN9HLu9.js.map → format-CR6v1pWE.js.map} +1 -1
  16. package/dist/_chunks/{handler-store-bIAstrxQ.js → handler-store-aQMpqPe7.js} +1 -1
  17. package/dist/_chunks/{handler-store-bIAstrxQ.js.map → handler-store-aQMpqPe7.js.map} +1 -1
  18. package/dist/_chunks/href-validation-2G-HZaQ8.js +124 -0
  19. package/dist/_chunks/href-validation-2G-HZaQ8.js.map +1 -0
  20. package/dist/_chunks/logger-CMd9P1xQ.js.map +1 -1
  21. package/dist/_chunks/metadata-routes-DESG8uk5.js.map +1 -1
  22. package/dist/_chunks/{navigation-root-B5-RmsPi.js → navigation-root-BQqFQI-n.js} +3 -3
  23. package/dist/_chunks/{navigation-root-B5-RmsPi.js.map → navigation-root-BQqFQI-n.js.map} +1 -1
  24. package/dist/_chunks/{registry-BI9cgCt7.js → registry-Dp_hJL4s.js} +1 -1
  25. package/dist/_chunks/{registry-BI9cgCt7.js.map → registry-Dp_hJL4s.js.map} +1 -1
  26. package/dist/_chunks/{resolve-schema-DU2nbVOi.js → resolve-schema-D3CbcdCW.js} +2 -2
  27. package/dist/_chunks/{resolve-schema-DU2nbVOi.js.map → resolve-schema-D3CbcdCW.js.map} +1 -1
  28. package/dist/_chunks/{router-ref-B2-2kIIC.js → router-ref-B50j42zB.js} +2 -2
  29. package/dist/_chunks/{router-ref-B2-2kIIC.js.map → router-ref-B50j42zB.js.map} +1 -1
  30. package/dist/_chunks/{schema-bridge-o0SwFtXW.js → schema-bridge-Cuy8BaYu.js} +2 -2
  31. package/dist/_chunks/{schema-bridge-o0SwFtXW.js.map → schema-bridge-Cuy8BaYu.js.map} +1 -1
  32. package/dist/_chunks/segment-classify-BjfuctV2.js.map +1 -1
  33. package/dist/_chunks/{segment-context-Bg0pFbLT.js → segment-context-BnxoPSFQ.js} +1 -1
  34. package/dist/_chunks/{segment-context-Bg0pFbLT.js.map → segment-context-BnxoPSFQ.js.map} +1 -1
  35. package/dist/_chunks/{ssr-data-DVX8S7vj.js → ssr-data-DxXyoRrz.js} +1 -1
  36. package/dist/_chunks/{ssr-data-DVX8S7vj.js.map → ssr-data-DxXyoRrz.js.map} +1 -1
  37. package/dist/_chunks/{stale-reload-CCqb62Z3.js → stale-reload-DIIIVGh_.js} +1 -1
  38. package/dist/_chunks/{stale-reload-CCqb62Z3.js.map → stale-reload-DIIIVGh_.js.map} +1 -1
  39. package/dist/_chunks/tracing-DP5djRq5.js.map +1 -1
  40. package/dist/_chunks/{use-query-states-C9G6LP0F.js → use-query-states-D9SBlAfp.js} +2 -2
  41. package/dist/_chunks/{use-query-states-C9G6LP0F.js.map → use-query-states-D9SBlAfp.js.map} +1 -1
  42. package/dist/_chunks/{use-segment-params-CIeinIx2.js → use-segment-params-x2poKmk8.js} +2 -2
  43. package/dist/_chunks/use-segment-params-x2poKmk8.js.map +1 -0
  44. package/dist/_chunks/{validation-AfEFM5ze.js → validation-BoWM_qI1.js} +31 -2
  45. package/dist/_chunks/validation-BoWM_qI1.js.map +1 -0
  46. package/dist/_chunks/walkers-BbEu2_Pp.js.map +1 -1
  47. package/dist/_chunks/warnings-CAzunaGo.js.map +1 -1
  48. package/dist/adapters/cloudflare-dev.js.map +1 -1
  49. package/dist/adapters/cloudflare-kv-cache.js.map +1 -1
  50. package/dist/adapters/cloudflare.js +1 -1
  51. package/dist/adapters/cloudflare.js.map +1 -1
  52. package/dist/adapters/nitro.js +1 -1
  53. package/dist/adapters/nitro.js.map +1 -1
  54. package/dist/cache/cache-api.d.ts +1 -1
  55. package/dist/cache/cache-api.d.ts.map +1 -1
  56. package/dist/cache/index.js +17 -39
  57. package/dist/cache/index.js.map +1 -1
  58. package/dist/cache/timber-cache.d.ts +1 -1
  59. package/dist/cache/timber-cache.d.ts.map +1 -1
  60. package/dist/cli.js.map +1 -1
  61. package/dist/client/error-boundary.js +2 -2
  62. package/dist/client/error-boundary.js.map +1 -1
  63. package/dist/client/index.d.ts.map +1 -1
  64. package/dist/client/index.js +14 -26
  65. package/dist/client/index.js.map +1 -1
  66. package/dist/client/internal.js +8 -8
  67. package/dist/client/internal.js.map +1 -1
  68. package/dist/client/link.d.ts +2 -4
  69. package/dist/client/link.d.ts.map +1 -1
  70. package/dist/client/navigation-context.d.ts.map +1 -1
  71. package/dist/client/use-pathname.d.ts.map +1 -1
  72. package/dist/client/use-router.d.ts.map +1 -1
  73. package/dist/client/use-search-params.d.ts.map +1 -1
  74. package/dist/codec.js +1 -1
  75. package/dist/codec.js.map +1 -1
  76. package/dist/cookies/index.js +3 -3
  77. package/dist/cookies/index.js.map +1 -1
  78. package/dist/cookies/validation.d.ts +11 -23
  79. package/dist/cookies/validation.d.ts.map +1 -1
  80. package/dist/dev-tools/error-page.d.ts.map +1 -1
  81. package/dist/fonts/virtual-modules.d.ts.map +1 -1
  82. package/dist/index.d.ts.map +1 -1
  83. package/dist/index.js +259 -3
  84. package/dist/index.js.map +1 -1
  85. package/dist/params/define-schema.d.ts.map +1 -1
  86. package/dist/params/index.js +2 -2
  87. package/dist/params/index.js.map +1 -1
  88. package/dist/plugins/cache.d.ts +31 -0
  89. package/dist/plugins/cache.d.ts.map +1 -0
  90. package/dist/routing/link-codegen.d.ts.map +1 -1
  91. package/dist/schema-bridge.d.ts.map +1 -1
  92. package/dist/search-params/index.js +3 -3
  93. package/dist/search-params/index.js.map +1 -1
  94. package/dist/segment-params/index.js +1 -1
  95. package/dist/server/actions.d.ts.map +1 -1
  96. package/dist/server/body-limits.d.ts.map +1 -1
  97. package/dist/server/cookie-context.d.ts +2 -2
  98. package/dist/server/cookie-context.d.ts.map +1 -1
  99. package/dist/server/csrf.d.ts +3 -2
  100. package/dist/server/csrf.d.ts.map +1 -1
  101. package/dist/server/deny-renderer.d.ts.map +1 -1
  102. package/dist/server/html-injector-core.d.ts.map +1 -1
  103. package/dist/server/html-injectors.d.ts.map +1 -1
  104. package/dist/server/index.js +17 -8
  105. package/dist/server/index.js.map +1 -1
  106. package/dist/server/internal.js +69 -21
  107. package/dist/server/internal.js.map +1 -1
  108. package/dist/server/pipeline-interception.d.ts.map +1 -1
  109. package/dist/server/pipeline-phases.d.ts +5 -1
  110. package/dist/server/pipeline-phases.d.ts.map +1 -1
  111. package/dist/server/pipeline.d.ts.map +1 -1
  112. package/dist/server/primitives.d.ts +5 -2
  113. package/dist/server/primitives.d.ts.map +1 -1
  114. package/dist/server/route-element-builder.d.ts.map +1 -1
  115. package/dist/server/rsc-entry/error-renderer.d.ts.map +1 -1
  116. package/dist/server/rsc-entry/index.d.ts.map +1 -1
  117. package/dist/server/rsc-entry/revalidate-renderer.d.ts +108 -0
  118. package/dist/server/rsc-entry/revalidate-renderer.d.ts.map +1 -0
  119. package/dist/server/rsc-entry/rsc-payload.d.ts.map +1 -1
  120. package/dist/server/rsc-entry/ssr-renderer.d.ts +15 -0
  121. package/dist/server/rsc-entry/ssr-renderer.d.ts.map +1 -1
  122. package/dist/server/sitemap-handler.d.ts.map +1 -1
  123. package/dist/server/ssr-wrappers.d.ts.map +1 -1
  124. package/dist/server/tree-builder.d.ts.map +1 -1
  125. package/dist/shared/href-validation.d.ts +38 -0
  126. package/dist/shared/href-validation.d.ts.map +1 -0
  127. package/dist/shims/font-google.js.map +1 -1
  128. package/dist/shims/font-local.js.map +1 -1
  129. package/package.json +5 -5
  130. package/src/cache/cache-api.ts +3 -2
  131. package/src/cache/timber-cache.ts +27 -4
  132. package/src/client/index.ts +1 -0
  133. package/src/client/link.tsx +13 -37
  134. package/src/client/navigation-context.ts +2 -0
  135. package/src/client/use-pathname.ts +1 -0
  136. package/src/client/use-router.ts +3 -0
  137. package/src/client/use-search-params.ts +1 -0
  138. package/src/client/use-segment-params.ts +1 -0
  139. package/src/config-validation.ts +1 -1
  140. package/src/cookies/validation.ts +58 -0
  141. package/src/dev-tools/error-page.ts +1 -0
  142. package/src/fonts/virtual-modules.ts +2 -0
  143. package/src/index.ts +5 -1
  144. package/src/params/define-schema.ts +1 -0
  145. package/src/plugins/cache.ts +180 -0
  146. package/src/routing/link-codegen.ts +5 -3
  147. package/src/schema-bridge.ts +3 -2
  148. package/src/server/action-client.ts +31 -13
  149. package/src/server/actions.ts +20 -3
  150. package/src/server/body-limits.ts +10 -2
  151. package/src/server/cookie-context.ts +7 -2
  152. package/src/server/cookie-parsing.ts +1 -1
  153. package/src/server/csrf.ts +39 -6
  154. package/src/server/deny-renderer.ts +0 -1
  155. package/src/server/html-injector-core.ts +6 -5
  156. package/src/server/html-injectors.ts +8 -5
  157. package/src/server/pipeline-interception.ts +1 -0
  158. package/src/server/pipeline-phases.ts +30 -19
  159. package/src/server/pipeline.ts +27 -1
  160. package/src/server/primitives.ts +19 -18
  161. package/src/server/route-element-builder.ts +2 -0
  162. package/src/server/rsc-entry/error-renderer.ts +4 -3
  163. package/src/server/rsc-entry/index.ts +16 -36
  164. package/src/server/rsc-entry/revalidate-renderer.ts +344 -0
  165. package/src/server/rsc-entry/rsc-payload.ts +0 -4
  166. package/src/server/rsc-entry/ssr-renderer.ts +76 -0
  167. package/src/server/sitemap-handler.ts +24 -2
  168. package/src/server/slot-resolver.ts +8 -2
  169. package/src/server/ssr-wrappers.tsx +2 -0
  170. package/src/server/tree-builder.ts +2 -0
  171. package/src/server/types.ts +2 -2
  172. package/src/shared/href-validation.ts +127 -0
  173. package/dist/_chunks/actions-BNhpxrnV.js.map +0 -1
  174. package/dist/_chunks/merge-search-params-Cm1j99HC.js +0 -41
  175. package/dist/_chunks/merge-search-params-Cm1j99HC.js.map +0 -1
  176. package/dist/_chunks/use-segment-params-CIeinIx2.js.map +0 -1
  177. package/dist/_chunks/validation-AfEFM5ze.js.map +0 -1
@@ -3,10 +3,10 @@ import { a as warnRedirectInSuspense, c as warnSuspenseWrappingChildren, i as wa
3
3
  import { i as getMetadataRouteServePath, n as classifyMetadataRoute, r as getMetadataRouteAutoLink, t as METADATA_ROUTE_CONVENTIONS } from "../_chunks/metadata-routes-DESG8uk5.js";
4
4
  import { n as classifyUrlSegment } from "../_chunks/segment-classify-BjfuctV2.js";
5
5
  import { a as logProxyError, c as logRequestReceived, d as logSwrRefetchFailed, f as logWaitUntilRejected, h as swallow, i as logMiddlewareShortCircuit, l as logRouteError, m as setLogger, n as logCacheMiss, o as logRenderError, p as logWaitUntilUnsupported, r as logMiddlewareError, s as logRequestCompleted, t as getLogger, u as logSlowRequest } from "../_chunks/logger-CMd9P1xQ.js";
6
- import { C as setMatchedSegmentPath, E as getCookie, O as getSetCookieHeaders, S as runWithRequestContext, T as setSegmentParams, _ as getHeader, b as getSegmentParams, c as DenySignal, d as RenderError, g as applyRequestHeaderOverlay, l as RedirectSignal, n as executeAction, o as coerce, r as isRscActionRequest, t as buildNoJsResponse, w as setMutableCookieContext, x as markResponseFlushed, y as getSearchParams } from "../_chunks/actions-BNhpxrnV.js";
6
+ import { C as setMatchedSegmentPath, E as getCookie, O as getSetCookieHeaders, S as runWithRequestContext, T as setSegmentParams, _ as getHeader, b as getSegmentParams, c as DenySignal, d as RenderError, g as applyRequestHeaderOverlay, l as RedirectSignal, n as executeAction, o as coerce, r as isRscActionRequest, t as buildNoJsResponse, w as setMutableCookieContext, x as markResponseFlushed, y as getSearchParams } from "../_chunks/actions-CHFblsdT.js";
7
7
  import "../client/error-boundary.js";
8
- import { n as toBracketKey } from "../_chunks/resolve-schema-DU2nbVOi.js";
9
- import "../_chunks/segment-context-Bg0pFbLT.js";
8
+ import { n as toBracketKey } from "../_chunks/resolve-schema-D3CbcdCW.js";
9
+ import "../_chunks/segment-context-BnxoPSFQ.js";
10
10
  import { readFile } from "node:fs/promises";
11
11
  import "node:crypto";
12
12
  import React, { createElement } from "react";
@@ -1621,6 +1621,7 @@ function escapeXml(str) {
1621
1621
  * followed by '/' or be an exact match.
1622
1622
  */
1623
1623
  function hasSegmentPrefix(pathname, prefix) {
1624
+ if (prefix === "/") return true;
1624
1625
  if (!pathname.startsWith(prefix)) return false;
1625
1626
  return pathname.length === prefix.length || pathname[prefix.length] === "/";
1626
1627
  }
@@ -1830,7 +1831,7 @@ async function runProxyPhase(config, getProxy, req, method, path) {
1830
1831
  const detailed = config.serverTiming === "detailed";
1831
1832
  try {
1832
1833
  const proxyExport = await getProxy();
1833
- const proxyFn = () => runProxy(proxyExport, req, () => handleRequest(config, req, method, path));
1834
+ const proxyFn = () => runProxy(proxyExport, req, () => handleRequest(config, req, method, path, true));
1834
1835
  return {
1835
1836
  kind: "response",
1836
1837
  phase: "proxy",
@@ -1944,16 +1945,23 @@ async function runRenderPhase(config, req, match, responseHeaders, requestHeader
1944
1945
  *
1945
1946
  * Used both as the top-level entry (when no proxy.ts is configured) and as
1946
1947
  * the `next()` continuation passed to `runProxy()`.
1948
+ *
1949
+ * @param pathIsCanonical When true, `path` has already been canonicalized by
1950
+ * `createPipeline` — skip re-canonicalization to prevent double-decode.
1951
+ * When false (default), runs canonicalize as a safety net for direct callers.
1947
1952
  */
1948
- async function handleRequest(config, req, method, path) {
1953
+ async function handleRequest(config, req, method, path, pathIsCanonical) {
1949
1954
  const stripTrailingSlash = config.stripTrailingSlash ?? true;
1950
- const url = new URL(req.url);
1951
- const result = canonicalize(url.pathname, stripTrailingSlash);
1952
- if (!result.ok) {
1953
- if (isDebug()) console.warn(`[timber] URL canonicalization rejected ${method} ${url.pathname} — responding with ${result.status}\n This usually means the URL contains encoded separators (%2f, %5c),\n null bytes (%00), path traversal (..), or malformed percent-encoding.`);
1954
- return new Response(null, { status: result.status });
1955
+ let canonicalPathname;
1956
+ if (pathIsCanonical) canonicalPathname = path;
1957
+ else {
1958
+ const result = canonicalize(path, stripTrailingSlash);
1959
+ if (!result.ok) {
1960
+ if (isDebug()) console.warn(`[timber] URL canonicalization rejected ${method} ${path} — responding with ${result.status}\n This usually means the URL contains encoded separators (%2f, %5c),\n null bytes (%00), path traversal (..), or malformed percent-encoding.`);
1961
+ return new Response(null, { status: result.status });
1962
+ }
1963
+ canonicalPathname = result.pathname;
1955
1964
  }
1956
- const canonicalPathname = result.pathname;
1957
1965
  if (config.matchMetadataRoute) {
1958
1966
  const metaMatch = config.matchMetadataRoute(canonicalPathname);
1959
1967
  if (metaMatch) try {
@@ -2033,7 +2041,7 @@ async function handleRequest(config, req, method, path) {
2033
2041
  }
2034
2042
  }
2035
2043
  if (!match) {
2036
- if (isDebug()) console.warn(`[timber] No route matched for pathname: ${canonicalPathname}\n Raw URL: ${url.pathname}\n Method: ${method}`);
2044
+ if (isDebug()) console.warn(`[timber] No route matched for pathname: ${canonicalPathname}\n Input path: ${path}\n Method: ${method}`);
2037
2045
  if (config.renderNoMatch) {
2038
2046
  const responseHeaders = new Headers();
2039
2047
  return cloneWithMutableHeaders(await config.renderNoMatch(req, responseHeaders));
@@ -2136,8 +2144,14 @@ function createPipeline(config) {
2136
2144
  method,
2137
2145
  path: canonicalPath
2138
2146
  });
2139
- else result = await handleRequest(config, canonicalReq, method, canonicalPath);
2147
+ else result = await handleRequest(config, canonicalReq, method, canonicalPath, true);
2140
2148
  await setSpanAttribute("http.response.status_code", result.status);
2149
+ const varyTokens = ["Accept"];
2150
+ if (config.interceptionRewrites?.length) varyTokens.push("X-Timber-URL");
2151
+ const existingVary = result.headers.get("Vary");
2152
+ const existingTokens = existingVary ? existingVary.toLowerCase().split(",").map((t) => t.trim()) : [];
2153
+ const newTokens = varyTokens.filter((t) => !existingTokens.includes(t.toLowerCase()));
2154
+ if (newTokens.length > 0) result.headers.set("Vary", existingVary ? `${existingVary}, ${newTokens.join(", ")}` : newTokens.join(", "));
2141
2155
  if (serverTiming === "detailed") {
2142
2156
  const timingHeader = getServerTimingHeader();
2143
2157
  if (timingHeader) result.headers.set("Server-Timing", timingHeader);
@@ -2844,12 +2858,34 @@ var SAFE_METHODS = new Set([
2844
2858
  "OPTIONS"
2845
2859
  ]);
2846
2860
  /**
2847
- * Validate the Origin header against the request's Host.
2861
+ * Derive the request's scheme from trusted sources.
2862
+ *
2863
+ * Priority:
2864
+ * 1. X-Forwarded-Proto (set by reverse proxies / load balancers)
2865
+ * 2. Request URL protocol
2866
+ *
2867
+ * Falls back to 'https' (fail closed) if neither is available.
2868
+ */
2869
+ function deriveRequestScheme(req) {
2870
+ const forwarded = req.headers.get("X-Forwarded-Proto");
2871
+ if (forwarded) {
2872
+ const proto = forwarded.split(",")[0].trim().toLowerCase();
2873
+ if (proto === "http" || proto === "https") return proto;
2874
+ }
2875
+ try {
2876
+ return new URL(req.url).protocol.replace(":", "");
2877
+ } catch {
2878
+ return "https";
2879
+ }
2880
+ }
2881
+ /**
2882
+ * Validate the Origin header against the request's full origin
2883
+ * (scheme + host + port).
2848
2884
  *
2849
2885
  * For mutation methods (POST, PUT, PATCH, DELETE):
2850
2886
  * - If `csrf: false`, skip validation.
2851
2887
  * - If `allowedOrigins` is set, Origin must match one exactly (no wildcards).
2852
- * - Otherwise, Origin's host must match the request's Host header.
2888
+ * - Otherwise, Origin must match the derived request origin.
2853
2889
  *
2854
2890
  * Safe methods (GET, HEAD, OPTIONS) always pass.
2855
2891
  */
@@ -2870,16 +2906,26 @@ function validateCsrf(req, config) {
2870
2906
  ok: false,
2871
2907
  status: 403
2872
2908
  };
2873
- let originHost;
2909
+ let originOrigin;
2910
+ try {
2911
+ originOrigin = new URL(origin).origin;
2912
+ } catch {
2913
+ return {
2914
+ ok: false,
2915
+ status: 403
2916
+ };
2917
+ }
2918
+ const scheme = deriveRequestScheme(req);
2919
+ let expectedOrigin;
2874
2920
  try {
2875
- originHost = new URL(origin).host;
2921
+ expectedOrigin = new URL(`${scheme}://${host}`).origin;
2876
2922
  } catch {
2877
2923
  return {
2878
2924
  ok: false,
2879
2925
  status: 403
2880
2926
  };
2881
2927
  }
2882
- return originHost === host ? { ok: true } : {
2928
+ return originOrigin === expectedOrigin ? { ok: true } : {
2883
2929
  ok: false,
2884
2930
  status: 403
2885
2931
  };
@@ -2909,6 +2955,8 @@ function parseBodySize(size) {
2909
2955
  default: throw new Error(`Unknown size unit: "${unit}"`);
2910
2956
  }
2911
2957
  }
2958
+ /** Strict integer pattern: one or more digits, nothing else. */
2959
+ var STRICT_INTEGER_RE = /^\d+$/;
2912
2960
  /** Check whether a request body exceeds the configured size limit (stateless, no ALS). */
2913
2961
  function enforceBodyLimits(req, kind, config) {
2914
2962
  const contentLength = req.headers.get("Content-Length");
@@ -2916,12 +2964,12 @@ function enforceBodyLimits(req, kind, config) {
2916
2964
  ok: false,
2917
2965
  status: 411
2918
2966
  };
2919
- const bodySize = Number.parseInt(contentLength, 10);
2920
- if (Number.isNaN(bodySize)) return {
2967
+ const trimmed = contentLength.trim();
2968
+ if (!STRICT_INTEGER_RE.test(trimmed)) return {
2921
2969
  ok: false,
2922
2970
  status: 411
2923
2971
  };
2924
- return bodySize <= resolveLimit(kind, config) ? { ok: true } : {
2972
+ return Number.parseInt(trimmed, 10) <= resolveLimit(kind, config) ? { ok: true } : {
2925
2973
  ok: false,
2926
2974
  status: 413
2927
2975
  };