¿Cómo cerrar correctamente el servidor Node.js Express?

7 minutos de lectura

Avatar de usuario de Vladimir Starkov
Vladímir Starkov

Necesito cerrar el servidor después de recibir una devolución de llamada de /auth/github/callback
dirección URL con lo habitual API HTTP El servidor de cierre está actualmente soportando con server.close([callback])

Función API, pero con el servidor node-express estoy obteniendo TypeError: Object function app(req, res){ app.handle(req, res); } has no method 'close'
error. Y no sé cómo encontrar información para resolver este problema.
¿Cómo debo cerrar el servidor express?

Notas de configuración de NodeJS:

$ node --version
v0.8.17
$ npm --version
1.2.0
$ npm view express version
3.0.6

Código de aplicación real:

var app = express();

// configure Express
app.configure(function() {
    // … configuration
});

app.get(
    '/auth/github/callback',
    passport.authenticate('github', { failureRedirect: '/login' }),
    function(req, res) {
        res.redirect("https://stackoverflow.com/");

        setTimeout(function () {
            app.close();
            // TypeError: Object function app(req, res){ app.handle(req, res); } has no method 'close'
        }, 3000)
    }
);

app.listen('http://localhost:5000/');

Además, encontré ‘nodejs express close…’ pero no estoy seguro de poder usarlo con el código que tengo: var app = express();.

  • Estoy comenzando un expreso en una prueba unitaria. En este ámbito, close() no detiene el servidor

    – JRichardsz

    6 de junio de 2021 a las 0:31

  • @JRichardsz tal vez la API haya cambiado en los últimos 8 años

    – Vladímir Starkov

    8 de junio de 2021 a las 8:46

  • @JRichardsz Ver stackoverflow.com/a/21739334/1057730

    – Vladímir Starkov

    8 de junio de 2021 a las 8:47

  • Creo que el problema está en debido a la moca. Prepararé una muestra ejecutable mínima. Mi solución es process.exit(0)

    – JRichardsz

    8 de junio de 2021 a las 14:12

  • @JRichardsz no es moca. process.exit(0) a la solución alternativa, es lo que ax es al dolor de cabeza.

    – Vladímir Starkov

    15 de junio de 2021 a las 9:19

Avatar de usuario de Vladimir Kuznetsov
Vladímir Kuznetsov

app.listen() devoluciones http.Server. deberías invocar close() en esa instancia y no en app instancia.

Ex.

app.get(
    '/auth/github/callback',
    passport.authenticate('github', { failureRedirect: '/login' }),
    function(req, res) {
        res.redirect("https://stackoverflow.com/");

        setTimeout(function () {
            server.close();
            // ^^^^^^^^^^^
        }, 3000)
    }
);

var server = app.listen('http://localhost:5000/');
// ^^^^^^^^^^

Puede inspeccionar las fuentes: /node_modules/express/lib/application.js

  • Extraño, no se cierra si accedo a alguna ruta.

    – Uday Hiwarale

    18 de julio de 2016 a las 22:37

  • @Uday, también experimenté esto. Descubrí que mi navegador tenía abierta una conexión persistente HTTP1.1, por lo que cuando presioné F5 parecía que el servidor no se cerraba. Si prueba con un navegador diferente, verá que el socket del servidor no se está ejecutando.

    –Rick Velde

    15 de diciembre de 2016 a las 22:41

  • Ese fue mi error, estaba llamando cerca app en lugar de server. salvó mi día Muchas gracias 👍

    –Edison Spencer

    6 de diciembre de 2019 a las 12:05

  • ¿Por qué el tiempo de espera?

    – Joao Pimentel Ferreira

    15 de julio de 2021 a las 12:39

  • @JoãoPimentelFerreira parece que Vladimir simplemente siguió el ejemplo que OP dio donde cierran después de 3 segundos

    – Oleg Valter está con Ucrania

    15 de julio de 2021 a las 12:40

Avatar de usuario de Michael
Miguel

En express v3 quitaron esta función.

Todavía puede lograr lo mismo asignando el resultado de app.listen() función y aplicar cerca de ella:

var server = app.listen(3000);
server.close((err) => {
  console.log('server closed')
  process.exit(err ? 1 : 0)
})

https://github.com/visionmedia/express/issues/1366

  • Usa algo como github.com/gajus/http-terminator para asegurar la terminación del servidor en caso de que haya conexiones persistentes o solicitudes que no produzcan una respuesta.

    – Gajus

    20 de enero de 2020 a las 3:16

  • corto y sencillo

    – Krupesh Anadkat

    28 de mayo de 2020 a las 12:56

Avatar de usuario de Neha Sharma
neha sharma

Si ocurre algún error en su aplicación express, entonces debe cerrar el servidor y puede hacerlo como se muestra a continuación:

var app = express();
var server = app.listen(process.env.PORT || 5000)

