nitropage
Version:
A free and open source, extensible visual page builder based on SolidStart.
90 lines (77 loc) • 3.07 kB
text/typescript
import {
getRequestURL,
send,
sendRedirect,
setResponseHeader,
setResponseHeaders,
setResponseStatus,
} from "h3";
import { NitroApp } from "../types";
const errorHandlerPlugin = (nitroApp: NitroApp) => {
const origErrorHandler = nitroApp.h3App.options.onError!;
nitroApp.h3App.options.onError = async (error, event) => {
const url = getRequestURL(event);
const referer = event.headers.get("referer");
const isServerFunction =
url.pathname === "/_server" || url.pathname === "/_server/";
// TODO: Fix this in solid-start
// E.g. GET-Requesting server functions results in undescriptive errors
// - If referer is missing, this results in "Invalid URL":
// https://github.com/solidjs/solid-start/blob/5568611d38ba30a9b03455d82e8f7a5afc0d5af8/packages/start/src/runtime/server-handler.ts#L287
// - If parsed is empty, this results in "Cannot read properties of undefined (reading 'entries')":
// https://github.com/solidjs/solid-start/blob/5568611d38ba30a9b03455d82e8f7a5afc0d5af8/packages/start/src/runtime/server-handler.ts#L297
if (isServerFunction && !referer && error.message === "Invalid URL") {
setResponseStatus(event, 400, "400 Bad Request");
return await send(event, "");
}
const isSensitive = error.unhandled || error.fatal;
if (isSensitive && import.meta.env.DEV) {
console.error(error);
}
if (!referer || !isServerFunction) {
return await origErrorHandler(error, event);
}
const result = await nitroApp.hooks.callHook("error", error, { event });
if (result || event.handled) {
return result;
}
const statusMessage = error.statusMessage || "Server Error";
const errorMessage =
!isSensitive || import.meta.env.DEV
? error.message
: "Something went wrong";
setResponseStatus(event, error.statusCode, statusMessage);
// Makes sure that the error is being catched in solid-router forms
// https://github.com/solidjs/solid-start/issues/1434#issuecomment-2097769617
// https://github.com/solidjs/solid-start/blob/v1.0.0-rc.1/packages/start/src/runtime/server-handler.ts#L223
setResponseHeaders(event, {
"X-Error": errorMessage.split("\n")[0],
});
const acceptsHtml = event.headers.get("accept")?.startsWith("text/html");
if (!acceptsHtml) {
return await send(
event,
JSON.stringify({
message: errorMessage,
}),
"application/json",
);
}
// Inspired by: https://github.com/solidjs/solid-start/blob/cceb4ed88c831387af94fa6a9548a401ab0ff17a/packages/start/src/runtime/server-handler.ts#L289
setResponseHeader(
event,
"set-cookie",
`flash=${encodeURIComponent(
JSON.stringify({
url: url.pathname + url.search,
result: errorMessage,
thrown: true,
error: true,
input: [],
}),
)}; Secure; HttpOnly;`,
);
return await sendRedirect(event, referer, 302);
};
};
export default errorHandlerPlugin;