liam xu
liam xu

Reputation: 3030

Angular 7 The 'Access-Control-Allow-Origin' header contains multiple values

I served the angular app in port 4202, and connect to the remove spring mvc app by below code.

this.http.post<Hero[]>('http://localhost:8080/api/hero/list', {"id":1}, httpOptions)

But it reported below error.

Failed to load http://localhost:8080/api/hero/list: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:4202' is therefore not allowed access. The response had HTTP status code 403.

So I tried to enable the cors in my spring web app by below annotion in controller method.

@CrossOrigin(origins = "http://localhost:4202")

I also tried to add a configuration class like below.

@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**");
    }
}

Then I refresh my frontend ui, it said below.

Failed to load http://localhost:8080/api/hero/list: The 'Access-Control-Allow-Origin' header contains multiple values 'http://localhost:4202, *', but only one is allowed. Origin 'http://localhost:4202' is therefore not allowed access.

Then I checked my chrome network like below, it really has duplicated 'Access-control-allow-origin' head. enter image description here

Then I googled a lot, find other guys met this issue since other web server in front of tomcat generate the second 'Access-control-allow-origin' head. But I only has one tomcat server except the server started by 'ng serve'.

Then I tried to visit this url(http://localhost:8080/api/hero/list) directly by fiddler instead of angular. And below is the screenshot, I can find that there is no duplicated 'Access-Control-Allow-Origin'. enter image description here

So I was guessing if it was caused by the nodejs server started by angular? Since I was newbie to angular I do not know how to look into this issue. Thanks.

Upvotes: 8

Views: 15626

Answers (4)

Sangeeth
Sangeeth

Reputation: 71

you configured cross origin filter config both on microservice and gateway. keep the configuration only in api gateway only as folllows,

@SpringBootApplication
@EnableEurekaClient
@EnableZuulProxy
public class ZuulApiGatewayApplication {

    public static void main(String[] args) {
        SpringApplication.run(ZuulApiGatewayApplication.class, args);
    }



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

Upvotes: 0

Ravi Soni
Ravi Soni

Reputation: 1343

I too got same issue. In my case my backend server was based on micro service architecture(spring webflux) and all micro services were updating cross origin header, due to which it had multiple values, then i fixed it by moving the cors configuration only to gateway, removing it from all other micro-services. That solved my issue!

Upvotes: 0

pranit patil
pranit patil

Reputation: 11

You are adding two headers in your backend code just remove @CrossOrigin(origins = "http://localhost:4202") and keep the WebConfig configuration only as you are allowing all origins in that config.

Upvotes: 1

HC42
HC42

Reputation: 131

Angular works on a different origin as your Java application server that is why there is CORS required. I am no Spring expert but as I understand your problem the following happens: When you do POST request the server adds the allow origin header by its self. It may read the Endpoints method specification to add the required allowed methods header (at least in Java EE) and sets the allow origin * header (which I strongly discourage for production, better set the expected allowed domains). Due to your Controller annotation an additional header is set. This invalid as only one cors origin header with one value is allowed by the CORS specification. Make sure only one is set by configuring your app server to set none and deal with this by some annotation or let the app server handle this or set this header by the loadbalancer (if you use one). The second thing (actually the initial error you got) is the preflight request. If you do a request that may change the server state (like a post request) cors requires you to answer an OPTIONS request first (so that the browser can check cors before you send the modifying request). This options request must have a 200ish response code and provide the cors allow headers for origin and methods (including post in your case).

For local development you can also use a proxy like this one. This does not forces you to deal with cors locally and modify your backend.

Upvotes: 1

Related Questions