¿Cómo solucionar el problema de CORS en tu aplicación?
El error de CORS (Cross-Origin Resource Sharing) es común al trabajar con aplicaciones web que intentan acceder a recursos desde un dominio diferente al de origen. Para resolverlo, puedes implementar un middleware que gestione las peticiones provenientes de otros orígenes, permitiendo o denegando el acceso según tus necesidades.
¿Qué es Quartz y cómo lo utilizamos?
Quartz es una librería que funciona como middleware para manejar errores de CORS. Su instalación es muy sencilla:
npminstall quartz
Una vez instalada, puedes integrarla en tu aplicación:
Esta configuración permite, por defecto, que cualquier dominio acceda a tu aplicación. Sin embargo, es esencial evaluar si esta apertura es adecuada para tu API.
¿Es seguro permitir el acceso a todos los orígenes?
Aunque abrir el acceso a todos los orígenes resuelve el problema de CORS, no siempre es la mejor opción. Para una API pública, esto podría ser aceptable, pero si se trata de un servicio con un conjunto controlado de aplicaciones, es mejor limitar el acceso a dominios específicos.
¿Cómo crear un Array de White-list para controlar el acceso?
Para limitar los orígenes que pueden acceder a tus recursos, necesitas crear un array de white-list. Este array contendrá los dominios que tienen permiso para hacer peticiones a tu API.
Luego de configurar tu white-list, es importante probar la aplicación para asegurarte de que sólo los dominios listados puedan hacer peticiones exitosas.
Desde un dominio permitido: Realiza una petición desde un puerto o dominio que esté en tu white-list. Deberías poder conectarte y obtener los datos sin problemas.
Desde un dominio no permitido: Intenta hacer una petición desde un origen que no esté listado. Deberías recibir un error indicando que la conexión no está permitida.
Por ejemplo:
// Ejemplo desde un dominio permitidofetch('http://localhost:3000/products').then(response=> response.json()).then(data=>console.log(data));// Ejemplo desde un dominio no permitidofetch('http://unauthorized-domain.com').catch(err=>console.error('Error:', err));
¿Cómo preparar tu entorno para deployment en Heroku?
Resolver el problema de CORS es solo un paso hacia el correcto funcionamiento de tu aplicación. Una vez configurada, puedes proceder a preparar el entorno para su despliegue en plataformas como Heroku. Asegúrate de revisar las dependencias, configuraciones de servidor y otras variables antes de hacer el deployment.
Adoptar medidas de seguridad adecuadas y gestionar correctamente el acceso a tu API es crítico para mantener la integridad y eficiencia de tus servicios. Implementa estas prácticas y controla el acceso hacia los recursos de tu aplicación eficientemente.
Ameeeeeeeeee esta claseeeeeeeee, creo que esto es bastante util para muchisimas cosas.
Curso 10/10
si colocas el : app.use(cors(options));
antes de la línea : routerApi(app);
bloquea todo, hasta la petición desde el localhost:3000/api/v1/products
como el cors es un midleware se debe colocar después de routerApi(app), y entonces ya te resuelve la petición localhost:3000/api/v1/products
pero aun tengo el problema con la petición desde el frontend, y he hecho la prueba utilizando el live serve de vs-code con puerto 5500 y levantando un http-server en puerto 8080. Colocando localhost o 127.0.0.1 y aun no me autoriza.
Será que se debe de definir el permiso para la petición GET, o algún permiso para headers?
Yo tenía el
app.use(cors(options));
antes de
routerApi(app);
y no me funcionaba, hasta que me di cuenta que el profe tiene el routerApi(app) hasta abajo. Eso hice y solucione mis problemas con el CORS.
Instala la extension cors en el navegador y la activas y complementa, y va funcionar.
A mi las peticiones de ésta clase no me han salido y tengo el mismo código que el profesor.
const express =require('express');const routerApi =require('./routes/index');const app =express();const port =3000;const{ logErrors, errorHandler, boomErrorHandler }=require('./middlewares/errorHandler');const cors =require('cors');app.use(express.json());const whitelist =// son los mismos (si pego los links platzi me impide comentar)const options ={origin:(origin, callback)=>{if(whitelist.includes(origin)){callback(null,true);}else{callback(newError('no permitido'),false);}}}app.use(cors(options));app.get('/',(req, res)=>{ res.send('Hola mi server en Express')})app.get('/nueva-ruta',(req, res)=>{ res.send('Hola soy una nueva ruta')})app.get('/home',(req, res)=>{ res.send('Aquí encontrarás nuestra página principal')})routerApi(app);app.use(logErrors);app.use(boomErrorHandler);app.use(errorHandler);app.listen(port,()=>{console.log('My port: '+ port);})
talvez es porque no estas poniendo la url como te sale en tu navegador, por ejemplo si en tu navegador sale "//127.0.0.1:5500" o "//localhost:5500" tienes que ponerlo exactamente igual, yo tuve el mismo problema intente poner localhost en lugar de la IP y no hacia la petición
Por lo que leí se debe poner el || !origin en el if para hacer peticiones desde la misma url.
Ordené mis middleware en mi archivo Index.js en este orden:
i) app.use(cors(options))
ii) routerApi(app);
iii) Middlewares de error
iv) app.listen(port, () =>...
Mi archivo frontend.html esta en la carpeta principal, al nivel del index.js y del package.json (no es necesario mover este archivo)
Ejecuté Live Server en el frontend.html y me fije que el navegador muestre exactamente el mismo origen que yo había declarado (puede ser 127.0.0.1:5500 o bien localhost:5500, pero debe ser exactamente el mismo!!)
Si no sale a la primera, recarga el navegador!! (Abre la consola del inspector)
Les dejo mi index.js:
const express =require('express');const cors =require('cors');const routerApi =require('./Routers');//el archivo index.js se busca en automáticoconst{ logErrors, errorHandler, boomErrorHandler }=require('./middlewares/error.handler');const app =express();const port =3000;app.use(express.json());//este es un Middlewareconst whitelist =["h ttp:// 127.0.0.1:5500","h ttps:// myapp.com"];const options ={origin:(origin, callback)=>{if(whitelist.includes(origin)){callback(null,true);}else{callback(newError('No tiene permiso para acceder'));}}}app.use(cors(options));app.get('/',(req, res)=>{ res.send('Hola, este es mi primer servidor!')});routerApi(app);// Este es el index.js de routing con express como atributoapp.use(logErrors);//Es muy importante poner este primero xq lleva el nextapp.use(boomErrorHandler);app.use(errorHandler);app.listen(port,()=>{console.log(`Estamos escuchando en el puerto h ttp://localhost:${port}`)})
Por si acaso, en la sgte clase el profe explica que para que el origen siga teniendo acceso a la aplicación es necesario aumentar !origin en el condicional...
const options ={origin:(origin, callback)=>{if(whitelist.includes(origin)||!origin){callback(null,true);}else{callback(newError('No tiene permiso para acceder'));}}}```
Muchas gracias @Tommby, me ayudó mucho tu aportación.
Igual algo que me pasó al final es que no estaba funcionando adecuadamente porque por alguna razón se paró nodemon con mi srcript de desarrollo, pero corriéndolo de nuevo desde la terminal ya funcionó de manera correcta.
¡Saludos!
problema de CORS
yo lo hice con el puerto predeterminado de live server :5500 en VScode , con el mismo código que el profesor enseña.
Gracias por la alternativa, si funciona.
Funciona, gracias
Como hace cors(options), para conocer nuestra whiteList?
Es que si vemos el codigo, al cors, le estamos pasando nuestro objeto options, y ya.
Yo supongo que él internamente busca la key origin, pero el condicional que esta dentro de nuestro objeto es donde tengo la duda, le estamos diciando whiteList.inclues(origin).
Mi pregunta es, como hace la función cors(), para saber cual origin poner dentro del includes?
Al final enviamos una función en donde ya nos envían el origen y teniendo esto tenemos una lista y por aparte tenemos la verificación del mismo origen por eso esta pregunta whitelist.includes(origin) || !origin
Consulta? en la validación !origin, es por que es el mismo origen y por eso no tiene valor, por eso da validación genera el valor true?
A mí no me funcionaba porque el archivo frontend.html lo tenia en la misma carpeta my-store. No sé si eso tenga que ver pero cambiarlo fuera de ahí solucionó mi problema. La primera opción que me había funcionado era esta:
Pero haciendo lo del cambio de ubicación del archivo, funcionó con el código de esta clase.
Buenas, una pregunta
Cómo hizo el profesor para levantar dos puertos al mismo tiempo, es decir, el 3000 para la API, y el 8000 para probar el front-end? O no estoy entendiendo bien como funciona o es muy facil y me complique mucho jaja ?
Gracias
A ya se como. Servicios como Aapache, Python o XAMPP para http.
Hola una duda, la lección 23 “Problema de CORS” ya me muestra un proyecto mas completo e integrado a una BD cosa que en las lecciones anteriores todo se trabajaba local con una variable productos.
Qué paso aquí o cómo veo la continuidad del curso?
Hola Me pasa lo mismo, creo que es de otro curso, tal vez POSTGRES ...
podemos ponerlo a prueba evitando crear el archivo html, abriendo una nueva pestaña con la url
about:blank
abrimos la consola y pegamos la siguiente líneas que contiene la función que hace la petición a la API
(async()=>{const response =awaitfetch('http://localhost:3000/api/v1/products');const data =await response.json();console.log(data);})()
Este video no es de aqui, debe estar en el otro curso el de node y postgresql
Fixed! Ya tenemos la clase correcta :D
Aún persiste el problema de la clase equivocada
Esta sería la manera de permitir acceso a nuestra API solo a los que pagan mensualmente (suponiendo que se vende o algo así), como por ejemplo tienes Netflix siempre y cuando pagues Netflix, o se usa otra tecnología para ese tipo de cosas?
Hola!
No creo que sea la forma ya que habilitar por ip puede ser engorroso ya que la persona que quiere acceder a tu API tendría que registrar su dominio o IP siempre, entonces si cambia en algún momento tendría que hacer una configuración en cambio. Me parece que se usa una API token, que es una ID única para el server que está consumiendo de la API.
No sé si la autenticación con esa token afecta el CORS sinceramente. La única experiencia que he tenido es con Firebase y ahí puedes configurar una regla en la que puede escribir o leer cualquier IP siempre y cuando se haya autenticado con email y contraseña. El cors, según recuerdo, se configura para que acepta cualquier IP siempre y cuando se haya cumplido la primera condición.
Gracias
Esta clase es de otro cursoo :(
Lo mismo pasa, esta tomando un ejemplo que no se vio dentro del curso.
¡Mi error! Ya quedó solucionado :ok_hand:
Solo se debe colocar en orden para quno bloquear el proceso
1* routerApi
2* app.use(cors(option))
y listo
Para los que les generó problemas de que no les aceptaba el server alterno del frontend para hacer la petición, acá les dejo la solución, despues de tanto buscar y leer y probar, de esta manera ya funciona:
app.use(express.json());const whitelist =['Aca va tu puerto del frontend como aparece'];const options ={origin:(origin, callback)=>{if(whitelist.includes(origin)||!origin){callback(null,true);}else{callback(newError('Not allowed by CORS'));}}}app.use(cors(options));
Espero que de esta manera les solucione sus inconvenientes....
es correcto, Cuando el navegador hace una solicitud del mismo origen o cuando usas herramientas como Postman o Insomnia, el valor de origin que recibe el servidor puede ser undefined, null, o false, por lo que se deben incluir estos datos en la validacion, !origin
Se perdio la continuidad del curso?
Hola, Jimmy. ¿Cómo así, me puedes decir donde pasa en que minuto o porque lo mencionas? Eso nos ayudará a evaluar y corregir de ser el caso.
Hola gente! Consulta. Puede ser que ésta clase este desfasada? Comienza hablando de las relaciones (muchos a muchos) y hasta ahora no habiamos visto nada sobre base de datos.
Muchas gracias.
Si así estoy yo, no entiendo porque ya en esta clase tienen la implementación de la DB y en las lecciones anteriores nada de eso se ha visto..
Esta clase me solucionó tantos problemas que he tenido en mi vida profesional 😄😄😄
También tuve el Errror en la que no podía acceder desde el frontend, pues en mi caso fue por el slash "/" que había puesto al final, mientras que el origin venia sin el, sacando eso se resolvió mi problema.
Duré un montón encontrando el error, pero realmente era solo quita el slash, muchas gracias
++Solucion de cors:++
const cors =require('cors');app.use(cors());
Si solo queremos hacer CORS a los endpoints de nuestra API, bajamos app.use(cors()) justo antes de que empiecen nuestras rutas hacia la API.
Habilitando cors de esa manera en index, hacepta cualquier origen.
Para habilitar el ingreso de host especificos, lo hacemos de esta manera:
++Desmenuzamos++
creamos una Whitelist (donde estarán los hosts o los sitios que queremos que ingresen)
const whitelist=['localhost:3000','pagina.co'];
crearemos una función que tendrá un origen que recibe dos parametros (asi es como funciona la librería de CORS), un origen y un callback. Si el origen esta en nuestro whitelist, lo dejamos pasar (true), en caso contrario devolvemos un error.