next-server.js 68 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. exports.default = void 0;
  6. require("./node-polyfill-fetch");
  7. require("./node-polyfill-web-streams");
  8. var _utils = require("../shared/lib/utils");
  9. var _fs = _interopRequireDefault(require("fs"));
  10. var _path = require("path");
  11. var _http = require("http");
  12. var _requestMeta = require("./request-meta");
  13. var _utils1 = require("../shared/lib/router/utils");
  14. var _constants = require("../shared/lib/constants");
  15. var _recursiveReaddirSync = require("./lib/recursive-readdir-sync");
  16. var _url = require("url");
  17. var _compression = _interopRequireDefault(require("next/dist/compiled/compression"));
  18. var _httpProxy = _interopRequireDefault(require("next/dist/compiled/http-proxy"));
  19. var _pathMatch = require("../shared/lib/router/utils/path-match");
  20. var _serverRouteUtils = require("./server-route-utils");
  21. var _getRouteFromAssetPath = _interopRequireDefault(require("../shared/lib/router/utils/get-route-from-asset-path"));
  22. var _sandbox = require("./web/sandbox");
  23. var _detectDomainLocale = require("../shared/lib/i18n/detect-domain-locale");
  24. var _node = require("./base-http/node");
  25. var _sendPayload = require("./send-payload");
  26. var _serveStatic = require("./serve-static");
  27. var _node1 = require("./api-utils/node");
  28. var _render = require("./render");
  29. var _appRender = require("./app-render");
  30. var _parseUrl = require("../shared/lib/router/utils/parse-url");
  31. var Log = _interopRequireWildcard(require("../build/output/log"));
  32. var _requireHook = _interopRequireDefault(require("../build/webpack/require-hook"));
  33. var _baseServer = _interopRequireWildcard(require("./base-server"));
  34. Object.keys(_baseServer).forEach(function(key) {
  35. if (key === "default" || key === "__esModule") return;
  36. if (key in exports && exports[key] === _baseServer[key]) return;
  37. Object.defineProperty(exports, key, {
  38. enumerable: true,
  39. get: function() {
  40. return _baseServer[key];
  41. }
  42. });
  43. });
  44. var _require = require("./require");
  45. var _denormalizePagePath = require("../shared/lib/page-path/denormalize-page-path");
  46. var _normalizePagePath = require("../shared/lib/page-path/normalize-page-path");
  47. var _loadComponents = require("./load-components");
  48. var _isError = _interopRequireWildcard(require("../lib/is-error"));
  49. var _utils2 = require("./web/utils");
  50. var _relativizeUrl = require("../shared/lib/router/utils/relativize-url");
  51. var _prepareDestination = require("../shared/lib/router/utils/prepare-destination");
  52. var _normalizeLocalePath = require("../shared/lib/i18n/normalize-locale-path");
  53. var _routeMatcher = require("../shared/lib/router/utils/route-matcher");
  54. var _middlewareRouteMatcher = require("../shared/lib/router/utils/middleware-route-matcher");
  55. var _env = require("@next/env");
  56. var _querystring = require("../shared/lib/router/utils/querystring");
  57. var _removeTrailingSlash = require("../shared/lib/router/utils/remove-trailing-slash");
  58. var _getNextPathnameInfo = require("../shared/lib/router/utils/get-next-pathname-info");
  59. var _bodyStreams = require("./body-streams");
  60. var _apiUtils = require("./api-utils");
  61. var _utils3 = require("./utils");
  62. var _responseCache = _interopRequireDefault(require("./response-cache"));
  63. var _incrementalCache = require("./lib/incremental-cache");
  64. var _utils4 = require("../build/webpack/loaders/next-serverless-loader/utils");
  65. var _routeRegex = require("../shared/lib/router/utils/route-regex");
  66. var _appPaths = require("../shared/lib/router/utils/app-paths");
  67. class NextNodeServer extends _baseServer.default {
  68. constructor(options){
  69. // Initialize super class
  70. super(options);
  71. /**
  72. * This sets environment variable to be used at the time of SSR by head.tsx.
  73. * Using this from process.env allows targeting both serverless and SSR by calling
  74. * `process.env.__NEXT_OPTIMIZE_CSS`.
  75. */ if (this.renderOpts.optimizeFonts) {
  76. process.env.__NEXT_OPTIMIZE_FONTS = JSON.stringify(this.renderOpts.optimizeFonts);
  77. }
  78. if (this.renderOpts.optimizeCss) {
  79. process.env.__NEXT_OPTIMIZE_CSS = JSON.stringify(true);
  80. }
  81. if (this.renderOpts.nextScriptWorkers) {
  82. process.env.__NEXT_SCRIPT_WORKERS = JSON.stringify(true);
  83. }
  84. if (!this.minimalMode) {
  85. const { ImageOptimizerCache } = require("./image-optimizer");
  86. this.imageResponseCache = new _responseCache.default(new ImageOptimizerCache({
  87. distDir: this.distDir,
  88. nextConfig: this.nextConfig
  89. }), this.minimalMode);
  90. }
  91. if (!options.dev) {
  92. // pre-warm _document and _app as these will be
  93. // needed for most requests
  94. (0, _loadComponents).loadComponents({
  95. distDir: this.distDir,
  96. pathname: "/_document",
  97. serverless: this._isLikeServerless,
  98. hasServerComponents: false,
  99. isAppPath: false
  100. }).catch(()=>{});
  101. (0, _loadComponents).loadComponents({
  102. distDir: this.distDir,
  103. pathname: "/_app",
  104. serverless: this._isLikeServerless,
  105. hasServerComponents: false,
  106. isAppPath: false
  107. }).catch(()=>{});
  108. }
  109. }
  110. compression = this.nextConfig.compress && this.nextConfig.target === "server" ? (0, _compression).default() : undefined;
  111. loadEnvConfig({ dev , forceReload }) {
  112. (0, _env).loadEnvConfig(this.dir, dev, Log, forceReload);
  113. }
  114. getResponseCache({ dev }) {
  115. var ref;
  116. const incrementalCache = new _incrementalCache.IncrementalCache({
  117. fs: this.getCacheFilesystem(),
  118. dev,
  119. serverDistDir: this.serverDistDir,
  120. appDir: this.nextConfig.experimental.appDir,
  121. maxMemoryCacheSize: this.nextConfig.experimental.isrMemoryCacheSize,
  122. flushToDisk: !this.minimalMode && this.nextConfig.experimental.isrFlushToDisk,
  123. incrementalCacheHandlerPath: (ref = this.nextConfig.experimental) == null ? void 0 : ref.incrementalCacheHandlerPath,
  124. getPrerenderManifest: ()=>{
  125. if (dev) {
  126. return {
  127. version: -1,
  128. routes: {},
  129. dynamicRoutes: {},
  130. notFoundRoutes: [],
  131. preview: null
  132. };
  133. } else {
  134. return this.getPrerenderManifest();
  135. }
  136. }
  137. });
  138. return new _responseCache.default(incrementalCache, this.minimalMode);
  139. }
  140. getPublicDir() {
  141. return (0, _path).join(this.dir, _constants.CLIENT_PUBLIC_FILES_PATH);
  142. }
  143. getHasStaticDir() {
  144. return _fs.default.existsSync((0, _path).join(this.dir, "static"));
  145. }
  146. getPagesManifest() {
  147. return require((0, _path).join(this.serverDistDir, _constants.PAGES_MANIFEST));
  148. }
  149. getAppPathsManifest() {
  150. if (this.nextConfig.experimental.appDir) {
  151. const appPathsManifestPath = (0, _path).join(this.serverDistDir, _constants.APP_PATHS_MANIFEST);
  152. return require(appPathsManifestPath);
  153. }
  154. }
  155. async hasPage(pathname) {
  156. let found = false;
  157. try {
  158. var ref;
  159. found = !!this.getPagePath(pathname, (ref = this.nextConfig.i18n) == null ? void 0 : ref.locales);
  160. } catch (_) {}
  161. return found;
  162. }
  163. getBuildId() {
  164. const buildIdFile = (0, _path).join(this.distDir, _constants.BUILD_ID_FILE);
  165. try {
  166. return _fs.default.readFileSync(buildIdFile, "utf8").trim();
  167. } catch (err) {
  168. if (!_fs.default.existsSync(buildIdFile)) {
  169. throw new Error(`Could not find a production build in the '${this.distDir}' directory. Try building your app with 'next build' before starting the production server. https://nextjs.org/docs/messages/production-start-no-build-id`);
  170. }
  171. throw err;
  172. }
  173. }
  174. getCustomRoutes() {
  175. const customRoutes = this.getRoutesManifest();
  176. let rewrites;
  177. // rewrites can be stored as an array when an array is
  178. // returned in next.config.js so massage them into
  179. // the expected object format
  180. if (Array.isArray(customRoutes.rewrites)) {
  181. rewrites = {
  182. beforeFiles: [],
  183. afterFiles: customRoutes.rewrites,
  184. fallback: []
  185. };
  186. } else {
  187. rewrites = customRoutes.rewrites;
  188. }
  189. return Object.assign(customRoutes, {
  190. rewrites
  191. });
  192. }
  193. generateImageRoutes() {
  194. return [
  195. {
  196. match: (0, _pathMatch).getPathMatch("/_next/image"),
  197. type: "route",
  198. name: "_next/image catchall",
  199. fn: async (req, res, _params, parsedUrl)=>{
  200. if (this.minimalMode) {
  201. res.statusCode = 400;
  202. res.body("Bad Request").send();
  203. return {
  204. finished: true
  205. };
  206. }
  207. const { getHash , ImageOptimizerCache , sendResponse , ImageError } = require("./image-optimizer");
  208. if (!this.imageResponseCache) {
  209. throw new Error("invariant image optimizer cache was not initialized");
  210. }
  211. const imagesConfig = this.nextConfig.images;
  212. if (imagesConfig.loader !== "default") {
  213. await this.render404(req, res);
  214. return {
  215. finished: true
  216. };
  217. }
  218. const paramsResult = ImageOptimizerCache.validateParams(req.originalRequest, parsedUrl.query, this.nextConfig, !!this.renderOpts.dev);
  219. if ("errorMessage" in paramsResult) {
  220. res.statusCode = 400;
  221. res.body(paramsResult.errorMessage).send();
  222. return {
  223. finished: true
  224. };
  225. }
  226. const cacheKey = ImageOptimizerCache.getCacheKey(paramsResult);
  227. try {
  228. var ref;
  229. const cacheEntry = await this.imageResponseCache.get(cacheKey, async ()=>{
  230. const { buffer , contentType , maxAge } = await this.imageOptimizer(req, res, paramsResult);
  231. const etag = getHash([
  232. buffer
  233. ]);
  234. return {
  235. value: {
  236. kind: "IMAGE",
  237. buffer,
  238. etag,
  239. extension: (0, _serveStatic).getExtension(contentType)
  240. },
  241. revalidate: maxAge
  242. };
  243. }, {});
  244. if ((cacheEntry == null ? void 0 : (ref = cacheEntry.value) == null ? void 0 : ref.kind) !== "IMAGE") {
  245. throw new Error("invariant did not get entry from image response cache");
  246. }
  247. sendResponse(req.originalRequest, res.originalResponse, paramsResult.href, cacheEntry.value.extension, cacheEntry.value.buffer, paramsResult.isStatic, cacheEntry.isMiss ? "MISS" : cacheEntry.isStale ? "STALE" : "HIT", imagesConfig.contentSecurityPolicy, cacheEntry.revalidate || 0, Boolean(this.renderOpts.dev));
  248. } catch (err) {
  249. if (err instanceof ImageError) {
  250. res.statusCode = err.statusCode;
  251. res.body(err.message).send();
  252. return {
  253. finished: true
  254. };
  255. }
  256. throw err;
  257. }
  258. return {
  259. finished: true
  260. };
  261. }
  262. },
  263. ];
  264. }
  265. generateStaticRoutes() {
  266. return this.hasStaticDir ? [
  267. {
  268. // It's very important to keep this route's param optional.
  269. // (but it should support as many params as needed, separated by '/')
  270. // Otherwise this will lead to a pretty simple DOS attack.
  271. // See more: https://github.com/vercel/next.js/issues/2617
  272. match: (0, _pathMatch).getPathMatch("/static/:path*"),
  273. name: "static catchall",
  274. fn: async (req, res, params, parsedUrl)=>{
  275. const p = (0, _path).join(this.dir, "static", ...params.path);
  276. await this.serveStatic(req, res, p, parsedUrl);
  277. return {
  278. finished: true
  279. };
  280. }
  281. },
  282. ] : [];
  283. }
  284. setImmutableAssetCacheControl(res) {
  285. res.setHeader("Cache-Control", "public, max-age=31536000, immutable");
  286. }
  287. generateFsStaticRoutes() {
  288. return [
  289. {
  290. match: (0, _pathMatch).getPathMatch("/_next/static/:path*"),
  291. type: "route",
  292. name: "_next/static catchall",
  293. fn: async (req, res, params, parsedUrl)=>{
  294. // make sure to 404 for /_next/static itself
  295. if (!params.path) {
  296. await this.render404(req, res, parsedUrl);
  297. return {
  298. finished: true
  299. };
  300. }
  301. if (params.path[0] === _constants.CLIENT_STATIC_FILES_RUNTIME || params.path[0] === "chunks" || params.path[0] === "css" || params.path[0] === "image" || params.path[0] === "media" || params.path[0] === this.buildId || params.path[0] === "pages" || params.path[1] === "pages") {
  302. this.setImmutableAssetCacheControl(res);
  303. }
  304. const p = (0, _path).join(this.distDir, _constants.CLIENT_STATIC_FILES_PATH, ...params.path || []);
  305. await this.serveStatic(req, res, p, parsedUrl);
  306. return {
  307. finished: true
  308. };
  309. }
  310. },
  311. ];
  312. }
  313. generatePublicRoutes() {
  314. if (!_fs.default.existsSync(this.publicDir)) return [];
  315. const publicFiles = new Set((0, _recursiveReaddirSync).recursiveReadDirSync(this.publicDir).map((p)=>encodeURI(p.replace(/\\/g, "/"))));
  316. return [
  317. {
  318. match: (0, _pathMatch).getPathMatch("/:path*"),
  319. matchesBasePath: true,
  320. name: "public folder catchall",
  321. fn: async (req, res, params, parsedUrl)=>{
  322. const pathParts = params.path || [];
  323. const { basePath } = this.nextConfig;
  324. // if basePath is defined require it be present
  325. if (basePath) {
  326. const basePathParts = basePath.split("/");
  327. // remove first empty value
  328. basePathParts.shift();
  329. if (!basePathParts.every((part, idx)=>{
  330. return part === pathParts[idx];
  331. })) {
  332. return {
  333. finished: false
  334. };
  335. }
  336. pathParts.splice(0, basePathParts.length);
  337. }
  338. let path = `/${pathParts.join("/")}`;
  339. if (!publicFiles.has(path)) {
  340. // In `next-dev-server.ts`, we ensure encoded paths match
  341. // decoded paths on the filesystem. So we need do the
  342. // opposite here: make sure decoded paths match encoded.
  343. path = encodeURI(path);
  344. }
  345. if (publicFiles.has(path)) {
  346. await this.serveStatic(req, res, (0, _path).join(this.publicDir, ...pathParts), parsedUrl);
  347. return {
  348. finished: true
  349. };
  350. }
  351. return {
  352. finished: false
  353. };
  354. }
  355. },
  356. ];
  357. }
  358. _validFilesystemPathSet = null;
  359. getFilesystemPaths() {
  360. if (this._validFilesystemPathSet) {
  361. return this._validFilesystemPathSet;
  362. }
  363. const pathUserFilesStatic = (0, _path).join(this.dir, "static");
  364. let userFilesStatic = [];
  365. if (this.hasStaticDir && _fs.default.existsSync(pathUserFilesStatic)) {
  366. userFilesStatic = (0, _recursiveReaddirSync).recursiveReadDirSync(pathUserFilesStatic).map((f)=>(0, _path).join(".", "static", f));
  367. }
  368. let userFilesPublic = [];
  369. if (this.publicDir && _fs.default.existsSync(this.publicDir)) {
  370. userFilesPublic = (0, _recursiveReaddirSync).recursiveReadDirSync(this.publicDir).map((f)=>(0, _path).join(".", "public", f));
  371. }
  372. let nextFilesStatic = [];
  373. nextFilesStatic = !this.minimalMode && _fs.default.existsSync((0, _path).join(this.distDir, "static")) ? (0, _recursiveReaddirSync).recursiveReadDirSync((0, _path).join(this.distDir, "static")).map((f)=>(0, _path).join(".", (0, _path).relative(this.dir, this.distDir), "static", f)) : [];
  374. return this._validFilesystemPathSet = new Set([
  375. ...nextFilesStatic,
  376. ...userFilesPublic,
  377. ...userFilesStatic,
  378. ]);
  379. }
  380. sendRenderResult(req, res, options) {
  381. return (0, _sendPayload).sendRenderResult({
  382. req: req.originalRequest,
  383. res: res.originalResponse,
  384. ...options
  385. });
  386. }
  387. sendStatic(req, res, path) {
  388. return (0, _serveStatic).serveStatic(req.originalRequest, res.originalResponse, path);
  389. }
  390. handleCompression(req, res) {
  391. if (this.compression) {
  392. this.compression(req.originalRequest, res.originalResponse, ()=>{});
  393. }
  394. }
  395. async handleUpgrade(req, socket, head) {
  396. await this.router.execute(req, socket, (0, _url).parse(req.url, true), head);
  397. }
  398. async proxyRequest(req, res, parsedUrl, upgradeHead) {
  399. const { query } = parsedUrl;
  400. delete parsedUrl.query;
  401. parsedUrl.search = (0, _serverRouteUtils).stringifyQuery(req, query);
  402. const target = (0, _url).format(parsedUrl);
  403. const proxy = new _httpProxy.default({
  404. target,
  405. changeOrigin: true,
  406. ignorePath: true,
  407. xfwd: true,
  408. ws: true,
  409. // we limit proxy requests to 30s by default, in development
  410. // we don't time out WebSocket requests to allow proxying
  411. proxyTimeout: upgradeHead && this.renderOpts.dev ? undefined : this.nextConfig.experimental.proxyTimeout || 30000
  412. });
  413. await new Promise((proxyResolve, proxyReject)=>{
  414. let finished = false;
  415. proxy.on("error", (err)=>{
  416. console.error(`Failed to proxy ${target}`, err);
  417. if (!finished) {
  418. finished = true;
  419. proxyReject(err);
  420. }
  421. });
  422. // if upgrade head is present treat as WebSocket request
  423. if (upgradeHead) {
  424. proxy.on("proxyReqWs", (proxyReq)=>{
  425. proxyReq.on("close", ()=>{
  426. if (!finished) {
  427. finished = true;
  428. proxyResolve(true);
  429. }
  430. });
  431. });
  432. proxy.ws(req, res, upgradeHead);
  433. proxyResolve(true);
  434. } else {
  435. proxy.on("proxyReq", (proxyReq)=>{
  436. proxyReq.on("close", ()=>{
  437. if (!finished) {
  438. finished = true;
  439. proxyResolve(true);
  440. }
  441. });
  442. });
  443. proxy.web(req.originalRequest, res.originalResponse);
  444. }
  445. });
  446. return {
  447. finished: true
  448. };
  449. }
  450. async runApi(req, res, query, params, page, builtPagePath) {
  451. const edgeFunctions = this.getEdgeFunctions();
  452. for (const item of edgeFunctions){
  453. if (item.page === page) {
  454. const handledAsEdgeFunction = await this.runEdgeFunction({
  455. req,
  456. res,
  457. query,
  458. params,
  459. page,
  460. appPaths: null
  461. });
  462. if (handledAsEdgeFunction) {
  463. return true;
  464. }
  465. }
  466. }
  467. const pageModule = await require(builtPagePath);
  468. query = {
  469. ...query,
  470. ...params
  471. };
  472. delete query.__nextLocale;
  473. delete query.__nextDefaultLocale;
  474. if (!this.renderOpts.dev && this._isLikeServerless) {
  475. if (typeof pageModule.default === "function") {
  476. (0, _baseServer).prepareServerlessUrl(req, query);
  477. await pageModule.default(req, res);
  478. return true;
  479. }
  480. }
  481. await (0, _node1).apiResolver(req.originalRequest, res.originalResponse, query, pageModule, {
  482. ...this.renderOpts.previewProps,
  483. revalidate: (newReq, newRes)=>this.getRequestHandler()(new _node.NodeNextRequest(newReq), new _node.NodeNextResponse(newRes)),
  484. // internal config so is not typed
  485. trustHostHeader: this.nextConfig.experimental.trustHostHeader
  486. }, this.minimalMode, this.renderOpts.dev, page);
  487. return true;
  488. }
  489. async renderHTML(req, res, pathname, query, renderOpts) {
  490. // Due to the way we pass data by mutating `renderOpts`, we can't extend the
  491. // object here but only updating its `serverComponentManifest` field.
  492. // https://github.com/vercel/next.js/blob/df7cbd904c3bd85f399d1ce90680c0ecf92d2752/packages/next/server/render.tsx#L947-L952
  493. renderOpts.serverComponentManifest = this.serverComponentManifest;
  494. renderOpts.serverCSSManifest = this.serverCSSManifest;
  495. if (this.nextConfig.experimental.appDir && (renderOpts.isAppPath || query.__flight__)) {
  496. const isPagesDir = !renderOpts.isAppPath;
  497. return (0, _appRender).renderToHTMLOrFlight(req.originalRequest, res.originalResponse, pathname, query, renderOpts, isPagesDir);
  498. }
  499. return (0, _render).renderToHTML(req.originalRequest, res.originalResponse, pathname, query, renderOpts);
  500. }
  501. streamResponseChunk(res, chunk) {
  502. res.originalResponse.write(chunk);
  503. // When both compression and streaming are enabled, we need to explicitly
  504. // flush the response to avoid it being buffered by gzip.
  505. if (this.compression && "flush" in res.originalResponse) {
  506. res.originalResponse.flush();
  507. }
  508. }
  509. async imageOptimizer(req, res, paramsResult) {
  510. const { imageOptimizer } = require("./image-optimizer");
  511. return imageOptimizer(req.originalRequest, res.originalResponse, paramsResult, this.nextConfig, this.renderOpts.dev, (newReq, newRes, newParsedUrl)=>this.getRequestHandler()(new _node.NodeNextRequest(newReq), new _node.NodeNextResponse(newRes), newParsedUrl));
  512. }
  513. getPagePath(pathname, locales) {
  514. return (0, _require).getPagePath(pathname, this.distDir, this._isLikeServerless, this.renderOpts.dev, locales, this.nextConfig.experimental.appDir);
  515. }
  516. async renderPageComponent(ctx, bubbleNoFallback) {
  517. const edgeFunctions = this.getEdgeFunctions() || [];
  518. if (edgeFunctions.length) {
  519. const appPaths = this.getOriginalAppPaths(ctx.pathname);
  520. const isAppPath = Array.isArray(appPaths);
  521. let page = ctx.pathname;
  522. if (isAppPath) {
  523. // When it's an array, we need to pass all parallel routes to the loader.
  524. page = appPaths[0];
  525. }
  526. for (const item of edgeFunctions){
  527. if (item.page === page) {
  528. await this.runEdgeFunction({
  529. req: ctx.req,
  530. res: ctx.res,
  531. query: ctx.query,
  532. params: ctx.renderOpts.params,
  533. page,
  534. appPaths
  535. });
  536. return null;
  537. }
  538. }
  539. }
  540. return super.renderPageComponent(ctx, bubbleNoFallback);
  541. }
  542. async findPageComponents({ pathname , query , params , isAppPath }) {
  543. const paths = [
  544. pathname
  545. ];
  546. if (query.amp) {
  547. // try serving a static AMP version first
  548. paths.unshift((isAppPath ? (0, _appPaths).normalizeAppPath(pathname) : (0, _normalizePagePath).normalizePagePath(pathname)) + ".amp");
  549. }
  550. if (query.__nextLocale) {
  551. paths.unshift(...paths.map((path)=>`/${query.__nextLocale}${path === "/" ? "" : path}`));
  552. }
  553. for (const pagePath of paths){
  554. try {
  555. const components = await (0, _loadComponents).loadComponents({
  556. distDir: this.distDir,
  557. pathname: pagePath,
  558. serverless: !this.renderOpts.dev && this._isLikeServerless,
  559. hasServerComponents: !!this.renderOpts.serverComponents,
  560. isAppPath
  561. });
  562. if (query.__nextLocale && typeof components.Component === "string" && !pagePath.startsWith(`/${query.__nextLocale}`)) {
  563. continue;
  564. }
  565. return {
  566. components,
  567. query: {
  568. ...components.getStaticProps ? {
  569. amp: query.amp,
  570. __nextDataReq: query.__nextDataReq,
  571. __nextLocale: query.__nextLocale,
  572. __nextDefaultLocale: query.__nextDefaultLocale,
  573. __flight__: query.__flight__
  574. } : query,
  575. // For appDir params is excluded.
  576. ...(isAppPath ? {} : params) || {}
  577. }
  578. };
  579. } catch (err) {
  580. // we should only not throw if we failed to find the page
  581. // in the pages-manifest
  582. if (!(err instanceof _utils.PageNotFoundError)) {
  583. throw err;
  584. }
  585. }
  586. }
  587. return null;
  588. }
  589. getFontManifest() {
  590. return (0, _require).requireFontManifest(this.distDir, this._isLikeServerless);
  591. }
  592. getServerComponentManifest() {
  593. if (!this.nextConfig.experimental.serverComponents) return undefined;
  594. return require((0, _path).join(this.distDir, "server", _constants.FLIGHT_MANIFEST + ".json"));
  595. }
  596. getServerCSSManifest() {
  597. if (!this.nextConfig.experimental.serverComponents) return undefined;
  598. return require((0, _path).join(this.distDir, "server", _constants.FLIGHT_SERVER_CSS_MANIFEST + ".json"));
  599. }
  600. getFallback(page) {
  601. page = (0, _normalizePagePath).normalizePagePath(page);
  602. const cacheFs = this.getCacheFilesystem();
  603. return cacheFs.readFile((0, _path).join(this.serverDistDir, "pages", `${page}.html`));
  604. }
  605. generateRoutes() {
  606. const publicRoutes = this.generatePublicRoutes();
  607. const imageRoutes = this.generateImageRoutes();
  608. const staticFilesRoutes = this.generateStaticRoutes();
  609. const fsRoutes = [
  610. ...this.generateFsStaticRoutes(),
  611. {
  612. match: (0, _pathMatch).getPathMatch("/_next/data/:path*"),
  613. type: "route",
  614. name: "_next/data catchall",
  615. check: true,
  616. fn: async (req, res, params, _parsedUrl)=>{
  617. const isNextDataNormalizing = (0, _requestMeta).getRequestMeta(req, "_nextDataNormalizing");
  618. // Make sure to 404 for /_next/data/ itself and
  619. // we also want to 404 if the buildId isn't correct
  620. if (!params.path || params.path[0] !== this.buildId) {
  621. if (isNextDataNormalizing) {
  622. return {
  623. finished: false
  624. };
  625. }
  626. await this.render404(req, res, _parsedUrl);
  627. return {
  628. finished: true
  629. };
  630. }
  631. // remove buildId from URL
  632. params.path.shift();
  633. const lastParam = params.path[params.path.length - 1];
  634. // show 404 if it doesn't end with .json
  635. if (typeof lastParam !== "string" || !lastParam.endsWith(".json")) {
  636. await this.render404(req, res, _parsedUrl);
  637. return {
  638. finished: true
  639. };
  640. }
  641. // re-create page's pathname
  642. let pathname = `/${params.path.join("/")}`;
  643. pathname = (0, _getRouteFromAssetPath).default(pathname, ".json");
  644. // ensure trailing slash is normalized per config
  645. if (this.router.catchAllMiddleware[0]) {
  646. if (this.nextConfig.trailingSlash && !pathname.endsWith("/")) {
  647. pathname += "/";
  648. }
  649. if (!this.nextConfig.trailingSlash && pathname.length > 1 && pathname.endsWith("/")) {
  650. pathname = pathname.substring(0, pathname.length - 1);
  651. }
  652. }
  653. if (this.nextConfig.i18n) {
  654. const { host } = (req == null ? void 0 : req.headers) || {};
  655. // remove port from host and remove port if present
  656. const hostname = host == null ? void 0 : host.split(":")[0].toLowerCase();
  657. const localePathResult = (0, _normalizeLocalePath).normalizeLocalePath(pathname, this.nextConfig.i18n.locales);
  658. const { defaultLocale } = (0, _detectDomainLocale).detectDomainLocale(this.nextConfig.i18n.domains, hostname) || {};
  659. let detectedLocale = "";
  660. if (localePathResult.detectedLocale) {
  661. pathname = localePathResult.pathname;
  662. detectedLocale = localePathResult.detectedLocale;
  663. }
  664. _parsedUrl.query.__nextLocale = detectedLocale;
  665. _parsedUrl.query.__nextDefaultLocale = defaultLocale || this.nextConfig.i18n.defaultLocale;
  666. if (!detectedLocale && !this.router.catchAllMiddleware[0]) {
  667. _parsedUrl.query.__nextLocale = _parsedUrl.query.__nextDefaultLocale;
  668. await this.render404(req, res, _parsedUrl);
  669. return {
  670. finished: true
  671. };
  672. }
  673. }
  674. return {
  675. pathname,
  676. query: {
  677. ..._parsedUrl.query,
  678. __nextDataReq: "1"
  679. },
  680. finished: false
  681. };
  682. }
  683. },
  684. ...imageRoutes,
  685. {
  686. match: (0, _pathMatch).getPathMatch("/_next/:path*"),
  687. type: "route",
  688. name: "_next catchall",
  689. // This path is needed because `render()` does a check for `/_next` and the calls the routing again
  690. fn: async (req, res, _params, parsedUrl)=>{
  691. await this.render404(req, res, parsedUrl);
  692. return {
  693. finished: true
  694. };
  695. }
  696. },
  697. ...publicRoutes,
  698. ...staticFilesRoutes,
  699. ];
  700. const restrictedRedirectPaths = this.nextConfig.basePath ? [
  701. `${this.nextConfig.basePath}/_next`
  702. ] : [
  703. "/_next"
  704. ];
  705. // Headers come very first
  706. const headers = this.minimalMode ? [] : this.customRoutes.headers.map((rule)=>(0, _serverRouteUtils).createHeaderRoute({
  707. rule,
  708. restrictedRedirectPaths
  709. }));
  710. const redirects = this.minimalMode ? [] : this.customRoutes.redirects.map((rule)=>(0, _serverRouteUtils).createRedirectRoute({
  711. rule,
  712. restrictedRedirectPaths
  713. }));
  714. const rewrites = this.generateRewrites({
  715. restrictedRedirectPaths
  716. });
  717. const catchAllMiddleware = this.generateCatchAllMiddlewareRoute();
  718. const catchAllRoute = {
  719. match: (0, _pathMatch).getPathMatch("/:path*"),
  720. type: "route",
  721. matchesLocale: true,
  722. name: "Catchall render",
  723. fn: async (req, res, _params, parsedUrl)=>{
  724. let { pathname , query } = parsedUrl;
  725. if (!pathname) {
  726. throw new Error("pathname is undefined");
  727. }
  728. // next.js core assumes page path without trailing slash
  729. pathname = (0, _removeTrailingSlash).removeTrailingSlash(pathname);
  730. if (this.nextConfig.i18n) {
  731. var ref;
  732. const localePathResult = (0, _normalizeLocalePath).normalizeLocalePath(pathname, (ref = this.nextConfig.i18n) == null ? void 0 : ref.locales);
  733. if (localePathResult.detectedLocale) {
  734. pathname = localePathResult.pathname;
  735. parsedUrl.query.__nextLocale = localePathResult.detectedLocale;
  736. }
  737. }
  738. const bubbleNoFallback = !!query._nextBubbleNoFallback;
  739. if (pathname === "/api" || pathname.startsWith("/api/")) {
  740. delete query._nextBubbleNoFallback;
  741. const handled = await this.handleApiRequest(req, res, pathname, query);
  742. if (handled) {
  743. return {
  744. finished: true
  745. };
  746. }
  747. }
  748. try {
  749. await this.render(req, res, pathname, query, parsedUrl, true);
  750. return {
  751. finished: true
  752. };
  753. } catch (err) {
  754. if (err instanceof _baseServer.NoFallbackError && bubbleNoFallback) {
  755. return {
  756. finished: false
  757. };
  758. }
  759. throw err;
  760. }
  761. }
  762. };
  763. const { useFileSystemPublicRoutes } = this.nextConfig;
  764. if (useFileSystemPublicRoutes) {
  765. this.appPathRoutes = this.getAppPathRoutes();
  766. this.dynamicRoutes = this.getDynamicRoutes();
  767. }
  768. return {
  769. headers,
  770. fsRoutes,
  771. rewrites,
  772. redirects,
  773. catchAllRoute,
  774. catchAllMiddleware,
  775. useFileSystemPublicRoutes,
  776. dynamicRoutes: this.dynamicRoutes,
  777. pageChecker: this.hasPage.bind(this),
  778. nextConfig: this.nextConfig
  779. };
  780. }
  781. // Used to build API page in development
  782. async ensureApiPage(_pathname) {}
  783. /**
  784. * Resolves `API` request, in development builds on demand
  785. * @param req http request
  786. * @param res http response
  787. * @param pathname path of request
  788. */ async handleApiRequest(req, res, pathname, query) {
  789. let page = pathname;
  790. let params = undefined;
  791. let pageFound = !(0, _utils1).isDynamicRoute(page) && await this.hasPage(page);
  792. if (!pageFound && this.dynamicRoutes) {
  793. for (const dynamicRoute of this.dynamicRoutes){
  794. params = dynamicRoute.match(pathname) || undefined;
  795. if (dynamicRoute.page.startsWith("/api") && params) {
  796. page = dynamicRoute.page;
  797. pageFound = true;
  798. break;
  799. }
  800. }
  801. }
  802. if (!pageFound) {
  803. return false;
  804. }
  805. // Make sure the page is built before getting the path
  806. // or else it won't be in the manifest yet
  807. await this.ensureApiPage(page);
  808. let builtPagePath;
  809. try {
  810. builtPagePath = this.getPagePath(page);
  811. } catch (err) {
  812. if ((0, _isError).default(err) && err.code === "ENOENT") {
  813. return false;
  814. }
  815. throw err;
  816. }
  817. return this.runApi(req, res, query, params, page, builtPagePath);
  818. }
  819. getCacheFilesystem() {
  820. return {
  821. readFile: (f)=>_fs.default.promises.readFile(f, "utf8"),
  822. readFileSync: (f)=>_fs.default.readFileSync(f, "utf8"),
  823. writeFile: (f, d)=>_fs.default.promises.writeFile(f, d, "utf8"),
  824. mkdir: (dir)=>_fs.default.promises.mkdir(dir, {
  825. recursive: true
  826. }),
  827. stat: (f)=>_fs.default.promises.stat(f)
  828. };
  829. }
  830. normalizeReq(req) {
  831. return req instanceof _http.IncomingMessage ? new _node.NodeNextRequest(req) : req;
  832. }
  833. normalizeRes(res) {
  834. return res instanceof _http.ServerResponse ? new _node.NodeNextResponse(res) : res;
  835. }
  836. getRequestHandler() {
  837. const handler = super.getRequestHandler();
  838. return async (req, res, parsedUrl)=>{
  839. return handler(this.normalizeReq(req), this.normalizeRes(res), parsedUrl);
  840. };
  841. }
  842. async render(req, res, pathname, query, parsedUrl, internal = false) {
  843. return super.render(this.normalizeReq(req), this.normalizeRes(res), pathname, query, parsedUrl, internal);
  844. }
  845. async renderToHTML(req, res, pathname, query) {
  846. return super.renderToHTML(this.normalizeReq(req), this.normalizeRes(res), pathname, query);
  847. }
  848. async renderError(err, req, res, pathname, query, setHeaders) {
  849. return super.renderError(err, this.normalizeReq(req), this.normalizeRes(res), pathname, query, setHeaders);
  850. }
  851. async renderErrorToHTML(err, req, res, pathname, query) {
  852. return super.renderErrorToHTML(err, this.normalizeReq(req), this.normalizeRes(res), pathname, query);
  853. }
  854. async render404(req, res, parsedUrl, setHeaders) {
  855. return super.render404(this.normalizeReq(req), this.normalizeRes(res), parsedUrl, setHeaders);
  856. }
  857. async serveStatic(req, res, path, parsedUrl) {
  858. if (!this.isServeableUrl(path)) {
  859. return this.render404(req, res, parsedUrl);
  860. }
  861. if (!(req.method === "GET" || req.method === "HEAD")) {
  862. res.statusCode = 405;
  863. res.setHeader("Allow", [
  864. "GET",
  865. "HEAD"
  866. ]);
  867. return this.renderError(null, req, res, path);
  868. }
  869. try {
  870. await this.sendStatic(req, res, path);
  871. } catch (error) {
  872. if (!(0, _isError).default(error)) throw error;
  873. const err = error;
  874. if (err.code === "ENOENT" || err.statusCode === 404) {
  875. this.render404(req, res, parsedUrl);
  876. } else if (typeof err.statusCode === "number" && POSSIBLE_ERROR_CODE_FROM_SERVE_STATIC.has(err.statusCode)) {
  877. res.statusCode = err.statusCode;
  878. return this.renderError(err, req, res, path);
  879. } else {
  880. throw err;
  881. }
  882. }
  883. }
  884. getStaticRoutes() {
  885. return this.hasStaticDir ? [
  886. {
  887. // It's very important to keep this route's param optional.
  888. // (but it should support as many params as needed, separated by '/')
  889. // Otherwise this will lead to a pretty simple DOS attack.
  890. // See more: https://github.com/vercel/next.js/issues/2617
  891. match: (0, _pathMatch).getPathMatch("/static/:path*"),
  892. name: "static catchall",
  893. fn: async (req, res, params, parsedUrl)=>{
  894. const p = (0, _path).join(this.dir, "static", ...params.path);
  895. await this.serveStatic(req, res, p, parsedUrl);
  896. return {
  897. finished: true
  898. };
  899. }
  900. },
  901. ] : [];
  902. }
  903. isServeableUrl(untrustedFileUrl) {
  904. // This method mimics what the version of `send` we use does:
  905. // 1. decodeURIComponent:
  906. // https://github.com/pillarjs/send/blob/0.17.1/index.js#L989
  907. // https://github.com/pillarjs/send/blob/0.17.1/index.js#L518-L522
  908. // 2. resolve:
  909. // https://github.com/pillarjs/send/blob/de073ed3237ade9ff71c61673a34474b30e5d45b/index.js#L561
  910. let decodedUntrustedFilePath;
  911. try {
  912. // (1) Decode the URL so we have the proper file name
  913. decodedUntrustedFilePath = decodeURIComponent(untrustedFileUrl);
  914. } catch {
  915. return false;
  916. }
  917. // (2) Resolve "up paths" to determine real request
  918. const untrustedFilePath = (0, _path).resolve(decodedUntrustedFilePath);
  919. // don't allow null bytes anywhere in the file path
  920. if (untrustedFilePath.indexOf("\0") !== -1) {
  921. return false;
  922. }
  923. // Check if .next/static, static and public are in the path.
  924. // If not the path is not available.
  925. if ((untrustedFilePath.startsWith((0, _path).join(this.distDir, "static") + _path.sep) || untrustedFilePath.startsWith((0, _path).join(this.dir, "static") + _path.sep) || untrustedFilePath.startsWith((0, _path).join(this.dir, "public") + _path.sep)) === false) {
  926. return false;
  927. }
  928. // Check against the real filesystem paths
  929. const filesystemUrls = this.getFilesystemPaths();
  930. const resolved = (0, _path).relative(this.dir, untrustedFilePath);
  931. return filesystemUrls.has(resolved);
  932. }
  933. generateRewrites({ restrictedRedirectPaths }) {
  934. let beforeFiles = [];
  935. let afterFiles = [];
  936. let fallback = [];
  937. if (!this.minimalMode) {
  938. const buildRewrite = (rewrite, check = true)=>{
  939. const rewriteRoute = (0, _serverRouteUtils).getCustomRoute({
  940. type: "rewrite",
  941. rule: rewrite,
  942. restrictedRedirectPaths
  943. });
  944. return {
  945. ...rewriteRoute,
  946. check,
  947. type: rewriteRoute.type,
  948. name: `Rewrite route ${rewriteRoute.source}`,
  949. match: rewriteRoute.match,
  950. matchesBasePath: true,
  951. matchesLocale: true,
  952. matchesLocaleAPIRoutes: true,
  953. matchesTrailingSlash: true,
  954. fn: async (req, res, params, parsedUrl, upgradeHead)=>{
  955. const { newUrl , parsedDestination } = (0, _prepareDestination).prepareDestination({
  956. appendParamsToQuery: true,
  957. destination: rewriteRoute.destination,
  958. params: params,
  959. query: parsedUrl.query
  960. });
  961. // external rewrite, proxy it
  962. if (parsedDestination.protocol) {
  963. return this.proxyRequest(req, res, parsedDestination, upgradeHead);
  964. }
  965. (0, _requestMeta).addRequestMeta(req, "_nextRewroteUrl", newUrl);
  966. (0, _requestMeta).addRequestMeta(req, "_nextDidRewrite", newUrl !== req.url);
  967. return {
  968. finished: false,
  969. pathname: newUrl,
  970. query: parsedDestination.query
  971. };
  972. }
  973. };
  974. };
  975. if (Array.isArray(this.customRoutes.rewrites)) {
  976. afterFiles = this.customRoutes.rewrites.map((r)=>buildRewrite(r));
  977. } else {
  978. beforeFiles = this.customRoutes.rewrites.beforeFiles.map((r)=>buildRewrite(r, false));
  979. afterFiles = this.customRoutes.rewrites.afterFiles.map((r)=>buildRewrite(r));
  980. fallback = this.customRoutes.rewrites.fallback.map((r)=>buildRewrite(r));
  981. }
  982. }
  983. return {
  984. beforeFiles,
  985. afterFiles,
  986. fallback
  987. };
  988. }
  989. getMiddlewareManifest() {
  990. if (this.minimalMode) return null;
  991. const manifest = require((0, _path).join(this.serverDistDir, _constants.MIDDLEWARE_MANIFEST));
  992. return manifest;
  993. }
  994. /** Returns the middleware routing item if there is one. */ getMiddleware() {
  995. var ref;
  996. const manifest = this.getMiddlewareManifest();
  997. const middleware = manifest == null ? void 0 : (ref = manifest.middleware) == null ? void 0 : ref["/"];
  998. if (!middleware) {
  999. return;
  1000. }
  1001. return {
  1002. match: getMiddlewareMatcher(middleware),
  1003. page: "/"
  1004. };
  1005. }
  1006. getEdgeFunctions() {
  1007. const manifest = this.getMiddlewareManifest();
  1008. if (!manifest) {
  1009. return [];
  1010. }
  1011. return Object.keys(manifest.functions).map((page)=>({
  1012. match: getEdgeMatcher(manifest.functions[page]),
  1013. page
  1014. }));
  1015. }
  1016. /**
  1017. * Get information for the edge function located in the provided page
  1018. * folder. If the edge function info can't be found it will throw
  1019. * an error.
  1020. */ getEdgeFunctionInfo(params) {
  1021. const manifest = require((0, _path).join(this.serverDistDir, _constants.MIDDLEWARE_MANIFEST));
  1022. let foundPage;
  1023. try {
  1024. foundPage = (0, _denormalizePagePath).denormalizePagePath((0, _normalizePagePath).normalizePagePath(params.page));
  1025. } catch (err) {
  1026. return null;
  1027. }
  1028. let pageInfo = params.middleware ? manifest.middleware[foundPage] : manifest.functions[foundPage];
  1029. if (!pageInfo) {
  1030. if (!params.middleware) {
  1031. throw new _utils.PageNotFoundError(foundPage);
  1032. }
  1033. return null;
  1034. }
  1035. var _env1, _wasm, _assets;
  1036. return {
  1037. name: pageInfo.name,
  1038. paths: pageInfo.files.map((file)=>(0, _path).join(this.distDir, file)),
  1039. env: (_env1 = pageInfo.env) != null ? _env1 : [],
  1040. wasm: ((_wasm = pageInfo.wasm) != null ? _wasm : []).map((binding)=>({
  1041. ...binding,
  1042. filePath: (0, _path).join(this.distDir, binding.filePath)
  1043. })),
  1044. assets: ((_assets = pageInfo.assets) != null ? _assets : []).map((binding)=>{
  1045. return {
  1046. ...binding,
  1047. filePath: (0, _path).join(this.distDir, binding.filePath)
  1048. };
  1049. })
  1050. };
  1051. }
  1052. /**
  1053. * Checks if a middleware exists. This method is useful for the development
  1054. * server where we need to check the filesystem. Here we just check the
  1055. * middleware manifest.
  1056. */ async hasMiddleware(pathname) {
  1057. const info = this.getEdgeFunctionInfo({
  1058. page: pathname,
  1059. middleware: true
  1060. });
  1061. return Boolean(info && info.paths.length > 0);
  1062. }
  1063. /**
  1064. * A placeholder for a function to be defined in the development server.
  1065. * It will make sure that the root middleware or an edge function has been compiled
  1066. * so that we can run it.
  1067. */ async ensureMiddleware() {}
  1068. async ensureEdgeFunction(_params) {}
  1069. /**
  1070. * This method gets all middleware matchers and execute them when the request
  1071. * matches. It will make sure that each middleware exists and is compiled and
  1072. * ready to be invoked. The development server will decorate it to add warns
  1073. * and errors with rich traces.
  1074. */ async runMiddleware(params) {
  1075. // Middleware is skipped for on-demand revalidate requests
  1076. if ((0, _apiUtils).checkIsManualRevalidate(params.request, this.renderOpts.previewProps).isManualRevalidate) {
  1077. return {
  1078. finished: false
  1079. };
  1080. }
  1081. const normalizedPathname = (0, _removeTrailingSlash).removeTrailingSlash(params.parsed.pathname || "");
  1082. // For middleware to "fetch" we must always provide an absolute URL
  1083. let url;
  1084. if (this.nextConfig.experimental.skipMiddlewareUrlNormalize) {
  1085. url = (0, _requestMeta).getRequestMeta(params.request, "__NEXT_INIT_URL");
  1086. } else {
  1087. // For middleware to "fetch" we must always provide an absolute URL
  1088. const query = (0, _querystring).urlQueryToSearchParams(params.parsed.query).toString();
  1089. const locale = params.parsed.query.__nextLocale;
  1090. url = `${(0, _requestMeta).getRequestMeta(params.request, "_protocol")}://${this.hostname}:${this.port}${locale ? `/${locale}` : ""}${params.parsed.pathname}${query ? `?${query}` : ""}`;
  1091. }
  1092. if (!url.startsWith("http")) {
  1093. throw new Error("To use middleware you must provide a `hostname` and `port` to the Next.js Server");
  1094. }
  1095. const page = {};
  1096. if (await this.hasPage(normalizedPathname)) {
  1097. page.name = params.parsedUrl.pathname;
  1098. } else if (this.dynamicRoutes) {
  1099. for (const dynamicRoute of this.dynamicRoutes){
  1100. const matchParams = dynamicRoute.match(normalizedPathname);
  1101. if (matchParams) {
  1102. page.name = dynamicRoute.page;
  1103. page.params = matchParams;
  1104. break;
  1105. }
  1106. }
  1107. }
  1108. const middleware = this.getMiddleware();
  1109. if (!middleware) {
  1110. return {
  1111. finished: false
  1112. };
  1113. }
  1114. if (!await this.hasMiddleware(middleware.page)) {
  1115. return {
  1116. finished: false
  1117. };
  1118. }
  1119. await this.ensureMiddleware();
  1120. const middlewareInfo = this.getEdgeFunctionInfo({
  1121. page: middleware.page,
  1122. middleware: true
  1123. });
  1124. if (!middlewareInfo) {
  1125. throw new _utils.MiddlewareNotFoundError();
  1126. }
  1127. const method = (params.request.method || "GET").toUpperCase();
  1128. const result = await (0, _sandbox).run({
  1129. distDir: this.distDir,
  1130. name: middlewareInfo.name,
  1131. paths: middlewareInfo.paths,
  1132. env: middlewareInfo.env,
  1133. edgeFunctionEntry: middlewareInfo,
  1134. request: {
  1135. headers: params.request.headers,
  1136. method,
  1137. nextConfig: {
  1138. basePath: this.nextConfig.basePath,
  1139. i18n: this.nextConfig.i18n,
  1140. trailingSlash: this.nextConfig.trailingSlash
  1141. },
  1142. url: url,
  1143. page: page,
  1144. body: (0, _requestMeta).getRequestMeta(params.request, "__NEXT_CLONABLE_BODY")
  1145. },
  1146. useCache: !this.nextConfig.experimental.runtime,
  1147. onWarning: params.onWarning
  1148. });
  1149. const allHeaders = new Headers();
  1150. for (let [key, value] of result.response.headers){
  1151. if (key !== "x-middleware-next") {
  1152. allHeaders.append(key, value);
  1153. }
  1154. }
  1155. if (!this.renderOpts.dev) {
  1156. result.waitUntil.catch((error)=>{
  1157. console.error(`Uncaught: middleware waitUntil errored`, error);
  1158. });
  1159. }
  1160. if (!result) {
  1161. this.render404(params.request, params.response, params.parsed);
  1162. return {
  1163. finished: true
  1164. };
  1165. } else {
  1166. for (let [key, value] of allHeaders){
  1167. result.response.headers.set(key, value);
  1168. if (key.toLowerCase() === "set-cookie") {
  1169. (0, _requestMeta).addRequestMeta(params.request, "_nextMiddlewareCookie", (0, _utils2).splitCookiesString(value));
  1170. }
  1171. }
  1172. }
  1173. return result;
  1174. }
  1175. generateCatchAllMiddlewareRoute(devReady) {
  1176. if (this.minimalMode) return [];
  1177. const routes = [];
  1178. if (!this.renderOpts.dev || devReady) {
  1179. if (this.getMiddleware()) {
  1180. const middlewareCatchAllRoute = {
  1181. match: (0, _pathMatch).getPathMatch("/:path*"),
  1182. matchesBasePath: true,
  1183. matchesLocale: true,
  1184. type: "route",
  1185. name: "middleware catchall",
  1186. fn: async (req, res, _params, parsed)=>{
  1187. const middleware = this.getMiddleware();
  1188. if (!middleware) {
  1189. return {
  1190. finished: false
  1191. };
  1192. }
  1193. const initUrl = (0, _requestMeta).getRequestMeta(req, "__NEXT_INIT_URL");
  1194. const parsedUrl = (0, _parseUrl).parseUrl(initUrl);
  1195. const pathnameInfo = (0, _getNextPathnameInfo).getNextPathnameInfo(parsedUrl.pathname, {
  1196. nextConfig: this.nextConfig
  1197. });
  1198. parsedUrl.pathname = pathnameInfo.pathname;
  1199. const normalizedPathname = (0, _removeTrailingSlash).removeTrailingSlash(parsed.pathname || "");
  1200. if (!middleware.match(normalizedPathname, req, parsedUrl.query)) {
  1201. return {
  1202. finished: false
  1203. };
  1204. }
  1205. let result;
  1206. try {
  1207. result = await this.runMiddleware({
  1208. request: req,
  1209. response: res,
  1210. parsedUrl: parsedUrl,
  1211. parsed: parsed
  1212. });
  1213. } catch (err) {
  1214. if ((0, _isError).default(err) && err.code === "ENOENT") {
  1215. await this.render404(req, res, parsed);
  1216. return {
  1217. finished: true
  1218. };
  1219. }
  1220. if (err instanceof _utils.DecodeError) {
  1221. res.statusCode = 400;
  1222. this.renderError(err, req, res, parsed.pathname || "");
  1223. return {
  1224. finished: true
  1225. };
  1226. }
  1227. const error = (0, _isError).getProperError(err);
  1228. console.error(error);
  1229. res.statusCode = 500;
  1230. this.renderError(error, req, res, parsed.pathname || "");
  1231. return {
  1232. finished: true
  1233. };
  1234. }
  1235. if ("finished" in result) {
  1236. return result;
  1237. }
  1238. if (result.response.headers.has("x-middleware-rewrite")) {
  1239. const value = result.response.headers.get("x-middleware-rewrite");
  1240. const rel = (0, _relativizeUrl).relativizeURL(value, initUrl);
  1241. result.response.headers.set("x-middleware-rewrite", rel);
  1242. }
  1243. if (result.response.headers.has("Location")) {
  1244. const value = result.response.headers.get("Location");
  1245. const rel = (0, _relativizeUrl).relativizeURL(value, initUrl);
  1246. result.response.headers.set("Location", rel);
  1247. }
  1248. if (!result.response.headers.has("x-middleware-rewrite") && !result.response.headers.has("x-middleware-next") && !result.response.headers.has("Location")) {
  1249. result.response.headers.set("x-middleware-refresh", "1");
  1250. }
  1251. result.response.headers.delete("x-middleware-next");
  1252. for (const [key, value] of Object.entries((0, _utils2).toNodeHeaders(result.response.headers))){
  1253. if ([
  1254. "x-middleware-rewrite",
  1255. "x-middleware-redirect",
  1256. "x-middleware-refresh",
  1257. ].includes(key)) {
  1258. continue;
  1259. }
  1260. if (key !== "content-encoding" && value !== undefined) {
  1261. res.setHeader(key, value);
  1262. }
  1263. }
  1264. res.statusCode = result.response.status;
  1265. res.statusMessage = result.response.statusText;
  1266. const location = result.response.headers.get("Location");
  1267. if (location) {
  1268. res.statusCode = result.response.status;
  1269. if (res.statusCode === 308) {
  1270. res.setHeader("Refresh", `0;url=${location}`);
  1271. }
  1272. res.body(location).send();
  1273. return {
  1274. finished: true
  1275. };
  1276. }
  1277. if (result.response.headers.has("x-middleware-rewrite")) {
  1278. const rewritePath = result.response.headers.get("x-middleware-rewrite");
  1279. const parsedDestination = (0, _parseUrl).parseUrl(rewritePath);
  1280. const newUrl = parsedDestination.pathname;
  1281. if (parsedDestination.protocol && (parsedDestination.port ? `${parsedDestination.hostname}:${parsedDestination.port}` : parsedDestination.hostname) !== req.headers.host) {
  1282. return this.proxyRequest(req, res, parsedDestination);
  1283. }
  1284. if (this.nextConfig.i18n) {
  1285. const localePathResult = (0, _normalizeLocalePath).normalizeLocalePath(newUrl, this.nextConfig.i18n.locales);
  1286. if (localePathResult.detectedLocale) {
  1287. parsedDestination.query.__nextLocale = localePathResult.detectedLocale;
  1288. }
  1289. }
  1290. (0, _requestMeta).addRequestMeta(req, "_nextRewroteUrl", newUrl);
  1291. (0, _requestMeta).addRequestMeta(req, "_nextDidRewrite", newUrl !== req.url);
  1292. return {
  1293. finished: false,
  1294. pathname: newUrl,
  1295. query: parsedDestination.query
  1296. };
  1297. }
  1298. if (result.response.headers.has("x-middleware-refresh")) {
  1299. res.statusCode = result.response.status;
  1300. for await (const chunk of result.response.body || []){
  1301. this.streamResponseChunk(res, chunk);
  1302. }
  1303. res.send();
  1304. return {
  1305. finished: true
  1306. };
  1307. }
  1308. return {
  1309. finished: false
  1310. };
  1311. }
  1312. };
  1313. routes.push(middlewareCatchAllRoute);
  1314. }
  1315. }
  1316. return routes;
  1317. }
  1318. getPrerenderManifest() {
  1319. if (this._cachedPreviewManifest) {
  1320. return this._cachedPreviewManifest;
  1321. }
  1322. const manifest = require((0, _path).join(this.distDir, _constants.PRERENDER_MANIFEST));
  1323. return this._cachedPreviewManifest = manifest;
  1324. }
  1325. getRoutesManifest() {
  1326. return require((0, _path).join(this.distDir, _constants.ROUTES_MANIFEST));
  1327. }
  1328. attachRequestMeta(req, parsedUrl) {
  1329. var ref, ref1;
  1330. const protocol = ((ref1 = (ref = req.originalRequest) == null ? void 0 : ref.socket) == null ? void 0 : ref1.encrypted) ? "https" : "http";
  1331. // When there are hostname and port we build an absolute URL
  1332. const initUrl = this.hostname && this.port ? `${protocol}://${this.hostname}:${this.port}${req.url}` : req.url;
  1333. (0, _requestMeta).addRequestMeta(req, "__NEXT_INIT_URL", initUrl);
  1334. (0, _requestMeta).addRequestMeta(req, "__NEXT_INIT_QUERY", {
  1335. ...parsedUrl.query
  1336. });
  1337. (0, _requestMeta).addRequestMeta(req, "_protocol", protocol);
  1338. (0, _requestMeta).addRequestMeta(req, "__NEXT_CLONABLE_BODY", (0, _bodyStreams).getClonableBody(req.body));
  1339. }
  1340. async runEdgeFunction(params) {
  1341. let middlewareInfo;
  1342. const { query , page } = params;
  1343. await this.ensureEdgeFunction({
  1344. page,
  1345. appPaths: params.appPaths
  1346. });
  1347. middlewareInfo = this.getEdgeFunctionInfo({
  1348. page,
  1349. middleware: false
  1350. });
  1351. if (!middlewareInfo) {
  1352. return null;
  1353. }
  1354. // For middleware to "fetch" we must always provide an absolute URL
  1355. const locale = query.__nextLocale;
  1356. const isDataReq = !!query.__nextDataReq;
  1357. const queryString = (0, _querystring).urlQueryToSearchParams(query).toString();
  1358. if (isDataReq) {
  1359. params.req.headers["x-nextjs-data"] = "1";
  1360. }
  1361. let normalizedPathname = (0, _appPaths).normalizeAppPath(page);
  1362. if ((0, _utils1).isDynamicRoute(normalizedPathname)) {
  1363. const routeRegex = (0, _routeRegex).getNamedRouteRegex(normalizedPathname);
  1364. normalizedPathname = (0, _utils4).interpolateDynamicPath(normalizedPathname, Object.assign({}, params.params, query), routeRegex);
  1365. }
  1366. const url = `${(0, _requestMeta).getRequestMeta(params.req, "_protocol")}://${this.hostname}:${this.port}${locale ? `/${locale}` : ""}${normalizedPathname}${queryString ? `?${queryString}` : ""}`;
  1367. if (!url.startsWith("http")) {
  1368. throw new Error("To use middleware you must provide a `hostname` and `port` to the Next.js Server");
  1369. }
  1370. const result = await (0, _sandbox).run({
  1371. distDir: this.distDir,
  1372. name: middlewareInfo.name,
  1373. paths: middlewareInfo.paths,
  1374. env: middlewareInfo.env,
  1375. edgeFunctionEntry: middlewareInfo,
  1376. request: {
  1377. headers: params.req.headers,
  1378. method: params.req.method,
  1379. nextConfig: {
  1380. basePath: this.nextConfig.basePath,
  1381. i18n: this.nextConfig.i18n,
  1382. trailingSlash: this.nextConfig.trailingSlash
  1383. },
  1384. url,
  1385. page: {
  1386. name: params.page,
  1387. ...params.params && {
  1388. params: params.params
  1389. }
  1390. },
  1391. body: (0, _requestMeta).getRequestMeta(params.req, "__NEXT_CLONABLE_BODY")
  1392. },
  1393. useCache: !this.nextConfig.experimental.runtime,
  1394. onWarning: params.onWarning
  1395. });
  1396. params.res.statusCode = result.response.status;
  1397. params.res.statusMessage = result.response.statusText;
  1398. result.response.headers.forEach((value, key)=>{
  1399. // the append handling is special cased for `set-cookie`
  1400. if (key.toLowerCase() === "set-cookie") {
  1401. params.res.setHeader(key, value);
  1402. } else {
  1403. params.res.appendHeader(key, value);
  1404. }
  1405. });
  1406. if (result.response.body) {
  1407. // TODO(gal): not sure that we always need to stream
  1408. (0, _bodyStreams).bodyStreamToNodeStream(result.response.body).pipe(params.res.originalResponse);
  1409. } else {
  1410. params.res.originalResponse.end();
  1411. }
  1412. return result;
  1413. }
  1414. get _isLikeServerless() {
  1415. return (0, _utils3).isTargetLikeServerless(this.nextConfig.target);
  1416. }
  1417. get serverDistDir() {
  1418. return (0, _path).join(this.distDir, this._isLikeServerless ? _constants.SERVERLESS_DIRECTORY : _constants.SERVER_DIRECTORY);
  1419. }
  1420. }
  1421. exports.default = NextNodeServer;
  1422. function _interopRequireDefault(obj) {
  1423. return obj && obj.__esModule ? obj : {
  1424. default: obj
  1425. };
  1426. }
  1427. function _getRequireWildcardCache() {
  1428. if (typeof WeakMap !== "function") return null;
  1429. var cache = new WeakMap();
  1430. _getRequireWildcardCache = function() {
  1431. return cache;
  1432. };
  1433. return cache;
  1434. }
  1435. function _interopRequireWildcard(obj) {
  1436. if (obj && obj.__esModule) {
  1437. return obj;
  1438. }
  1439. if (obj === null || typeof obj !== "object" && typeof obj !== "function") {
  1440. return {
  1441. default: obj
  1442. };
  1443. }
  1444. var cache = _getRequireWildcardCache();
  1445. if (cache && cache.has(obj)) {
  1446. return cache.get(obj);
  1447. }
  1448. var newObj = {};
  1449. var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor;
  1450. for(var key in obj){
  1451. if (Object.prototype.hasOwnProperty.call(obj, key)) {
  1452. var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null;
  1453. if (desc && (desc.get || desc.set)) {
  1454. Object.defineProperty(newObj, key, desc);
  1455. } else {
  1456. newObj[key] = obj[key];
  1457. }
  1458. }
  1459. }
  1460. newObj.default = obj;
  1461. if (cache) {
  1462. cache.set(obj, newObj);
  1463. }
  1464. return newObj;
  1465. }
  1466. if (_utils3.shouldUseReactRoot) {
  1467. process.env.__NEXT_REACT_ROOT = "true";
  1468. }
  1469. (0, _requireHook).default();
  1470. const MiddlewareMatcherCache = new WeakMap();
  1471. const EdgeMatcherCache = new WeakMap();
  1472. function getMiddlewareMatcher(info) {
  1473. const stored = MiddlewareMatcherCache.get(info);
  1474. if (stored) {
  1475. return stored;
  1476. }
  1477. if (!Array.isArray(info.matchers)) {
  1478. throw new Error(`Invariant: invalid matchers for middleware ${JSON.stringify(info)}`);
  1479. }
  1480. const matcher = (0, _middlewareRouteMatcher).getMiddlewareRouteMatcher(info.matchers);
  1481. MiddlewareMatcherCache.set(info, matcher);
  1482. return matcher;
  1483. }
  1484. /**
  1485. * Hardcoded every possible error status code that could be thrown by "serveStatic" method
  1486. * This is done by searching "this.error" inside "send" module's source code:
  1487. * https://github.com/pillarjs/send/blob/master/index.js
  1488. * https://github.com/pillarjs/send/blob/develop/index.js
  1489. */ const POSSIBLE_ERROR_CODE_FROM_SERVE_STATIC = new Set([
  1490. // send module will throw 500 when header is already sent or fs.stat error happens
  1491. // https://github.com/pillarjs/send/blob/53f0ab476145670a9bdd3dc722ab2fdc8d358fc6/index.js#L392
  1492. // Note: we will use Next.js built-in 500 page to handle 500 errors
  1493. // 500,
  1494. // send module will throw 404 when file is missing
  1495. // https://github.com/pillarjs/send/blob/53f0ab476145670a9bdd3dc722ab2fdc8d358fc6/index.js#L421
  1496. // Note: we will use Next.js built-in 404 page to handle 404 errors
  1497. // 404,
  1498. // send module will throw 403 when redirecting to a directory without enabling directory listing
  1499. // https://github.com/pillarjs/send/blob/53f0ab476145670a9bdd3dc722ab2fdc8d358fc6/index.js#L484
  1500. // Note: Next.js throws a different error (without status code) for directory listing
  1501. // 403,
  1502. // send module will throw 400 when fails to normalize the path
  1503. // https://github.com/pillarjs/send/blob/53f0ab476145670a9bdd3dc722ab2fdc8d358fc6/index.js#L520
  1504. 400,
  1505. // send module will throw 412 with conditional GET request
  1506. // https://github.com/pillarjs/send/blob/53f0ab476145670a9bdd3dc722ab2fdc8d358fc6/index.js#L632
  1507. 412,
  1508. // send module will throw 416 when range is not satisfiable
  1509. // https://github.com/pillarjs/send/blob/53f0ab476145670a9bdd3dc722ab2fdc8d358fc6/index.js#L669
  1510. 416,
  1511. ]);
  1512. function getEdgeMatcher(info) {
  1513. const stored = EdgeMatcherCache.get(info);
  1514. if (stored) {
  1515. return stored;
  1516. }
  1517. if (!Array.isArray(info.matchers) || info.matchers.length !== 1) {
  1518. throw new Error(`Invariant: invalid matchers for middleware ${JSON.stringify(info)}`);
  1519. }
  1520. const matcher = (0, _routeMatcher).getRouteMatcher({
  1521. re: new RegExp(info.matchers[0].regexp),
  1522. groups: {}
  1523. });
  1524. EdgeMatcherCache.set(info, matcher);
  1525. return matcher;
  1526. }
  1527. //# sourceMappingURL=next-server.js.map