Skip to content

Commit

Permalink
feat: pageContext.isBaseMissing (#2153)
Browse files Browse the repository at this point in the history
  • Loading branch information
brillout committed Feb 15, 2025
1 parent 370fbb4 commit fab3841
Show file tree
Hide file tree
Showing 5 changed files with 85 additions and 9 deletions.
33 changes: 33 additions & 0 deletions docs/pages/base-url/+Page.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -155,3 +155,36 @@ export default {
Example:
- <RepoLink path='/examples/base-url-server/' />
## Setup
If you set a Base URL for your SSR server, then make sure to properly install <Link href="/renderPage">`renderPage()`</Link>.
You can use your server to only route URLs that include the Base URL, for example with Express.js:
```
// Make sure `/some-base/` aligns with your base setting
app.get('/some-base/*', async (req, res) => {
// Keep the Base URL (Vike expects it)
const pageContextInit = { urlOriginal: req.url }
const pageContext = await renderPage(pageContextInit)
assert(!pageContext.isBaseMissing)
// ...
})
```
Or you can use `pageContext.isBaseMissing`:
```
app.get('*', async (req, res, next) => {
const pageContextInit = { urlOriginal: req.url }
const pageContext = await renderPage(pageContextInit)
if (pageContext.isBaseMissing) return next()
// ...
})
```
Both approaches work equally well.
> When the Base URL is missing then `await renderPage()` is effectively synchronous and very quick: the superflous Vike middleware call is negligible.
1 change: 1 addition & 0 deletions docs/pages/pageContext/+Page.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ Built-in properties:
- **`pageContext.abortReason`**: Set by <Link href="/render" text={<code>throw render()</code>} /> and used by the <Link text="error page" href="/error-page" />.
- **`pageContext.abortStatusCode`**: Set by <Link href="/render" text={<code>throw render()</code>} /> and used by the <Link text="error page" href="/error-page" />.
- **`pageContext.errorWhileRendering`**: The first error (if there is any) that occurred while rendering the page, see <Link href="/error-tracking" />.
- **`pageContext.isBaseMissing`**: Whether the Base URL is missing in the URL of the HTTP request made to the SSR server, see <Link href="/base-url#setup" />.


## Custom
Expand Down
25 changes: 16 additions & 9 deletions vike/node/runtime/renderPage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@ import {
createHttpResponseRedirect,
createHttpResponsePageContextJson,
HttpResponse,
createHttpResponseError
createHttpResponseError,
createHttpResponseBaseIsMissing
} from './renderPage/createHttpResponse.js'
import { logRuntimeError, logRuntimeInfo } from './renderPage/loggerRuntime.js'
import { isNewError } from './renderPage/isNewError.js'
Expand Down Expand Up @@ -151,7 +152,10 @@ async function renderPageAndPrepare(
const globalContext = await getGlobalContextInternal()

// Check Base URL
await assertBaseUrl(pageContextInit, globalContext)
{
const pageContextHttpResponse = await checkBaseUrl(pageContextInit, globalContext)
if (pageContextHttpResponse) return pageContextHttpResponse
}

// Normalize URL
{
Expand Down Expand Up @@ -661,16 +665,19 @@ async function handleAbortError(
return { pageContextAbort }
}

async function assertBaseUrl(pageContextInit: { urlOriginal: string }, globalContext: GlobalContextInternal) {
async function checkBaseUrl(pageContextInit: { urlOriginal: string }, globalContext: GlobalContextInternal) {
const { baseServer } = globalContext
const { urlOriginal } = pageContextInit
const { isBaseMissing } = parseUrl(urlOriginal, baseServer)
assertUsage(
!isBaseMissing,
`${pc.code('renderPage(pageContextInit)')} (https://vike.dev/renderPage) called with ${pc.code(
`pageContextInit.urlOriginal===${JSON.stringify(urlOriginal)}`
)} which doesn't start with Base URL ${pc.code(baseServer)} (https://vike.dev/base-url)`
)
if (!isBaseMissing) return
const pageContext = createPageContext(pageContextInit)
const httpResponse = createHttpResponseBaseIsMissing(urlOriginal, baseServer)
objectAssign(pageContext, {
httpResponse,
isBaseMissing: true as const
})
checkType<PageContextAfterRender>(pageContext)
return pageContext
}

function renderInvalidRequest(pageContextInit: { urlOriginal: string }) {
Expand Down
28 changes: 28 additions & 0 deletions vike/node/runtime/renderPage/createHttpResponse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ export { createHttpResponsePageContextJson }
export { createHttpResponseError }
export { createHttpResponseRedirect }
export { createHttpResponseFavicon404 }
export { createHttpResponseBaseIsMissing }
export type { HttpResponse }

import type { GetPageAssets } from './getPageAssets.js'
Expand Down Expand Up @@ -81,6 +82,33 @@ function createHttpResponseFavicon404(): HttpResponse {
return httpResponse
}

function createHttpResponseBaseIsMissing(urlOriginal: string, baseServer: string): HttpResponse {
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,
'text/html;charset=utf-8',
[],
`
<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 createHttpResponseError(
pageContext: null | {
_pageFilesAll: PageFile[]
Expand Down
7 changes: 7 additions & 0 deletions vike/shared/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,13 @@ type PageContextBuiltInCommon<Data> = {
// TODO/v1-release: remove
/** @deprecated */
pageExports: Record<string, unknown>

/**
* Whether the Base URL is missing in the URL of the HTTP request made to the SSR server.
*
* https://vike.dev/base-url#setup
*/
isBaseMissing?: true
}

type PageContextBuiltInServer<Data> = PageContextBuiltInCommon<Data> & PageContextUrlServer
Expand Down

0 comments on commit fab3841

Please sign in to comment.