Spring Cloud - Zuul Proxy is producing a No 'Access-Control-Allow-Origin' ajax response

30,356

Solution 1

Adding this piece of code to your class annotated with @EnableZuulProxy should do the trick.

@Bean
public CorsFilter corsFilter() {
    final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    final CorsConfiguration config = new CorsConfiguration();
    config.setAllowCredentials(true);
    config.addAllowedOrigin("*");
    config.addAllowedHeader("*");
    config.addAllowedMethod("OPTIONS");
    config.addAllowedMethod("HEAD");
    config.addAllowedMethod("GET");
    config.addAllowedMethod("PUT");
    config.addAllowedMethod("POST");
    config.addAllowedMethod("DELETE");
    config.addAllowedMethod("PATCH");
    source.registerCorsConfiguration("/**", config);
    return new CorsFilter(source);
}

Solution 2

I had a similar problem, with Angular Web app consuming RESTful services implemented by Spring Boot with Zuul and Spring Security.

None of the above solutions worked. I realized that the problem was NOT in Zuul, but in Spring Security.

As the official documentation (CORS with Spring Security) states, when using Spring Security, CORS must be configured prior to Spring Security.

Finally, I was able to integrate Grinish Nepal's (see prior answers) solution into a solution that works.

Without further ado, here is the code that enables CORS with Spring Security and Zuul:


    @Configuration
    @EnableWebSecurity
    public class SecurityConfig extends WebSecurityConfigurerAdapter {
        //irrelevant for this problem
        @Autowired
        private MyBasicAuthenticationEntryPoint authenticationEntryPoint;

        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http
                    //configure CORS -- uses a Bean by the name of     corsConfigurationSource (see method below)
                    //CORS must be configured prior to Spring Security
                    .cors().and()
                    //configuring security - irrelevant for this problem
                    .authorizeRequests()
                        .anyRequest().authenticated()
                        .and()
                    .httpBasic()
                    .authenticationEntryPoint(authenticationEntryPoint);

            //irrelevant for this problem
            http.addFilterAfter(new CustomFilter(),
                    BasicAuthenticationFilter.class);
        }

        //The CORS filter bean - Configures allowed CORS any (source) to any 
        //(api route and method) endpoint
        @Bean
        CorsConfigurationSource corsConfigurationSource() {
            final UrlBasedCorsConfigurationSource source = new     UrlBasedCorsConfigurationSource();
            final CorsConfiguration config = new CorsConfiguration();
            config.setAllowCredentials(true);
            config.addAllowedOrigin(CorsConfiguration.ALL);
            config.addAllowedHeaders(Collections.singletonList(CorsConfiguration.ALL));
            config.addAllowedMethod("OPTIONS");
            config.addAllowedMethod("HEAD");
            config.addAllowedMethod("GET");
            config.addAllowedMethod("PUT");
            config.addAllowedMethod("POST");
            config.addAllowedMethod("DELETE");
            config.addAllowedMethod("PATCH");
            source.registerCorsConfiguration("/**", config);
            return source;
        }

        //configuring BA usernames and passwords - irrelevant for this problem
        @Autowired
        public void configureGlobal(AuthenticationManagerBuilder auth) throws     Exception {
           ...
        }
    }

Solution 3

When your application runs on http://localhost:8383 then you can only make AJAX-calls to http://localhost:8383. Zuul doesn't and cannot change that.

What Zuul can do is mapping requests for e.g. http://localhost:8383/zuul/ to http://localhost:8080/zuul/. But your browser would have to call http://localhost:8383/zuul/springapp/departments and you have to configure that mapping.

Solution 4

Just adding the following to the configuration worked for me

zuul:
    ignoredHeaders: Access-Control-Allow-Credentials, Access-Control-Allow-Origin

Solution 5

I had the same issue, and i have fixed by adding CorsFilter bean

  @Bean
  public FilterRegistrationBean corsFilter() {
    UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    CorsConfiguration config = new CorsConfiguration();
    config.setAllowCredentials(true);
    config.addAllowedOrigin("*");
    config.addAllowedHeader("*");
    config.addAllowedMethod("*");
    source.registerCorsConfiguration("/**", config);
    FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source));
    bean.setOrder(0);
    return bean;
  }

And adding zuul's properties this code

zuul:
  sensitiveHeaders:
  ignored-headers: Access-Control-Allow-Credentials, Access-Control-Allow-Origin

You can find more detail about the issue here

Share:
30,356
Given
Author by

