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, workerType: "render" }, { pages: { 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