"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 _apiUtils = require("../../../../server/api-utils");
var _denormalizePagePath = require("../../../../server/denormalize-page-path");
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 _utils2 = require("../../../../server/utils");
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 Document1;
        let Error1;
        let notFoundMod;
        let getStaticProps;
        let getStaticPaths;
        let getServerSideProps;
        [getStaticProps, getServerSideProps, getStaticPaths, Component, App, config, { default: Document1  }, { default: Error1  }, 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: Document1,
            buildManifest,
            getStaticProps,
            getServerSideProps,
            getStaticPaths,
            reactLoadableManifest,
            canonicalBase,
            buildId,
            assetPrefix,
            runtimeConfig: (runtimeConfig || {
            }).publicRuntimeConfig || {
            },
            previewProps: encodedPreviewProps,
            env: process.env,
            basePath,
            ..._renderOpts
        };
        let _nextData = false;
        let defaultLocale = i18n === null || i18n === void 0 ? void 0 : i18n.defaultLocale;
        let detectedLocale = i18n === null || i18n === void 0 ? 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);
            parsedUrl = 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 || localeResult === void 0 ? void 0 : localeResult.defaultLocale) || defaultLocale;
            detectedLocale = (localeResult === null || localeResult === void 0 ? void 0 : localeResult.detectedLocale) || detectedLocale;
            routeNoAssetPath = (localeResult === null || localeResult === void 0 ? 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 || i18n === void 0 ? void 0 : i18n.locales,
                locale: detectedLocale,
                defaultLocale,
                domainLocales: i18n === null || i18n === void 0 ? void 0 : i18n.domains
            }, 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 || ref === void 0 ? 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 && trustQuery && 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, _apiUtils).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 : Error1;
                        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 || i18n === void 0 ? void 0 : i18n.locales,
                            defaultLocale: i18n === null || i18n === void 0 ? void 0 : i18n.defaultLocale
                        }));
                        const html = result2 ? await (0, _utils2).resultsToString([
                            result2
                        ]) : '';
                        (0, _sendPayload).sendPayload(req, res, html, 'html', {
                            generateEtags,
                            poweredByHeader
                        }, {
                            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();
                        return null;
                    } else {
                        (0, _sendPayload).sendPayload(req, res, _nextData ? JSON.stringify(renderOpts.pageData) : result, _nextData ? 'json' : 'html', {
                            generateEtags,
                            poweredByHeader
                        }, {
                            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 ? await (0, _utils2).resultsToString([
                result
            ]) : null;
        } catch (err) {
            if (!parsedUrl) {
                parsedUrl = (0, _url).parse(req.url, true);
            }
            if (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: Error1,
                        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: Error1,
                err: res.statusCode === 404 ? undefined : err
            }));
            return result2 ? await (0, _utils2).resultsToString([
                result2
            ]) : null;
        }
    }
    return {
        renderReqToHTML,
        render: async function render(req, res) {
            try {
                const html = await renderReqToHTML(req, res);
                if (html) {
                    (0, _sendPayload).sendPayload(req, res, html, 'html', {
                        generateEtags,
                        poweredByHeader
                    });
                }
            } catch (err) {
                console.error(err);
                // Throw the error to crash the serverless function
                throw err;
            }
        }
    };
}

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