Given

Updated on July 21, 2022

Comments

  • Given
    Given almost 2 years

    Startup Appplication:

    @SpringBootApplication
    @EnableZuulProxy
    public class ZuulServer {
    
         public static void main(String[] args) {
             new SpringApplicationBuilder(ZuulServer.class).web(true).run(args);
         }
     }
    

    My YAML file is like this:

    server:
       port:8080
    
    spring:
       application:
          name: zuul
    
    eureka:
    client:
      enabled: true
        serviceUrl:
           defaultZone: http://localhost:8761/eureka/
    
    
    
    zuul:
        proxy:
           route:
             springapp: /springapp
    

    I have a microservice application (on port 8081) called springapp and has some rest services. Below is my client UI app:

        <html>
        <head>
            <title>TODO supply a title</title>
            <meta charset="UTF-8">
            <meta name="viewport" content="width=device-width, initial-scale=1.0">
            <script type="text/javascript" src="js/libs/jquery/jquery.min.js" ></script>
        </head>
        <body>
            <script type="text/javascript">
                $.ajax({
                    url: 'http://localhost:8080/zuul/springapp/departments',
                    type: 'GET'
                }).done(function (data) {
                    consoe.log(data);
                    document.write(data);
                });
            </script>        
    
        </body>
    </html>
    

    But I get a

    XMLHttpRequest cannot load http://localhost:8080/zuul/springapp/departments. No
        'Access-Control-Allow-Origin' header is present on the requested
        resource. Origin 'http://localhost:8383' is therefore not allowed access.
    

    This UI HTML5 app is on http://localhost:8383/SimpleAPp/index.html. CORS, CORS, CORS... Please help. BTW the http://localhost:8080/zuul/springapp/departments returns a json list as supposed to when on the browser address bar. The spring.io blog here says that there is no need for a filter because the zuulproxy takes care of that but I don't know why it is not working for me.

  • Given
    Given over 9 years
    Thanks for trying to answer but the reason I added the tags is because of the @EnableZuulProxy which is from the spring cloud. On this post on the spring.io blog they say that there is no need for that Filter which you mentioned because the ZuulProxy does a reverse proxy for the consuming client. Hope this makes sense.
  • Dave Syer
    Dave Syer over 9 years
    Yes, but as @zeroflagL says below, that just means you have to send all requests through the proxy.
  • Given
    Given over 9 years
    Thanks a lot. That worked for me :) My other question now is: What would you do if you have an angular js app wrapped in Cordova/Phonegap and using static files in the app instead of serving the files from the proxy server? I ask because my solution as of now only works because the static file with the ajax request resides on the ZuulProxy server.
  • Given
    Given over 9 years
    I have a solution for the immediately above angular.js scenario. I added a CORS Filter as shown here to the ZuulProxy. So any request that goes to the ZuulProxy from the same domain as the proxy or from some other source will be allowed :)
  • Stackee007
    Stackee007 over 9 years
    If I assume correct, CORS Filter only works if the app is hosted on root (/) context. If the app is hosted on any other context you need to fallback on enabling CORS specifc to that servlet container.
  • CuriousCoder
    CuriousCoder over 6 years
    Do you add this class in the application with zuul or the application which has the microservice?
  • reiley
    reiley almost 6 years
    This works, thanks!! But, shouldn't this be the default behavior?
  • Pallavi
    Pallavi over 5 years
    Can you please provide complete code.. I stuck in these issue from a very long time
  • Pallavi
    Pallavi over 5 years
    @Mate with these solution I am getting pop-up which asks me to enter username , password. Please help me with these setting
  • Mate Šimović
    Mate Šimović over 5 years
    @Pallavi My solution above is for people who are trying to enable CORS while using Zuul and Spring Security, with some method of authentication. My example uses .httpBasic() authentication, which is why your browser will ask for username and password in a popup. If you don't need Spring Security, use the accepted answer or try my solution with removing all the code under comments: //configuring security - irrelevant for this problem, //irrelevant for this problem, //configuring BA usernames and passwords - irrelevant for this problem. Hope this helps, and let me know if it works.
  • Grinish Nepal
    Grinish Nepal over 5 years
    @Pallavi whats the problem you are having this is the complete code to set the CORS Filter.
  • Pallavi
    Pallavi over 5 years
    @GrinishNepal I just want to know where is the right place to put these code, I tried multiple combinations. My project structure is like Angular6 -> ApiGateway -> microservices