Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 836
liam xu Avatar asked Nov 01 '18 08:11

liam xu


People also ask

Does the Access-Control allow Origin header contains multiple values?

The 'Access-Control-Allow-Origin' header contains multiple values, but only one is allowed. When defining multiple domains separated by coma in Settings > Advanced > Security > AccessControlAllowOrigin, they are not taken into account. It works when defined only one.

How do I enable Access-Control allow Origin header?

Limiting the possible Access-Control-Allow-Origin values to a set of allowed origins requires code on the server side to check the value of the Origin request header, compare that to a list of allowed origins, and then if the Origin value is in the list, set the Access-Control-Allow-Origin value to the same value as ...

What is Access-Control allow header?

The Access-Control-Allow-Headers response header is used in response to a preflight request which includes the Access-Control-Request-Headers to indicate which HTTP headers can be used during the actual request. This header is required if the request has an Access-Control-Request-Headers header.


2 Answers

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.

like image 114
HC42 Avatar answered Nov 15 '22 03:11

HC42


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.

like image 41
pranit patil Avatar answered Nov 15 '22 05:11

pranit patil