tutoriales.com

Documentación Automática de APIs REST con OpenAPI (Swagger): Una Guía Práctica

Este tutorial te guiará a través del proceso de documentar tus APIs REST de manera automática y eficiente utilizando la especificación OpenAPI (anteriormente Swagger). Descubre cómo definir tus endpoints, modelos y autenticación, y cómo generar documentación interactiva y clientes SDK para diferentes lenguajes.

Intermedio15 min de lectura37 views
Reportar error

Las APIs REST se han convertido en el estándar de facto para la comunicación entre servicios y aplicaciones. Sin embargo, una API sin una documentación clara y actualizada es tan útil como un mapa sin leyendas: confusa y difícil de usar. Aquí es donde entra en juego OpenAPI (anteriormente conocido como Swagger).

OpenAPI es una especificación estándar e independiente del lenguaje para describir APIs REST. Permite a los humanos y a las máquinas entender las capacidades de un servicio REST sin necesidad de acceder al código fuente o a la documentación de red. En este tutorial, exploraremos cómo utilizar OpenAPI para documentar tus APIs de manera efectiva y automática, mejorando la colaboración y la integración.

🎯 ¿Por Qué Documentar APIs con OpenAPI?

La documentación es un pilar fundamental en el desarrollo de APIs. Una buena documentación acelera la integración, reduce los errores y mejora la experiencia del desarrollador. OpenAPI ofrece múltiples ventajas:

  • Claridad y Consistencia: Proporciona un formato estándar para describir todos los aspectos de tu API.
  • Interacción Sencilla: Herramientas como Swagger UI generan documentación interactiva que permite probar los endpoints directamente desde el navegador.
  • Generación de Código: Permite generar automáticamente clientes (SDKs) para diversos lenguajes de programación, así como stubs de servidores.
  • Validación: Facilita la validación de solicitudes y respuestas conforme a la especificación definida.
  • Colaboración: Actúa como un contrato claro entre los equipos frontend y backend.
  • Automatización: Permite automatizar pruebas, integración continua y despliegues.
💡 Consejo: Considera la documentación como parte integral de tu proceso de desarrollo, no como una tarea posterior.

📖 Conceptos Clave de OpenAPI

Antes de sumergirnos en la práctica, es esencial entender algunos términos y conceptos fundamentales.

La Especificación OpenAPI (OAS)

OAS es un formato basado en JSON o YAML para describir una API REST. Define la estructura de tu API, incluyendo:

  • Información General: Título, descripción, versión de la API.
  • Servidores: URLs base de la API.
  • Rutas (Paths): Endpoints individuales de la API (ej. /users, /products/{id}).
  • Operaciones (Operations): Métodos HTTP para cada ruta (GET, POST, PUT, DELETE, etc.).
  • Parámetros: Entradas para las operaciones (query, header, path, cookie, body).
  • Esquemas (Schemas): Modelos de datos para las solicitudes y respuestas (JSON Schema).
  • Respuestas: Códigos de estado HTTP y sus cuerpos de respuesta asociados.
  • Seguridad: Mecanismos de autenticación y autorización.

Swagger vs. OpenAPI

Es común confundir estos términos, pero la relación es sencilla:

  • OpenAPI Specification (OAS): Es el estándar de la industria, la especificación en sí misma.
  • Swagger: Es un conjunto de herramientas de código abierto que implementan la especificación OpenAPI. Incluye:
    • Swagger UI: Genera una interfaz de usuario interactiva para la documentación de la API.
    • Swagger Editor: Una herramienta basada en navegador para escribir especificaciones OpenAPI.
    • Swagger Codegen: Genera clientes SDK, stubs de servidores y documentación en varios lenguajes.

En resumen, OpenAPI es la definición, y Swagger son las herramientas para trabajar con esa definición.

🔥 Importante: La versión 3.x de la especificación es `OpenAPI Specification`. Las versiones anteriores eran `Swagger Specification`. Asegúrate de usar la terminología correcta.

