167 lines
6.6 KiB
JavaScript
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
|