Ir al contenido
Volver al blog

Diagnosticar una API que funciona en localhost pero falla en producción

Sigue la URL y la respuesta de cada petición para distinguir CORS, rutas ausentes, proxies de desarrollo y errores disfrazados de HTML.

  • API
  • frontend
  • CORS
  • Vite

Que una petición funcione en tu ordenador no demuestra que funcione desde la web publicada. En local quizá el frontend y la API comparten origen, un proxy de Vite reescribe la ruta o el navegador usa una URL que solo existe en tu equipo. En producción cambian el dominio, el protocolo, las rutas y la política del navegador. El primer paso es identificar qué petición sale realmente del navegador y qué respuesta recibe.

Esta guía diagnostica el límite entre frontend y API. No cubre cómo construir y publicar una aplicación React, ni cómo configurar variables públicas de Vite: para eso están la guía de React y Vite desde Git y la explicación de variables de Vite. Si estás decidiendo dónde ejecutar cada parte, consulta qué alojamiento necesita una web creada con IA.

1. Lee la petición en Network

Abre las herramientas del navegador, selecciona Network/Red, reproduce una sola acción y pulsa la petición fallida. Anota la URL completa, método, estado, Content-Type, iniciador y si antes aparece una petición OPTIONS. No publiques aquí cookies, cabeceras de autorización, cuerpos con datos personales ni claves.

Comprueba el host de la URL. Si aparece localhost, 127.0.0.1 o una dirección privada, el navegador del visitante intentará conectarse a su propio dispositivo o red: no a tu ordenador ni a tu servidor. Sustituye esa dirección por una ruta del backend accesible desde la web o por un dominio HTTPS real que controles. Busca también esas cadenas en los archivos construidos; una variable con nombre de producción no cambia el valor incrustado si no reconstruyes la aplicación.

Una ruta como /api/orders se solicita al mismo origen que sirvió la página. Solo funcionará si la plataforma, el servidor web o un proxy de producción entrega esa ruta a tu API. Que Vite acepte server.proxy durante npm run dev no introduce ese proxy en los archivos estáticos producidos por npm run build. El navegador descargado no puede inventar un servicio de backend.

2. Distingue el preflight de la petición real

Cuando una llamada entre orígenes usa JSON, Authorization u otras cabeceras no simples, el navegador suele enviar primero OPTIONS. El servidor debe responder con el origen permitido y los métodos y cabeceras que autoriza. Si ese preflight se rechaza, el navegador no envía después la petición principal.

Eso es distinto de una petición simple, como cierto POST con Content-Type: text/plain. El servidor puede recibirla y cambiar estado aunque CORS impida que JavaScript lea la respuesta. CORS regula qué respuestas puede leer un navegador; no autentica al usuario ni garantiza que el servidor no haya procesado la escritura. No uses Access-Control-Allow-Origin: * como parche ni como control de acceso. Valida la identidad y los permisos en el backend, valida el cuerpo y aplica protección contra CSRF cuando corresponda. Verifica también el Origin según el diseño; ese encabezado por sí solo tampoco sustituye la autenticación.

3. Un estado 200 puede contener la página equivocada

Mira el tipo y el cuerpo de la respuesta. Si una llamada a /api/profile devuelve 200 y text/html con el HTML de la aplicación, probablemente una regla de fallback ha enviado la página principal en vez de la respuesta API. Para el navegador el transporte terminó correctamente, pero tu código esperaba JSON. Otro indicio es 404, 502 o una página de error HTML en la ruta API.

No marques la operación como guardada solo porque fetch() no lanzó una excepción: los estados HTTP de error normalmente también producen una respuesta. Comprueba response.ok y el tipo de contenido antes de procesar la respuesta. Por ejemplo:

const response = await fetch('/api/status');
const type = response.headers.get('content-type') || '';
if (!response.ok || !type.includes('application/json')) {
  throw new Error(`Respuesta inesperada: HTTP ${response.status}`);
}
const data = await response.json();

Esto solo comprueba el estado HTTP, el MIME y que el cuerpo se pueda analizar como JSON; no valida sus campos. Comprueba la forma del objeto y el resultado de la operación antes de indicar que se ha guardado. Tampoco corrige la ruta ni crea una API.

4. Reproduce el fallo por capas

Prueba la URL exacta del backend fuera del navegador con un cliente HTTP, usando datos sintéticos. Si también falla, revisa DNS, TLS, ruta, proceso, método y registros del backend. Si el cliente HTTP funciona y Chrome falla, revisa preflight, origen y cabeceras. Si Chrome muestra 200 pero el cuerpo es HTML, corrige el enrutamiento del servidor o el fallback. Repite después una operación de solo lectura; evita probar escrituras sobre datos reales.

En el backend confirma si la solicitud llegó y si produjo efecto. Una consola del navegador que dice “blocked by CORS” no demuestra que no hubo escritura. Usa identificadores de petición y registros que no incluyan secretos para correlacionar el resultado.

Qué se probó y qué no

El ensayo local de este artículo ejecutó diez casos con servidor HTTP y Chrome sobre un fixture sintético: proxy de desarrollo, ausencia de proxy en el build estático, fallback HTML con estado 200, ruta del mismo origen, preflight permitido y rechazado, escritura simple cuyo resultado queda oculto por CORS, controles independientes de escritura, ciclo de vida del proceso y rutas/assets en dos tamaños de ventana. Todos pasaron en ese fixture. También se verificó que un Origin falsificado podía escribir en la demostración con guardia por origen, lo que confirma que ese control no equivale a autenticación.

El fixture no es una integración del producto Hostbrid ni de una cuenta de cliente. No prueba autenticación, cookies, pagos, base de datos, correo, TLS, persistencia ni despliegues de clientes. La demo CORS-only permite intencionadamente una escritura sintética y no debe copiarse como patrón de producción. La prueba tampoco demuestra indexación o posicionamiento.

Para ejecutar la aplicación con un proceso continuo, comprueba la disponibilidad y límites de Projects; para controlar el sistema operativo y operarlo tú, revisa VPS. Elige según el proceso real que requiere tu backend y confirma el alcance y precio del plan antes de contratar.

Gestiona tus webs, servidores y correo.

Es gratis y tarda un minuto.

Mínimo 8 caracteres. Ni sólo números ni una contraseña común.

Te mandaremos un correo para confirmar la cuenta.