securityos/node_modules/next/dist/esm/server/lib/route-resolver.js

167 lines
6.6 KiB
JavaScript

import "../require-hook";
import "../node-polyfill-fetch";
import url from "url";
import path from "path";
import { findPageFile } from "./find-page-file";
import { getRequestMeta } from "../request-meta";
import setupDebug from "next/dist/compiled/debug";
import { getCloneableBody } from "../body-streams";
import { findPagesDir } from "../../lib/find-pages-dir";
import { setupFsCheck } from "./router-utils/filesystem";
import { proxyRequest } from "./router-utils/proxy-request";
import { getResolveRoutes } from "./router-utils/resolve-routes";
import { PERMANENT_REDIRECT_STATUS } from "../../shared/lib/constants";
import { formatHostname } from "./format-hostname";
import { signalFromNodeResponse } from "../web/spec-extension/adapters/next-request";
import { getMiddlewareRouteMatcher } from "../../shared/lib/router/utils/middleware-route-matcher";
import { pipeReadable } from "../pipe-readable";
const debug = setupDebug("next:router-server");
export async function makeResolver(dir, nextConfig, middleware, { hostname = "localhost", port = 3000 }) {
const fsChecker = await setupFsCheck({
dir,
dev: true,
minimalMode: false,
config: nextConfig
});
const { appDir, pagesDir } = findPagesDir(dir);
// we format the hostname so that it can be fetched
const fetchHostname = formatHostname(hostname);
fsChecker.ensureCallback(async (item)=>{
let result = null;
if (item.type === "appFile") {
if (!appDir) {
throw new Error("no app dir present");
}
result = await findPageFile(appDir, item.itemPath, nextConfig.pageExtensions, true);
} else if (item.type === "pageFile") {
if (!pagesDir) {
throw new Error("no pages dir present");
}
result = await findPageFile(pagesDir, item.itemPath, nextConfig.pageExtensions, false);
}
if (!result) {
throw new Error(`failed to find page file ${item.type} ${item.itemPath}`);
}
});
const distDir = path.join(dir, nextConfig.distDir);
const middlewareInfo = middleware ? {
name: "middleware",
paths: middleware.files.map((file)=>path.join(process.cwd(), file)),
wasm: [],
assets: []
} : {};
if (middleware == null ? void 0 : middleware.files.length) {
var _middleware_matcher;
fsChecker.middlewareMatcher = getMiddlewareRouteMatcher(((_middleware_matcher = middleware.matcher) == null ? void 0 : _middleware_matcher.map((item)=>({
regexp: item,
originalSource: item
}))) || [
{
regexp: ".*",
originalSource: "/:path*"
}
]);
}
const resolveRoutes = getResolveRoutes(fsChecker, nextConfig, {
dir,
port,
hostname,
isNodeDebugging: false,
dev: true
}, {
async initialize () {
return {
async requestHandler (req, res) {
if (!req.headers["x-middleware-invoke"]) {
throw new Error(`Invariant unexpected request handler call`);
}
const cloneableBody = getCloneableBody(req);
const { run } = require("../web/sandbox");
const result = await run({
distDir,
name: middlewareInfo.name || "/",
paths: middlewareInfo.paths || [],
edgeFunctionEntry: middlewareInfo,
request: {
headers: req.headers,
method: req.method || "GET",
nextConfig: {
i18n: nextConfig.i18n,
basePath: nextConfig.basePath,
trailingSlash: nextConfig.trailingSlash
},
url: `http://${fetchHostname}:${port}${req.url}`,
body: cloneableBody,
signal: signalFromNodeResponse(res)
},
useCache: true,
onWarning: console.warn
});
const err = new Error();
err.result = result;
throw err;
},
async upgradeHandler () {
throw new Error(`Invariant: unexpected upgrade handler call`);
}
};
},
deleteAppClientCache () {},
async deleteCache () {},
async clearModuleContext () {},
async propagateServerField () {}
}, {});
return async function resolveRoute(req, res) {
const routeResult = await resolveRoutes({
req,
res,
isUpgradeReq: false,
signal: signalFromNodeResponse(res)
});
const { matchedOutput, bodyStream, statusCode, parsedUrl, resHeaders, finished } = routeResult;
debug("requestHandler!", req.url, {
matchedOutput,
statusCode,
resHeaders,
bodyStream: !!bodyStream,
parsedUrl: {
pathname: parsedUrl.pathname,
query: parsedUrl.query
},
finished
});
for (const key of Object.keys(resHeaders || {})){
res.setHeader(key, resHeaders[key]);
}
if (!bodyStream && statusCode && statusCode > 300 && statusCode < 400) {
const destination = url.format(parsedUrl);
res.statusCode = statusCode;
res.setHeader("location", destination);
if (statusCode === PERMANENT_REDIRECT_STATUS) {
res.setHeader("Refresh", `0;url=${destination}`);
}
res.end(destination);
return;
}
// handle middleware body response
if (bodyStream) {
res.statusCode = statusCode || 200;
return await pipeReadable(bodyStream, res);
}
if (finished && parsedUrl.protocol) {
var _getRequestMeta;
await proxyRequest(req, res, parsedUrl, undefined, (_getRequestMeta = getRequestMeta(req, "__NEXT_CLONABLE_BODY")) == null ? void 0 : _getRequestMeta.cloneBodyStream(), nextConfig.experimental.proxyTimeout);
return;
}
res.setHeader("x-nextjs-route-result", "1");
res.end();
return {
type: "rewrite",
statusCode: 200,
headers: resHeaders,
url: url.format(parsedUrl)
};
};
}
//# sourceMappingURL=route-resolver.js.map