Cors policy error when use Angular 7 post on ionic 4

abdullah picture abdullah · Aug 18, 2019 · Viewed 10.2k times · Source

I'm upset to post similar problem but spend more than 3 days and couldn't solve the problem.

Platform: Ionic 4 Angular 7

When I try to Post I have cors policy Error.

Access to XMLHttpRequest at 'https://mersinders.com/api/service.php?run=giris' from origin 'http://localhost:8100' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status.

When I disable chrome security everything works fine.

"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" --disable-web-security --disable-gpu --user-data-dir=~/chromeTemp

HttpErrorResponse {headers: HttpHeaders, status: 400, statusText: "Bad Request", url: "https://mersinders.com/api/service.php?run=giris", ok: false, …}

The problem start after using below header on Php api side.

header('Status: 400', TRUE, 400); header('Status: 404', TRUE, 404);

I have config.ini.php which include db informations and connections, And service.php which switch case "service.php?run=XXXXX" .

When I set header in service.php

header('Access-Control-Allow-Origin: *');
header("Access-Control-Allow-Credentials: true");
header('Access-Control-Allow-Methods: GET, PUT, POST, DELETE, OPTIONS'); header('Access-Control-Max-Age: 1000');
header('Access-Control-Allow-Headers: Content-Type, Content-Range, Content-Disposition, Content-Description');

include('config.ini.php');

I get below error.

Access to XMLHttpRequest at 'https://mersinders.com/api/service.php?run=giris' from origin 'http://localhost:8100' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.

When I set header in .htaccess

Header always set Access-Control-Allow-Origin "*" Header always set Access-Control-Allow-Methods "POST, GET,HEAD" Header always set Access-Control-Max-Age "1000"

I get below error.

Access to XMLHttpRequest at 'https://mersinders.com/api/service.php?run=giris' from origin 'http://localhost:8100' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status.

But Everything works fine on security disabled chrome and postman. Also I tried

proxy.config.json

{
    "/api/*": {
        "target": "https://mersinders.com",
        "secure": false,
        "logLevel": "debug"

    }
}

and ionic.config.json

{
    "name": "mersinders",
    "integrations": {
        "cordova": {}
    },
    "type": "angular",
    "proxies": [{
        "path": "/api/*",
        "proxyUrl": "https://mersinders.com"
    }]
}

and tsconfig.app.json

{
  "extends": "../tsconfig.json",
  "compilerOptions": {
    "outDir": "../out-tsc/app",
    "types": []
  },
  "exclude": [
    "test.ts",
    "**/*.spec.ts"
  ],
  "proxies": [
    {
      "path": "/api/*",
      "proxyUrl": "https://mersinders.com"
    }
  ]
}

My post function

 var headers = new HttpHeaders();
    headers.append("Accept", 'application/json');
    headers.append('Content-Type', 'application/json');
    headers.append('Access-Control-Allow-Origin', '*');

    let postData = {
      "username": this.userData.username,
      "password": this.userData.password,
      "clientIp": this.cekIp(),

    }
    console.log(postData);
    this.http.post(environment.SERVER_URL + "service.php?run=giris", postData,{ headers:headers, observe: 'response' })
      .subscribe(response => {
        if (response.status == 200 && response.body[0].ogretmen_token != "") {
          this.isUser.token = response.body[0].ogretmen_token;
          en_isUser.Loggedin = true;
          en_isUser.token = this.isUser.token;
          en_isUser.guid = this.isUser.guid;
          this.status.girisCode = response.status;
          //   this.storage.set('token',this.isUser.token);
          window.localStorage.setItem('token', this.isUser.token);
          this.router.navigate(['/tabs/anasayfa']);
        }
        console.log(this.isUser.token);
      }, error => {
        this.status.girisCode = error.status;
        this.isUpdated = error.error;
        console.log(error);
      });

Question 1) How can We solve cors policy error. And why my headers works only in .htaccess .

Post work with ionic 4 native http but I want to use Angular 7 Http. Thanks for advices.

Edit: When I check logs in server I saw; AH01623: client method denied by server configuration: 'OPTIONS' ,

And I used Postman to check if any problem. I saw that When I post data from chrome it seems "POST" in postman but at server it is OPTIONS and blocked.

Edit1: After more try I saw that https://cors-anywhere.herokuapp.com/ convert OPTIONS request to POST request that is why it work on chrome.

And I tried to make OPTIONS request via postman and it is failed(405 Not Allowed). but POST request from Postman success. It seems backend problem . Could someone help why headers works in htaccess but not work in service.php file(Possible?: option method can reach .htaccess and after that server drop that request ? ).

Answer

abdullah picture abdullah · Aug 19, 2019

I spent more than 3 days to solve cors problem and finally it is solved. The problem was OPTIONS not allowed in httpd conf file. I followed below steps.

In this time period I faced with.

error 1) Which means you didn't add header("Access-Control-Allow-Origin: *"); to service.php file

Access to XMLHttpRequest at 'https://mersinders.com/api/service.php?run=giris' from origin 'http://localhost:8100' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

error 2) Which means "You post something but before posting we want to check security if server doesnt return us status:200 we will not post your request".

Access to XMLHttpRequest at 'https://mersinders.com/api/service.php?run=giris' from origin 'http://localhost:8100' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status.

finally I have below headers for service.php

if (isset($_SERVER['HTTP_ORIGIN'])) {

    header("Access-Control-Allow-Origin: {$_SERVER['HTTP_ORIGIN']}");
    header('Access-Control-Allow-Credentials: true');
    header('Access-Control-Max-Age: 86400');    // cache for 1 day
}

// Access-Control headers are received during OPTIONS requests
if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') {

    if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD']))
        // may also be using PUT, PATCH, HEAD etc
        header("Access-Control-Allow-Methods: GET, POST, OPTIONS");         

    if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']))
        header("Access-Control-Allow-Headers: {$_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']}");

    exit(0);
}

Post function

send(){
 var headers = new HttpHeaders();
    headers.append("Accept", 'application/json');
    headers.append('Content-Type', 'application/json');
    headers.append('Access-Control-Allow-Origin', '*');

    let postData = {
      "username": this.userData.username,
      "password": this.userData.password,
      "clientIp": this.cekIp(),

    }
    console.log(postData);
    this.http.post(environment.SERVER_URL + "service.php?run=giris", postData,{ headers:headers, observe: 'response' })
      .subscribe(response => {
        console.log(response);
      }, error => {

        console.log(error);
      });

}

And nothing in htaccess.

Please follow server logs while you are trying to fix this problem. I wanted to explain it for someone not spend much time as I spent.