Ir al contenido
angel.library

CORS en Express

CORS (Cross-Origin Resource Sharing) es un mecanismo del navegador, no del servidor — Express no “bloquea” nada por sí solo; es el navegador el que rechaza la respuesta si el servidor no autoriza explícitamente el origen que hizo la request.

Por defecto, el navegador impide que JavaScript ejecutado en https://mi-frontend.com lea la respuesta de https://mi-api.com porque son orígenes distintos. Esta política evita que un sitio lea datos de otro sin permiso. CORS es la forma en que el servidor declara qué orígenes pueden acceder a su respuesta.

Esto solo aplica cuando frontend y backend están en orígenes distintos (dominios, puertos o protocolos distintos) — una API Express separada del frontend (típico si el frontend es una SPA aparte) necesita CORS; una app full-stack donde todo se sirve desde el mismo origen (como Astro o Next.js, ver sus respectivas guías) generalmente no.

Ventana de terminal
pnpm add cors
app.ts
import cors from "cors"
import express from "express"
const app = express()
app.use(cors()) // permite CUALQUIER origen — cómodo en desarrollo, rara vez correcto en producción
app.use(
cors({
origin: "https://mi-frontend.com",
credentials: true // necesario si el frontend manda cookies (ver Cookies vs sesiones)
})
)
// Varios orígenes permitidos (ej: producción + preview de Vercel)
app.use(
cors({
origin: ["https://mi-frontend.com", "https://staging.mi-frontend.com"]
})
)
const origenesPermitidos = ["https://mi-frontend.com", "http://localhost:5173"]
app.use(
cors({
origin: (origin, callback) => {
if (!origin || origenesPermitidos.includes(origin)) {
callback(null, true)
} else {
callback(new Error("Origen no permitido por CORS"))
}
}
})
)
app.get("/publico", cors(), handler) // esta ruta sí permite cross-origin
app.get("/interno", handler) // esta no (sin el middleware cors())
Opción de cors({...})Qué controla
originQué origen(es) puede leer la respuesta
credentials: truePermite mandar cookies/auth headers en la request cross-origin
methodsQué verbos HTTP permite (GET, POST, etc.)
allowedHeadersQué headers custom puede mandar el cliente
  • cors() sin opciones (origin: '*' implícito) es válido para una API pública sin autenticación, pero incompatible con credentials: true — el navegador rechaza esa combinación por diseño (no se puede permitir cookies desde “cualquier origen”).
  • CORS protege al navegador, no al servidor — no es una medida de seguridad contra requests hechas fuera del navegador (curl, Postman, otro servidor); para eso hace falta autenticación real, ver Middleware de autenticación.
  • Un error de CORS en la consola del navegador (blocked by CORS policy) es del lado del cliente — la request en general sí llegó al servidor y se ejecutó; lo que se bloquea es que el navegador le entregue la respuesta al código JS que la pidió.