Tuesday, April 19, 2016

Spring Boot CORS Not Working?

For the life of me I could not get the CORS Configuration for Spring Boot to write the needed headers to the response. I wrote my own filter that could read the CORS Config and used it in WebMVC Configuration to solve it.

package com.dronze.app;
import com.dronze.filter.CorsFilter;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.web.DispatcherServletAutoConfiguration;
import org.springframework.boot.context.embedded.EmbeddedServletContainerFactory;
import org.springframework.boot.context.embedded.FilterRegistrationBean;
import org.springframework.boot.context.embedded.ServletRegistrationBean;
import org.springframework.boot.context.embedded.jetty.JettyEmbeddedServletContainerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.servlet.DispatcherServlet;
/**
* Created by claytongraham on 10/25/15.
*/
@Configuration
@ComponentScan(basePackages = {"com.dronze"})
@PropertySource("classpath:/application-${dronze.env:dev}.properties")
public class AppConfig {
@Bean
public EmbeddedServletContainerFactory servletContainer() {
JettyEmbeddedServletContainerFactory server = new JettyEmbeddedServletContainerFactory();
return server;
}
@Bean
public DispatcherServlet dispatcherServlet() {
return new DispatcherServlet();
}
@Bean
public ServletRegistrationBean dispatcherServletRegistration() {
ServletRegistrationBean registration = new ServletRegistrationBean(
dispatcherServlet(), "/rest/api/*");
registration.setName(DispatcherServletAutoConfiguration.DEFAULT_DISPATCHER_SERVLET_REGISTRATION_BEAN_NAME);
return registration;
}
@Bean
public FilterRegistrationBean corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.addAllowedOrigin("*");
config.addAllowedHeader("Content-Type");
config.addAllowedMethod("OPTIONS");
config.addAllowedMethod("GET");
config.addAllowedMethod("PUT");
config.addAllowedMethod("POST");
config.addAllowedMethod("DELETE");
source.registerCorsConfiguration("/**", config);
final FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source));
bean.setOrder(0);
return bean;
}
}
view raw AppConfig.java hosted with ❤ by GitHub
package com.dronze.filter;
/**
* Custom Filter Created by claytongraham on 4/19/16.
*/
import com.amazonaws.util.StringUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.util.Assert;
import org.springframework.web.cors.*;
import org.springframework.web.filter.OncePerRequestFilter;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import java.util.*;
public class CorsFilter extends OncePerRequestFilter {
public static final String CUSTOM_ALLOW_CORS_HEADER = "Accept-Cors-Requests-Origin";
private CorsProcessor processor = new DefaultCorsProcessor();
private final CorsConfigurationSource configSource;
/**
* Constructor accepting a {@link CorsConfigurationSource} used by the filter to find
* the {@link org.springframework.web.cors.CorsConfiguration} to use for each incoming request.
* @see org.springframework.web.cors.UrlBasedCorsConfigurationSource
*/
public CorsFilter(CorsConfigurationSource configSource) {
this.configSource = configSource;
}
/**
* Configure a custom {@link CorsProcessor} to use to apply the matched
* {@link org.springframework.web.cors.CorsConfiguration} for a request.
* <p>By default {@link DefaultCorsProcessor} is used.
*/
public void setCorsProcessor(CorsProcessor processor) {
Assert.notNull(processor, "CorsProcessor must not be null");
this.processor = processor;
}
public static boolean isCorsRequest(HttpServletRequest request) {
return (!StringUtils.isNullOrEmpty(request.getHeader(HttpHeaders.ORIGIN)));
}
private String getCSVList(List<String> items){
String[] array = (String[])items.toArray(new String[items.size()]);
return StringUtils.join(",", array);
}
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
FilterChain filterChain) throws ServletException, IOException {
CorsConfiguration corsConfiguration = configSource.getCorsConfiguration(request);
if(isCorsRequest(request)){
response.addHeader("Access-Control-Allow-Origin", getCSVList(corsConfiguration.getAllowedOrigins()));
response.addHeader("Access-Control-Allow-Headers", getCSVList(corsConfiguration.getAllowedHeaders()));
response.addHeader("Access-Control-Allow-Methods", getCSVList(corsConfiguration.getAllowedMethods()));
}
filterChain.doFilter(request, response);
}
}
view raw CorsFilter.java hosted with ❤ by GitHub

No comments: