rsnext/packages/next/build/webpack/loaders/next-middleware-ssr-loader/render.ts

87 lines
2.3 KiB
TypeScript
Raw Normal View History

import type { NextConfig } from '../../../../server/config-shared'
import { NextRequest } from '../../../../server/web/spec-extension/request'
import { toNodeHeaders } from '../../../../server/web/utils'
import WebServer from '../../../../server/web-server'
import { WebNextRequest, WebNextResponse } from '../../../../server/base-http'
const createHeaders = (args?: any) => ({
...args,
'x-middleware-ssr': '1',
'Cache-Control': 'no-cache, no-store, max-age=0, must-revalidate',
})
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(),
})
}
export function getRender({
Document,
isServerComponent,
config,
}: {
Document: any
isServerComponent: boolean
config: NextConfig
}) {
// Polyfilled for `path-browserify`.
process.cwd = () => ''
const server = new WebServer({
conf: config,
minimalMode: true,
})
const requestHandler = server.getRequestHandler()
return async function render(request: NextRequest) {
const { nextUrl: url, cookies, headers } = request
const { pathname, searchParams } = url
const query = Object.fromEntries(searchParams)
const req = {
url: pathname,
cookies,
headers: toNodeHeaders(headers),
}
// Preflight request
if (request.method === 'HEAD') {
return new Response(null, {
headers: createHeaders(),
})
}
// @TODO: We should move this into server/render.
if (Document.getInitialProps) {
const err = new Error(
'`getInitialProps` in Document component is not supported with `concurrentFeatures` enabled.'
)
return sendError(req, err)
}
const renderServerComponentData = isServerComponent
? query.__flight__ !== undefined
: false
const serverComponentProps =
isServerComponent && query.__props__
? JSON.parse(query.__props__)
: undefined
// Extend the context.
Object.assign((self as any).__server_context, {
renderServerComponentData,
serverComponentProps,
})
const extendedReq = new WebNextRequest(request)
const extendedRes = new WebNextResponse()
requestHandler(extendedReq, extendedRes)
return await extendedRes.toResponse()
}
}