Aplicaciones Web Orientadas a Servicios ITIID-05

Practica: Consumir una API Externa con Login


En esta práctica aprenderás a consumir una API externa simulada creada por el profesor simulando ser parte del equipo de desarrollo de Backend.

El objetivo es practicar:

  • Peticiones fetch()
  • Login con token
  • Consumo de endpoints protegidos
  • Simulación de una base de datos externa

1. Estructura del Proyecto

Crea una carpeta en tu computadora llamada:

CLA-API-USE/

Dentro coloca esta estructura:

CLA-API-USE/

├── index.html
├── panel.html

└── services/
    ├── login.js
    └── panel.js

2. Login (index.html)

Este archivo permite iniciar sesión consumiendo la API externa.

index.html

<!doctype html>
<html lang="es">
  <head>
    <meta charset="UTF-8" />
    <title>Login - Consumo API externa</title>
  </head>

  <body>
    <h2>Login</h2>

    <input id="user" placeholder="Usuario" />
    <input id="pass" type="password" placeholder="Contraseña" />

    <button onclick="login()">Entrar</button>

    <script src="services/login.js"></script>
  </body>
</html>

3. Código Login (services/login.js)

Aquí se realiza el POST hacia el endpoint /api/login.

async function login() {
  const user = document.getElementById("user").value;
  const pass = document.getElementById("pass").value;

  try {
    const res = await fetch("https://fake-api-e1k.pages.dev/api/login", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
      },
      body: JSON.stringify({ user, pass }),
    });

    if (!res.ok) {
      alert("Credenciales incorrectas");
      return;
    }

    const data = await res.json();

    // Guardar token
    localStorage.setItem("token", data.token);

    alert("Login correcto");

    // Ir al panel
    window.location.href = "panel.html";
  } catch (error) {
    alert("Error conectando con la API");
    console.error(error);
  }
}

4. Panel Principal (panel.html)

Después del login, este archivo permite consultar diferentes recursos:

  • Alumnos
  • Pagos
  • Calificaciones
<!doctype html>
<html lang="es">
  <head>
    <meta charset="UTF-8" />
    <title>Panel</title>
  </head>

  <body>
    <h2>Panel de Datos</h2>

    <button onclick="cargar('alumnos')">Ver Alumnos</button>
    <button onclick="cargar('pagos')">Ver Pagos</button>
    <button onclick="cargar('calificaciones')">Ver Calificaciones</button>

    <pre id="output"></pre>

    <script src="services/panel.js"></script>
  </body>
</html>

5. Código Panel (services/panel.js)

Este archivo consume la API usando el token guardado.

async function cargar(endpoint) {
  const token = localStorage.getItem("token");

  if (!token) {
    alert("No autorizado");
    window.location.href = "login.html";
    return;
  }

  try {
    const res = await fetch("https://fake-api-e1k.pages.dev/api/" + endpoint, {
      headers: {
        Authorization: "Bearer " + token,
      },
    });

    if (!res.ok) {
      alert("Error: token inválido o recurso no disponible");
      return;
    }

    const data = await res.json();
    generarTabla(data);
  } catch (error) {
    alert("Error conectando con la API");
    console.error(error);
  }
}

function generarTabla(data) {
  const output = document.getElementById("output");

  if (!data) {
    output.innerHTML = "<p>No hay datos disponibles</p>";
    return;
  }

  // Si es un objeto, buscar el array dentro (por si tiene estructura {data: [...]} o similar)
  let dataArray = data;
  if (!Array.isArray(data) && typeof data === "object") {
    // Buscar la primera propiedad que sea un array
    for (const key in data) {
      if (Array.isArray(data[key])) {
        dataArray = data[key];
        break;
      }
    }
    // Si no encontró array, convertir el objeto a array
    if (!Array.isArray(dataArray)) {
      dataArray = [data];
    }
  } else if (!Array.isArray(data)) {
    dataArray = [data];
  }

  if (dataArray.length === 0) {
    output.innerHTML = "<p>No hay datos disponibles</p>";
    return;
  }

  const tabla = document.createElement("table");

  // Obtener las claves del primer objeto
  const columnas = Object.keys(dataArray[0]);

  // Crear encabezado
  const encabezado = tabla.createTHead();
  const filaEncabezado = encabezado.insertRow();
  columnas.forEach((columna) => {
    const th = document.createElement("th");
    th.textContent = columna.charAt(0).toUpperCase() + columna.slice(1);
    filaEncabezado.appendChild(th);
  });

  // Crear cuerpo
  const cuerpo = tabla.createTBody();
  dataArray.forEach((objeto) => {
    const fila = cuerpo.insertRow();
    columnas.forEach((columna) => {
      const celda = fila.insertCell();
      const valor = objeto[columna];
      celda.textContent =
        typeof valor === "object" ? JSON.stringify(valor) : valor;
    });
  });

  output.innerHTML = "";
  output.appendChild(tabla);
}

function logout() {
  localStorage.removeItem("token");
  window.location.href = "login.html";
}

Endpoints disponibles en la API

La API del profesor tiene estos endpoints:

RecursoEndpoint
Login/api/login
Alumnos/api/alumnos
Pagos/api/pagos
Calificaciones/api/calificaciones

Actividad para entregar

  1. Iniciar sesión correctamente
  2. Mostrar alumnos
  3. Mostrar pagos
  4. Mostrar calificaciones
  5. Cambiar el diseño para que no sea solo JSON (tabla HTML)

⭐ Extra (reto)

  • Agregar botón “Cerrar sesión”
  • Limpiar token con:
localStorage.removeItem("token");

Esta práctica simula cómo una aplicación real consume una base de datos externa mediante API.