jueves, 30 de enero de 2014

Configuración CORS en servicios JERSEY RESTFul

Si para crear los servicios RESTFul de vuestro backend habéis usado Jersey (https://jersey.java.net/), es posible que al invocar esos servicios web desde un frontend alojado en otro domino (o máquina) os devuelva un error con el texto “No 'Access-Control-Allow-Origin' header is present on the requested resource.

Esto se debe a la configuración de CORS que tenemos en nuestro backend (Cross-Origin Resource Sharing) no nos permite recibir peticiones de fuera de nuestro dominio.

No me voy a explanar en el por qué, solo en como decirle a Jersey que acepte todas esas peticiones.

Creando un Filtro para los Responses

En nuestro backend, deberemos crear una clase filter de Jersey (ContainerResponseFilter) con el siguiente código:

package <mi.paquete>;

import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.ResponseBuilder;

import com.sun.jersey.spi.container.ContainerRequest;
import com.sun.jersey.spi.container.ContainerResponse;
import com.sun.jersey.spi.container.ContainerResponseFilter;

public class ResponseCorsFilter implements ContainerResponseFilter {

    @Override
    public ContainerResponse filter(ContainerRequest req, ContainerResponse contResp) {

        ResponseBuilder resp = Response.fromResponse(contResp.getResponse());
        resp.header("Access-Control-Allow-Origin", "*")
                .header("Access-Control-Allow-Methods", "GET, POST, OPTIONS");

        String reqHead = req.getHeaderValue("Access-Control-Request-Headers");

        if(null != reqHead && !reqHead.equals("")){
            resp.header("Access-Control-Allow-Headers", reqHead);
        }

        contResp.setResponse(resp.build());
            return contResp;
    }

}



Cambiando la configuración de la app web

Tras esto, abriremos nuestro archivo web.xml  y buscaremos <servlet-name>Jersey Web Application</servlet-name>

Dentro del tag <servlet> y justo debajo de <servlet-class>, están las declaraciones <init-param> del servlet de Jersey. Justo debajo de los existentes añadiremos este otro:

<init-param>
    <param-name>com.sun.jersey.spi.container.ContainerResponseFilters</param-name>
    <param-value><mi.paquete>.ResponseCorsFilter</param-value>
</init-param>

Es importante no confundirse con los otros init-param que se declaran en el archivo al principio, y hacerlo dentro del tag <servlet> que define al Jersey.




Y con esto, ya funcionará ;-)


Os debo un post en el que explicar como usar los servicios  Jersey RESTFul en Google App Engine.