raj kumar
raj kumar

Reputation: 113

Angular2-Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource

I am calling a http post in Angular 2. This is working fine in post man but when I implement this API call in Angular 2 I get No 'Access-Control-Allow' error. Here is my code

getInspections(): Observable<IInspection[]> {
        if (!this.inspections) {
            let body =JSON.stringify({"Statuses":["Submitted", "Opened"]});
            let headers = new Headers({ 'Content-Type': 'application/json' });

            headers.append('Access-Control-Allow-Origin','*');
            let options = new RequestOptions({ headers: headers });

            return this.http.post(this._baseUrl + '/api/Inspect/ListI',body,options)
                .map((res: Response) => {
                    this.inspections = res.json();
                    return this.inspections;
                })
                .catch(this.handleError);
        }
        else {
            //return cached data
            return this.createObservable(this.inspections);
        }
    }

Or can I do this? Just pass header instead of options

getInspections(): Observable<IInspection[]> {
        if (!this.inspections) {
            let body =JSON.stringify({"Statuses":["Submitted", "Opened"]});
            let headers = new Headers({ 'Content-Type': 'application/json' });

            //headers.append('Access-Control-Allow-Origin','*');
          //  let options = new RequestOptions({ headers:headers });

            return this.http.post(this._baseUrl + '/api/Inspect/ListI',body,headers)
                .map((res: Response) => {
                    this.inspections = res.json();
                    return this.inspections;
                })
                .catch(this.handleError);
        }
        else {
            //return cached data
            return this.createObservable(this.inspections);
        }
    }

Upvotes: 8

Views: 34684

Answers (2)

Matrim
Matrim

Reputation: 643

When using non-standard headers (json is apparently considered non-standard) then a pre-flight check is carried out to ask if the requested action (in this case 'post') can be carried out. Only the server can respond with the permissive headers. How you respond does depend on your server language. In my webapi2 I implement cors in the WebAppConfig

 var cors = new EnableCorsAttribute("http://localhost:3000", "*", "GET, HEAD, OPTIONS, POST, PUT");
        cors.SupportsCredentials = true;
        config.EnableCors(cors);

Note for a live server you would replace the localhost ref with a web configed list ( or specific location where the caller resides). The SupportsCredentials is only needed if you are using authentication.

To handle the pre-flight I added a method to Globals.asax which just intercepts pre-flight messages and returns enough data for the post to move ahead.

protected void Application_BeginRequest()
    {
        if (Request.Headers.AllKeys.Contains("Origin") && Request.HttpMethod == "OPTIONS")
        {
            var origin = HttpContext.Current.Request.Headers["Origin"];

            Response.Headers.Add("Access-Control-Allow-Origin", origin);
            Response.Headers.Add("Access-Control-Allow-Headers", "content-type, withcredentials, Access-Control-Allow-Headers, Origin,Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers");
            Response.Headers.Add("Access-Control-Allow-Credentials", "true");
            Response.Headers.Add("Access-Control-Allow-Methods", "GET, HEAD, OPTIONS, POST, PUT");

            Response.Flush();
        }
    }

Note here that I am cheating somewhat by reflecting the origin back - this is not safe in a production environment and should list the specific servers otherwise you are being too loose with security.

Be aware that there are some dev cheats. - If you run on internet explorer on localhost (for dev purposes) then ie ignores the port which most other browsers do not so making things easier. There is also a CORS enhancement for Chrome which adds the headers for you. Finally you will see a lot of code that uses '*' returns (to permit all) - by all means use them to get the code working but before release lock these down far more aggressively.

Upvotes: 3

G&#252;nter Z&#246;chbauer
G&#252;nter Z&#246;chbauer

Reputation: 657318

CORS headers like

headers.append('Access-Control-Allow-Origin','*');

need to be provided by the server. Adding them on the client is pointless.

Upvotes: 11

Related Questions