Aprendiendo a depurar aplicaciones en Node.js

Este es un práctico tutorial de cómo depurar tus aplicaciones hechas en Node.js. Con esto aprenderás a hacer esta tarea por completo y de la mejor manera. Esta guía lo ayudará a comenzar a depurar tus aplicaciones y scripts Node.js. Continúa leyendo y entérate de mas.

Habilitar un inspector

Cuando se inicia con el interruptor --inspect , un proceso Node.js escucha a través de WebSockets los comandos de diagnóstico definidos por el protocolo Inspector de forma predeterminada en el host y el puerto 127.0.0.1:9229. A cada proceso también se le asigna un UUID único (por ejemplo 0f2c936f-b1cd-4ac9-aab3-f63b0f33d55e).

Los clientes de Inspector deben conocer y especificar la dirección de host, el puerto y el UUID para conectarse a la interfaz de WebSocket. La URL completa ws://127.0.0.1:9229/0f2c936f-b1cd-4ac9-aab3-f63b0f33d55e depende, por supuesto, del host y el puerto reales y con el UUID correcto para la instancia.

El Inspector también incluye un punto final HTTP para servir metadatos sobre el depurador, incluida su URL de WebSocket, UUID y la URL de Chrome DevTools. Obtén estos metadatos enviando una solicitud HTTP a http://[host:port]/json/list. Esto devuelve un objeto JSON como el siguiente; utiliza la propiedad webSocketDebuggerUrl como la URL para conectarse directamente a Inspector.


{
"description": "node.js instance",
"devtoolsFrontendUrl": "chrome-devtools://devtools/bundled/inspector.html?experiments=true&v8only=true&ws=127.0.0.1:9229/0f2c936f-b1cd-4ac9-aab3-f63b0f33d55e",
"faviconUrl": "https://nodejs.org/static/favicon.ico",
"id": "0f2c936f-b1cd-4ac9-aab3-f63b0f33d55e",
"title": "node",
"type": "node",
"url": "file://",
"webSocketDebuggerUrl": "ws://127.0.0.1:9229/0f2c936f-b1cd-4ac9-aab3-f63b0f33d55e"
}

También se puede dar instrucciones a un proceso Node.js iniciado sin –inspect para comenzar a escuchar los mensajes de depuración señalizándolo con SIGUSR1 (en Linux y OS X). A partir del Node 7, esto activa la API de depuración heredada; en el Node 8 y posterior activará la API Inspector.

La seguridad se ve implicada

Dado que el depurador tiene acceso completo al entorno de ejecución Node.js, un actor malintencionado capaz de conectarse a este puerto puede ejecutar código arbitrario en nombre del proceso del nodo. Es importante comprender las implicaciones de seguridad de exponer el puerto de depuración en redes públicas y privadas.

Exponer el puerto de depuración públicamente no es seguro

Si el depurador está vinculado a una dirección IP pública, o 0.0.0.0, cualquier cliente que pueda acceder a su dirección IP podrá conectarse al depurador sin ninguna restricción y podrá ejecutar código arbitrario.

Por defecto se enlaza node –inspect a 127.0.0.1. Debe proporcionar explícitamente una dirección IP pública o 0.0.0.0, etc., si desea permitir conexiones externas al depurador. Hacerlo puede exponerlo a una amenaza de seguridad potencialmente importante. Le sugerimos que asegure los cortafuegos y los controles de acceso adecuados para evitar una exposición de seguridad.

Las aplicaciones locales tienen acceso completo al inspector.

Incluso si vincula el puerto del inspector a 127.0.0.1 (el valor predeterminado), cualquier aplicación que se ejecute localmente en su PC tendrá acceso sin restricciones. Esto es por diseño para permitir que los depuradores locales puedan adjuntar convenientemente.

Navegadores, websockets y política del mismo origen.

Los sitios web abiertos en un navegador web pueden hacer solicitudes WebSocket y HTTP bajo el modelo de seguridad del navegador. Es necesaria una conexión HTTP inicial para obtener un Id de sesión de depurador único. La misma política de origen impide que los sitios web puedan realizar esta conexión HTTP.

Para mayor seguridad contra los ataques de reencuadernación de DNS, Node.js verifica que las cabeceras del ‘Host’ para la conexión especifiquen una dirección IP o localhost o localhost6 con precisión.

Estas políticas de seguridad no permiten conectarse a un servidor de depuración remoto especificando el nombre del host. Puedes evitar esta restricción especificando la dirección IP o utilizando túneles ssh como se describe a continuación.

