Ionic can't get open cors

2019-06-09 11:59发布

问题:

I am trying to get API data from live server in ionic android app but it returns this error:

Access to XMLHttpRequest at 'https://example.com/api/categories/' from origin 'http://192.168.43.71:8100' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

Server settings

Now I am using Laravel for live server which is giving the API here is how I set CORS in my laravel application:

/bootstrap/app.php

<?php
    header('Access-Control-Allow-Origin: *');
    header('Access-Control-Allow-Methods: GET');
    header('Access-Control-Allow-Headers: *');
    // rest of the file

due to my setup above I'm getting this result on CORS tester

Ionic settings

So I've been reading how to solve this issue and came cross lots of similar solutions and this is what I add to my ionic.config.json file

"proxies": [
    {
      "path": "/api/*",
      "proxyUrl": "https://example.com/api/"
    }
  ]

Get request (ionic services)

Here is how I request my get method

apiUrl = 'https://example.com/api/categories/';
  constructor(private http: HttpClient) { }

  getCategories(): Observable<any> {
    return this.http.get(`${this.apiUrl}`).pipe(
      map(categories => categories)
    );
  }

Any idea what else should I do to fix this issue?

回答1:

I solved my issue using these Headers for my API:

header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Credentials: true ");
header("Access-Control-Allow-Methods:GET,POST");
header("Access-Control-Allow-Headers: Authorization, Content-Type, Depth, User-Agent, X-File-Size, X-Requested-With, If-Modified-Since, X-File-Name, Cache-Control");

And Angular Http:

//GET data details
 getData(authToken){
      const httpOptions = {
          headers: new HttpHeaders({
              'Accept': 'application/json, text/plain',
              'Content-Type':  'application/json',
              'Authorization': authToken
            })
   };
   //console.log(authToken);
   return this.http.get(this.apiGetUrl, httpOptions).retry(3);
 }
Like the previous answer, an Options request automatically gets sent with the GET or POST. If you have apache servers, you can echo$headers = apache_request_headers(); to see what is all coming through. Comparison for $_SERVER and Apache here.

In my case, I run if statements:

if(isset($headers["Authorization"]) && isset($headers["Content-Type"])){
  //handle get request
  }
else{
  //handle options request
   echo " False,Re-routing Options Request";
  }

I would test your HTTP call in the browser and look at dev tools to confirm the requests being sent. I hope this helps!



回答2:

SOLVED

Thanks to Stephen Romero for pointing the important part of this solution,

based on stephen answer I added this code to my function:

const httpOptions = {
      headers: new HttpHeaders({
        'Accept': 'application/json, text/plain',
        'Content-Type': 'application/json'
      })
    };

and used it in my get request like:

return this.http.get(`${this.apiUrl}`, httpOptions).pipe(

Now the for header permissions I used (installed) this package for on my laravel app and made config file set as code below:

return [
    /*
    |--------------------------------------------------------------------------
    | Laravel CORS
    |--------------------------------------------------------------------------
    |
    | allowedOrigins, allowedHeaders and allowedMethods can be set to array('*')
    | to accept any value.
    |
    */

    'supportsCredentials' => false,
    'allowedOrigins' => ['*'],
    'allowedOriginsPatterns' => [],
    'allowedHeaders' => ['*'],
    'allowedMethods' => ['GET', 'OPTIONS'],
    'exposedHeaders' => [],
    'maxAge' => 0,

];

FOR those who doesn't use Laravel

Set your headers like this:

if($request_method = 'GET'){
    header('Access-Control-Allow-Origin: *');
    header('Access-Control-Allow-Methods: GET, OPTIONS');
    header('Access-Control-Allow-Headers: Authorization, Expires, Pragma, DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range');
    header("Access-Control-Expose-Headers: *");
}

The most important part of this headers is Access-Control-Allow-Headers part, if you simply use * it won't work! you need to set headers name.

Hope it helps.

Update

Forgot to mention in order to avoid error 301 you need to remove / from end of your api url.

// my api (before)
https://example.com/api/categories/

//changed to
https://example.com/api/categories


回答3:

Perhaps at some point a preflight OPTIONS request is done by the client and since it isn't a listed method in your Access-Control-Allow-Methods it ends up in a CORS issue.

You should try to make a request to your server endpoint with OPTIONS method to check if this is the case, you can use POSTMAN to make this test.

Then try to add the OPTIONS method to the Access-Control-Allow-Methods and check the difference.