🌍 Probador CORS
Envía un preflight CORS (OPTIONS) y petición real desde un Origin elegido para verificar Access-Control-Allow-Origin / Methods / Headers / Credentials / Max-Age.
📚 Fundamentos CORS
• Los navegadores bloquean fetch / XHR a otros orígenes.
• CORS permite al servidor declarar "orígenes permitidos" mediante Access-Control-Allow-Origin.
• Una solicitud preflight es una solicitud OPTIONS que el navegador envía antes de la solicitud real. Ocurre cuando se utilizan encabezados personalizados o métodos no simples (PUT, DELETE, etc.).
• Access-Control-Allow-Credentials: true no puede combinarse con Access-Control-Allow-Origin: * — debe usar un origen específico.
📖 Qué te dice este diagnóstico
Este diagnóstico envía una petición real con cabecera Origin más un OPTIONS de comprobación previa, e informa de las cabeceras Access-Control-* que devuelve. La premisa clave es que sólo los navegadores aplican CORS: curl y las llamadas entre servidores lo ignoran por completo. CORS no es, por tanto, un mecanismo que proteja tu API, sino uno que impide que un sitio malicioso use en silencio las credenciales ya guardadas en el navegador del usuario.
| Elemento | Qué significa | Cómo corregirlo |
|---|---|---|
| Enumerar varios orígenes | Access-Control-Allow-Origin admite exactamente un origen, o *. Una lista separada por comas es inválida según la especificación y el navegador rechaza la cabecera entera. Es una causa muy frecuente de la queja de que está configurado pero sigue fallando. |
Compara el Origin de la petición con una lista blanca en el servidor y devuelve sólo el único valor que coincidió. Como la respuesta ahora varía según el origen, añade siempre Vary: Origin. Si lo olvidas, tu CDN cachea la primera respuesta y se la sirve a otro origen. |
| Se lanza un preflight en cada petición | Enviar Content-Type: application/json, añadir Authorization o una cabecera propia, o usar un método distinto de GET, POST o HEAD hace que la petición deje de ser simple, así que un OPTIONS extra precede a la real. Eso duplica las idas y vueltas por llamada, algo que se nota en conexiones con latencia alta. |
Enumera todas las cabeceras que envías de verdad en Access-Control-Allow-Headers —falta una y el preflight falla— y cachea su resultado con Access-Control-Max-Age. Chrome lo limita a 7200 segundos, así que cualquier valor mayor se recorta en silencio. |
| Las respuestas de error no llevan CORS | Muchos frameworks se saltan su middleware cuando una excepción produce un 500, así que la respuesta sale sin Access-Control-Allow-Origin. El navegador entonces no deja leer el cuerpo y la consola sólo muestra un error de CORS. La causa real, una excepción del servidor, queda del todo oculta. |
Añade las mismas cabeceras CORS a tu manejador de excepciones y a las respuestas de error_page. Para diagnosticar, el primer paso es mirar el código de estado real en la pestaña Network. Si es un 500 o un 404, la configuración de CORS es irrelevante y lo que hay que arreglar está en la aplicación. |
CORS no es autorización. Con o sin Access-Control-Allow-Origin: *, cualquiera puede seguir llamando a la API con curl. Si hay datos que proteger, implementa autenticación por token o validación de sesión. El otro malentendido habitual es que configurar CORS previene también el CSRF: no es así, porque los envíos de <form> y las cargas de <img> quedan fuera del alcance de CORS. Para el CSRF hacen falta cookies SameSite y un token propio.