117

I have added the CORS in header but I am still getting the CORS issue in my request. What is the correct way to add and handle CORS and other requests in the headers?

Here is service file code:

import { HttpClient, HttpHeaders, HttpClientModule } from '@angular/common/http';
const httpOptions = {
  headers: new HttpHeaders({ 
    'Access-Control-Allow-Origin':'*',
    'Authorization':'authkey',
    'userid':'1'
  })
};

public baseurl = 'http://localhost/XXXXXX';

userAPI(data): Observable<any> {
  return this.http.post(this.baseurl, data, httpOptions)
    .pipe(
      tap((result) => console.log('result-->',result)),
      catchError(this.handleError('error', []))
    );
}

Error:

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:4200' is therefore not allowed access

failed: Http failure response for (unknown url): 0 Unknown Error

In my server-side code, I've added CORS in the index file.

header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET, POST, PATCH, PUT, DELETE, OPTIONS');
header('Access-Control-Allow-Headers: Origin, Content-Type, X-Auth-Token');
Troy Alford
  • 26,660
  • 10
  • 64
  • 82
Aman Kumar
  • 1,572
  • 4
  • 17
  • 25

8 Answers8

57

In my experience the plugins worked with HTTP but not with the latest httpClient. Also, configuring the CORS response headers on the server wasn't really an option. So, I created a proxy.conf.json file to act as a proxy server. This is for development purposes only.

Read more about this here.

proxy.conf.json file:

{
  "/posts": {
    "target": "https://example.com",
    "secure": true,
    "pathRewrite": {
    "^/posts": ""
  },
    "changeOrigin": true
  }
}

I placed the proxy.conf.json file right next the the package.json file in the same directory.

Then I modified the start command in the package.json file:

"start": "ng serve --proxy-config proxy.conf.json"

The HTTP call from my app component:

return this._http.get('/posts/pictures?method=GetPictures')
.subscribe((returnedStuff) => {
  console.log(returnedStuff);
});

Lastly to run my app, I'd have to use npm start or ng serve --proxy-config proxy.conf.json

rgantla
  • 1,926
  • 10
  • 16
  • 31
    It works just for development purposes. You can't build your app with that proxy tool – Vladlen Gladis Jul 10 '18 at 14:02
  • Could someone here please have a look at the question at https://stackoverflow.com/questions/55429787/proxy-to-multiple-paths-angular?noredirect=1#comment97578761_55429787 – Kingsley Mar 30 '19 at 13:19
  • what should we set the `target` as in the proxy.config file? – A-Sharabiani Sep 13 '19 at 14:56
  • i tied it showing status ok but now getting new error. `HttpErrorResponse {headers: HttpHeaders, status: 200, statusText: "OK", url: "http://localhost:4200/", ok: false, …} error: SyntaxError: Unexpected token < in JSON at position 0 at JSON.parse () message: "Unexpected token < in JSON at position 0" " ` – Aman Gupta Sep 13 '19 at 19:23
  • 9
    this doesn't work in production builds, so it can't be a proper solution – Aaron Matthews Dec 01 '19 at 17:08
  • Some updated link to the setup of the proxy.conf.json file : https://angular.io/guide/build#proxying-to-a-backend-server – Wasabi May 05 '21 at 12:05
  • This doesn't help at all – Alberto Alegria Dec 19 '22 at 09:22
11

You can also try the fetch function and the no-cors mode. I sometimes find it easier to configure it than Angular's built-in http module. You can right-click requests in the Chrome Dev tools network tab and copy them in the fetch syntax, which is great.

import { from } from 'rxjs';

// ...

result = from( // wrap the fetch in a from if you need an rxjs Observable
  fetch(
    this.baseurl,
    {
      body: JSON.stringify(data)
      headers: {
        'Content-Type': 'application/json',
      },
      method: 'POST',
      mode: 'no-cors'
    }
  )
);
metakermit
  • 21,267
  • 15
  • 86
  • 95
  • 1
    The code in the question is trying to *read* the response. `no-cors` blocks that. It also blocks setting the content-type to `application/json`. – Quentin Aug 27 '19 at 13:48
  • Very specific case, for https://api.github.com/orgs/nesign/repos, I saw `Access to XMLHttpRequest at '..' from origin '..' has been blocked by CORS policy: Request header field x-timezone is not allowed by Access-Control-Allow-Headers in preflight response.` unable to override `Access-Control-Request-Headers: cache-control,x-timezone` which got added by default :( and Github has this in response `Access-Control-Allow-Headers: Authorization, Content-Type, If-Match, If-Modified-Since, If-None-Match, If-Unmodified-Since, Accept-Encoding, X-GitHub-OTP, X-Requested-With, User-Agent` fetch worked – Anand Rockzz Sep 05 '19 at 04:47
  • Oops! x-timezone was added by me - I had _over engineered_ the `httpclient` with an interceptor long time back :) – Anand Rockzz Sep 05 '19 at 05:06
  • Thank you for the mode parameter. I have an app that sends an api request to a local computer and prints labels. The angular app is in the cloud so using a proxy is not possible because the request has to come from inside the network. – Kyle Waid Apr 14 '21 at 14:02
