"use strict";
Object.defineProperty(exports, "__esModule", {
    value: true
});
exports.getPageHandler = getPageHandler;
var _url = require("url");
var _utils = require("../../../../shared/lib/utils");
var _sendPayload = require("../../../../server/send-payload");
var _utils1 = require("./utils");
var _render = require("../../../../server/render");
var _node = require("../../../../server/api-utils/node");
var _denormalizePagePath = require("../../../../shared/lib/page-path/denormalize-page-path");
var _apiUtils = require("../../../../server/api-utils");
var _loadCustomRoutes = require("../../../../lib/load-custom-routes");
var _getRouteFromAssetPath = _interopRequireDefault(require("../../../../shared/lib/router/utils/get-route-from-asset-path"));
var _constants = require("../../../../shared/lib/constants");
var _renderResult = _interopRequireDefault(require("../../../../server/render-result"));
var _isError = _interopRequireDefault(require("../../../../lib/is-error"));
function _interopRequireDefault(obj) {
    return obj && obj.__esModule ? obj : {
        default: obj
    };
}
function getPageHandler(ctx) {
    const { page , pageComponent , pageConfig , pageGetStaticProps , pageGetStaticPaths , pageGetServerSideProps , appModule , documentModule , errorModule , notFoundModule , encodedPreviewProps , pageIsDynamic , generateEtags , poweredByHeader , runtimeConfig , buildManifest , reactLoadableManifest , i18n , buildId , basePath , assetPrefix , canonicalBase , escapedBuildId ,  } = ctx;
    const { handleLocale , handleRewrites , handleBasePath , defaultRouteRegex , dynamicRouteMatcher , interpolateDynamicPath , getParamsFromRouteMatches , normalizeDynamicRouteParams , normalizeVercelUrl ,  } = (0, _utils1).getUtils(ctx);
    async function renderReqToHTML(req, res, renderMode, _renderOpts, _params) {
        let Component;
        let App;
        let config;
        let Document;
        let Error;
        let notFoundMod;
        let getStaticProps;
        let getStaticPaths;
        let getServerSideProps;
        [getStaticProps, getServerSideProps, getStaticPaths, Component, App, config, { default: Document  }, { default: Error  }, notFoundMod, ] = await Promise.all([
            pageGetStaticProps,
            pageGetServerSideProps,
            pageGetStaticPaths,
            pageComponent,
            appModule,
            pageConfig,
            documentModule,
            errorModule,
            notFoundModule, 
        ]);
        const fromExport = renderMode === "export" || renderMode === true;
        const nextStartMode = renderMode === "passthrough";
        let hasValidParams = true;
        (0, _apiUtils).setLazyProp({
            req: req
        }, "cookies", (0, _apiUtils).getCookieParser(req.headers));
        const options = {
            App,
            Document,
            ComponentMod: {
                default: Component
            },
            buildManifest,
            getStaticProps,
            getServerSideProps,
            getStaticPaths,
            reactLoadableManifest,
            canonicalBase,
            buildId,
            assetPrefix,
            runtimeConfig: (runtimeConfig || {}).publicRuntimeConfig || {},
            previewProps: encodedPreviewProps,
            env: process.env,
            basePath,
            supportsDynamicHTML: false,
            ..._renderOpts
        };
        let _nextData = false;
        let defaultLocale = i18n == null ? void 0 : i18n.defaultLocale;
        let detectedLocale = i18n == null ? void 0 : i18n.defaultLocale;
        let parsedUrl;
        try {
            var ref;
            // We need to trust the dynamic route params from the proxy
            // to ensure we are using the correct values
            const trustQuery = !getStaticProps && req.headers[_utils1.vercelHeader];
            parsedUrl = (0, _url).parse(req.url, true);
            let routeNoAssetPath = parsedUrl.pathname;
            if (basePath) {
                routeNoAssetPath = routeNoAssetPath.replace(new RegExp(`^${basePath}`), "") || "/";
            }
            const origQuery = Object.assign({}, parsedUrl.query);
            handleRewrites(req, parsedUrl);
            handleBasePath(req, parsedUrl);
            // remove ?amp=1 from request URL if rendering for export
            if (fromExport && parsedUrl.query.amp) {
                const queryNoAmp = Object.assign({}, origQuery);
                delete queryNoAmp.amp;
                req.url = (0, _url).format({
                    ...parsedUrl,
                    search: undefined,
                    query: queryNoAmp
                });
            }
            if (parsedUrl.pathname.match(/_next\/data/)) {
                _nextData = page !== "/_error";
                parsedUrl.pathname = (0, _getRouteFromAssetPath).default(parsedUrl.pathname.replace(new RegExp(`/_next/data/${escapedBuildId}/`), "/"), ".json");
                routeNoAssetPath = parsedUrl.pathname;
            }
            const localeResult = handleLocale(req, res, parsedUrl, routeNoAssetPath, fromExport || nextStartMode);
            defaultLocale = (localeResult == null ? void 0 : localeResult.defaultLocale) || defaultLocale;
            detectedLocale = (localeResult == null ? void 0 : localeResult.detectedLocale) || detectedLocale;
            routeNoAssetPath = (localeResult == null ? void 0 : localeResult.routeNoAssetPath) || routeNoAssetPath;
            if (parsedUrl.query.nextInternalLocale) {
                detectedLocale = parsedUrl.query.nextInternalLocale;
                delete parsedUrl.query.nextInternalLocale;
            }
            const renderOpts = Object.assign({
                Component,
                pageConfig: config,
                nextExport: fromExport,
                isDataReq: _nextData,
                locales: i18n == null ? void 0 : i18n.locales,
                locale: detectedLocale,
                defaultLocale,
                domainLocales: i18n == null ? void 0 : i18n.domains,
                optimizeCss: process.env.__NEXT_OPTIMIZE_CSS,
                nextScriptWorkers: process.env.__NEXT_SCRIPT_WORKERS,
                crossOrigin: process.env.__NEXT_CROSS_ORIGIN
            }, options);
            if (page === "/_error" && !res.statusCode) {
                res.statusCode = 404;
            }
            let params = {};
            if (!fromExport && pageIsDynamic) {
                const result = normalizeDynamicRouteParams(trustQuery ? parsedUrl.query : dynamicRouteMatcher(parsedUrl.pathname));
                hasValidParams = result.hasValidParams;
                params = result.params;
            }
            let nowParams = null;
            if (pageIsDynamic && !hasValidParams && ((ref = req.headers) == null ? void 0 : ref["x-now-route-matches"])) {
                nowParams = getParamsFromRouteMatches(req, renderOpts, detectedLocale);
            }
            // make sure to set renderOpts to the correct params e.g. _params
            // if provided from worker or params if we're parsing them here
            renderOpts.params = _params || params;
            normalizeVercelUrl(req, !!trustQuery);
            // normalize request URL/asPath for fallback/revalidate pages since the
            // proxy sets the request URL to the output's path for fallback pages
            if (pageIsDynamic && nowParams && defaultRouteRegex) {
                const _parsedUrl = (0, _url).parse(req.url);
                _parsedUrl.pathname = interpolateDynamicPath(_parsedUrl.pathname, nowParams);
                parsedUrl.pathname = _parsedUrl.pathname;
                req.url = (0, _url).format(_parsedUrl);
            }
            // make sure to normalize asPath for revalidate and _next/data requests
            // since the asPath should match what is shown on the client
            if (!fromExport && (getStaticProps || getServerSideProps)) {
                // don't include dynamic route params in query while normalizing
                // asPath
                if (pageIsDynamic && defaultRouteRegex) {
                    delete parsedUrl.search;
                    for (const param of Object.keys(defaultRouteRegex.groups)){
                        delete origQuery[param];
                    }
                }
                parsedUrl.pathname = (0, _denormalizePagePath).denormalizePagePath(parsedUrl.pathname);
                renderOpts.resolvedUrl = (0, _url).format({
                    ...parsedUrl,
                    query: origQuery
                });
                // For getServerSideProps we need to ensure we use the original URL
                // and not the resolved URL to prevent a hydration mismatch on asPath
                renderOpts.resolvedAsPath = getServerSideProps ? (0, _url).format({
                    ...parsedUrl,
                    pathname: routeNoAssetPath,
                    query: origQuery
                }) : renderOpts.resolvedUrl;
            }
            const isFallback = parsedUrl.query.__nextFallback;
            const previewData = (0, _node).tryGetPreviewData(req, res, options.previewProps);
            const isPreviewMode = previewData !== false;
            if (process.env.__NEXT_OPTIMIZE_FONTS) {
                renderOpts.optimizeFonts = true;
                /**
         * __webpack_require__.__NEXT_FONT_MANIFEST__ is added by
         * font-stylesheet-gathering-plugin
         */ // @ts-ignore
                renderOpts.fontManifest = __webpack_require__.__NEXT_FONT_MANIFEST__;
            }
            let result = await (0, _render).renderToHTML(req, res, page, Object.assign({}, getStaticProps ? {
                ...parsedUrl.query.amp ? {
                    amp: "1"
                } : {}
            } : parsedUrl.query, nowParams ? nowParams : params, _params, isFallback ? {
                __nextFallback: "true"
            } : {}), renderOpts);
            if (!renderMode) {
                if (_nextData || getStaticProps || getServerSideProps) {
                    if (renderOpts.isNotFound) {
                        res.statusCode = 404;
                        if (_nextData) {
                            res.end('{"notFound":true}');
                            return null;
                        }
                        const NotFoundComponent = notFoundMod ? notFoundMod.default : Error;
                        const errPathname = notFoundMod ? "/404" : "/_error";
                        const result2 = await (0, _render).renderToHTML(req, res, errPathname, parsedUrl.query, Object.assign({}, options, {
                            getStaticProps: notFoundMod ? notFoundMod.getStaticProps : undefined,
                            getStaticPaths: undefined,
                            getServerSideProps: undefined,
                            Component: NotFoundComponent,
                            err: undefined,
                            locale: detectedLocale,
                            locales: i18n == null ? void 0 : i18n.locales,
                            defaultLocale: i18n == null ? void 0 : i18n.defaultLocale
                        }));
                        (0, _sendPayload).sendRenderResult({
                            req,
                            res,
                            result: result2 != null ? result2 : _renderResult.default.empty,
                            type: "html",
                            generateEtags,
                            poweredByHeader,
                            options: {
                                private: isPreviewMode || page === "/404",
                                stateful: !!getServerSideProps,
                                revalidate: renderOpts.revalidate
                            }
                        });
                        return null;
                    } else if (renderOpts.isRedirect && !_nextData) {
                        const redirect = {
                            destination: renderOpts.pageData.pageProps.__N_REDIRECT,
                            statusCode: renderOpts.pageData.pageProps.__N_REDIRECT_STATUS,
                            basePath: renderOpts.pageData.pageProps.__N_REDIRECT_BASE_PATH
                        };
                        const statusCode = (0, _loadCustomRoutes).getRedirectStatus(redirect);
                        if (basePath && redirect.basePath !== false && redirect.destination.startsWith("/")) {
                            redirect.destination = `${basePath}${redirect.destination}`;
                        }
                        if (statusCode === _constants.PERMANENT_REDIRECT_STATUS) {
                            res.setHeader("Refresh", `0;url=${redirect.destination}`);
                        }
                        res.statusCode = statusCode;
                        res.setHeader("Location", redirect.destination);
                        res.end(redirect.destination);
                        return null;
                    } else {
                        (0, _sendPayload).sendRenderResult({
                            req,
                            res,
                            result: _nextData ? _renderResult.default.fromStatic(JSON.stringify(renderOpts.pageData)) : result != null ? result : _renderResult.default.empty,
                            type: _nextData ? "json" : "html",
                            generateEtags,
                            poweredByHeader,
                            options: {
                                private: isPreviewMode || renderOpts.is404Page,
                                stateful: !!getServerSideProps,
                                revalidate: renderOpts.revalidate
                            }
                        });
                        return null;
                    }
                }
            } else if (isPreviewMode) {
                res.setHeader("Cache-Control", "private, no-cache, no-store, max-age=0, must-revalidate");
            }
            if (renderMode) return {
                html: result,
                renderOpts
            };
            return result ? result.toUnchunkedString() : null;
        } catch (err) {
            if (!parsedUrl) {
                parsedUrl = (0, _url).parse(req.url, true);
            }
            if ((0, _isError).default(err) && err.code === "ENOENT") {
                res.statusCode = 404;
            } else if (err instanceof _utils.DecodeError) {
                res.statusCode = 400;
            } else {
                console.error("Unhandled error during request:", err);
                // Backwards compat (call getInitialProps in custom error):
                try {
                    await (0, _render).renderToHTML(req, res, "/_error", parsedUrl.query, Object.assign({}, options, {
                        getStaticProps: undefined,
                        getStaticPaths: undefined,
                        getServerSideProps: undefined,
                        Component: Error,
                        err: err,
                        // Short-circuit rendering:
                        isDataReq: true
                    }));
                } catch (underErrorErr) {
                    console.error("Failed call /_error subroutine, continuing to crash function:", underErrorErr);
                }
                // Throw the error to crash the serverless function
                if ((0, _utils).isResSent(res)) {
                    console.error("!!! WARNING !!!");
                    console.error("Your function crashed, but closed the response before allowing the function to exit.\\n" + "This may cause unexpected behavior for the next request.");
                    console.error("!!! WARNING !!!");
                }
                throw err;
            }
            const result2 = await (0, _render).renderToHTML(req, res, "/_error", parsedUrl.query, Object.assign({}, options, {
                getStaticProps: undefined,
                getStaticPaths: undefined,
                getServerSideProps: undefined,
                Component: Error,
                err: res.statusCode === 404 ? undefined : err
            }));
            return result2 ? result2.toUnchunkedString() : null;
        }
    }
    return {
        renderReqToHTML,
        render: async function render(req, res) {
            try {
                const html = await renderReqToHTML(req, res);
                if (html) {
                    (0, _sendPayload).sendRenderResult({
                        req,
                        res,
                        result: _renderResult.default.fromStatic(html),
                        type: "html",
                        generateEtags,
                        poweredByHeader
                    });
                }
            } catch (err) {
                console.error(err);
                // Throw the error to crash the serverless function
                throw err;
            }
        }
    };
}

//# sourceMappingURL=page-handler.js.map