🛠️ Creando Tu Primera Especificación OpenAPI (YAML)

Vamos a construir una especificación OpenAPI para una API simple de gestión de tareas (CRUD de Tareas). Usaremos YAML por su legibilidad, aunque JSON también es una opción válida.

1. Información Básica de la API

Comenzamos definiendo la versión de la especificación OpenAPI, la información general de la API y los servidores donde estará disponible.

openapi: 3.0.0
info:
  title: API de Gestión de Tareas
  description: Una API sencilla para crear, leer, actualizar y eliminar tareas.
  version: 1.0.0
servers:
  - url: http://localhost:3000/api/v1
    description: Servidor de desarrollo
  - url: https://api.ejemplo.com/v1
    description: Servidor de producción
  • openapi: Indica la versión de la especificación que estamos utilizando (aquí 3.0.0).
  • info: Contiene metadatos de la API como el título, una descripción y la versión de la API en sí.
  • servers: Un array de objetos que especifican las URLs base de la API. Útil para entornos de desarrollo, staging y producción.

2. Definiendo Rutas y Operaciones (Paths)

Ahora definiremos los endpoints (paths) y las operaciones HTTP (GET, POST, PUT, DELETE) para nuestra API de tareas.

páginas:
  /tareas:
    get:
      summary: Obtener todas las tareas
      description: Recupera una lista de todas las tareas disponibles.
      operationId: getTareas
      responses:
        '200':
          description: Lista de tareas recuperada exitosamente.
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/Tarea'
    post:
      summary: Crear una nueva tarea
      description: Crea una nueva tarea en el sistema.
      operationId: createTarea
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/NuevaTarea'
      responses:
        '201':
          description: Tarea creada exitosamente.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Tarea'
        '400':
          description: Solicitud inválida.

  /tareas/{id}:
    get:
      summary: Obtener una tarea por ID
      description: Recupera los detalles de una tarea específica por su ID.
      operationId: getTareaById
      parameters:
        - in: path
          name: id
          schema:
            type: string
            format: uuid
          required: true
          description: El ID único de la tarea.
      responses:
        '200':
          description: Detalles de la tarea recuperados exitosamente.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Tarea'
        '404':
          description: Tarea no encontrada.
    put:
      summary: Actualizar una tarea existente
      description: Actualiza los detalles de una tarea específica por su ID.
      operationId: updateTarea
      parameters:
        - in: path
          name: id
          schema:
            type: string
            format: uuid
          required: true
          description: El ID único de la tarea a actualizar.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/NuevaTarea'
      responses:
        '200':
          description: Tarea actualizada exitosamente.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Tarea'
        '400':
          description: Solicitud inválida.
        '404':
          description: Tarea no encontrada.
    delete:
      summary: Eliminar una tarea
      description: Elimina una tarea específica por su ID.
      operationId: deleteTarea
      parameters:
        - in: path
          name: id
          schema:
            type: string
            format: uuid
          required: true
          description: El ID único de la tarea a eliminar.
      responses:
        '204':
          description: Tarea eliminada exitosamente (No Content).
        '404':
          description: Tarea no encontrada.
  • Cada ruta (/tareas, /tareas/{id}) tiene una o más operaciones HTTP.
  • summary y description proporcionan una explicación concisa y detallada de la operación.
  • operationId: Un identificador único para la operación, útil para la generación de código.
  • parameters: Define los parámetros que la operación espera. Pueden ser path, query, header o cookie.
  • requestBody: Describe el cuerpo de la solicitud para operaciones como POST y PUT.
  • responses: Define las posibles respuestas HTTP, incluyendo el código de estado, una descripción y el esquema del cuerpo de la respuesta.
  • $ref: Una referencia a un componente definido en la sección components (que veremos a continuación). Esto promueve la reutilización y modularidad.

3. Definiendo Componentes (Schemas y Más)

