0

I am building an API with Yii2 and have enabled the CORS filter to handle requests from a web frontend which is working.

However because of the pre-flight OPTIONS request and then the real POST request I am getting two records added to the database, one for each request. I would have thought that Yii should accept the OPTIONS request, return the correct headers and then exit. Why does it actually process the full request?

I am working around this for now by adding this to the top of the controller action:

if(Yii::$app->request->getMethod() == 'OPTIONS') {
    return;
}

Is that the best approach or am I missing something?

Dubby
  • 2,290
  • 4
  • 27
  • 38
  • in CORS you should use `'Access-Control-Request-Headers' => ['Expiry']` in order to continue your algorithm. – Touqeer Shafi Mar 01 '16 at 09:50
  • how is your `urlManager::rules` configured ? and how did you set your CORS filter ? by default `yii\rest\UrlRule` will redirect any OPTIONS verb to `yii\rest\OptionsAction` which role is only deliver a list of accepted verbs. So with default configs it is impossible that an OPTIONS verb is treated as POST. Maybe a wrong OPTIONS answer is making the front resending the POST request. show more code please and check in your browser's network tab the ordered list of the sent requests. – Salem Ouerdani Mar 13 '16 at 12:38
  • This doesn't seem to be an issue anymore. Later versions of Yii will exit the script once the CORS headers have been sent. – Dubby Mar 14 '16 at 23:04

1 Answers1

0

That should be wrong because a browser need the options response to know the allowed list of verbs he can send. Otherwise a 401 error may be raised. Its source code can be seen here:

class OptionsAction extends \yii\base\Action
{
    public $collectionOptions = ['GET', 'POST', 'HEAD', 'OPTIONS'];
    public $resourceOptions = ['GET', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS'];

    public function run($id = null)
    {
        if (Yii::$app->getRequest()->getMethod() !== 'OPTIONS') {
            Yii::$app->getResponse()->setStatusCode(405);
        }
        $options = $id === null ? $this->collectionOptions : $this->resourceOptions;
        Yii::$app->getResponse()->getHeaders()->set('Allow', implode(', ', $options));
    }
}

And that is all what it does: sending a list of allowed verbs within a response headers.

Maybe the POST request has been sent twice from client script due to unexpected responses. Try to apply the answer I posted in your other question instead. I think it will also solve this:

Yii2 CORS with Auth not working for non CRUD actions.

Community
  • 1
  • 1
Salem Ouerdani
  • 7,596
  • 3
  • 40
  • 52