[SOLUCIONADO] Cross-Origin Request Blocked en Route Handlers y API Routes de Next.js
Al consumir una API creada en Next.js (utilizando el directorio App Router app/api/.../route.ts o Pages Router pages/api/...) desde una aplicación frontend externa (como una app de React Native, Flutter o un subdominio diferente), el navegador bloquea la llamada con: Access to fetch at ... from origin ... has been blocked by CORS policy: Response to preflight request doesn't pass access control check.
El Diagnóstico Rápido
La Solución Paso a Paso
-
1
Paso 1: Manejar la petición previa OPTIONS en Next.js App Router
Los navegadores envían una petición preliminar
OPTIONSantes de cualquierPOST,PUTo petición con cabeceras personalizadas. En tu archivoapp/api/tu-ruta/route.js:JAVASCRIPTconst corsHeaders = { 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS', 'Access-Control-Allow-Headers': 'Content-Type, Authorization', }; export async function OPTIONS() { return new Response(null, { status: 204, headers: corsHeaders, }); } export async function GET(request) { return Response.json({ mensaje: "Éxito" }, { headers: corsHeaders }); } -
2
Paso 2: Configurar cabeceras CORS globales en next.config.js
Si tienes muchas rutas API, es más limpio aplicar las cabeceras en
next.config.jsonext.config.mjs:JAVASCRIPT/** @type {import('next').NextConfig} */ const nextConfig = { async headers() { return [ { source: "/api/:path*", headers: [ { key: "Access-Control-Allow-Credentials", value: "true" }, { key: "Access-Control-Allow-Origin", value: "*" }, { key: "Access-Control-Allow-Methods", value: "GET,DELETE,PATCH,POST,PUT,OPTIONS" }, { key: "Access-Control-Allow-Headers", value: "X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, Content-Type, Date, X-Api-Version, Authorization" }, ] } ]; } }; module.exports = nextConfig; -
3
Paso 3: Manejo de credenciales (Cookies y Authorization)
Si tu aplicación envía cookies de sesión o tokens de autenticación con
credentials: 'include', el comodínAccess-Control-Allow-Origin: *será rechazado por los navegadores por seguridad. Debes especificar el dominio exacto:JAVASCRIPT'Access-Control-Allow-Origin': 'https://tu-dominio-cliente.com', 'Access-Control-Allow-Credentials': 'true'
Preguntas Frecuentes
¿Por qué ocurre este error en producción pero funcionaba en localhost?
Porque en desarrollo local ambos proyectos compartían el puerto o se originaban en localhost, lo que relaja las políticas en ciertos navegadores, mientras que en producción los dominios son completamente distintos.
¿Puedo solucionar CORS usando un Middleware de Next.js?
Sí, creando un archivo middleware.js en la raíz que intercepte rutas /api/:path* e inyecte los encabezados CORS en cada NextResponse.
Consejo de Prevención
Prácticas de seguridad recomendadas:
- Nunca uses comodines
*si transmites cookies de autenticación o datos sensibles. - Utiliza el paquete oficial
corssi sigues utilizando el Pages Router tradicional de Next.js (pages/api).