UNPKG

next

Version:

The React Framework

252 lines (251 loc) • 11.2 kB
var _self___RSC_MANIFEST; import '../../server/web/globals'; import { adapter } from '../../server/web/adapter'; import { IncrementalCache } from '../../server/lib/incremental-cache'; import * as pageMod from 'VAR_USERLAND'; import { setReferenceManifestsSingleton } from '../../server/app-render/encryption-utils'; import { createServerModuleMap } from '../../server/app-render/action-utils'; import { initializeCacheHandlers } from '../../server/use-cache/handlers'; import { BaseServerSpan } from '../../server/lib/trace/constants'; import { getTracer, SpanKind } from '../../server/lib/trace/tracer'; import { WebNextRequest, WebNextResponse } from '../../server/base-http/web'; import { getIsPossibleServerAction } from '../../server/lib/server-action-request-meta'; import { getBotType } from '../../shared/lib/router/utils/is-bot'; import { interopDefault } from '../../lib/interop-default'; import { normalizeAppPath } from '../../shared/lib/router/utils/app-paths'; import { checkIsOnDemandRevalidate } from '../../server/api-utils'; import { CloseController } from '../../server/web/web-on-close'; // OPTIONAL_IMPORT:incrementalCacheHandler // Initialize the cache handlers interface. initializeCacheHandlers(); // INJECT:nextConfig const maybeJSONParse = (str)=>str ? JSON.parse(str) : undefined; const rscManifest = (_self___RSC_MANIFEST = self.__RSC_MANIFEST) == null ? void 0 : _self___RSC_MANIFEST['VAR_PAGE']; const rscServerManifest = maybeJSONParse(self.__RSC_SERVER_MANIFEST); if (rscManifest && rscServerManifest) { setReferenceManifestsSingleton({ page: 'VAR_PAGE', clientReferenceManifest: rscManifest, serverActionsManifest: rscServerManifest, serverModuleMap: createServerModuleMap({ serverActionsManifest: rscServerManifest }) }); } export const ComponentMod = pageMod; async function requestHandler(req, event) { let srcPage = 'VAR_PAGE'; const normalizedSrcPage = normalizeAppPath(srcPage); const relativeUrl = `${req.nextUrl.pathname}${req.nextUrl.search}`; const baseReq = new WebNextRequest(req); const baseRes = new WebNextResponse(undefined); 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, buildManifest, prerenderManifest, reactLoadableManifest, clientReferenceManifest, subresourceIntegrityManifest, dynamicCssManifest, nextFontManifest, resolvedPathname, serverActionsManifest, interceptionRoutePatterns, routerServerContext } = prepareResult; const isPossibleServerAction = getIsPossibleServerAction(req); const botType = getBotType(req.headers.get('User-Agent') || ''); const { isOnDemandRevalidate } = checkIsOnDemandRevalidate(req, prerenderManifest.preview); const closeController = new CloseController(); const renderContext = { page: normalizedSrcPage, query, params, sharedContext: { buildId }, fallbackRouteParams: null, renderOpts: { App: ()=>null, Document: ()=>null, pageConfig: {}, ComponentMod, Component: interopDefault(ComponentMod), routeModule: pageRouteModule, params, page: srcPage, postponed: undefined, shouldWaitOnAllReady: false, serveStreamingMetadata: true, supportsDynamicResponse: true, buildManifest, nextFontManifest, reactLoadableManifest, subresourceIntegrityManifest, dynamicCssManifest, serverActionsManifest, clientReferenceManifest, setIsrStatus: routerServerContext == null ? void 0 : routerServerContext.setIsrStatus, dir: pageRouteModule.relativeProjectDir, botType, isDraftMode: false, isRevalidate: false, isOnDemandRevalidate, isPossibleServerAction, assetPrefix: nextConfig.assetPrefix, nextConfigOutput: nextConfig.output, crossOrigin: nextConfig.crossOrigin, trailingSlash: nextConfig.trailingSlash, previewProps: prerenderManifest.preview, deploymentId: nextConfig.deploymentId, enableTainting: nextConfig.experimental.taint, htmlLimitedBots: nextConfig.htmlLimitedBots, devtoolSegmentExplorer: nextConfig.experimental.devtoolSegmentExplorer, reactMaxHeadersLength: nextConfig.reactMaxHeadersLength, multiZoneDraftMode: false, cacheLifeProfiles: nextConfig.experimental.cacheLife, basePath: nextConfig.basePath, serverActions: nextConfig.experimental.serverActions, experimental: { isRoutePPREnabled: false, expireTime: nextConfig.expireTime, staleTimes: nextConfig.experimental.staleTimes, cacheComponents: Boolean(nextConfig.experimental.cacheComponents), clientSegmentCache: Boolean(nextConfig.experimental.clientSegmentCache), clientParamParsing: Boolean(nextConfig.experimental.clientParamParsing), dynamicOnHover: Boolean(nextConfig.experimental.dynamicOnHover), inlineCss: Boolean(nextConfig.experimental.inlineCss), authInterrupts: Boolean(nextConfig.experimental.authInterrupts), clientTraceMetadata: nextConfig.experimental.clientTraceMetadata || [] }, incrementalCache: await pageRouteModule.getIncrementalCache(baseReq, nextConfig, prerenderManifest), waitUntil: event.waitUntil.bind(event), onClose: (cb)=>{ closeController.onClose(cb); }, onAfterTaskError: ()=>{}, onInstrumentationRequestError: (error, _request, errorContext)=>pageRouteModule.onRequestError(baseReq, error, errorContext, routerServerContext), dev: pageRouteModule.isDev } }; let finalStatus = 200; const renderResultToResponse = (result)=>{ const varyHeader = pageRouteModule.getVaryHeader(resolvedPathname, interceptionRoutePatterns); // Handle null responses if (result.isNull) { finalStatus = 500; closeController.dispatchClose(); return new Response(null, { status: 500 }); } // Extract metadata const { metadata } = result; const headers = new Headers(); finalStatus = metadata.statusCode || baseRes.statusCode || 200; req.fetchMetrics = metadata.fetchMetrics; // Set content type const contentType = result.contentType || 'text/html; charset=utf-8'; headers.set('Content-Type', contentType); headers.set('x-edge-runtime', '1'); if (varyHeader) { headers.set('Vary', varyHeader); } // Add existing headers for (const [key, value] of Object.entries({ ...baseRes.getHeaders(), ...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)); closeController.dispatchClose(); 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); }).finally(()=>closeController.dispatchClose()); return new Response(readable, { status: finalStatus, headers }); }; const invokeRender = async (span)=>{ try { const result = await pageRouteModule.render(baseReq, baseRes, renderContext).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 = normalizedSrcPage; 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} ${relativeUrl}`); } }); return renderResultToResponse(result); } catch (err) { await pageRouteModule.onRequestError(baseReq, err, { routerKind: 'App Router', routePath: normalizedSrcPage, routeType: 'render', revalidateReason: undefined }); // rethrow so that we can handle serving error page throw err; } }; const tracer = getTracer(); return tracer.withPropagatedContext(req.headers, ()=>tracer.trace(BaseServerSpan.handleRequest, { spanName: `${req.method} ${relativeUrl}`, kind: SpanKind.SERVER, attributes: { 'http.method': req.method, 'http.target': relativeUrl, 'http.route': normalizedSrcPage } }, invokeRender)); } export default function nHandler(opts) { return adapter({ ...opts, IncrementalCache, handler: requestHandler, incrementalCacheHandler }); } //# sourceMappingURL=edge-ssr-app.js.map