La sección components es crucial para definir estructuras de datos reutilizables (schemas), parámetros comunes, headers de seguridad, etc.

components:
  schemas:
    Tarea:
      type: object
      required:
        - id
        - titulo
        - completada
      properties:
        id:
          type: string
          format: uuid
          description: ID único de la tarea.
          readOnly: true
          example: 07d1a2f1-c7e0-4b1f-8e3b-9d6c5e8a7b6c
        titulo:
          type: string
          description: Título descriptivo de la tarea.
          example: Comprar víveres
        descripcion:
          type: string
          description: Detalles adicionales de la tarea.
          nullable: true
          example: Leche, huevos, pan y frutas.
        completada:
          type: boolean
          description: Indica si la tarea ha sido completada.
          default: false
          example: false
        fechaCreacion:
          type: string
          format: date-time
          description: Fecha y hora de creación de la tarea.
          readOnly: true
          example: '2023-10-27T10:00:00Z'
    NuevaTarea:
      type: object
      required:
        - titulo
      properties:
        titulo:
          type: string
          description: Título descriptivo de la nueva tarea.
          example: Organizar documentos
        descripcion:
          type: string
          description: Detalles adicionales para la nueva tarea.
          nullable: true
          example: Archivar facturas y recibos.
        completada:
          type: boolean
          description: Estado inicial de completado de la tarea.
          default: false
          example: false
  • schemas: Define los modelos de datos de tu API usando JSON Schema. Tarea representa una tarea completa con su id generado, mientras que NuevaTarea representa la estructura de datos para crear una tarea (sin id, readOnly ni fechaCreacion al inicio).
  • type: El tipo de dato (object, string, integer, boolean, array, etc.).
  • format: Un formato adicional para string (date-time, uuid, email, etc.) o integer (int32, int64).
  • required: Un array de propiedades que son obligatorias.
  • readOnly: Indica que la propiedad es solo de lectura y no debe ser enviada en la solicitud.
  • example: Un valor de ejemplo para la propiedad, útil en la documentación interactiva.

📌 Nota: Los `$ref` son fundamentales para mantener tu especificación DRY (Don't Repeat Yourself) y modular.

✨ Integrando Swagger UI para Documentación Interactiva

Una vez que tienes tu especificación OpenAPI, el siguiente paso es visualizarla de manera interactiva. Swagger UI es la herramienta más popular para esto.

1. Guardar la Especificación

Guarda tu especificación YAML completa en un archivo, por ejemplo, openapi.yaml.

2. Configurar un Servidor Simple (Ejemplo con Node.js y Express)

Podemos servir Swagger UI a través de un servidor web. Aquí un ejemplo mínimo con Node.js y Express, utilizando el paquete swagger-ui-express.

// app.js
const express = require('express');
const swaggerUi = require('swagger-ui-express');
const YAML = require('yamljs');
const path = require('path');

const app = express();
const port = 3001;

// Cargar la especificación OpenAPI
const swaggerDocument = YAML.load(path.join(__dirname, './openapi.yaml'));

// Middleware para servir la documentación de Swagger UI
app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerDocument));

app.get('/', (req, res) => {
  res.send('¡Hola desde tu API de Tareas! Visita /api-docs para la documentación.');
});

app.listen(port, () => {
  console.log(`Servidor escuchando en http://localhost:${port}`);
  console.log(`Documentación de API disponible en http://localhost:${port}/api-docs`);
});

Para ejecutar este ejemplo, necesitarás instalar las dependencias:

npm init -y
npm install express swagger-ui-express yamljs

Luego, ejecuta:

node app.js

Ahora, abre tu navegador y ve a http://localhost:3001/api-docs. ¡Verás tu documentación interactiva!

openapi.yaml swagger-ui-express (Node.js/Express) Navegador Web (Swagger UI)

3. Explorando Swagger UI

