vike
Version:
(Replaces Next.js/Nuxt) 🔨 Composable framework to build advanced applications with flexibility and stability.
137 lines (136 loc) • 6.79 kB
JavaScript
export { createHttpResponsePage };
export { createHttpResponsePageJson };
export { createHttpResponseErrorFallback };
export { createHttpResponseErrorFallback_noGlobalContext };
export { createHttpResponseErrorFallbackJson };
export { createHttpResponseRedirect };
export { createHttpResponse404 };
export { createHttpResponseBaseIsMissing };
export { createHttpResponseFromUniversalMiddleware };
import { escapeHtml } from '../../../utils/escapeHtml.js';
import { assert, assertWarning } from '../../../utils/assert.js';
import { getErrorPageId, isErrorPage } from '../../../shared-server-client/error-page.js';
import { getHttpResponseBody, getHttpResponseBodyStreamHandlers } from './getHttpResponseBody.js';
import { getEarlyHints } from './getEarlyHints.js';
import { assertNoInfiniteHttpRedirect } from './createHttpResponse/assertNoInfiniteHttpRedirect.js';
import { resolveHeadersResponseFinal } from './headersResponse.js';
import { stringify } from '@brillout/json-serializer/stringify';
import '../../assertEnvServer.js';
const contentTypeJson = 'application/json';
const contentTypeHtml = 'text/html;charset=utf-8';
const htmlFallbackLog = 'This HTML was generated by Vike.';
async function createHttpResponsePage(htmlRender, renderHook, pageContext) {
let statusCode = pageContext.abortStatusCode;
if (!statusCode) {
const isError = !pageContext.pageId || isErrorPage(pageContext.pageId, pageContext._globalContext._pageConfigs);
if (pageContext.errorWhileRendering) {
assert(isError);
}
if (!isError) {
assert(pageContext.is404 === null);
statusCode = 200;
}
else {
assert(pageContext.is404 === true || pageContext.is404 === false);
statusCode = pageContext.is404 ? 404 : 500;
}
}
const earlyHints = getEarlyHints(await pageContext.__getPageAssets());
const headers = resolveHeadersResponseFinal(pageContext, statusCode);
return createHttpResponse(statusCode, contentTypeHtml, headers, htmlRender, earlyHints, renderHook);
}
function createHttpResponse404(errMsg404) {
const httpResponse = createHttpResponse(404, contentTypeHtml, [], getHtmlFallback(`<p>${errMsg404}.</p>`));
return httpResponse;
}
function createHttpResponseBaseIsMissing(urlOriginal, baseServer) {
const httpResponse = createHttpResponse(
// We use the error code `500` to signal a failing state because this HTTP response should never be used, see https://vike.dev/base-url#setup
// In other words: this HTTP response is expected to be generated but isn't expected to be actually used.
500, contentTypeHtml, [], `
<h1>Error: Base URL is missing</h1>
<p>
<a href="https://vike.dev/renderPage"><code>renderPage(pageContextInit)</code></a> called with <code>pageContextInit.urlOriginal===${JSON.stringify(urlOriginal)}</code> which doesn't start with the Base URL <code>${baseServer}</code>.
</p>
<p>
See <a href="https://vike.dev/base-url#setup">vike.dev/base-url#setup</a> for how to properly setup your server while using a Base URL.
</p>
<style>
code {
font-family: monospace;
background-color: #eaeaea;
padding: 3px 5px;
border-radius: 4px;
}
</style>
`);
return httpResponse;
}
function createHttpResponseErrorFallback(pageContext) {
const reason = (() => {
const errorPageId = getErrorPageId(pageContext._globalContext._pageFilesAll, pageContext._globalContext._pageConfigs);
if (errorPageId) {
return "the error page (https://vike.dev/error-page) couldn't be rendered (for example if an error occurred while rendering the error page)";
}
else {
return 'no error page (https://vike.dev/error-page) is defined, make sure to create one';
}
})();
return createHttpResponseError_(reason);
}
function createHttpResponseErrorFallback_noGlobalContext() {
return createHttpResponseError_('no error page (https://vike.dev/error-page) could be rendered');
}
function createHttpResponseError_(reason) {
const httpResponse = createHttpResponse(500, contentTypeHtml, [], getHtmlFallback('<p>An error occurred.</p>', `${htmlFallbackLog} Vike returned this HTML because ${reason}.`));
return httpResponse;
}
function createHttpResponseErrorFallbackJson() {
const httpResponse = createHttpResponse(500, contentTypeJson, [], stringify({ serverSideError: true }));
return httpResponse;
}
async function createHttpResponsePageJson(pageContextSerialized) {
const httpResponse = createHttpResponse(200, contentTypeJson, [], pageContextSerialized, [], null);
return httpResponse;
}
function createHttpResponseRedirect({ url, statusCode }, pageContextInit) {
assertNoInfiniteHttpRedirect(url, pageContextInit);
assert(url);
assert(statusCode);
assert(300 <= statusCode && statusCode <= 399);
const headers = [['Location', url]];
return createHttpResponse(statusCode, contentTypeHtml, headers,
// For bots / programmatic crawlig: show what's going on.
// For users: showing a blank page is probably better than a flickering text.
getHtmlFallback(`<p style="display: none">Redirecting to ${escapeHtml(url)}</p>`));
}
function createHttpResponseFromUniversalMiddleware(response, earlyHints) {
const body = response.body ?? getHtmlFallback('<p style="display: none">No HTTP response body.</p>');
const httpResponse = createHttpResponseCommon(response.status, Array.from(response.headers.entries()), body, earlyHints);
return httpResponse;
}
function getHtmlFallback(bodyHtml, logText = htmlFallbackLog) {
return `${bodyHtml}<script>console.log(${JSON.stringify(logText)})</script>`;
}
function createHttpResponse(statusCode, contentType, headers, htmlRender, earlyHints, renderHook) {
headers.push(['Content-Type', contentType]);
assert(renderHook || typeof htmlRender === 'string');
return createHttpResponseCommon(statusCode, headers, htmlRender, earlyHints, renderHook);
}
function createHttpResponseCommon(statusCode, headers, htmlRender, earlyHints = [], renderHook = null) {
const contentType = headers.find(([k]) => k.toLowerCase() === 'content-type')?.[1];
return {
statusCode,
headers,
// TO-DO/next-major-release: remove
get contentType() {
assertWarning(false, 'pageContext.httpResponse.contentType is deprecated and will be removed in the next major release. Use pageContext.httpResponse.headers instead, see https://vike.dev/migration/0.4.134', { onlyOnce: true });
return contentType;
},
earlyHints,
get body() {
return getHttpResponseBody(htmlRender, renderHook);
},
...getHttpResponseBodyStreamHandlers(htmlRender, renderHook),
};
}