Preflight Requests en CORS: Qué son y cómo funcionan
Preflight Requests en CORS: Qué son y cómo funcionan
Si alguna vez has inspeccionado las solicitudes de tu navegador en la pestaña Network de las DevTools y has visto una solicitud con el método OPTIONS, es probable que hayas encontrado un Preflight Request. Pero, ¿qué es exactamente? ¿Por qué ocurre y cómo afecta a nuestras aplicaciones web?
En este artículo te explicaremos de manera sencilla qué son los Preflight Requests, cómo funcionan y qué hacer si te encuentras con ellos.
1. ¿Qué es un Preflight Request?
Un Preflight Request es una solicitud que el navegador envía automáticamente antes de realizar una solicitud real a un servidor, con el objetivo de verificar si dicho servidor permite la operación que se intenta hacer.
Esta verificación es parte del mecanismo de seguridad llamado CORS (Cross-Origin Resource Sharing), que protege a los usuarios de ataques maliciosos al restringir las solicitudes entre diferentes dominios.
Específicamente, un Preflight Request ocurre cuando un cliente web (como tu navegador) quiere hacer una solicitud cross-origin que:
- Usa un método HTTP diferente de
GET
,POST
oHEAD
. - Incluye headers personalizados como
Authorization
oX-Custom-Header
. - Tiene un
Content-Type
no estándar (ejemplo:application/json
,multipart/form-data
).
Si la solicitud que estás intentando hacer cumple alguna de estas condiciones, el navegador primero enviará un Preflight Request con el método OPTIONS, preguntándole al servidor:
"¿Me das permiso para hacer esta solicitud?"
Si el servidor responde afirmativamente, el navegador enviará la solicitud real.
2. ¿Cómo funciona un Preflight Request?
El proceso se desarrolla en tres pasos:
Paso 1: El navegador envía una solicitud OPTIONS
Antes de enviar la solicitud real, el navegador manda una solicitud con el método OPTIONS para consultar qué permisos tiene el servidor.
Ejemplo de un Preflight Request enviado por el navegador:
OPTIONS /api/data HTTP/1.1
Host: api.ejemplo.com
Origin: https://miapp.com
Access-Control-Request-Method: POST
Access-Control-Request-Headers: Authorization, Content-Type
En este caso, el navegador está preguntando al servidor si le permite hacer una solicitud POST
con los headers Authorization
y Content-Type
.
Paso 2: El servidor responde con los permisos CORS
Si el servidor permite la solicitud, responderá con los encabezados adecuados:
HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://miapp.com
Access-Control-Allow-Methods: POST, GET, OPTIONS
Access-Control-Allow-Headers: Authorization, Content-Type
Access-Control-Max-Age: 86400
Aquí el servidor está diciendo:
✅ Sí, permito solicitudes desde https://miapp.com
.
✅ Puedes usar los métodos POST
, GET
y OPTIONS
.
✅ Te dejo incluir los headers Authorization
y Content-Type
.
✅ No vuelvas a preguntarme en las próximas 24 horas (86400
segundos).
Paso 3: El navegador envía la solicitud real
Si la respuesta del servidor es positiva, el navegador procederá a enviar la solicitud real.
POST /api/data HTTP/1.1
Host: api.ejemplo.com
Authorization: Bearer 123456
Content-Type: application/json
Si el servidor no permite la solicitud, el navegador bloqueará la operación y mostrará un error en la consola.
3. ¿Cuándo se genera un Preflight Request?
El preflight ocurre solo en solicitudes cross-origin que no cumplen las condiciones de "solicitud simple" definidas en CORS.
Una solicitud simple no genera preflight si cumple con estos requisitos:
✔ Usa los métodos GET
, POST
o HEAD
.
✔ No usa headers personalizados (excepto Content-Type
con valores text/plain
, application/x-www-form-urlencoded
o multipart/form-data
).
✔ No usa credenciales (Authorization
, cookies o tokens en headers
).
Si una solicitud no cumple con estos requisitos, el navegador forzará un Preflight Request antes de enviarla.
Ejemplos:
Genera preflight (usa PUT
y header Authorization
):
fetch('https://api.ejemplo.com/data', {
method: 'PUT',
headers: {
'Authorization': 'Bearer token123',
'Content-Type': 'application/json'
},
body: JSON.stringify({ name: "Javier" })
});
No genera preflight (usa POST
y Content-Type
permitido):
fetch('https://api.ejemplo.com/data', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: 'name=Javier'
});
4. ¿Cómo evitar Preflight Requests innecesarios?
Si bien los preflight requests son necesarios para la seguridad, en algunas situaciones pueden afectar el rendimiento al generar solicitudes adicionales. Algunas estrategias para reducirlos son:
Usa métodos HTTP simples (GET
, POST
, HEAD
)
Evita PUT
, DELETE
, PATCH
si no son estrictamente necesarios.
Usa Content-Type
permitido
Si solo necesitas enviar datos simples, usa:
application/x-www-form-urlencoded
multipart/form-data
text/plain
Evita application/json
si no es necesario.
No uses headers personalizados innecesarios
Evita headers no estándar como X-Custom-Header
.
Habilita Access-Control-Max-Age
en el servidor
Esto permite que el navegador recuerde la autorización del preflight por un tiempo y no lo repita en cada solicitud.
Ejemplo:
Access-Control-Max-Age: 86400
Esto indica que el navegador puede omitir el preflight durante 24 horas.
Los Preflight Requests son un mecanismo de seguridad en CORS que ayuda a evitar solicitudes no autorizadas entre distintos dominios. Aunque pueden generar tráfico adicional, hay formas de optimizarlos reduciendo headers personalizados, usando métodos HTTP simples y configurando correctamente el servidor.
Si ves solicitudes OPTIONS en la pestaña Network del navegador, ya sabes qué significan y cómo gestionarlas para mejorar el rendimiento de tu aplicación.
Últimas publicaciones
Suscribete a nuestro Newsletter y recibe información para mejorar tus conocimientos y posibilidad de conseguir un mejor empleo
Subscribete en LinkedIn