1import { createServer, type IncomingMessage, type ServerResponse } from 'http' 2import { parse } from 'url' 4import * as _ from 'lodash-es' 21export type RunNextCtxStore = { 23 handleRequest?: (opts: {app: any, req: IncomingMessage, res: ServerResponse, parsedUrl: any}) => Promise<boolean | void> 24 handleUpgrade?: (req: IncomingMessage, socket: any, head: Buffer) => void 27export const runNext = async (props?: {dev?: boolean, devListenAllInterfaces?: boolean}) => { 29 return await doRunNext(props) 34const doRunNext = async (props: {dev?: boolean, devListenAllInterfaces?: boolean}={}) => { 36 const nodeEnv = process.env.NODE_ENV 40 Error.stackTraceLimit = 100 41 process.on('uncaughtException', (err) => { 42 console.error('[uncaughtException]', err?.stack || err) 44 process.on('unhandledRejection', (reason) => { 45 const stack = (reason as Error)?.stack || reason 46 console.error('[unhandledRejection]', stack) 55 const hostname = (isDevPc && !props.devListenAllInterfaces && !getEnvConfItem('devListenAllInterfaces')) ? '127.0.0.1' : '0.0.0.0' 57 const ctxStore = (runNextCtx.getStore() ?? {}) as RunNextCtxStore 58 const {pagesDir} = ctxStore 60 dev: dev as boolean, port, 63 throwIf(() => dev && nodeEnv != 'development', { 67 const handle = app.getRequestHandler() 68 const {handleRequest, handleUpgrade} = (runNextCtx.getStore() ?? {}) as RunNextCtxStore 73 const server = createServer(async (req, res) => { 74 const startTime = Date.now() 76 const parsedUrl = parse(req.url!, true) 77 const { pathname } = parsedUrl 79 if (pathname?.startsWith('/health/')) { 80 const probeType = pathname.split('/')[2] 86 if (await handleRequest({app, req, res, parsedUrl})) return 89 await handle(req, res, parsedUrl) 90 if (pathname && !pathname.startsWith('/_next/') && !pathname.startsWith('/api/graphql')) { 91 console.log(`${req.method} ${pathname} ${res.statusCode} in ${Date.now() - startTime}ms`) 95 res.end(genericServerErr) 96 const isSharedErr = err instanceof PtErr 97 console.error('Error occurred handling', req.url, {isSharedErr}, err) 105 const g = globalThis as unknown as { __runNextUpgradeServer?: typeof server, __runNextUpgradeHandler?: typeof handleUpgrade } 106 const prevServer = g.__runNextUpgradeServer 107 if (prevServer && prevServer !== server) { 108 prevServer.removeListener('upgrade', g.__runNextUpgradeHandler!) 110 if (prevServer !== server) { 111 server.on('upgrade', handleUpgrade) 112 g.__runNextUpgradeServer = server 113 g.__runNextUpgradeHandler = handleUpgrade 117 server.listen(port, hostname as string, () => { 118 const displayHost = isDevPc && pagesDir ? `${pagesDir.split('/').pop()}.localhost` : hostname 119 const name = process.env.PT_DEPLOY_NAME, deployHostname = process.env.PT_DEPLOY_HOSTNAME 120 const host = isDevPc ? `${displayHost}:${port}` : deployHostname 121 const servedBy = name ? ` {name: '${name}', host: '${host}'}` : '' 122 console.log(`> Ready on http://${displayHost}:${port}${servedBy}`) 125 return new Promise((resolv, reject) => {}) // fake promise, to accurately represent server^ keeps running