mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-13 14:32:03 +00:00
fix(api-handler): widen safeRequestProp narrow-catch to tolerate undefined requests
Follow-up to commit `61d156e7`. The narrow catch initially recognised only the V8 private-field TypeError wordings, but unit tests routinely invoke route handlers as `GET()` with no arguments — the wrapper then reads `args[0]` as `undefined` and the read callback raises `TypeError: Cannot read properties of undefined (reading 'url')`, which is not a private-field error. The classifier is renamed to `isTolerableRequestProbeError` and now also matches the "cannot read properties of undefined / null" TypeError shape (both modern V8 wording and the older `Cannot read property 'X' of undefined` form). Any other TypeError still rethrows so production regressions stay visible. This restores the no-arg-direct-invoke contract that `src/app/api/auth/me/source-priority/__tests__/route.test.ts` and similar vitest suites rely on (`GET()` with no request to assert the auth-gate path returns 401). Verification: pnpm typecheck → clean pnpm vitest run api-handler-safe-request-prop → 11 / 11 pass pnpm vitest run src/app/api/auth/me/source-priority → 6 / 6 pass pnpm vitest run (full unit) → 3751 / 3751
This commit is contained in:
1 parent
bbc0afd555
commit
fcda115123
2 files changed
+57
-21
No files matched your search
+21
-7
@@ -41,18 +41,32 @@ export class HttpError extends Error {
|
||||
// and fall back to safe defaults so logging instrumentation never
|
||||
// crashes the handler.
|
||||
//
|
||||
// The catch is narrowed to the V8 private-field TypeError. Any other
|
||||
// The catch is narrowed to two well-known shapes: the V8 private-field
|
||||
// TypeError, and the `Cannot read properties of undefined/null` shape
|
||||
// raised when the wrapper is invoked without a request (vitest tests
|
||||
// frequently invoke handlers as `GET()` with no args, mirroring the
|
||||
// shape Next.js exercises for the static-export pass). Any other
|
||||
// exception is a real bug in the read callback or in a downstream
|
||||
// header parser and must surface — swallowing it here would hide
|
||||
// header parser and must surface — swallowing it would hide
|
||||
// regressions in production instrumentation.
|
||||
function isPrivateFieldAccessError(err: unknown): boolean {
|
||||
function isTolerableRequestProbeError(err: unknown): boolean {
|
||||
if (!(err instanceof TypeError)) return false;
|
||||
const msg = err.message ?? "";
|
||||
return (
|
||||
// V8 — current
|
||||
msg.includes("private member") ||
|
||||
// V8 — alternative
|
||||
msg.includes("private field") ||
|
||||
// Bun / older V8 wording variant
|
||||
msg.includes("private name")
|
||||
// Bun / older V8
|
||||
msg.includes("private name") ||
|
||||
// No request handed in at all (vitest direct-invoke or
|
||||
// force-static placeholder reduced to undefined / null).
|
||||
// Covers both modern `Cannot read properties of undefined
|
||||
// (reading 'X')` and the older `Cannot read property 'X' of
|
||||
// undefined` wordings.
|
||||
/Cannot read propert(?:y|ies)\b.*\bof (?:undefined|null)\b/.test(
|
||||
msg,
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -64,7 +78,7 @@ function safeRequestProp<R>(
|
||||
try {
|
||||
return read(request as NextRequest);
|
||||
} catch (err) {
|
||||
if (isPrivateFieldAccessError(err)) return fallback;
|
||||
if (isTolerableRequestProbeError(err)) return fallback;
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
@@ -72,7 +86,7 @@ function safeRequestProp<R>(
|
||||
/** @internal — exposed for unit tests of the narrow-catch contract. */
|
||||
export const __testables = {
|
||||
safeRequestProp,
|
||||
isPrivateFieldAccessError,
|
||||
isTolerableRequestProbeError,
|
||||
};
|
||||
|
||||
// Next.js route handlers come in two shapes — `(request)` for static routes
|
||||
|
||||
Reference in new issue
Block a user