Regla
Evite involuntarias global variable caching.In Node.js
y Python servidores, globales variables persisten en a través de
peticiones, causando datos de datos y carrera condiciones de carrera.
Lenguajes compatibles: JavaScript, TypeScript, PythonIntroducción
Las variables globales en los servidores Node.js persisten durante toda la vida del proceso, no sólo durante una única petición. Cuando los gestores de peticiones almacenan datos de usuario en variables globales, esos datos permanecen accesibles para peticiones posteriores de usuarios diferentes. Esto crea vulnerabilidades de seguridad donde los datos de sesión del usuario A, tokens de autenticación o información personal se filtran al usuario B.
Por qué es importante
Consecuencias para la seguridad (fugas de datos): Las variables globales que almacenan en caché datos específicos del usuario crean fugas de datos entre solicitudes. El estado de autenticación, los datos de sesión o la información personal de un usuario se vuelven visibles para otros usuarios, lo que viola los límites de privacidad y seguridad.
Condiciones de carrera: Cuando múltiples peticiones concurrentes modifican la misma variable global, hay una alta probabilidad de comportamiento impredecible. Los datos del usuario A pueden ser sobrescritos por la petición del usuario B a mitad del proceso, lo que puede dar lugar a cálculos incorrectos, estados corruptos o que los usuarios vean los datos de los demás.
Complejidad de la depuración: los problemas causados por el almacenamiento en caché de variables globales son notoriamente difíciles de reproducir porque dependen del tiempo de solicitud y de la concurrencia. Los errores aparecen de forma intermitente en producción bajo carga, pero rara vez se manifiestan en pruebas de desarrollo con un solo hilo.
Fugas de memoria: Las variables globales que acumulan datos sin limpiar crecen sin límites con el tiempo. Cada petición añade más datos a las cachés o matrices globales, lo que acaba por agotar la memoria del servidor y obliga a reiniciar el proceso.
Ejemplos de códigos
❌ No conforme:
let currentUser = null;
let requestData = {};
app.get('/profile', async (req, res) => {
currentUser = await getUserById(req.userId);
requestData = req.body;
const profile = await buildUserProfile(currentUser);
res.json(profile);
});
function buildUserProfile(user) {
return {
name: currentUser.name,
data: requestData
};
}
Por qué está mal: Las variables globales currentUser y requestData persisten a través de las peticiones. Cuando varias peticiones se ejecutan simultáneamente, la petición del usuario B puede sobrescribir currentUser mientras buildUserProfile() del usuario A todavía se está ejecutando, haciendo que el usuario A vea los datos del usuario B.
✅ Conforme:
app.get('/profile', async (req, res) => {
const currentUser = await getUserById(req.userId);
const requestData = req.body;
const profile = buildUserProfile(currentUser, requestData);
res.json(profile);
});
function buildUserProfile(user, data) {
return {
name: user.name,
data: data
};
}
Por qué es importante: Todos los datos específicos de la solicitud se almacenan en variables locales asignadas al gestor de la solicitud. Cada solicitud tiene un estado aislado que no puede filtrarse a otras solicitudes concurrentes. Las funciones reciben datos a través de parámetros en lugar de acceder al estado global, lo que elimina las condiciones de carrera.
Conclusión
Mantén todos los datos específicos de la petición en variables locales u objetos de petición proporcionados por tu framework. Utiliza variables globales sólo para estados realmente compartidos, como configuración, agrupaciones de conexiones o cachés de sólo lectura. Cuando el estado global sea necesario, utiliza controles de concurrencia adecuados y asegúrate de que los datos nunca sean específicos del usuario.
.avif)