Swagger UI te permitirá:

  • Ver todos los endpoints y sus métodos HTTP.
  • Expandir cada operación para ver detalles como parámetros, requestBody y posibles respuestas.
  • Hacer clic en "Try it out" para enviar solicitudes de prueba directamente desde la interfaz.
  • Ver los esquemas de los modelos de datos.
💡 Consejo: Usa el botón "Authorize" en Swagger UI si tu API requiere autenticación (que definiremos en la siguiente sección).

🔒 Añadiendo Seguridad a Tu Especificación OpenAPI

La mayoría de las APIs requieren algún tipo de autenticación o autorización. OpenAPI permite describir estos mecanismos.

Vamos a añadir autenticación basada en Bearer Token (OAuth2 o JWT).

1. Definir Esquemas de Seguridad

En la sección components, agrega securitySchemes:

# ... (después de 'schemas')
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
  • BearerAuth: Es un nombre arbitrario para nuestro esquema de seguridad.
  • type: http: Indica que es un esquema de autenticación HTTP.
  • scheme: bearer: Especifica que usará el esquema Bearer.
  • bearerFormat: JWT: Información adicional sobre el formato del token.

2. Aplicar Seguridad a Operaciones Específicas o Globalmente

Puedes aplicar la seguridad a una operación individual o a toda la API.

A nivel global (para todas las operaciones):

# ... (después de 'servers')
security:
  - BearerAuth: []

Esto significa que todas las operaciones requerirán BearerAuth.

A nivel de operación (ej. solo para POST, PUT, DELETE):

# ... dentro de una operación POST, PUT o DELETE
    post:
      # ...
      security:
        - BearerAuth: []
      # ...

Si aplicas seguridad a nivel global y también a nivel de operación, la definición a nivel de operación sobrescribe la global para esa operación específica.

Después de actualizar tu openapi.yaml y reiniciar tu servidor Node.js, verás un botón "Authorize" en Swagger UI. Al hacer clic, podrás introducir tu token de autenticación, y este se enviará con todas las solicitudes de "Try it out".

⚙️ Generación de Clientes SDK y Stubs de Servidor con Swagger Codegen

Una de las características más poderosas de OpenAPI es la capacidad de generar código automáticamente. Swagger Codegen es la herramienta más conocida para esto.

1. Instalar Swagger Codegen

Swagger Codegen es una aplicación Java. Puedes usarlo a través de un archivo .jar descargable o Docker.

Opción 1: Descargar el JAR (requiere Java instalado)

Descarga el .jar de la última versión desde Maven Central (reemplaza 6.x.x con la versión actual).

Renómbralo a openapi-generator-cli.jar.

Opción 2: Usar Docker (recomendado)

Si tienes Docker instalado, es la forma más sencilla:

docker pull openapitools/openapi-generator-cli

2. Generar un Cliente SDK

Vamos a generar un cliente SDK en JavaScript (fetch) para nuestra API de Tareas.

Usando el JAR:

java -jar openapi-generator-cli.jar generate \
  -i openapi.yaml \
  -g javascript-fetch \
  -o ./clients/javascript-fetch-client

Usando Docker:

docker run --rm -v ${PWD}:/local openapitools/openapi-generator-cli generate \
  -i /local/openapi.yaml \
  -g javascript-fetch \
  -o /local/clients/javascript-fetch-client
  • -i openapi.yaml: Especifica el archivo de entrada de la especificación OpenAPI.
  • -g javascript-fetch: Indica el generador que queremos usar (hay cientos).
  • -o ./clients/javascript-fetch-client: La carpeta de salida donde se generará el código.

Después de ejecutar esto, encontrarás una nueva carpeta clients/javascript-fetch-client con todo el código necesario para interactuar con tu API desde JavaScript. Esto incluye modelos de datos, clientes para cada etiqueta de operación, y archivos de configuración.

3. Generar un Stub de Servidor

También puedes generar un stub de servidor. Por ejemplo, para un servidor Node.js con Express:

Usando el JAR:

