Reputation: 113
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
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
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