next.js/test/e2e/app-dir/graceful-shutdown-next-after/custom-server/server.mjs
server.mjs113 lines2.5 KB
import next from 'next'
import * as http from 'node:http'

const debug = (...args) => {
  if (!process.env.DEBUG) return
  console.log('debug ::', ...args)
}

async function main() {
  debug('starting custom server...')
  const currentPort = parseInt(process.env.PORT, 10) || 3000
  const isDev = process.env.NODE_ENV !== 'production'

  const nextServer = next({
    hostname: 'localhost',
    port: currentPort,
    dev: isDev,
    quiet: false,
  })

  debug('nextServer.prepare()')
  await nextServer.prepare()
  const nextRequestHandler = nextServer.getRequestHandler()

  debug('http.createServer()')
  const httpServer = http.createServer(async (req, res) => {
    try {
      await nextRequestHandler(req, res)
    } catch (err) {
      console.error(err)
      res.statusCode = 500
      res.end('Internal Server Error')
    }
  })

  const cleanup = once(async () => {
    // in dev, there might be a devserver websocket connection
    // that prevents `httpServer.close` from completing, so skip it
    if (!isDev) {
      debug('closing HTTP server...')
      await new Promise((resolve) =>
        httpServer.close((err) => {
          if (err) {
            console.error(err)
          }
          resolve()
        })
      )
    }

    debug('closing Next server...')
    await nextServer.close()

    debug('cleanup finished')
  })

  /** @type {NodeJS.SignalsListener} */
  const onShutdownSignal = async (signal) => {
    debug('onShutdownSignal', signal)
    try {
      await cleanup()
    } finally {
      process.exit(0)
    }
  }

  process.on('SIGTERM', onShutdownSignal)
  process.on('SIGINT', onShutdownSignal)

  try {
    await new Promise((resolve, reject) => {
      httpServer.on('error', reject)
      debug('httpServer.listen()')
      httpServer.listen(currentPort, (err) => {
        if (err) {
          reject(err)
        } else {
          resolve()
        }
        httpServer.off('error', reject)
      })
    })

    console.log(
      [
        `Custom server started`,
        // next test modes parse this to find the appUrl
        `- Local:        http://${nextServer.hostname}:${nextServer.port}`,
      ].join('\n')
    )
  } catch (err) {
    console.error('Failed to start server:', err)
    process.exit(1)
  }
}

/**
 * @template T
 * @param {() => T} cb
 * @returns {() => T} cb
 * */
function once(cb) {
  let state = { didRun: false, value: undefined }
  return () => {
    if (!state.didRun) {
      state = { didRun: true, value: cb() }
    }
    return state.value
  }
}

main()
Quest for Codev2.0.0
/
SIGN IN