astro
Version:
Astro is a modern site builder with web best practices, performance, and DX front-of-mind.
75 lines (74 loc) • 2.54 kB
JavaScript
import { ASTRO_ERROR_HEADER } from "../constants.js";
import { attachCookiesToResponse } from "../cookies/index.js";
import { getEnvironment } from "../environment/index.js";
import { renderErrorFromState } from "../errors/handler.js";
import { markFeatureUsed, FetchFeatures } from "../fetch/features.js";
import { applyRewriteToState } from "../rewrites/handler.js";
import { callMiddleware } from "./callMiddleware.js";
import { getMiddleware } from "./load.js";
import { sequence } from "./index.js";
async function handleMiddleware(state, renderRouteCallback) {
markFeatureUsed(state.manifest, FetchFeatures.middleware);
await state.getProps();
const apiContext = state.getAPIContext();
state.counter++;
if (state.counter === 4) {
return new Response("Loop Detected", {
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/508
status: 508,
statusText: "Astro detected a loop where you tried to call the rewriting logic more than four times."
});
}
const next = async (ctx, payload) => {
if (payload) {
state.logger.debug("router", "Called rewriting to:", payload);
const result = await getEnvironment(state.manifest).tryRewrite(
state.manifest,
payload,
state.request
);
applyRewriteToState(state, payload, result);
}
return renderRouteCallback(state, ctx);
};
let response;
if (state.skipMiddleware) {
response = await next(apiContext);
} else {
const middleware = await getMiddleware(state.manifest);
const composed = sequence(middleware);
response = await callMiddleware(composed, apiContext, next);
}
attachCookiesToResponse(response, state.cookies);
state.response = response;
return response;
}
async function handleMiddlewareWithErrorFallback(state, renderRouteCallback) {
if (!state.routeData) {
return new Response(null, { status: 404, headers: { [ASTRO_ERROR_HEADER]: "true" } });
}
let nextError;
try {
return await handleMiddleware(state, async (s, ctx) => {
try {
return await renderRouteCallback(s, ctx);
} catch (err) {
nextError = err;
throw err;
}
});
} catch (err) {
if (err === nextError) throw err;
state.logger.error(null, err.stack || err.message || String(err));
return renderErrorFromState(state, state.request, {
...state.renderOptions,
status: 500,
error: err,
pathname: state.pathname
});
}
}
export {
handleMiddleware,
handleMiddlewareWithErrorFallback
};