2

I was getting a CORS error when calling an endpoint, see error below:

XMLHttpRequest cannot load http://domain.com/v1/airtime. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://domain.com' is therefore not allowed access. The response had HTTP status code 404.

I added Header set Access-Control-Allow-Origin "*" in the .htaccess file in the API root folder. The error disappeared and was replaced with the one below:

XMLHttpRequest cannot load domain/v1/airtime. Response for preflight has invalid HTTP status code 404

Every other solutions I sought could not resolve the issue. What can I do to handle the preflight error?

Below is the code which I used to solve CORS in the BaseController but seems it is not enough and I am still getting preflight error.

    // add CORS filter
    $behaviors['corsFilter'] = [
        'class' => Cors::className(),
        'cors' => [
            // restrict access to
            'Origin' => ['*'],
            'Access-Control-Request-Method' => ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS'],
            // Allow only POST and PUT methods
            'Access-Control-Request-Headers' => ['*'],
            // Allow only headers 'X-Wsse'
            'Access-Control-Allow-Credentials' => true,
            // Allow OPTIONS caching
            'Access-Control-Max-Age' => 86400,
            // Allow the X-Pagination-Current-Page header to be exposed to the browser.
            'Access-Control-Expose-Headers' => [],
    ];`

My proxy.conf.json file has the content below:

{ "/api": { "target": "http://domain.com/v1", "secure": false, "pathRewrite" : {"^api" : ""} } }

  • Either set header `Access-Control-Allow-Origin` to `*` on your server side (yii), or use a **proxy** in your angular2 application. http://stackoverflow.com/questions/36002493/no-access-control-allow-origin-header-in-angular-2-app – briosheje Jan 12 '17 at 17:15
  • I have set header Access-Control-Allow-Origin "*" in yii as stated in my question. The proxy too seems not to work as I am still getting a 404. – Ayotunde Salako Jan 13 '17 at 08:39
  • Are you sure you are pointing the correct URL with the correct port? 404 is page not found or resource not found. Can you please post your proxy configuration in angular2? – briosheje Jan 13 '17 at 10:25
  • I have added my proxy.conf.json content to the question. – Ayotunde Salako Jan 13 '17 at 10:39
  • If I test with postman it works but it doesn't work on the browser. The API is hosted on EC2 Ubuntu Instance. – Ayotunde Salako Jan 13 '17 at 10:50
  • it is good that it works with postman - reassuring - however, postman WILL NOT do a preflight OPTIONS request BUT the browser will - The preflight check is to ensure that your Access CORS headers are OK - If they are all OK then the browser will make the GET / POST - If not then it will not - This is why I want you to check your headers in postman, it seems like you do not have all the response headers you should have .. where is your Access-Control-Request-Method in the response? – danday74 Jan 13 '17 at 12:39
  • @danday74 I added: 'Access-Control-Request-Method' => ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS'], to the .htaccess file and I got this error: XMLHttpRequest cannot load http://domain.com/v1/airtime. Response for preflight has invalid HTTP status code 404 – Ayotunde Salako Jan 13 '17 at 12:44
  • Wait, you should set **Access-Control-Allow-Methods** on your server side, not **Access-Control-Request-Method**, also, it should be **Access-Control-Allow-Headers**. Both these headers are used to respond to a Preflight request, check here: https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#Access-Control-Request-Headers – briosheje Jan 13 '17 at 13:30
  • @briosheje please see my .htaccess rules to solve preflight: Header set Access-Control-Allow-Origin "*" Header set Access-Control-Allow-Methods "GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS" Header set Access-Control-Allow-Headers "Authorization" The rules set in the API can be seen in my question above. – Ayotunde Salako Jan 13 '17 at 13:59
  • i understand they are in your code BUT ARE THEY IN YOUR HTTP RESPONSE HEADERS when postman makes a request? – danday74 Jan 13 '17 at 15:13
  • Appears like they are not in my response headers. This is what postman returned: Access-Control-Allow-Credentials →true Access-Control-Allow-Origin →* Access-Control-Expose-Headers → Connection →close Content-Length →65 Content-Type →application/json; charset=UTF-8 Date →Fri, 13 Jan 2017 12:05:38 GMT Server →Apache/2.4.18 (Ubuntu) – Ayotunde Salako Jan 13 '17 at 19:31
  • Possible duplicate of [Post Request working in Postman but returns Preflight error in Angular 2 app](https://stackoverflow.com/questions/41633212/post-request-working-in-postman-but-returns-preflight-error-in-angular-2-app) – Salem Ouerdani Jan 13 '18 at 06:11

2 Answers2

0

its a 404 page or resource not found. Does the resource exist? You got the request URL and method right?

Do you allow the preflight OPTIONS method? Ensure this is an allowed CORS method.

When you request to that URL outside of Angular2 does it work (e.g. using GET / POST in postman)? If no, then fix that first.

danday74
  • 52,471
  • 49
  • 232
  • 283
  • I allowed the preflight OPTIONS method and GET / POST works in postman. – Ayotunde Salako Jan 13 '17 at 10:52
  • ok good sounds like you asre getting close, can you check the response headers in postman, do you see your CORS (Access) headers in the response headers? – danday74 Jan 13 '17 at 10:56
  • please see below what is in the response headers: `Access-Control-Allow-Credentials →true Access-Control-Allow-Origin →* Access-Control-Expose-Headers → Connection →close Content-Length →65 Content-Type →application/json; charset=UTF-8 Date →Fri, 13 Jan 2017 12:05:38 GMT Server →Apache/2.4.18 (Ubuntu)` – Ayotunde Salako Jan 13 '17 at 12:09
  • i cant see Access-Control-Request-Method in there but it is in your code? – danday74 Jan 13 '17 at 12:17
  • Yes it is in my code. 'Access-Control-Request-Method' => ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS'], – Ayotunde Salako Jan 13 '17 at 12:43
0

I am assuming you have this same Issue:

In certain cases a browser will automatically perform a preflight request to check the list of allowed methods or verbs before actually sending the reel one. You can see those within your browser's network tab. I guess in Postman you are directly sending the POST request while the pre-sent OPTIONS request should be the failing one.

Yii has a built-in action which is defined under the ActiveController class to respond to such requests. But in your case you are directly extending its parent controller instead so you'll need to manually define a similar action inside your controllers (or a parent one to them) responding to preflight requests:

Add this to your base controller

public function actionOptions() 
{
if (Yii::$app->getRequest()->getMethod() !== 'OPTIONS') {
    Yii::$app->getResponse()->setStatusCode(405);
}

$allowed_verbs = ['GET', 'POST', 'HEAD', 'OPTIONS'];
Yii::$app->getResponse()->getHeaders()->set('Allow', implode(', ', $allowed_verbs));
}

Also; as you are not using the built-in routing mechanism for REST; in your case you'll also need to manually define rules to that Options action: (edited version of the code from your comments)

'urlManager' => [ 
'enablePrettyUrl' => true,
'enableStrictParsing' => true,
'showScriptName' => false,
'rules' => [ 
    'POST <version:[\w-]+>/users/verify' => '<version>/user',

    // OPTTIONS URI ENDPOINTS
    'OPTIONS <version:[\w-]+>/users/verify' => '<version>/user',
],
];
Tiwa Babalola
  • 265
  • 5
  • 10