/*
* This file is part of anycook. The new internet cookbook
* Copyright (C) 2014 Jan Graßegger
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see [http://www.gnu.org/licenses/].
*/
package de.anycook.api.filter.cors;
import de.anycook.conf.Configuration;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerResponseContext;
import javax.ws.rs.container.ContainerResponseFilter;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
import javax.ws.rs.ext.Provider;
/**
* Adds Access-Control-Allow headers to response
* @author Jan Graßegger <jan@anycook.de>
*
*/
@Provider
public class CorsFilter implements ContainerResponseFilter {
public final static Pattern hostPattern = Pattern.compile("http(s)*://(.*)anycook\\.de");
private final Logger logger;
/**
*
*/
public CorsFilter() {
logger = LogManager.getLogger(getClass());
}
@Override
public void filter(ContainerRequestContext requestContext,
ContainerResponseContext responseContext) {
String method = requestContext.getMethod();
String path = requestContext.getUriInfo().getPath();
logger.debug(String.format("filtering: %s:%s", method, path));
CORSRequestType corsType = CORSRequestType.detect(requestContext);
switch(corsType){
case PREFLIGHT:
filterPreFlight(requestContext, responseContext);
case ACTUAL:
filterActualRequest(requestContext, responseContext);
}
}
private void filterPreFlight(ContainerRequestContext requestContext,
ContainerResponseContext responseContext) {
logger.debug("filtering preflight for "+requestContext.getUriInfo().getPath());
String origin = requestContext.getHeaderString("Origin");
if(!checkOrigin(origin))
responseContext.setStatusInfo(Response.Status.FORBIDDEN);
String methodHeader = requestContext.getHeaderString("Access-Control-Request-Method");
if(methodHeader == null)
responseContext.setStatusInfo(Response.Status.FORBIDDEN);
String requestHeaders =
requestContext.getHeaderString("Access-Control-Request-Headers");
logger.info("requestHeader: "+requestHeaders);
MultivaluedMap<String, Object> headers = responseContext.getHeaders();
headers.putSingle("Access-Control-Allow-Origin", origin);
headers.putSingle("Access-Control-Allow-Credentials", "true");
headers.putSingle("Access-Control-Allow-Methods", methodHeader);
headers.putSingle("Access-Control-Allow-Headers", "x-requested-with," +
(requestHeaders == null ? "" : requestHeaders));
}
private void filterActualRequest(ContainerRequestContext requestContext,
ContainerResponseContext responseContext) {
String origin = requestContext.getHeaderString("Origin");
if(!checkOrigin(origin))
responseContext.setStatusInfo(Response.Status.FORBIDDEN);
MultivaluedMap<String, Object> headers = responseContext.getHeaders();
headers.putSingle("Access-Control-Allow-Origin", origin);
headers.putSingle("Access-Control-Allow-Credentials", "true");
if(responseContext.getStatus() == 201)
headers.putSingle("Access-Control-Expose-Headers", "Location");
}
public static boolean checkOrigin(String origin){
if(Configuration.getInstance().isDeveloperMode()) return true;
if(origin == null)
return false;
Matcher hostMatcher = hostPattern.matcher(origin);
return hostMatcher.matches();
}
/**
* @param hh
* @return
*/
// public static Response buildResponse(String origin) {
//// if(!checkOrigin(origin))
//// throw new WebApplicationException(401);
//
// ResponseBuilder resp = Response.ok();
// resp.header("Access-Control-Allow-Origin", origin);
// resp.header("Access-Control-Allow-Credentials", "true");
// return resp.build();
// }
}