astro
Version:
Astro is a modern site builder with web best practices, performance, and DX front-of-mind.
83 lines (82 loc) • 2.9 kB
JavaScript
import { FetchState } from "../fetch/fetch-state.js";
import { AstroMiddleware } from "../middleware/astro-middleware.js";
import { PagesHandler } from "../pages/handler.js";
import { getCustom404Route, getCustom500Route } from "../routing/helpers.js";
import { isAstroError } from "./index.js";
import { MiddlewareNoDataOrNextCalled, MiddlewareNotAResponse } from "./errors-data.js";
class DevErrorHandler {
#app;
#shouldInjectCspMetaTags;
#astroMiddleware;
#pagesHandler;
constructor(app, options) {
this.#app = app;
this.#shouldInjectCspMetaTags = options.shouldInjectCspMetaTags;
this.#astroMiddleware = new AstroMiddleware(app.pipeline);
this.#pagesHandler = new PagesHandler(app.pipeline);
}
async renderError(request, {
skipMiddleware = false,
error,
status,
response: _response,
pathname,
...resolvedRenderOptions
}) {
if (isAstroError(error) && [MiddlewareNoDataOrNextCalled.name, MiddlewareNotAResponse.name].includes(error.name)) {
throw error;
}
const app = this.#app;
const shouldInjectCspMetaTags = this.#shouldInjectCspMetaTags;
const resolvedPathname = pathname ?? new FetchState(app.pipeline, request).pathname;
const renderRoute = async (routeData) => {
try {
const preloadedComponent = await app.pipeline.getComponentByRoute(routeData);
const errorState = new FetchState(app.pipeline, request);
errorState.skipMiddleware = skipMiddleware;
errorState.clientAddress = resolvedRenderOptions.clientAddress;
errorState.shouldInjectCspMetaTags = shouldInjectCspMetaTags ? !!app.manifest.csp : false;
errorState.routeData = routeData;
errorState.pathname = resolvedPathname;
errorState.status = status;
errorState.componentInstance = preloadedComponent;
errorState.locals = resolvedRenderOptions.locals ?? {};
errorState.initialProps = { error };
const response = await this.#astroMiddleware.handle(
errorState,
this.#pagesHandler.handle.bind(this.#pagesHandler)
);
if (error) {
app.logger.error("router", error.stack || error.message);
}
return response;
} catch (_err) {
if (skipMiddleware === false) {
return this.renderError(request, {
...resolvedRenderOptions,
status: 500,
skipMiddleware: true,
error: _err,
pathname: resolvedPathname
});
}
throw _err;
}
};
if (status === 404) {
const custom404 = getCustom404Route(app.manifestData);
if (custom404) {
return renderRoute(custom404);
}
}
const custom500 = getCustom500Route(app.manifestData);
if (!custom500) {
throw error;
} else {
return renderRoute(custom500);
}
}
}
export {
DevErrorHandler
};