2022-01-26 07:22:11 +01:00
|
|
|
import type { NextConfig } from '../../../../server/config-shared'
|
|
|
|
|
2021-11-16 21:43:57 +01:00
|
|
|
import { NextRequest } from '../../../../server/web/spec-extension/request'
|
2021-11-26 19:04:36 +01:00
|
|
|
import { toNodeHeaders } from '../../../../server/web/utils'
|
2021-11-16 21:43:57 +01:00
|
|
|
|
2022-01-26 07:22:11 +01:00
|
|
|
import WebServer from '../../../../server/web-server'
|
|
|
|
import { WebNextRequest, WebNextResponse } from '../../../../server/base-http'
|
|
|
|
|
2021-11-22 19:53:22 +01:00
|
|
|
const createHeaders = (args?: any) => ({
|
|
|
|
...args,
|
|
|
|
'x-middleware-ssr': '1',
|
2022-01-18 17:56:08 +01:00
|
|
|
'Cache-Control': 'no-cache, no-store, max-age=0, must-revalidate',
|
2021-11-22 19:53:22 +01:00
|
|
|
})
|
|
|
|
|
2021-12-21 20:24:57 +01:00
|
|
|
function sendError(req: any, error: Error) {
|
|
|
|
const defaultMessage = 'An error occurred while rendering ' + req.url + '.'
|
|
|
|
return new Response((error && error.message) || defaultMessage, {
|
|
|
|
status: 500,
|
|
|
|
headers: createHeaders(),
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2021-11-16 21:43:57 +01:00
|
|
|
export function getRender({
|
|
|
|
Document,
|
|
|
|
isServerComponent,
|
2022-01-26 07:22:11 +01:00
|
|
|
config,
|
2021-11-16 21:43:57 +01:00
|
|
|
}: {
|
|
|
|
Document: any
|
|
|
|
isServerComponent: boolean
|
2022-01-26 07:22:11 +01:00
|
|
|
config: NextConfig
|
2021-11-16 21:43:57 +01:00
|
|
|
}) {
|
2022-01-26 07:22:11 +01:00
|
|
|
// Polyfilled for `path-browserify`.
|
|
|
|
process.cwd = () => ''
|
|
|
|
const server = new WebServer({
|
|
|
|
conf: config,
|
|
|
|
minimalMode: true,
|
|
|
|
})
|
|
|
|
const requestHandler = server.getRequestHandler()
|
|
|
|
|
2021-11-16 21:43:57 +01:00
|
|
|
return async function render(request: NextRequest) {
|
2021-11-22 19:53:22 +01:00
|
|
|
const { nextUrl: url, cookies, headers } = request
|
2021-11-16 21:43:57 +01:00
|
|
|
const { pathname, searchParams } = url
|
|
|
|
|
|
|
|
const query = Object.fromEntries(searchParams)
|
2021-12-21 20:24:57 +01:00
|
|
|
const req = {
|
|
|
|
url: pathname,
|
|
|
|
cookies,
|
|
|
|
headers: toNodeHeaders(headers),
|
|
|
|
}
|
2021-11-16 21:43:57 +01:00
|
|
|
|
|
|
|
// Preflight request
|
|
|
|
if (request.method === 'HEAD') {
|
2021-11-22 19:53:22 +01:00
|
|
|
return new Response(null, {
|
|
|
|
headers: createHeaders(),
|
2021-11-16 21:43:57 +01:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2022-01-26 07:22:11 +01:00
|
|
|
// @TODO: We should move this into server/render.
|
2021-12-21 20:24:57 +01:00
|
|
|
if (Document.getInitialProps) {
|
|
|
|
const err = new Error(
|
|
|
|
'`getInitialProps` in Document component is not supported with `concurrentFeatures` enabled.'
|
|
|
|
)
|
|
|
|
return sendError(req, err)
|
|
|
|
}
|
|
|
|
|
2021-11-16 21:43:57 +01:00
|
|
|
const renderServerComponentData = isServerComponent
|
|
|
|
? query.__flight__ !== undefined
|
|
|
|
: false
|
2021-12-10 11:22:31 +01:00
|
|
|
|
|
|
|
const serverComponentProps =
|
|
|
|
isServerComponent && query.__props__
|
|
|
|
? JSON.parse(query.__props__)
|
|
|
|
: undefined
|
|
|
|
|
2022-01-26 07:22:11 +01:00
|
|
|
// Extend the context.
|
|
|
|
Object.assign((self as any).__server_context, {
|
2021-11-16 21:43:57 +01:00
|
|
|
renderServerComponentData,
|
2021-12-10 11:22:31 +01:00
|
|
|
serverComponentProps,
|
2021-11-16 21:43:57 +01:00
|
|
|
})
|
2022-01-26 07:22:11 +01:00
|
|
|
|
|
|
|
const extendedReq = new WebNextRequest(request)
|
|
|
|
const extendedRes = new WebNextResponse()
|
|
|
|
requestHandler(extendedReq, extendedRes)
|
|
|
|
return await extendedRes.toResponse()
|
2021-11-16 21:43:57 +01:00
|
|
|
}
|
|
|
|
}
|