7

If you are like me and you are using a local SMS Gateway server and you make a GET request to an IP like 192.168.0.xx you will get for sure CORS error.

Unfortunately I could not find an Angular solution, but with the help of a previous replay I got my solution and I am posting an updated version for Angular 7 8 9

import {from} from 'rxjs';

getData(): Observable<any> {
    return from(
      fetch(
        'http://xxxxx', // the url you are trying to access
        {
          headers: {
            'Content-Type': 'application/json',
          },
          method: 'GET', // GET, POST, PUT, DELETE
          mode: 'no-cors' // the most important option
        }
      ));
  }

Just .subscribe like the usual.

Avram Virgil
  • 1,170
  • 11
  • 22
3

Make the header looks like this for HttpClient in NG5:

let httpOptions = {
      headers: new HttpHeaders({
        'Content-Type': 'application/json',
        'apikey': this.apikey,
        'appkey': this.appkey,
      }),
      params: new HttpParams().set('program_id', this.program_id)
    };

You will be able to make api call with your localhost url, it works for me ..

  • Please never forget your params columnd in the header: such as params: new HttpParams().set('program_id', this.program_id)
Damon Wu
  • 57
  • 4
2

A POST with httpClient in Angular 6 was also doing an OPTIONS request:

Headers General:

Request URL:https://hp-probook/perl-bin/muziek.pl/=/postData
Request Method:OPTIONS
Status Code:200 OK
Remote Address:127.0.0.1:443
Referrer Policy:no-referrer-when-downgrade

My Perl REST server implements the OPTIONS request with return code 200.

The next POST request Header:

Accept:*/*
Accept-Encoding:gzip, deflate, br
Accept-Language:nl-NL,nl;q=0.8,en-US;q=0.6,en;q=0.4
Access-Control-Request-Headers:content-type
Access-Control-Request-Method:POST
Connection:keep-alive
Host:hp-probook
Origin:http://localhost:4200
Referer:http://localhost:4200/
User-Agent:Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.109 Safari/537.36

Notice Access-Control-Request-Headers:content-type.

So, my backend perl script uses the following headers:

 -"Access-Control-Allow-Origin" => '*',
 -"Access-Control-Allow-Methods" => 'GET,POST,PATCH,DELETE,PUT,OPTIONS',
 -"Access-Control-Allow-Headers" => 'Origin, Content-Type, X-Auth-Token, content-type',

With this setup the GET and POST worked for me!

SwissCodeMen
  • 4,222
  • 8
  • 24
  • 34
Rob Lassche
  • 841
  • 10
  • 16
1

please import requestoptions from angular cors

import {RequestOptions, Request, Headers } from '@angular/http';

and add request options in your code like given below

let requestOptions = new RequestOptions({ headers:null, withCredentials: 
    true });

send request option in your api request

code snippet below-

 let requestOptions = new RequestOptions({ headers:null, 
     withCredentials: true });
     return this.http.get(this.config.baseUrl + 
     this.config.getDropDownListForProject, requestOptions)
     .map(res => 
     {
      if(res != null)
      { 
        return res.json();
        //return true;
      }
    })
  .catch(this.handleError);

}

and add CORS in your backend PHP code where all api request will land first.

try this and let me know if it is working or not i had a same issue i was adding CORS from angular5 that was not working then i added CORS to backend and it worked for me

SwissCodeMen
  • 4,222
  • 8
  • 24
  • 34
raj yadav
  • 204
  • 3
  • 10
0

add this comment in your API file

header('Access-Control-Allow-Origin: *');
header("Access-Control-Allow-Headers: X-API-KEY, Origin, X-Requested-With, Content-Type, Accept, Access-Control-Request-Method, Authorization");
header("Access-Control-Allow-Methods: GET, POST, OPTIONS, PUT, DELETE, PATCH");

I've tried to implement these solutions to add CORS header response to Laravel to my project but I still have not had any success:

https://github.com/barryvdh/laravel-cors

https://github.com/spatie/laravel-cors

I'm hoping that someone has encountered a similar issue and can help.

-8

The following worked for me after hours of trying

      $http.post("http://localhost:8080/yourresource", parameter, {headers: 
      {'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*' } }).

However following code did not work, I am unclear as to why, hopefully someone can improve this answer.

          $http({   method: 'POST', url: "http://localhost:8080/yourresource", 
                    parameter, 
                    headers: {'Content-Type': 'application/json', 
                              'Access-Control-Allow-Origin': '*',
                              'Access-Control-Allow-Methods': 'POST'} 
                })
MG Developer
  • 859
  • 11
  • 17