Si ocurre algún error, nuestra aplicación recibirá una señal llamada SIGTERM. Puedes leer más SIGTERM aquí – https://www.gnu.org/software/libc/manual/html_node/Terminación-Señales.html

process.on('SIGTERM', () => {
  console.info('SIGTERM signal received.');
  console.log('Closing http server.');
  server.close((err) => {
    console.log('Http server closed.');
    process.exit(err ? 1 : 0);
  });
});

  • lo siento, no es relevante. La pregunta es sobre el apagado manual del servidor y no sobre el manejo de errores

    – Vladímir Starkov

    1 de julio de 2019 a las 15:56

  • ¿está seguro? server.close tiene una devolución de llamada? no lo veo en la documentacion

    – Joao Pimentel Ferreira

    15 de julio de 2021 a las 12:40

  • @JoãoPimentelFerreira – sí, es ciertamente hay

    – Oleg Valter está con Ucrania

    15 de julio de 2021 a las 12:43

  • @OlegValter gracias pero leí que el servidor expressJs ya no hereda del servidor http de nodejs

    – Joao Pimentel Ferreira

    15 de julio de 2021 a las 12:48

  • @JoãoPimentelFerreira la última vez que revisé, app.listen la llamada todavía lo hace: “El método app.listen() devuelve un objeto http.Server y (para HTTP) es un método conveniente para lo siguiente”

    – Oleg Valter está con Ucrania

    15 de julio de 2021 a las 12:58


He respondido una variación de “cómo terminar un servidor HTTP” muchas veces en diferentes canales de soporte de node.js. Desafortunadamente, no podría recomendar ninguna de las bibliotecas existentes porque son carente de una u otra manera. Desde entonces, armé un paquete que (creo) está manejando todos los casos que se esperan de la terminación elegante del servidor HTTP(S) de express.js.

https://github.com/gajus/http-terminator

El principal beneficio de http-terminator es eso:

  • no parchea la API de Node.js
  • inmediatamente destruye todos los sockets sin una solicitud HTTP adjunta
  • permite un tiempo de espera elegante para los sockets con solicitudes HTTP en curso
  • maneja correctamente las conexiones HTTPS
  • informa a las conexiones que usan keep-alive que el servidor se está cerrando configurando una conexión: cerrar encabezado
  • no termina el proceso de Node.js

vocación server.close hace el trabajo

server.close((err) => {
  console.log('server closed')
  process.exit(err ? 1 : 0)
})

también es bueno escuchar las señales del sistema (usuario) y apagarlas correctamente también, para eso debe escuchar en ambos SIGTERM y SIGINT

const port = process.env.PORT || 5000;
const server = app.listen(port);
console.log(`listening on port:${port}`);
for (let signal of ["SIGTERM", "SIGINT"])
    process.on(signal, () => {
        console.info(`${signal} signal received.`);
        console.log("Closing http server.");
        server.close((err) => {
            console.log("Http server closed.");
            process.exit(err ? 1 : 0);
        });
    });

Avatar de usuario de João Pimentel Ferreira
joão pimentel ferreira

Pregunta anterior pero ahora nodo v18.2.0 introducido server.closeAllConnections(). se debe notar que server.close nunca ejecuta su devolución de llamada cuando el navegador envía la solicitud Connection: keep-aliveporque server.close solo evita que el servidor acepte nuevas conexiones, no cierra las conexiones antiguas.

Antes de Node v18.2.0, abordé este problema esperando 5 segundos para que el servidor se apagara, después de lo cual forzaría la salida.

Este código engloba ambas situaciones

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

function gracefulShutdown (signal) {
  if (signal) console.log(`\nReceived signal ${signal}`)
  console.log('Gracefully closing http server')

  // closeAllConnections() is only available from Node v18.02
  if (server.closeAllConnections) server.closeAllConnections()
  else setTimeout(() => process.exit(0), 5000)

  try {
    server.close(function (err) {
      if (err) {
        console.error('There was an error', err)
        process.exit(1)
      } else {
        console.log('http server closed successfully. Exiting!')
        process.exit(0)
      }
    })
  } catch (err) {
    console.error('There was an error', err)
    setTimeout(() => process.exit(1), 500)
  }
}

La mayoría de las respuestas llaman process.exit(), no creo que sea una buena idea. Probablemente necesite realizar algún desmontaje, además simplemente no es necesario.

const server = app.listen(port);

server.on('close', () => {
  // Perform some teardown, for example with Knex.js: knex.destroy()
});

// FYI Docker "stop" sends SIGTERM
// If SIGTERM is not catched, Docker is forced to kill the container after ~10s
// and this provokes an exit code 137 instead of 0 (success)
process.on('SIGTERM', () => server.close());

Consulte la documentación de Express.js 4.x: https://expressjs.com/en/advanced/healthcheck-graceful-shutdown.html#graceful-shutdown

¿Ha sido útil esta solución?