java -jar openapi-generator-cli.jar generate \
  -i openapi.yaml \
  -g nodejs-express \
  -o ./servers/nodejs-express-stub

Usando Docker:

docker run --rm -v ${PWD}:/local openapitools/openapi-generator-cli generate \
  -i /local/openapi.yaml \
  -g nodejs-express \
  -o /local/servers/nodejs-express-stub

Esto creará un proyecto Node.js/Express con controladores, rutas y modelos pregenerados que puedes usar como punto de partida para implementar tu API real. ¡Te ahorra mucho tiempo en la configuración inicial!

⚠️ Advertencia: Los stubs de servidor generados son solo un esqueleto. Debes implementar la lógica de negocio en los controladores para que la API funcione correctamente.

📈 Herramientas Adicionales del Ecosistema OpenAPI

El ecosistema OpenAPI es vasto. Aquí hay algunas otras herramientas que pueden ser útiles:

  • Swagger Editor: Para escribir y validar tu especificación OpenAPI directamente en el navegador.
  • Redoc: Otra herramienta de documentación alternativa a Swagger UI, a menudo preferida por su diseño limpio y moderno.
  • Stoplight Studio: Un IDE visual para diseñar, documentar y probar APIs basadas en OpenAPI.
  • Postman: Permite importar especificaciones OpenAPI para generar colecciones de solicitudes, lo que facilita las pruebas.
  • Herramientas de Linting: Como spectral para asegurar que tu especificación sigue las mejores prácticas y estándares internos.

Integración con CI/CD

La documentación automática brilla en flujos de CI/CD. Puedes configurar tu pipeline para:

  1. Validar la especificación OpenAPI en cada push.
  2. Generar automáticamente la documentación de Swagger UI y desplegarla.
  3. Generar clientes SDK para diferentes lenguajes y publicarlos en repositorios de paquetes internos.

Esto asegura que tu documentación esté siempre sincronizada con la última versión de tu API, reduciendo la deriva de la documentación.

Paso 1: Desarrollador modifica código y especificación OpenAPI.
Paso 2: `git push` a repositorio.
Paso 3: Pipeline CI/CD se activa.
Paso 4: Valida `openapi.yaml` con `spectral`.
Paso 5: Genera Swagger UI y lo despliega a un servidor de documentación.
Paso 6: Genera SDKs con Swagger Codegen y los publica.
Paso 7: Notifica el éxito o fallo.

📝 Consejos y Mejores Prácticas

  • Sé Detallado: Cuanta más información proporciones (descripciones, ejemplos, formatos), más útil será tu documentación.
  • Valida Constantemente: Usa herramientas como Swagger Editor o linters para asegurarte de que tu especificación es válida y consistente.
  • Mantén la Actualización: La documentación desactualizada es peor que no tener documentación. Integra la generación automática en tu flujo de trabajo para mantenerla al día.
  • Usa Ejemplos Reales: Los ejemplos en tus schemas y responses hacen que la documentación sea mucho más fácil de entender.
  • Organiza con Etiquetas (Tags): Usa la propiedad tags en tus operaciones para agrupar endpoints relacionados en Swagger UI.
  • Versionado: Incluye la versión de tu API en la sección info y considera cómo el versionado de la API afectará tu especificación OpenAPI.
Documentación Completa (90%)

Conclusión

La documentación de APIs con OpenAPI es una inversión que rinde dividendos en eficiencia, colaboración y facilidad de uso. Al adoptar esta especificación y sus herramientas asociadas como Swagger UI y Swagger Codegen, no solo estarás creando APIs robustas, sino también APIs que son un placer para consumir.

Esperamos que esta guía práctica te haya proporcionado las herramientas y el conocimiento necesario para empezar a documentar tus APIs REST de manera profesional. ¡Ahora, a construir APIs bien documentadas!

Tutoriales relacionados

Comentarios (0)

Aún no hay comentarios. ¡Sé el primero!