Clientes Inspectores

Varias herramientas comerciales y de código abierto pueden conectarse al Inspector de nodos. A continuación se ofrece información básica sobre estos temas:

  • node-inspect
    • Depurador CLI soportado por la Fundación Node.js que utiliza el Protocolo Inspector.
    • Una versión se incluye con Node y se puede utilizar con el nodo inspect myscript.js.
    • La última versión también puede instalarse de forma independiente (por ejemplo, npm install -g node-inspect) y utilizarse con node-inspect myscript.js.
  • Chrome DevTools 55+
    • Opción 1: Abrir chrome://inspect en un navegador basado en Chromium. Haga clic en el botón Configurar y asegúrese de que el host y el puerto de destino aparecen en la lista.
    • Opción 2: Copie devtoolsFrontendUrl de la salida de /json/list (ver arriba) o el texto –inspect hint y péguelo en Chrome.
    • Opción 3: Instale Chrome Extension NIM (Administrador del Inspector de Nodos): https://chrome.google.com/webstore/detail/nim-node-inspector-manage/gnhhdgbaldcilmgcpfddgdbkhjohddkj
  • Visual Studio Code 1.10+
    • En el panel de depuración, haga clic en el icono de configuración para abrir .vscode/launch.json. Seleccione «Node.js» para la configuración inicial.
  • Visual Studio 2017
    • Elige «Depurar > Iniciar depuración» en el menú o pulsa F5.
  • JetBrains WebStorm 2017.1+ y otros IDEs de JetBrains
    • Cree una nueva configuración de depuración de Node.js y pulse Depurar. –inspect se usará por defecto para Node.js 7+. Para desactivar js.debugger.node.use.inspect en el Registro IDE.
  • Interfaz remota de Chrome
    • Tiene una biblioteca para facilitar las conexiones a los puntos finales del protocolo Inspector

Opciones de la línea de comandos

La tabla siguiente enumera el impacto de varios indicadores de tiempo de ejecución en la depuración:

  1. –inspect:
    • Habilitar el agente de inspección
    • Escuchar en la dirección y puerto predeterminados (127.0.0.0.1:9229)
  2. –inspect=[host:port]:
    • Habilitar el agente de inspección
    • Enlazar a dirección o host de nombre de host (predeterminado: 127.0.0.0.1)
    • Escuchar en el puerto (predeterminado: 9229)
  3. –inspect-brk
    • Habilitar el agente de inspección
    • Escuchar en la dirección y puerto predeterminados (127.0.0.1:9229)
    • Pausa antes de que comience el código de usuario
  4. –inspect-brk=[host:port]
    • Habilitar el agente de inspección
    • Enlazar a dirección o host de nombre de host (predeterminado: 127.0.0.0.1)
    • Escuchar en el puerto (predeterminado: 9229)
    • Pausa antes de que comience el código de usuario
  5. node inspect script.js
    • Spawn proceso hijo para ejecutar el script del usuario bajo –inspect flag; y usar el proceso principal para ejecutar el depurador CLI.
  6. node inspect –port=xxxx script.js
    • Spawn proceso hijo para ejecutar el script del usuario bajo –inspect flag; y usar el proceso principal para ejecutar el depurador CLI.
    • Escuchar en el puerto (predeterminado: 9229)

Habilitación de escenarios de depuración remota

Te recomiendo que nunca hagas que el depurador escuche en una dirección IP pública. Si necesitas permitir conexiones de depuración remotas, te recomiendo el uso de túneles ssh en su lugar. Te proporciono el siguiente ejemplo sólo con fines ilustrativos. Por favor, comprende el riesgo de seguridad de permitir el acceso remoto a un servicio privilegiado antes de proceder.

Supongamos que está ejecutando Node.js en una máquina remota, remota.ejemplo.com, que desea poder depurar. En esa máquina, debe iniciar el proceso del nodo con el inspector escuchando sólo localhost (el predeterminado).


$ node --inspect server.js

[php]

Ahora, en su máquina local desde donde desea iniciar una conexión de cliente de depuración, puede configurar un túnel ssh:

[php]

$ ssh -L 9221:localhost:9229 ejemplo_de@usuario.remoto.com

Esto inicia una sesión de túnel ssh donde una conexión al puerto 9221 de su máquina local será reenviada al puerto 9229 de remota.ejemplo.com. Ahora puedes adjuntar un depurador como Chrome DevTools o Visual Studio Code a localhost:9221, que debería ser capaz de depurar como si la aplicación Node.js se estuviera ejecutando localmente.