Manejo de CORS con Node.js

    Introducción

    En este artículo, veremos qué es CORS, cómo puede configurar CORS con Express y cómo personalizar el middleware CORS según sus necesidades.

    Que es CORS

    CORS es la abreviatura de Intercambio de recursos entre orígenes. Es un mecanismo para permitir o restringir los recursos solicitados en un servidor web dependiendo de dónde se inició la solicitud HTTP.

    Esta política se utiliza para proteger un determinado servidor web del acceso de otro sitio web o dominio. Por ejemplo, solo los dominios permitidos podrán acceder a los archivos alojados en un servidor, como una hoja de estilo, una imagen o un script.

    Si está actualmente en http://example.com/page1 y te refieres a una imagen de http://image.com/myimage.jpg no podrás recuperar esa imagen a menos que http://image.com permite compartir orígenes cruzados con http://example.com.

    Hay un encabezado HTTP llamado origin en cada solicitud HTTP. Define desde dónde se originó la solicitud de dominio. Podemos utilizar la información del encabezado para restringir o permitir recursos de nuestro servidor web para protegerlos.

    Por defecto, las solicitudes de cualquier otro origen estarán restringidas por el navegador.

    Por ejemplo, mientras aún se encuentra en la etapa de desarrollo, si está utilizando una biblioteca de interfaz como React, su aplicación de interfaz se servirá en http://localhost:3000. Mientras tanto, su servidor Express puede estar ejecutándose en un puerto diferente, como http://localhost:2020.

    Debido a esto, deberá permitir CORS entre esos servidores.

    Si ve este error común en la consola de su navegador. Las restricciones de CORS podrían ser el problema:

    CORS es realmente útil cuando está ofreciendo una API pública y le gustaría controlar el acceso a ciertos recursos y cómo la gente los usa.

    Además, si desea usar su propia API o archivos en una página web diferente, simplemente puede configurar CORS para permitir eso, mientras bloquea a otros.

    Configuración de CORS con Express

    Comencemos con un proyecto nuevo. Haremos un directorio para él, lo ingresaremos y ejecutaremos npm init con la configuración predeterminada:

    $ mkdir myapp
    $ cd myapp
    $ npm init -y
    

    Luego instalemos los módulos requeridos. Estaremos usando express y el cors middleware:

    $ npm i --save express
    $ npm i --save cors
    

    Entonces comencemos a crear una aplicación web rápida con dos rutas para demostrar cómo funciona CORS.

    Haremos un archivo, llamado index.js que actúa como un servidor web, con un par de controladores de solicitudes:

    const express = require('express');
    const cors = require('cors');
    
    const app = express();
    
    app.get("https://Pharos.sh.com/", (req, res) => {
        res.json({
            message: 'Hello World'
        });
    });
    
    app.get('/:name', (req, res) => {
        let name = req.params.name;
    
        res.json({
            message: `Hello ${name}`
        });
    });
    
    app.listen(2020, () => {
        console.log('server is listening on port 2020');
    });
    

    Ejecutemos la aplicación y el servidor:

    $ node index.js
    

    Ahora, si vas a http://localhost:2020/ – el servidor debe devolver un mensaje JSON:

    {
      "message": "Hello World"
    }
    

    Alternativamente, si vas a http://localhost:2020/something debería ver:

    {
      "message": "Hello something"
    }
    

    Habilitar todas las solicitudes CORS

    Si desea habilitar CORS para todas las solicitudes, simplemente puede usar el cors middleware antes de configurar sus rutas:

    const express = require('express');
    const cors = require('cors');
    
    const app = express();
    
    app.use(cors())
    
    ......
    

    Esto permitirá acceder a todas las rutas desde cualquier lugar de la web si eso es lo que necesita. Entonces, en nuestro ejemplo, ambas rutas serán accesibles para todos los dominios.

    Por ejemplo, si nuestro servidor se ejecuta en http://www.example.com y ofrece contenido como imágenes; permitimos otros dominios, como http://www.differentdomain.com para referir el contenido de http://www.example.com.

    Así, una página web en http://www.differentdomain.com puede usar nuestro dominio como fuente para una imagen:

    <img src="https://www.example.com/img/cat.jpg">
    

    Habilitar CORS para una sola ruta

    Pero si necesita que una determinada ruta sea accesible y no otras rutas, puede configurar cors en una ruta determinada como middleware en lugar de configurarlo para toda la aplicación:

    app.get("https://Pharos.sh.com/", cors(), (req, res) => {
        res.json({
            message: 'Hello World'
        });
    });
    

    Esto permitirá que una determinada ruta sea accesible por cualquier dominio. Entonces, en tu caso, solo el / La ruta será accesible para todos los dominios. los /:name La ruta solo será accesible para las solicitudes que se iniciaron en el mismo dominio que la API, que es http://localhost:2020 en nuestro caso.

    Por ejemplo, si intenta enviar una solicitud de recuperación al / ruta desde un origen diferente: tendrá éxito y obtendrá el Hello World mensaje como respuesta:

    fetch('http://localhost:2020/')
        .then(response => response.json())
        .then(data => console.log(data))
        .catch(err => console.error(err));
    

    Debería ver que la respuesta del servidor se registró correctamente en la consola si ejecuta este código:

    {
        message: 'Hello World'
    }
    

    Pero si intenta acceder a cualquier otra ruta que no sea la ruta raíz, como http://localhost:2020/name o http://localhost:2020/img/cat.png esta solicitud será bloqueada por el navegador:

    fetch('http://localhost:2020/name/janith')
      .then(response => response.json())
      .then(data => console.log(data))
      .catch(err => console.error(err));
    

    Debería ver el siguiente error si intenta ejecutar este código en una aplicación web diferente:

    Configurar CORS con opciones

    También puede usar las opciones de configuración con CORS para personalizar esto aún más. Puede usar la configuración para permitir el acceso a un solo dominio o subdominios, configurar métodos HTTP que estén permitidos, como GET y POST dependiendo de sus requerimientos.

    Así es como puede permitir el acceso de un solo dominio usando las opciones de CORS:

    var corsOptions = {
        origin: 'http://localhost:8080',
        optionsSuccessStatus: 200 // For legacy browser support
    }
    
    app.use(cors(corsOptions));
    

    Si configura el nombre de dominio en el origen, el servidor permitirá CORS desde el dominio configurado. Entonces la API será accesible desde http://localhost:8080 en nuestro caso y bloqueado para otros dominios.

    Si enviamos un GET solicitud, acceder a cualquier ruta debería funcionar, ya que las opciones se aplican a nivel de aplicación, no a nivel de función.

    Entonces, si ejecutamos el siguiente código y enviamos una solicitud desde http://localhost:8080 a http://localhost:2020:

    fetch('http://localhost:2020/')
      .then(response => response.json())
      .then(data => console.log(data))
      .catch(err => console.error(err));
    
    // Or
    
    fetch('http://localhost:2020/name/janith')
      .then(response => response.json())
      .then(data => console.log(data))
      .catch(err => console.error(err));
    

    Se nos permite obtener la información de esa aplicación y dominio.

    También puede configurar los métodos HTTP permitidos si lo desea:

    var corsOptions = {
        origin: 'http://localhost:8080',
        optionsSuccessStatus: 200 // For legacy browser support
        methods: "GET, PUT"
    }
    
    app.use(cors(corsOptions));
    

    Si enviamos un POST solicitud de http://localhost:8080, será bloqueado por el navegador como solo GET y PUT son compatibles:

    fetch('http://localhost:2020', {
      method: 'POST',
      body: JSON.stringify({name: "janith"}),
    })
    .then(response => response.json())
    .then(data => console.log(data))
    .catch(err => console.error(err));
    

    Para ver una lista completa de opciones de configuración, consulte la documentación oficial.

    Configuración de orígenes dinámicos de CORS mediante una función

    Si las configuraciones no satisfacen sus requisitos, puede crear su función para personalizar CORS.

    Por ejemplo, supongamos que desea permitir el uso compartido de CORS para .jpg archivos http://something.com y http://example.com:

    const allowlist = ['http://something.com', 'http://example.com'];
    
        const corsOptionsDelegate = (req, callback) => {
        let corsOptions;
    
        let isDomainAllowed = whitelist.indexOf(req.header('Origin')) !== -1;
        let isExtensionAllowed = req.path.endsWith('.jpg');
    
        if (isDomainAllowed && isExtensionAllowed) {
            // Enable CORS for this request
            corsOptions = { origin: true }
        } else {
            // Disable CORS for this request
            corsOptions = { origin: false }
        }
        callback(null, corsOptions)
    }
    
    app.use(cors(corsOptionsDelegate));
    

    La función de devolución de llamada aceptará dos parámetros. El primero es un error por donde pasamos null y el segundo son opciones por donde pasamos { origin: false }. El segundo parámetro podría ser muchas opciones que se construyen utilizando el request objeto del controlador de solicitudes Express.

    Entonces, una aplicación web alojada en http://something.com o http://example.com podría referir una imagen con .jpg extensión desde el servidor como hemos configurado en nuestra función personalizada.

    Entonces, el siguiente archivo adjunto de imagen será exitoso desde cualquiera de estos:

    <img src="https://yourdomain.com/img/cat.jpg">
    

    Pero se bloqueará el siguiente archivo adjunto:

    <img src="https://yourdomain.com/img/cat.png">
    

    Cargando lista de orígenes permitidos desde como fuente de datos

    También puede usar una lista de dominios permitidos de una base de datos o usar cualquier fuente de datos de respaldo para permitir CORS:

    var corsOptions = {
        origin: function (origin, callback) {
            // Loading a list of allowed origins from the database
            // Ex.. origins = ['http://example.com', 'http//something.com']
            database.loadOrigins((error, origins) => {
                callback(error, origins);
            });
        }
    }
    
    app.use(cors(corsOptions));
    

    Conclusión

    En este artículo, hemos cubierto qué es CORS y cómo puede configurarlo con Express. Luego, configuramos CORS para todas las solicitudes, para solicitudes específicas, agregamos opciones y restricciones, así como también definimos una función personalizada para la configuración dinámica de CORS.

     

    Etiquetas:

    Deja una respuesta

    Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *