kjelsrud.dev/node_modules/astro/dist/vite-plugin-astro-server/route.js
2023-07-19 21:31:30 +02:00

211 lines
6.6 KiB
JavaScript

import mime from "mime";
import { attachToResponse } from "../core/cookies/index.js";
import { call as callEndpoint } from "../core/endpoint/dev/index.js";
import { throwIfRedirectNotAllowed } from "../core/endpoint/index.js";
import { AstroErrorData, isAstroError } from "../core/errors/index.js";
import { warn } from "../core/logger/core.js";
import { loadMiddleware } from "../core/middleware/loadMiddleware.js";
import { preload, renderPage } from "../core/render/dev/index.js";
import { getParamsAndProps } from "../core/render/index.js";
import { createRequest } from "../core/request.js";
import { matchAllRoutes } from "../core/routing/index.js";
import { getSortedPreloadedMatches } from "../prerender/routing.js";
import { isServerLikeOutput } from "../prerender/utils.js";
import { log404 } from "./common.js";
import { handle404Response, writeSSRResult, writeWebResponse } from "./response.js";
const clientLocalsSymbol = Symbol.for("astro.locals");
function getCustom404Route(manifest) {
const route404 = /^\/404\/?$/;
return manifest.routes.find((r) => route404.test(r.route));
}
async function matchRoute(pathname, env, manifest) {
const { logging, settings, routeCache } = env;
const matches = matchAllRoutes(pathname, manifest);
const preloadedMatches = await getSortedPreloadedMatches({ env, matches, settings });
for await (const { preloadedComponent, route: maybeRoute, filePath } of preloadedMatches) {
try {
await getParamsAndProps({
mod: preloadedComponent,
route: maybeRoute,
routeCache,
pathname,
logging,
ssr: isServerLikeOutput(settings.config)
});
return {
route: maybeRoute,
filePath,
resolvedPathname: pathname,
preloadedComponent,
mod: preloadedComponent
};
} catch (e) {
if (isAstroError(e) && e.title === AstroErrorData.NoMatchingStaticPathFound.title) {
continue;
}
throw e;
}
}
const altPathname = pathname.replace(/(index)?\.html$/, "");
if (altPathname !== pathname) {
return await matchRoute(altPathname, env, manifest);
}
if (matches.length) {
const possibleRoutes = matches.flatMap((route) => route.component);
warn(
logging,
"getStaticPaths",
`${AstroErrorData.NoMatchingStaticPathFound.message(
pathname
)}
${AstroErrorData.NoMatchingStaticPathFound.hint(possibleRoutes)}`
);
}
log404(logging, pathname);
const custom404 = getCustom404Route(manifest);
if (custom404) {
const filePath = new URL(`./${custom404.component}`, settings.config.root);
const preloadedComponent = await preload({ env, filePath });
return {
route: custom404,
filePath,
resolvedPathname: pathname,
preloadedComponent,
mod: preloadedComponent
};
}
return void 0;
}
async function handleRoute({
matchedRoute,
url,
pathname,
status = getStatus(matchedRoute),
body,
origin,
env,
manifestData,
incomingRequest,
incomingResponse,
manifest
}) {
const { logging, settings } = env;
if (!matchedRoute) {
return handle404Response(origin, incomingRequest, incomingResponse);
}
if (matchedRoute.route.type === "redirect" && !settings.config.experimental.redirects) {
writeWebResponse(
incomingResponse,
new Response(`To enable redirect set experimental.redirects to \`true\`.`, {
status: 400
})
);
return;
}
const { config } = settings;
const filePath = matchedRoute.filePath;
const { route, preloadedComponent } = matchedRoute;
const buildingToSSR = isServerLikeOutput(config);
const request = createRequest({
url,
headers: buildingToSSR ? incomingRequest.headers : new Headers(),
method: incomingRequest.method,
body,
logging,
ssr: buildingToSSR,
clientAddress: buildingToSSR ? incomingRequest.socket.remoteAddress : void 0,
locals: Reflect.get(incomingRequest, clientLocalsSymbol)
// Allows adapters to pass in locals in dev mode.
});
for (const [name, value] of Object.entries(config.server.headers ?? {})) {
if (value)
incomingResponse.setHeader(name, value);
}
const options = {
env,
filePath,
preload: preloadedComponent,
pathname,
request,
route
};
const middleware = await loadMiddleware(env.loader, env.settings.config.srcDir);
if (middleware) {
options.middleware = middleware;
}
if (route.type === "endpoint") {
const result = await callEndpoint(options);
if (result.type === "response") {
if (result.response.headers.get("X-Astro-Response") === "Not-Found") {
const fourOhFourRoute = await matchRoute("/404", env, manifestData);
return handleRoute({
matchedRoute: fourOhFourRoute,
url: new URL("/404", url),
pathname: "/404",
status: 404,
body,
origin,
env,
manifestData,
incomingRequest,
incomingResponse,
manifest
});
}
throwIfRedirectNotAllowed(result.response, config);
await writeWebResponse(incomingResponse, result.response);
} else {
let contentType = "text/plain";
const filepath = route.pathname || route.segments.map((segment) => segment.map((p) => p.content).join("")).join("/");
const computedMimeType = mime.getType(filepath);
if (computedMimeType) {
contentType = computedMimeType;
}
const response = new Response(Buffer.from(result.body, result.encoding), {
status: 200,
headers: {
"Content-Type": `${contentType};charset=utf-8`
}
});
attachToResponse(response, result.cookies);
await writeWebResponse(incomingResponse, response);
}
} else {
const result = await renderPage(options);
if (result.status === 404) {
const fourOhFourRoute = await matchRoute("/404", env, manifestData);
return handleRoute({
...options,
matchedRoute: fourOhFourRoute,
url: new URL(pathname, url),
status: 404,
body,
origin,
env,
manifestData,
incomingRequest,
incomingResponse,
manifest
});
}
throwIfRedirectNotAllowed(result, config);
let response = result;
if (status && response.status !== status) {
response = new Response(result.body, { ...result, status });
}
return await writeSSRResult(request, response, incomingResponse);
}
}
function getStatus(matchedRoute) {
if (!matchedRoute)
return 404;
if (matchedRoute.route.route === "/404")
return 404;
if (matchedRoute.route.route === "/500")
return 500;
}
export {
handleRoute,
matchRoute
};