import '../../server/web/globals'; import { adapter } from '../../server/web/adapter'; import { IncrementalCache } from '../../server/lib/incremental-cache'; import * as cacheHandlers from '../../server/use-cache/handlers'; import Document from 'VAR_MODULE_DOCUMENT'; import * as appMod from 'VAR_MODULE_APP'; import * as userlandPage from 'VAR_USERLAND'; import * as userlandErrorPage from 'VAR_MODULE_GLOBAL_ERROR'; // OPTIONAL_IMPORT:* as userland500Page // OPTIONAL_IMPORT:incrementalCacheHandler import RouteModule from '../../server/route-modules/pages/module'; import { WebNextRequest, WebNextResponse } from '../../server/base-http/web'; import { getTracer, SpanKind } from '../../server/lib/trace/tracer'; import { BaseServerSpan } from '../../server/lib/trace/constants'; import { HTML_CONTENT_TYPE_HEADER } from '../../lib/constants'; import { toNodeOutgoingHttpHeaders } from '../../server/web/utils'; // INJECT:pageRouteModuleOptions // INJECT:errorRouteModuleOptions // INJECT:user500RouteModuleOptions // INJECT_RAW:cacheHandlerImports const pageMod = { ...userlandPage, routeModule: new RouteModule({ ...pageRouteModuleOptions, components: { App: appMod.default, Document }, userland: userlandPage, distDir: process.env.__NEXT_RELATIVE_DIST_DIR || '', relativeProjectDir: process.env.__NEXT_RELATIVE_PROJECT_DIR || '' }) }; const errorMod = { ...userlandErrorPage, routeModule: new RouteModule({ ...errorRouteModuleOptions, components: { App: appMod.default, Document }, userland: userlandErrorPage, distDir: process.env.__NEXT_RELATIVE_DIST_DIR || '', relativeProjectDir: process.env.__NEXT_RELATIVE_PROJECT_DIR || '' }) }; // FIXME: this needs to be made compatible with the template const error500Mod = userland500Page ? { ...userland500Page, routeModule: new RouteModule({ ...user500RouteModuleOptions, components: { App: appMod.default, Document }, userland: userland500Page, distDir: process.env.__NEXT_RELATIVE_DIST_DIR || '', relativeProjectDir: process.env.__NEXT_RELATIVE_PROJECT_DIR || '' }) } : null; export const ComponentMod = pageMod; async function requestHandler(req, _event) { var _nextConfig_i18n; let srcPage = 'VAR_DEFINITION_PATHNAME'; const relativeUrl = `${req.nextUrl.pathname}${req.nextUrl.search}`; const baseReq = new WebNextRequest(req); const pageRouteModule = pageMod.routeModule; const prepareResult = await pageRouteModule.prepare(baseReq, null, { srcPage, multiZoneDraftMode: false }); if (!prepareResult) { return new Response('Bad Request', { status: 400 }); } const { query, params, buildId, nextConfig, deploymentId, isNextDataRequest, buildManifest, prerenderManifest, reactLoadableManifest, subresourceIntegrityManifest, dynamicCssManifest, clientAssetToken } = prepareResult; cacheHandlers.initializeCacheHandlers(nextConfig.cacheMaxMemorySize); // INJECT_RAW:cacheHandlerRegistration const renderContext = { page: srcPage, query, params, sharedContext: { buildId, deploymentId, clientAssetToken, customServer: undefined }, renderContext: { isFallback: false, isDraftMode: false, developmentNotFoundSourcePage: undefined }, renderOpts: { params, page: srcPage, supportsDynamicResponse: true, Component: pageMod.Component, ComponentMod: pageMod, pageConfig: pageMod.pageConfig, routeModule: pageMod.routeModule, previewProps: prerenderManifest.preview, basePath: nextConfig.basePath, assetPrefix: nextConfig.assetPrefix, images: nextConfig.images, optimizeCss: nextConfig.experimental.optimizeCss, nextConfigOutput: nextConfig.output, nextScriptWorkers: nextConfig.experimental.nextScriptWorkers, disableOptimizedLoading: nextConfig.experimental.disableOptimizedLoading, domainLocales: (_nextConfig_i18n = nextConfig.i18n) == null ? void 0 : _nextConfig_i18n.domains, distDir: '', crossOrigin: nextConfig.crossOrigin ? nextConfig.crossOrigin : undefined, largePageDataBytes: nextConfig.experimental.largePageDataBytes, isExperimentalCompile: nextConfig.experimental.isExperimentalCompile, // `htmlLimitedBots` is passed to server as serialized config in string format experimental: { clientTraceMetadata: nextConfig.experimental.clientTraceMetadata }, buildManifest, subresourceIntegrityManifest, reactLoadableManifest, dynamicCssManifest } }; let finalStatus = 200; const renderResultToResponse = (result)=>{ // Handle null responses if (result.isNull) { finalStatus = 500; return new Response(null, { status: 500 }); } // Extract metadata const { metadata } = result; finalStatus = metadata.statusCode || 200; const headers = new Headers(); // Set content type const contentType = result.contentType || HTML_CONTENT_TYPE_HEADER; headers.set('Content-Type', contentType); // Add metadata headers if (metadata.headers) { for (const [key, value] of Object.entries(metadata.headers)){ if (value !== undefined) { if (Array.isArray(value)) { // Handle multiple header values for (const v of value){ headers.append(key, String(v)); } } else { headers.set(key, String(value)); } } } } // Handle static response if (!result.isDynamic) { const body = result.toUnchunkedString(); headers.set('Content-Length', String(new TextEncoder().encode(body).length)); return new Response(body, { status: finalStatus, headers }); } // Handle dynamic/streaming response // For edge runtime, we need to create a readable stream that pipes from the result const { readable, writable } = new TransformStream(); // Start piping the result to the writable stream // This is done asynchronously to avoid blocking the response creation result.pipeTo(writable).catch((err)=>{ console.error('Error piping RenderResult to response:', err); }); return new Response(readable, { status: finalStatus, headers }); }; const invokeRender = async (span)=>{ try { const result = await pageRouteModule.render(// @ts-expect-error we don't type this for edge baseReq, new WebNextResponse(undefined), { ...renderContext, renderOpts: { ...renderContext.renderOpts, getServerSideProps: pageMod.getServerSideProps, Component: pageMod.default || pageMod, ComponentMod: pageMod, pageConfig: pageMod.config, isNextDataRequest } }).finally(()=>{ if (!span) return; span.setAttributes({ 'http.status_code': finalStatus, 'next.rsc': false }); const rootSpanAttributes = tracer.getRootSpanAttributes(); // We were unable to get attributes, probably OTEL is not enabled if (!rootSpanAttributes) { return; } if (rootSpanAttributes.get('next.span_type') !== BaseServerSpan.handleRequest) { console.warn(`Unexpected root span type '${rootSpanAttributes.get('next.span_type')}'. Please report this Next.js issue https://github.com/vercel/next.js`); return; } const route = rootSpanAttributes.get('next.route'); if (route) { const name = `${req.method} ${route}`; span.setAttributes({ 'next.route': route, 'http.route': route, 'next.span_name': name }); span.updateName(name); } else { span.updateName(`${req.method} ${srcPage}`); } }); return renderResultToResponse(result); } catch (err) { const errModule = error500Mod || errorMod; const errRouteModule = errModule.routeModule; if (errRouteModule.isDev) { throw err; } const silenceLog = false; await errRouteModule.onRequestError(baseReq, err, { routerKind: 'Pages Router', routePath: srcPage, routeType: 'render', revalidateReason: undefined }, silenceLog); const errResult = await errRouteModule.render(// @ts-expect-error we don't type this for edge baseReq, new WebNextResponse(undefined), { ...renderContext, page: error500Mod ? '/500' : '/_error', renderOpts: { ...renderContext.renderOpts, getServerSideProps: errModule.getServerSideProps, Component: errModule.default || errModule, ComponentMod: errModule, pageConfig: errModule.config } }); return renderResultToResponse(errResult); } }; const tracer = getTracer(); return tracer.withPropagatedContext(req.headers, ()=>tracer.trace(BaseServerSpan.handleRequest, { spanName: `${req.method} ${srcPage}`, kind: SpanKind.SERVER, attributes: { 'http.method': req.method, 'http.target': relativeUrl, 'http.route': srcPage } }, invokeRender)); } const internalHandler = (opts)=>{ return adapter({ ...opts, IncrementalCache, handler: requestHandler, incrementalCacheHandler, bypassNextUrl: true, page: 'VAR_DEFINITION_PATHNAME' }); }; export async function handler(request, ctx) { const result = await internalHandler({ request: { url: request.url, method: request.method, headers: toNodeOutgoingHttpHeaders(request.headers), nextConfig: { basePath: process.env.__NEXT_BASE_PATH, i18n: process.env.__NEXT_I18N_CONFIG, trailingSlash: Boolean(process.env.__NEXT_TRAILING_SLASH), experimental: { cacheLife: process.env.__NEXT_CACHE_LIFE, authInterrupts: Boolean(process.env.__NEXT_EXPERIMENTAL_AUTH_INTERRUPTS), clientParamParsingOrigins: process.env.__NEXT_CLIENT_PARAM_PARSING_ORIGINS } }, page: { name: 'VAR_DEFINITION_PATHNAME' }, body: request.method !== 'GET' && request.method !== 'HEAD' ? request.body ?? undefined : undefined, waitUntil: ctx.waitUntil, requestMeta: ctx.requestMeta, signal: ctx.signal || new AbortController().signal } }); ctx.waitUntil == null ? void 0 : ctx.waitUntil.call(ctx, result.waitUntil); return result.response; } // backwards compat export default internalHandler; //# sourceMappingURL=edge-ssr.js.map