vike
Version:
(Replaces Next.js/Nuxt) ๐จ Composable framework to build advanced applications with flexibility and stability.
572 lines (571 loc) โข 29.5 kB
JavaScript
export { renderPageServer };
export { getRequestTag };
import { renderPageServerAfterRoute } from './renderPageServer/renderPageServerAfterRoute.js';
import { createPageContextServer, createPageContextServerWithoutGlobalContext, } from './renderPageServer/createPageContextServer.js';
import { route } from '../../shared-server-client/route/index.js';
import { assert, assertWarning, assertUsage } from '../../utils/assert.js';
import { onSetupRuntime } from '../../utils/assertSetup.js';
import { catchInfiniteLoop } from '../../utils/catchInfiniteLoop.js';
import { checkType } from '../../utils/checkType.js';
import { getGlobalObject } from '../../utils/getGlobalObject.js';
import { hasProp } from '../../utils/hasProp.js';
import { isSameErrorMessage } from '../../utils/isSameErrorMessage.js';
import { objectAssign } from '../../utils/objectAssign.js';
import { normalizeUrlPathname, removeBaseServer, modifyUrlPathname, prependBase, removeUrlOrigin, setUrlOrigin, getUrlPretty, } from '../../utils/parseUrl-extras.js';
import { isUrl, parseUrl, isUri } from '../../utils/parseUrl.js';
import { updateType } from '../../utils/updateType.js';
import { getPageContextAddendumAbort, isAbortError, logAbort, addNewPageContextAborted, } from '../../shared-server-client/route/abort.js';
import { getGlobalContextServerInternal, initGlobalContext_renderPage, } from './globalContext.js';
import { handlePageContextRequestUrl } from './renderPageServer/handlePageContextRequestUrl.js';
import { createHttpResponse404, createHttpResponseRedirect, createHttpResponsePageJson, createHttpResponseErrorFallback, createHttpResponseErrorFallback_noGlobalContext, createHttpResponseBaseIsMissing, createHttpResponseFromUniversalMiddleware, } from './renderPageServer/createHttpResponse.js';
import { logRuntimeError, logRuntimeInfo } from './loggerRuntime.js';
import { assertArguments } from './renderPageServer/assertArguments.js';
import { log404 } from './renderPageServer/log404/index.js';
import pc from '@brillout/picocolors';
import { getPageContextClientSerializedAbort, getPageContextClientSerialized, } from './renderPageServer/html/serializeContext.js';
import { getErrorPageId } from '../../shared-server-client/error-page.js';
import { handleErrorWithoutErrorPage } from './renderPageServer/handleErrorWithoutErrorPage.js';
import { loadPageConfigsLazyServerSide, } from './renderPageServer/loadPageConfigsLazyServerSide.js';
import { resolveRedirects } from './renderPageServer/resolveRedirects.js';
import { getVikeConfigError } from '../../shared-server-node/getVikeConfigError.js';
import { forkPageContext } from '../../shared-server-client/forkPageContext.js';
import { getAsyncLocalStorage } from './asyncHook.js';
import '../assertEnvServer.js';
import { enhance, apply, universalSymbol, UniversalRouter, getAdapterRuntime, } from '@universal-middleware/core';
import { createRequestAdapter } from '@universal-middleware/node/request';
const globalObject = getGlobalObject('runtime/renderPageServer.ts', {
httpRequestsCount: 0,
});
// `renderPageServer()` calls `renderPageServerNominal()` while ensuring that errors are `console.error(err)` instead of `throw err`, so that Vike never triggers a server shut down. (Throwing an error in an Express.js middleware shuts down the whole Express.js server.)
async function renderPageServer(pageContextInit) {
assertArguments(...arguments);
assert(hasProp(pageContextInit, 'urlOriginal', 'string')); // assertUsage() already implemented at assertArguments()
assertIsUrl(pageContextInit.urlOriginal);
onSetupRuntime();
const requestId = getRequestId();
const pageContextSkipRequest = getPageContextSkipRequest(pageContextInit, requestId);
if (pageContextSkipRequest)
return pageContextSkipRequest;
const urlOriginalPretty = getUrlPretty(pageContextInit.urlOriginal);
logHttpRequest(urlOriginalPretty, pageContextInit, requestId);
const asyncLocalStorage = await getAsyncLocalStorage();
const asyncStore = !asyncLocalStorage ? null : { requestId };
const render = async () => await renderPageServerEntryOnceBegin(pageContextInit, requestId, asyncStore);
const pageContextFinish = !asyncLocalStorage ? await render() : await asyncLocalStorage.run(asyncStore, render);
logHttpResponse(urlOriginalPretty, pageContextFinish);
checkType(pageContextFinish);
assertPageContextFinish(pageContextFinish);
return pageContextFinish;
}
async function renderPageServerEntryOnceBegin(pageContextInit, requestId, asyncStore) {
// Invalid config
{
const vikeConfigError = getVikeConfigError();
if (vikeConfigError) {
return getPageContextInvalidVikeConfig(vikeConfigError.err, pageContextInit, requestId);
}
}
// Prepare context
try {
await initGlobalContext_renderPage();
}
catch (err) {
// Errors are expected:
// - assertUsage() such as:
// ```bash
// Re-build your app (you're using 1.2.3 but your app was built with 1.2.2)
// ```
// - initGlobalContext_renderPage() depends on +onCreateGlobalContext hooks
assert(!isAbortError(err));
const pageContext = createPageContextServerWithoutGlobalContext(pageContextInit, requestId);
logRuntimeError(err, pageContext);
const pageContextHttpErrorFallback = getPageContextHttpErrorFallback_noGlobalContext(err, pageContextInit, requestId);
return pageContextHttpErrorFallback;
}
{
const vikeConfigError = getVikeConfigError();
if (vikeConfigError) {
return getPageContextInvalidVikeConfig(vikeConfigError.err, pageContextInit, requestId);
}
else {
// `globalContext` now contains the entire Vike config and getVikeConfig() isn't called anymore for this request.
}
}
const { globalContext } = await getGlobalContextServerInternal();
const pageContextBegin = getPageContextBegin(pageContextInit, globalContext, requestId, asyncStore);
const middlewares = (globalContext.config.middleware ?? []).flat();
const renderPageServerEntry = () => renderPageServerEntryOnce(pageContextBegin, globalContext, requestId);
if (middlewares.length === 0) {
return renderPageServerEntry();
}
else {
return renderPageServerEntryWithMiddlewares(pageContextBegin, renderPageServerEntry, middlewares);
}
}
async function renderPageServerEntryOnce(pageContextBegin, globalContext, requestId) {
// Check Base URL
{
const pageContextHttpResponse = await checkBaseUrl(pageContextBegin, globalContext);
if (pageContextHttpResponse)
return pageContextHttpResponse;
}
// Normalize URL
{
const pageContextHttpResponse = await normalizeUrl(pageContextBegin, globalContext);
if (pageContextHttpResponse)
return pageContextHttpResponse;
}
// Permanent redirects (HTTP status code `301`)
{
const pageContextHttpResponse = await getPermanentRedirect(pageContextBegin, globalContext);
if (pageContextHttpResponse)
return pageContextHttpResponse;
}
// First renderPageServerEntryRecursive() call
return await renderPageServerEntryRecursive(pageContextBegin, globalContext, requestId);
}
async function renderPageServerEntryRecursive(pageContextBegin, globalContext, requestId) {
catchInfiniteLoop(`[${getRequestTag(requestId)}] renderPageServerEntryRecursive()`);
const pageContextNominalPageBegin = fork(pageContextBegin);
const pageContextAddendumAbort = getPageContextAddendumAbort(pageContextBegin.pageContextsAborted);
objectAssign(pageContextNominalPageBegin, pageContextAddendumAbort);
objectAssign(pageContextNominalPageBegin, { errorWhileRendering: null });
const onError = async (err) => {
assert(err);
assert(pageContextNominalPageSuccess === undefined);
logRuntimeError(err, pageContextNominalPageBegin);
return await renderPageServerEntryRecursive_onError(err, pageContextBegin, pageContextNominalPageBegin, globalContext, requestId);
};
// Route
let pageContextFromRoute;
try {
pageContextFromRoute = await route(pageContextNominalPageBegin);
}
catch (err) {
return await onError(err);
}
objectAssign(pageContextNominalPageBegin, pageContextFromRoute);
if (pageContextNominalPageBegin.pageId !== null) {
assert(pageContextNominalPageBegin.pageId);
objectAssign(pageContextNominalPageBegin, { is404: null });
}
else {
objectAssign(pageContextNominalPageBegin, { is404: true });
log404(pageContextNominalPageBegin);
const errorPageId = getErrorPageId(pageContextNominalPageBegin._globalContext._pageFilesAll, pageContextNominalPageBegin._globalContext._pageConfigs);
if (!errorPageId) {
assert(hasProp(pageContextNominalPageBegin, 'pageId', 'null')); // Help TS
return handleErrorWithoutErrorPage(pageContextNominalPageBegin);
}
objectAssign(pageContextNominalPageBegin, { pageId: errorPageId });
}
assert(hasProp(pageContextNominalPageBegin, 'pageId', 'string'));
assert(pageContextNominalPageBegin.errorWhileRendering === null);
// - Render page (nominal, i.e. not the error page)
// - Render 404 page
// (`var` instead of `let` because of assert() above that can be called before reaching this line https://stackoverflow.com/a/11444416/270274)
var pageContextNominalPageSuccess;
try {
pageContextNominalPageSuccess = await renderPageServerAfterRoute(pageContextNominalPageBegin);
}
catch (err) {
return await onError(err);
}
assert(pageContextNominalPageBegin === pageContextNominalPageSuccess);
return pageContextNominalPageSuccess;
}
// When the normal page threw an error
// - Can be a URL rewrite upon `throw render('/some-url')`
// - Can be rendering the error page
// - Can be rendering Vike's generic error page (if no error page is defined, or if the error page throws an error)
async function renderPageServerEntryRecursive_onError(err, pageContextBegin, pageContextNominalPageBegin, globalContext, requestId) {
assert(pageContextNominalPageBegin);
assert(hasProp(pageContextNominalPageBegin, 'urlOriginal', 'string'));
assert(err);
const pageContextErrorPageInit = fork(pageContextBegin);
objectAssign(pageContextErrorPageInit, {
is404: false,
errorWhileRendering: err,
routeParams: {},
});
// Handle `throw redirect()` and `throw render()` while rendering nominal page
if (isAbortError(err)) {
const handled = await handleAbort(err, pageContextBegin, pageContextNominalPageBegin, requestId, pageContextErrorPageInit, globalContext);
if (handled.pageContextReturn) {
// - throw redirect()
// - throw render(url)
// - throw render(abortStatusCode) if pageContext.json request
return handled.pageContextReturn;
}
else {
// - throw render(abortStatusCode) if not pageContext.json request
objectAssign(pageContextErrorPageInit, handled.pageContextAbort);
}
}
{
const errorPageId = getErrorPageId(globalContext._pageFilesAll, globalContext._pageConfigs);
if (!errorPageId) {
objectAssign(pageContextErrorPageInit, { pageId: null });
return handleErrorWithoutErrorPage(pageContextErrorPageInit);
}
objectAssign(pageContextErrorPageInit, { pageId: errorPageId });
}
let pageContextErrorPage;
try {
pageContextErrorPage = await renderPageServerAfterRoute(pageContextErrorPageInit);
}
catch (errErrorPage) {
// Handle `throw redirect()` and `throw render()` while rendering error page
if (isAbortError(errErrorPage)) {
const handled = await handleAbort(errErrorPage, pageContextBegin, pageContextNominalPageBegin, requestId, pageContextErrorPageInit, globalContext);
if (handled.pageContextReturn) {
// - throw redirect()
// - throw render(url)
return handled.pageContextReturn;
}
else {
// - throw render(abortStatusCode)
const pageContextAbort = errErrorPage._pageContextAbort;
assertWarning(false, `Failed to render error page because ${pc.cyan(pageContextAbort._abortCall)} was called: make sure ${pc.cyan(pageContextAbort._abortCaller)} doesn't occur while the error page is being rendered.`, { onlyOnce: false });
const pageContextHttpErrorFallback = getPageContextHttpErrorFallback(err, pageContextBegin);
return pageContextHttpErrorFallback;
}
}
if (isSameErrorMessage(errErrorPage, err)) {
logRuntimeError(errErrorPage, pageContextErrorPageInit);
}
const pageContextHttpErrorFallback = getPageContextHttpErrorFallback(err, pageContextBegin);
return pageContextHttpErrorFallback;
}
return pageContextErrorPage;
}
const requestAdapter = createRequestAdapter();
async function renderPageServerEntryWithMiddlewares(pageContext, renderPageServerEntry, middlewares) {
const router = new UniversalRouter(true, false);
let httpResponseVikeCore = undefined;
// Wrap rendering into universal-middleware routing
apply(router, [
enhance(async function adaptRenderPageServerEntryOnceInternal() {
const pageContextHttpResponse = await renderPageServerEntry();
const { httpResponse } = pageContextHttpResponse;
pageContext = pageContextHttpResponse;
httpResponseVikeCore = httpResponse;
const readable = httpResponse.getReadableWebStream();
return new Response(readable, {
status: httpResponse.statusCode,
headers: httpResponse.headers,
});
}, {
name: 'vike',
method: ['GET', 'POST', 'PUT', 'PATCH', 'HEAD', 'OPTIONS'],
path: '/**', // rou3 format
immutable: true, // avoids cloning the function we just created
}),
...middlewares,
]);
const handler = router[universalSymbol];
const request = pageContext._reqWeb ??
(pageContext._reqDev
? requestAdapter(pageContext._reqDev)
: new Request(new URL(pageContext.urlOriginal, 'http://localhost').toString(), {
headers: pageContext.headers ?? {},
}));
const res = await handler(request, {}, getAdapterRuntime('other', { params: undefined }));
const httpResponse = createHttpResponseFromUniversalMiddleware(res, httpResponseVikeCore?.earlyHints);
objectAssign(pageContext, { httpResponse });
return pageContext;
}
function logHttpRequest(urlOriginal, pageContextInit, requestId) {
const pageContext = createPageContextServerWithoutGlobalContext(pageContextInit, requestId);
logRuntimeInfo?.(getRequestInfoMessage(urlOriginal), pageContext, 'info');
}
/* Alternative icons:
const arrowRight = pc.dim('ยป')
const arrowLeft = pc.dim('ยซ')
const arrowRight = pc.dim('>>')
const arrowLeft = pc.dim('<<')
*/
const arrowRight = pc.dim('โ');
const arrowLeft = pc.dim('โ');
function getRequestInfoMessage(urlOriginal) {
return `HTTP request ${arrowRight} ${prettyUrl(urlOriginal)}`;
}
function logHttpResponse(urlOriginalPretty, pageContextReturn) {
const statusCode = pageContextReturn.httpResponse?.statusCode ?? null;
let msg;
let isNominal;
{
const { errorWhileRendering } = pageContextReturn;
const isSkipped = statusCode === null && !errorWhileRendering;
if (isSkipped) {
// - URL doesn't include Base URL
// - Can we abort earlier so that `logHttpResponse()` and `logHttpRequest()` aren't even called?
// - Error loading a Vike config file
// - We should show `HTTP response ${urlOriginalPretty} ERR` instead.
// - Maybe we can/should make the error available at pageContext.errorWhileRendering
assert(errorWhileRendering === null || errorWhileRendering === undefined);
msg = `HTTP response ${arrowLeft} ${prettyUrl(urlOriginalPretty)} ${pc.dim('null')}`;
// Erroneous value (it should sometimes be `false`) but it's fine as it doesn't seem to have much of an impact.
isNominal = true;
}
else {
const isSuccess = statusCode !== null && statusCode >= 200 && statusCode <= 399;
isNominal = isSuccess || statusCode === 404;
const color = (s) => pc.bold(isSuccess ? pc.green(String(s)) : pc.red(String(s)));
const isRedirect = statusCode && 300 <= statusCode && statusCode <= 399;
const type = isRedirect ? 'redirect' : `response ${arrowLeft}`;
if (isRedirect) {
assert(pageContextReturn.httpResponse);
const headerRedirect = pageContextReturn.httpResponse.headers
.slice()
.reverse()
.find((header) => header[0] === 'Location');
assert(headerRedirect);
const urlRedirect = headerRedirect[1];
urlOriginalPretty = urlRedirect;
}
msg = `HTTP ${type} ${prettyUrl(urlOriginalPretty)} ${color(statusCode ?? 'ERR')}`;
}
}
logRuntimeInfo?.(msg, pageContextReturn, isNominal ? 'info' : 'error');
}
function prettyUrl(url) {
try {
url = decodeURI(url);
}
catch {
// https://github.com/vikejs/vike/pull/2367#issuecomment-2800967564
}
return pc.bold(url);
}
function getPageContextHttpErrorFallback(err, pageContextBegin) {
const pageContextHttpErrorFallback = fork(pageContextBegin);
const httpResponse = createHttpResponseErrorFallback(pageContextBegin);
objectAssign(pageContextHttpErrorFallback, {
httpResponse,
errorWhileRendering: err,
});
return pageContextHttpErrorFallback;
}
function getPageContextHttpErrorFallback_noGlobalContext(err, pageContextInit, requestId) {
const pageContextHttpErrorFallback = createPageContextServerWithoutGlobalContext(pageContextInit, requestId);
const httpResponse = createHttpResponseErrorFallback_noGlobalContext();
objectAssign(pageContextHttpErrorFallback, {
httpResponse,
errorWhileRendering: err,
});
return pageContextHttpErrorFallback;
}
function getPageContextBegin(pageContextInit, globalContext, requestId, asyncStore) {
const { isClientSideNavigation, _urlHandler, _isPageContextJsonRequest } = handlePageContextUrl(pageContextInit.urlOriginal);
const pageContextBegin = createPageContextServer(pageContextInit, globalContext, {
isPrerendering: false,
urlHandler: _urlHandler,
isClientSideNavigation,
requestId,
});
objectAssign(pageContextBegin, {
_requestId: requestId,
_asyncStore: asyncStore,
_isPageContextJsonRequest,
// This array is shared between all pageContext objects, i.e. the following is true for any `i` and `j` index:
// ```js
// const pageContextsAborted_i = pageContextsAborted[i].pageContextsAborted
// const pageContextsAborted_j = pageContextsAborted[j].pageContextsAborted
// assert(pageContextsAborted_i === pageContextsAborted_j)
// ```
pageContextsAborted: [],
});
return pageContextBegin;
}
function handlePageContextUrl(urlOriginal) {
const { isPageContextJsonRequest } = handlePageContextRequestUrl(urlOriginal);
return {
isClientSideNavigation: !!isPageContextJsonRequest,
_isPageContextJsonRequest: isPageContextJsonRequest,
_urlHandler: (url) => handlePageContextRequestUrl(url).urlWithoutPageContextRequestSuffix,
};
}
function getRequestId() {
const requestId = ++globalObject.httpRequestsCount;
assert(requestId >= 1);
return requestId;
}
function assertIsUrl(urlOriginal) {
assertUsage(isUrl(urlOriginal), `${pc.code('renderPage(pageContextInit)')} (https://vike.dev/renderPage) called with ${pc.code(`pageContextInit.urlOriginal===${JSON.stringify(urlOriginal)}`)} which isn't a valid URL.`);
}
function assertIsNotViteRequest(urlPathname, urlOriginal) {
const isViteRequest = urlPathname.startsWith('/@vite/client') || urlPathname.startsWith('/@fs/') || urlPathname.startsWith('/__vite_ping');
if (!isViteRequest)
return;
assertUsage(false, `${pc.code('renderPage(pageContextInit)')} called with ${pc.code(`pageContextInit.urlOriginal===${JSON.stringify(urlOriginal)}`)} which is unexpected because the URL ${pc.bold(urlOriginal)} should have already been handled by the development middleware: make sure the ${pc.cyan('createDevMiddleware()')} middleware is executed *before* the ${pc.cyan('renderPage()')} middleware, see ${pc.underline('https://vike.dev/renderPage')}`);
}
async function normalizeUrl(pageContextBegin, globalContext) {
const pageContext = fork(pageContextBegin);
const { trailingSlash, disableUrlNormalization } = globalContext.config;
if (disableUrlNormalization)
return null;
const { urlOriginal } = pageContext;
const { isPageContextJsonRequest } = handlePageContextRequestUrl(urlOriginal);
if (isPageContextJsonRequest)
return null;
const urlNormalized = normalizeUrlPathname(urlOriginal, trailingSlash ?? false, globalContext.baseServer);
if (!urlNormalized)
return null;
logRuntimeInfo?.(`URL normalized from ${pc.cyan(urlOriginal)} to ${pc.cyan(urlNormalized)} (https://vike.dev/url-normalization)`, pageContext, 'info');
const httpResponse = createHttpResponseRedirect({ url: urlNormalized, statusCode: 301 }, pageContext);
objectAssign(pageContext, { httpResponse });
return pageContext;
}
async function getPermanentRedirect(pageContextBegin, globalContext) {
const pageContext = fork(pageContextBegin);
const urlWithoutBase = removeBaseServer(pageContext.urlOriginal, globalContext.baseServer);
let origin = null;
let urlTargetExternal = null;
let urlTarget = modifyUrlPathname(urlWithoutBase, (urlPathname) => {
const urlTarget = resolveRedirects(globalContext.config.redirects ?? [], urlPathname);
if (urlTarget === null)
return null;
if (!isUrl(urlTarget)) {
// E.g. `urlTarget === 'mailto:some@example.com'`
assert(isUri(urlTarget));
urlTargetExternal = urlTarget;
return null;
}
const { urlModified, origin: origin_ } = removeUrlOrigin(urlTarget);
origin = origin_;
return urlModified;
});
if (urlTargetExternal) {
urlTarget = urlTargetExternal;
}
else {
let originChanged = false;
if (origin) {
const urlModified = setUrlOrigin(urlTarget, origin);
if (urlModified !== false) {
originChanged = true;
urlTarget = urlModified;
}
}
if (normalize(urlTarget) === normalize(urlWithoutBase))
return null;
if (!originChanged)
urlTarget = prependBase(urlTarget, globalContext.baseServer);
assert(urlTarget !== pageContext.urlOriginal);
}
logRuntimeInfo?.(`Permanent redirection defined by config.redirects (https://vike.dev/redirects)`, pageContext, 'info');
const httpResponse = createHttpResponseRedirect({ url: urlTarget, statusCode: 301 }, pageContext);
objectAssign(pageContext, { httpResponse });
return pageContext;
}
function normalize(url) {
return url || '/';
}
async function handleAbort(errAbort, pageContextBegin,
// handleAbortError() creates a new pageContext object and we don't merge pageContextNominalPageBegin to it: we only use some pageContextNominalPageBegin information.
pageContextNominalPageBegin, requestId, pageContextErrorPageInit, globalContext) {
logAbort(errAbort, globalContext._isProduction, pageContextNominalPageBegin);
const pageContextAbort = errAbort._pageContextAbort;
assert(pageContextAbort);
addNewPageContextAborted(pageContextBegin.pageContextsAborted, pageContextNominalPageBegin, pageContextAbort);
const pageContext = fork(pageContextBegin);
const pageContextAddendumAbort = getPageContextAddendumAbort(pageContextBegin.pageContextsAborted);
objectAssign(pageContext, pageContextAddendumAbort);
assert(pageContextAddendumAbort === pageContextAbort);
// Client-side navigation โ [`pageContext.json` request](https://vike.dev/pageContext.json)
if (pageContextBegin.isClientSideNavigation) {
let pageContextSerialized;
if (pageContextAbort.abortStatusCode) {
const errorPageId = getErrorPageId(globalContext._pageFilesAll, globalContext._pageConfigs);
const abortCall = pageContextAbort._abortCall;
assert(abortCall);
assertUsage(errorPageId, `You called ${pc.cyan(abortCall)} but you didn't define an error page, make sure to define one https://vike.dev/error-page`);
objectAssign(pageContext, { pageId: errorPageId });
objectAssign(pageContext, pageContextErrorPageInit, true);
updateType(pageContext, await loadPageConfigsLazyServerSide(pageContext));
// We include pageContextInit: we don't only serialize pageContextAbort because the error page may need to access pageContextInit
pageContextSerialized = getPageContextClientSerialized(pageContext, false);
}
else {
pageContextSerialized = getPageContextClientSerializedAbort(pageContextAbort, false);
}
const httpResponse = await createHttpResponsePageJson(pageContextSerialized);
objectAssign(pageContext, { httpResponse });
return { pageContextReturn: pageContext };
}
// URL Rewrite โ `throw render(url)`
if (pageContextAbort._urlRewrite) {
// Recursive renderPageServerEntryRecursive() call
const pageContextReturn = await renderPageServerEntryRecursive(pageContextBegin, globalContext, requestId);
return { pageContextReturn };
}
// URL Redirection โ `throw redirect()`
if (pageContextAbort._urlRedirect) {
const httpResponse = createHttpResponseRedirect(pageContextAbort._urlRedirect, pageContextBegin);
objectAssign(pageContext, { httpResponse });
return { pageContextReturn: pageContext };
}
// Render error page โ `throw render(abortStatusCode)` if not pageContext.json request
assert(pageContextAbort.abortStatusCode);
return { pageContextAbort };
}
async function checkBaseUrl(pageContextBegin, globalContext) {
const pageContext = fork(pageContextBegin);
const { baseServer } = globalContext;
const { urlOriginal } = pageContext;
const { isBaseMissing } = parseUrl(urlOriginal, baseServer);
if (!isBaseMissing)
return;
const httpResponse = createHttpResponseBaseIsMissing(urlOriginal, baseServer);
objectAssign(pageContext, {
httpResponse,
isBaseMissing: true,
});
checkType(pageContext);
return pageContext;
}
function getPageContextSkipRequest(pageContextInit, requestId) {
const urlPathnameWithBase = parseUrl(pageContextInit.urlOriginal, '/').pathname;
assertIsNotViteRequest(urlPathnameWithBase, pageContextInit.urlOriginal);
let errMsg404;
if (urlPathnameWithBase.endsWith('/favicon.ico')) {
errMsg404 = 'No favicon.ico found';
}
if (urlPathnameWithBase.endsWith('.well-known/appspecific/com.chrome.devtools.json')) {
// https://chromium.googlesource.com/devtools/devtools-frontend/+/main/docs/ecosystem/automatic_workspace_folders.md
// https://www.reddit.com/r/node/comments/1kcr0wh/odd_request_coming_into_my_localhost_server_from/
errMsg404 = 'Not supported';
}
if (!errMsg404)
return;
const pageContext = createPageContextServerWithoutGlobalContext(pageContextInit, requestId);
const httpResponse = createHttpResponse404(errMsg404);
objectAssign(pageContext, { httpResponse });
checkType(pageContext);
return pageContext;
}
function getPageContextInvalidVikeConfig(err, pageContextInit, requestId) {
const pageContext = createPageContextServerWithoutGlobalContext(pageContextInit, requestId);
logRuntimeInfo?.(pc.bold(pc.red('Error loading Vike config โ see error above')), pageContext, 'error');
const pageContextHttpErrorFallback = getPageContextHttpErrorFallback_noGlobalContext(err, pageContextInit, requestId);
return pageContextHttpErrorFallback;
}
function fork(pageContext) {
const pageContextNew = forkPageContext(pageContext);
if (pageContext._asyncStore)
pageContext._asyncStore.pageContext = pageContextNew;
assert(pageContextNew._asyncStore === pageContext._asyncStore);
return pageContextNew;
}
function assertPageContextFinish(pageContextFinish) {
assert(pageContextFinish.httpResponse);
if (pageContextFinish.isClientSideNavigation) {
const headers = new Headers(pageContextFinish.httpResponse.headers);
const contentType = headers.get('Content-Type');
assert(contentType?.toLowerCase() === 'application/json');
}
}
function getRequestTag(requestId) {
return `request-${requestId}`;
}