Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I enable CORS headers in the Swagger /v2/api-docs offered by Springfox Swagger?

I have the following file in my project:

@Configuration
@Order(Ordered.LOWEST_PRECEDENCE)
public class SwaggerConfig {

    @Bean
    public Docket apiSwagger2Documentation() { .... }
}

And in the Application.java there is:

@SpringBootApplication
@ComponentScan(basePackages = { ... })
@EnableSwagger2
public class Application {
    ...
}

The Swagger JSON is available under /v2/api-docs, that works fine.

What I would like to do, is to enable CORS headers for that endpoint.

For my own controllers, I have added @CrossOrigin to the controller classes, those APIs then have CORS headers, that works fine. But for the Swagger JSON URL I haven't written a controller myself, so I cannot use that annotation.

I have added the following method to the SwaggerConfig, as described in "Global CORS Configuration" in CORS support in Spring Framework.

    @Bean
    public WebMvcConfigurer corsConfigurer() {
        System.out.println("*** corsConfigurer called");
        return new WebMvcConfigurerAdapter() {
            @Override public void addCorsMappings(CorsRegistry registry) {
                System.out.println("*** addCorsMappings called");
                registry.addMapping("/v2/api-docs");
            }
        };
    }

Both print statements get printed, so the method is being called. But when I call the URL with curl:

curl -H "Origin: foo.com"  \
   -H "Access-Control-Request-Method: GET"   \
   -X OPTIONS \ 
   --verbose  \
   http://localhost:9274/v2/api-docs

The CORS headers are not in the response. (In contrast to my own controller methods, annotated with @CrossOrigin, where the response does have the CORS headers.)

I am using springfox-swagger2 version 2.7.0, and spring-boot-starter-web 1.5.2.

What can I do to enable CORS headers on the Swagger JSON API endpoint?

like image 533
Adrian Smith Avatar asked Aug 14 '17 14:08

Adrian Smith


2 Answers

I think you need a generic web filter as opposed to Web Mvc configuration.

@Bean
public CorsFilter corsFilter() {
    UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();

    // Allow anyone and anything access. Probably ok for Swagger spec
    CorsConfiguration config = new CorsConfiguration();
    config.setAllowCredentials(true);
    config.addAllowedOrigin("*");
    config.addAllowedHeader("*");
    config.addAllowedMethod("*");

    source.registerCorsConfiguration("/v2/api-docs", config);
    return new CorsFilter(source);
}
like image 168
Strelok Avatar answered Oct 18 '22 17:10

Strelok


Thanks to @Barath for the answer. The solution was to ignore the Spring documentation, that code just seems to silently not work.

(It's a shame, the Spring stuff is quite advanced when it does work, for example, the "Access-Control-Allow-Headers" response header to the pre-flight request is set based on what headers the Java API method actually offers.)

Ignore Spring's implementation of CORS and do your own. I have put the code here that worked for me:

@Component
public class CorsFilter implements Filter {

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
    throws IOException, ServletException {
        HttpServletResponse response = (HttpServletResponse) res;
        HttpServletRequest request = (HttpServletRequest) req;
        response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
        response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Credentials", "true");
        response.setHeader("Access-Control-Allow-Headers", "Foo, Bar, Baz");
        chain.doFilter(req, res);
    }

    @Override
    public void init(FilterConfig filterConfig) {}

    @Override
    public void destroy() {}
}

Remember to add any @RequestHeader that you've used in any REST method to the Access-Control-Allow-Headers response header

like image 34
Adrian Smith Avatar answered Oct 18 '22 18:10

Adrian Smith