/** * Copyright 2014-2017 Linagora, Université Joseph Fourier, Floralis * * The present code is developed in the scope of the joint LINAGORA - * Université Joseph Fourier - Floralis research program and is designated * as a "Result" pursuant to the terms and conditions of the LINAGORA * - Université Joseph Fourier - Floralis research program. Each copyright * holder of Results enumerated here above fully & independently holds complete * ownership of the complete Intellectual Property rights applicable to the whole * of said Results, and may freely exploit it in any manner which does not infringe * the moral rights of the other copyright holders. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package net.roboconf.dm.rest.services.cors; import java.util.LinkedHashMap; import java.util.Map; 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; import net.roboconf.core.utils.Utils; /** * A filter to handle CORS. * <p> * CORS means Cross-Origin Domain.<br> * We use this filter to allow our REST clients to be served from * a different domain than our REST API. * </p> * <p> * As an example, the REST API can be served from http://localhost:8080/rest * and our client be served from http://localhost. Without this filter, the REST invocations will not work. * </p> * * @author Vincent Zurczak - Linagora */ public class ResponseCorsFilter implements ContainerResponseFilter { public static final String CORS_REQ_HEADERS = "Access-Control-Request-Headers"; public static final String ORIGIN = "Origin"; static final String CORS_ALLOW_ORIGIN = "Access-Control-Allow-Origin"; static final String CORS_ALLOW_METHODS = "Access-Control-Allow-Methods"; static final String CORS_ALLOW_CREDENTIALS = "Access-Control-Allow-Credentials"; static final String CORS_ALLOW_HEADERS = "Access-Control-Allow-Headers"; static final String VALUE_ALLOWED_METHODS = "GET, DELETE, POST, PUT, OPTIONS"; static final String VALUE_ALLOW_CREDENTIALS = "true"; @Override public ContainerResponse filter( ContainerRequest req, ContainerResponse contResp ) { ResponseBuilder resp = Response.fromResponse( contResp.getResponse()); Map<String,String> headers = buildHeaders( req.getHeaderValue( CORS_REQ_HEADERS ), req.getHeaderValue( ORIGIN )); for( Map.Entry<String,String> h : headers.entrySet()) resp.header( h.getKey(), h.getValue()); contResp.setResponse( resp.build()); return contResp; } /** * Finds the right headers to set on the response to prevent CORS issues. * @param reqCorsHeader the headers related to CORS * @return a non-null map */ public static Map<String,String> buildHeaders( String reqCorsHeader, String requestUri ) { Map<String,String> result = new LinkedHashMap<> (); result.put( CORS_ALLOW_ORIGIN, requestUri ); result.put( CORS_ALLOW_METHODS, VALUE_ALLOWED_METHODS ); result.put( CORS_ALLOW_CREDENTIALS, VALUE_ALLOW_CREDENTIALS ); if( ! Utils.isEmptyOrWhitespaces( reqCorsHeader )) result.put( CORS_ALLOW_HEADERS, reqCorsHeader ); return result; } }