From 1b1274f4d35d976b97a2106ccdc6bd45be34f8ca Mon Sep 17 00:00:00 2001 From: hjhopp <33412234+hjhopp@users.noreply.github.com> Date: Tue, 12 Dec 2023 08:05:52 -0800 Subject: [PATCH] fix: distinguish better between not found and internal error (#11131) Create dedicated NotFound error class for this --- .changeset/warm-otters-compete.md | 5 +++++ packages/kit/src/runtime/client/client.js | 7 +++++-- packages/kit/src/runtime/control.js | 12 ++++++++++++ packages/kit/src/runtime/server/respond.js | 4 ++-- packages/kit/src/runtime/server/utils.js | 20 ++++++++++---------- 5 files changed, 34 insertions(+), 14 deletions(-) create mode 100644 .changeset/warm-otters-compete.md diff --git a/.changeset/warm-otters-compete.md b/.changeset/warm-otters-compete.md new file mode 100644 index 000000000000..958a8d40b8a3 --- /dev/null +++ b/.changeset/warm-otters-compete.md @@ -0,0 +1,5 @@ +--- +'@sveltejs/kit': patch +--- + +fix: distinguish better between not-found and internal-error diff --git a/packages/kit/src/runtime/client/client.js b/packages/kit/src/runtime/client/client.js index c9216056da92..f64e3447f224 100644 --- a/packages/kit/src/runtime/client/client.js +++ b/packages/kit/src/runtime/client/client.js @@ -31,7 +31,7 @@ import * as devalue from 'devalue'; import { compact } from '../../utils/array.js'; import { validate_page_exports } from '../../utils/exports.js'; import { unwrap_promises } from '../../utils/promises.js'; -import { HttpError, Redirect } from '../control.js'; +import { HttpError, Redirect, NotFound } from '../control.js'; import { INVALIDATED_PARAM, TRAILING_SLASH_PARAM, validate_depends } from '../shared.js'; import { INDEX_KEY, PRELOAD_PRIORITIES, SCROLL_KEY, SNAPSHOT_KEY } from './constants.js'; import { stores } from './singletons.js'; @@ -1331,7 +1331,10 @@ export function create_client(app, target) { return ( app.hooks.handleError({ error, event }) ?? - /** @type {any} */ ({ message: event.route.id != null ? 'Internal Error' : 'Not Found' }) + /** @type {any} */ ({ + message: + event.route.id === null && error instanceof NotFound ? 'Not Found' : 'Internal Error' + }) ); } diff --git a/packages/kit/src/runtime/control.js b/packages/kit/src/runtime/control.js index d27725429038..6bacb73f9273 100644 --- a/packages/kit/src/runtime/control.js +++ b/packages/kit/src/runtime/control.js @@ -30,6 +30,18 @@ export class Redirect { } } +export class NotFound extends Error { + /** + * @param {string} pathname + */ + constructor(pathname) { + super(); + + this.status = 404; + this.message = `Not found: ${pathname}`; + } +} + /** * @template {Record | undefined} [T=undefined] */ diff --git a/packages/kit/src/runtime/server/respond.js b/packages/kit/src/runtime/server/respond.js index 22fadabf38d3..4e183c53a4f0 100644 --- a/packages/kit/src/runtime/server/respond.js +++ b/packages/kit/src/runtime/server/respond.js @@ -18,7 +18,7 @@ import { exec } from '../../utils/routing.js'; import { redirect_json_response, render_data } from './data/index.js'; import { add_cookies_to_headers, get_cookies } from './cookie.js'; import { create_fetch } from './fetch.js'; -import { Redirect } from '../control.js'; +import { Redirect, NotFound } from '../control.js'; import { validate_layout_exports, validate_layout_server_exports, @@ -480,7 +480,7 @@ export async function respond(request, options, manifest, state) { manifest, state, status: 404, - error: new Error(`Not found: ${event.url.pathname}`), + error: new NotFound(event.url.pathname), resolve_opts }); } diff --git a/packages/kit/src/runtime/server/utils.js b/packages/kit/src/runtime/server/utils.js index 8605076494c6..89cd4e9b8ec5 100644 --- a/packages/kit/src/runtime/server/utils.js +++ b/packages/kit/src/runtime/server/utils.js @@ -2,7 +2,7 @@ import { DEV } from 'esm-env'; import { json, text } from '../../exports/index.js'; import { coalesce_to_error } from '../../utils/error.js'; import { negotiate } from '../../utils/http.js'; -import { HttpError } from '../control.js'; +import { HttpError, NotFound } from '../control.js'; import { fix_stack_trace } from '../shared-server.js'; import { ENDPOINT_METHODS } from '../../constants.js'; @@ -97,17 +97,17 @@ export async function handle_fatal_error(event, options, error) { export async function handle_error_and_jsonify(event, options, error) { if (error instanceof HttpError) { return error.body; - } else { - if (__SVELTEKIT_DEV__ && typeof error == 'object') { - fix_stack_trace(error); - } + } - return ( - (await options.hooks.handleError({ error, event })) ?? { - message: event.route.id != null ? 'Internal Error' : 'Not Found' - } - ); + if (__SVELTEKIT_DEV__ && typeof error == 'object') { + fix_stack_trace(error); } + + return ( + (await options.hooks.handleError({ error, event })) ?? { + message: event.route.id === null && error instanceof NotFound ? 'Not Found' : 'Internal Error' + } + ); } /**