¿Están tus servicios REST en otro servidor?

 ·  ☕ 9 min  ·  ✍️ eiximenis

    Nota: Este post ha sido importado de mi blog de geeks.ms. Es posible que algo no se vea del todo "correctamente". En cualquier caso puedes acceder a la versión original aquí

    Muy buenas, en este post vamos a hablar de lo que ocurre si los servicios REST de tu aplicación están en otro servidor distinto al de tu aplicación web… Terminaremos hablando de CORS, pero antes lo haremos de JSONP y empezaremos por el…

    … Orígen

    No, no me refiero a la onírica película con Di Caprio, aunque muchas veces el desarrollo web se parezca a una pesadilla, si no a lo que en el mundo web entendemos como el origen de una web.

    Es un concepto muy sencillo pero que debemos tener siempre presente: protocolo, host y número de puerto conforman un orígen. Así las urls

    ¿Es simple no? Bueno pues ahora la regla de oro: Los navegadores tienen prohibido procesar una llamada Ajax (con XmlHttpRequest) desde una página que esté en un orígen hacia una URL que sea de otro origen.

    Punto.

    Vale, que nos impidan hacer peticiones ajax a otro dominio es una muy buena medida de seguridad, pero a veces es una necesidad legítima: Imagina que tienes la API REST de tu aplicación publicada en http://api.foo.com y tu aplicación web en http://foo.com. Pues si desde tu web quieres hacer una petición ajax a alguno de tus servicios: mala suerte.

    Para hacer algunas demos voy a crear una solución de vs2012 con dos proyectos web:

    image

    Uno será mi aplicación web y el otro será mi API. El proyecto WebApi (que yo he llamado CORSDemo) tan solo tiene un controlador, que responde a las peticiones de tipo /Beer/id:

    public class BeersController : ApiController

    {

        public Beer Get(int id)

        {

            return new Beer {Name = "Cerveza " + id, Id = id};

        }

    }

    Por otro lado la aplicación web (que he llamado CORSDemo.Web) tiene un solo controlador (Home) que devuelve una vista. Dicha vista intenta hacer una llamada Ajax al servicio REST:

    <h2>Indexh2>

     

    @section scripts

    {

        <script>

        (function() {

                var xhr = new XMLHttpRequest();

                console.log(‘Invocando servicio REST’);

                xhr.open(‘GET’, ‘http://localhost:2614/Beers/10’, true);

                xhr.setRequestHeader("Accept", "application/json");

                xhr.addEventListener(‘readystatechange’, function (e) {

                    console.log(‘readyState: ‘ + xhr.readyState)

                    console.log(‘status: ‘ + xhr.status);

                    console.log(‘response: ‘ + xhr.responseText);

                });

                xhr.send();

        })();

        script>

    }

    Si pongo en marcha el proyecto, efectivamente en mi IIS Express tengo dos aplicaciones web:

    image

    En mi caso la aplicación WebApi está en localhost:2614 y la aplicación web está en localhost:2628. Y si navego a localhost:2628 veo lo que ya me esperaba:

    image

    El navegador me muestra el error que no puede realizar la llamada ya que el servicio REST está en otro orígen.

    Rompiendo la barrera – jsonp

    Por suerte (y por desgracia también, todo tiene las dos caras de la moneda), hay muchas cabezas pensantes por ahí y algunas de ellas se dedicaron a ver si existía alguna posible manera de saltarse esta medida de seguridad. Y dieron con una. Ciertamente no abrieron un boquete en la muralla de seguridad, pero sí una brecha y durante vario tiempo nos hemos estado aprovechando de ella. Esta brecha es la técnica conocida como jsonp. Veamos muy brevemente en que consiste…

    El objetivo final es conseguir llamar al servicio REST que tenemos y recuperar los datos. Eso debemos hacerlo de forma asíncrona al igual que hace XMLHttpRequest, que ya hemos visto que no podemos usar.

    La técnica de jsonp es muy simple, pero requiere eso sí que los servicios REST devuelvan json (no sirve si devuelven algún otro tipo de datos como XML).

    Consiste básicamente en sustuir la llamada AJAX por un tag

    Si quieres, puedes invitarme a un café xD

    eiximenis
    ESCRITO POR
    eiximenis
    Compulsive Developer