La limitación de tasa (Rate Limiting) es una técnica utilizada para controlar la cantidad de solicitudes que un cliente puede hacer a un servidor en un período de tiempo determinado. Esto es crucial para proteger tu servidor GraphQL de abusos y garantizar un rendimiento estable y predecible.

¿Por qué es Importante la Limitación de Tasa?

  1. Protección contra Abuso: Evita que un solo cliente consuma todos los recursos del servidor.
  2. Estabilidad del Sistema: Mantiene el rendimiento del servidor bajo control, evitando sobrecargas.
  3. Equidad: Asegura que todos los clientes tengan acceso justo a los recursos del servidor.
  4. Seguridad: Puede ayudar a mitigar ataques de denegación de servicio (DoS).

Estrategias Comunes de Limitación de Tasa

  1. Límite Fijo (Fixed Window): Permite un número fijo de solicitudes en un período de tiempo determinado.
  2. Ventana Deslizante (Sliding Window): Permite un número fijo de solicitudes en un período de tiempo, pero la ventana se desliza con cada solicitud.
  3. Token Bucket: Utiliza un "cubo" de tokens que se llenan a una tasa constante. Cada solicitud consume un token.
  4. Leaky Bucket: Similar al Token Bucket, pero las solicitudes se procesan a una tasa constante, y el exceso se descarta.

Implementación de Limitación de Tasa en GraphQL

Ejemplo con Express.js y express-rate-limit

Vamos a implementar una limitación de tasa básica utilizando express-rate-limit en un servidor GraphQL configurado con Express.js.

  1. Instalación de Dependencias

    npm install express express-rate-limit express-graphql graphql
    
  2. Configuración del Servidor

    const express = require('express');
    const { graphqlHTTP } = require('express-graphql');
    const { buildSchema } = require('graphql');
    const rateLimit = require('express-rate-limit');
    
    // Definir el esquema de GraphQL
    const schema = buildSchema(`
      type Query {
        hello: String
      }
    `);
    
    // Definir los resolvers
    const root = {
      hello: () => {
        return 'Hello, world!';
      },
    };
    
    // Crear una instancia de Express
    const app = express();
    
    // Configurar la limitación de tasa
    const limiter = rateLimit({
      windowMs: 15 * 60 * 1000, // 15 minutos
      max: 100, // Limitar cada IP a 100 solicitudes por ventana
      message: 'Too many requests from this IP, please try again later.'
    });
    
    // Aplicar la limitación de tasa a todas las rutas
    app.use(limiter);
    
    // Configurar el endpoint de GraphQL
    app.use('/graphql', graphqlHTTP({
      schema: schema,
      rootValue: root,
      graphiql: true,
    }));
    
    // Iniciar el servidor
    app.listen(4000, () => {
      console.log('Running a GraphQL API server at http://localhost:4000/graphql');
    });
    

Explicación del Código

  • Dependencias: Importamos express, express-rate-limit, express-graphql y graphql.
  • Esquema y Resolvers: Definimos un esquema simple con una consulta hello y su resolver correspondiente.
  • Express App: Creamos una instancia de Express.
  • Rate Limiter: Configuramos express-rate-limit para permitir un máximo de 100 solicitudes por IP cada 15 minutos.
  • Middleware: Aplicamos el middleware de limitación de tasa a todas las rutas.
  • GraphQL Endpoint: Configuramos el endpoint de GraphQL con express-graphql.
  • Servidor: Iniciamos el servidor en el puerto 4000.

Ejercicio Práctico

Ejercicio

  1. Objetivo: Implementar una limitación de tasa en un servidor GraphQL que permita un máximo de 50 solicitudes por IP cada 10 minutos.
  2. Instrucciones:
    • Modifica el código anterior para ajustar la ventana de tiempo y el número máximo de solicitudes.
    • Prueba el servidor enviando más de 50 solicitudes en 10 minutos desde la misma IP y observa el mensaje de error.

Solución

const express = require('express');
const { graphqlHTTP } = require('express-graphql');
const { buildSchema } = require('graphql');
const rateLimit = require('express-rate-limit');

// Definir el esquema de GraphQL
const schema = buildSchema(`
  type Query {
    hello: String
  }
`);

// Definir los resolvers
const root = {
  hello: () => {
    return 'Hello, world!';
  },
};

// Crear una instancia de Express
const app = express();

// Configurar la limitación de tasa
const limiter = rateLimit({
  windowMs: 10 * 60 * 1000, // 10 minutos
  max: 50, // Limitar cada IP a 50 solicitudes por ventana
  message: 'Too many requests from this IP, please try again later.'
});

// Aplicar la limitación de tasa a todas las rutas
app.use(limiter);

// Configurar el endpoint de GraphQL
app.use('/graphql', graphqlHTTP({
  schema: schema,
  rootValue: root,
  graphiql: true,
}));

// Iniciar el servidor
app.listen(4000, () => {
  console.log('Running a GraphQL API server at http://localhost:4000/graphql');
});

Conclusión

La limitación de tasa es una técnica esencial para proteger tu servidor GraphQL de abusos y mantener un rendimiento estable. En este módulo, aprendimos sobre diferentes estrategias de limitación de tasa y cómo implementarlas en un servidor GraphQL utilizando express-rate-limit. Asegúrate de ajustar los parámetros de limitación de tasa según las necesidades específicas de tu aplicación para lograr un equilibrio entre seguridad y usabilidad.

En el próximo tema, exploraremos la Autenticación y Autorización en GraphQL, donde aprenderemos a proteger nuestras consultas y mutaciones con mecanismos de seguridad robustos.

© Copyright 2024. Todos los derechos reservados