Yii Framework Forum: OPTIONS REQUEST : Preflight error in angular2 and Yii2 application - Yii Framework Forum

Jump to content

Page 1 of 1
  • You cannot start a new topic
  • You cannot reply to this topic

OPTIONS REQUEST : Preflight error in angular2 and Yii2 application

#1 User is offline   yiilover 

  • Newbie
  • Yii
  • Group: Members
  • Posts: 15
  • Joined: 09-October 13

Posted 10 November 2017 - 09:39 AM

Hi All,

I have been searching the internet for the past week for a bug that I'm currently experiencing, and no luck. the best description that I can find is this one.

(Add handleOptions to Cors filter so OPTIONS requests are handled for the preflight check. #14618).


I'm using angular2 to make a post request to a Yii2 Rest API, the problem that I'm expereining is that the browser send an OPTIONS request first and when it does that , YII2 doesn't know how to handle it and send back 401 error with a preflight


Request URL:http://localhost/analytic/backend/web/v1/api/test
Request Method:OPTIONS
Status Code:401 Unauthorized
Remote Address:[::1]:80
Referrer Policy:no-referrer-when-downgrade
Response Headers
view parsed






zone.js:2744 OPTIONS http://localhost/analytic/backend/web/v1/api/test 401 (Unauthorized)
dashboard:1 Failed to load http://localhost/analytic/backend/web/v1/api/test: Response for preflight has invalid HTTP status code 401



I looked at the Yii2 documentation and have implemented CORS as follow.



use yii\rest\Controller;
use yii\filters\auth\HttpBearerAuth;

/**
 * Site controller
 */
class ApiController extends Controller
{

      public function behaviors()
    {
        $behaviors = parent::behaviors();
        $behaviors['contentNegotiator'] = [
            'class' => ContentNegotiator::className(),
            'formats' => [
                'application/json' => Response::FORMAT_JSON,
            ],
        ];
        // remove authentication filter
        $auth = $behaviors['authenticator'];
        unset($behaviors['authenticator']);
        // add CORS filter
        $behaviors['corsFilter'] = [
        'class' => \yii\filters\Cors::className(),
            ];
        // re-add authentication filter
        $behaviors['authenticator'] = $auth;
        // avoid authentication on CORS-pre-flight requests (HTTP OPTIONS method)
        $behaviors['authenticator']['except'] = ['options'];
        $behaviors['authenticator'] = [
        'class' => HttpBearerAuth::className(),


 ];

        return $behaviors;
    }


}




I am able to authenticate fine if I commented out 'HttpBearerAuth::className()' do a post through angular, then uncomment that line then do another post.

example.


          // $behaviors['authenticator'] = [
        // 'class' => HttpBearerAuth::className(),
        //     ];


Post through angular, then uncomment those lines.

        $behaviors['authenticator'] = [
        'class' => HttpBearerAuth::className(),
            ];


the reason why it works when I do that is that the browser sends all following request as POST and not OPTIONS.



Moreover, when I perform the same request with POSTMAN, it works fine with no issues and that's because POSTMAN sends it as a POST request.



Any help is appreciated. thank you
0

#2 User is offline   yiilover 

  • Newbie
  • Yii
  • Group: Members
  • Posts: 15
  • Joined: 09-October 13

Posted 10 November 2017 - 08:15 PM

I figured it out and in case someone had the same issue as me, here is how to go about it.


Create a custom CORS


<?php
namespace common\helpers;

use Yii;
use yii\filters\Cors;

class CorsCustom extends Cors

{
    public function beforeAction($action)
    {
        parent::beforeAction($action);

        if (Yii::$app->getRequest()->getMethod() === 'OPTIONS') {
            Yii::$app->getResponse()->getHeaders()->set('Allow', 'POST GET PUT');
            Yii::$app->end();
        }

        return true;
    }
}



use it in your REST API controller.


   public function behaviors()
    {
        $behaviors = parent::behaviors();
        $behaviors['contentNegotiator'] = [
            'class' => ContentNegotiator::className(),
            'formats' => [
                'application/json' => Response::FORMAT_JSON,
            ],
        ];
        // remove authentication filter
        $auth = $behaviors['authenticator'];
        unset($behaviors['authenticator']);
        // add CORS filter
        $behaviors['corsFilter'] = [
        'class' => CorsCustom::className(),
            ];
        // re-add authentication filter
        $behaviors['authenticator'] = $auth;
        // avoid authentication on CORS-pre-flight requests (HTTP OPTIONS method)
        $behaviors['authenticator']['except'] = ['options'];
        $behaviors['authenticator'] = [
        'class' => HttpBearerAuth::className(),
        'except'=>['login']
            ];

        return $behaviors;
    }

0

Share this topic:


Page 1 of 1
  • You cannot start a new topic
  • You cannot reply to this topic

1 User(s) are reading this topic
0 members, 1 guests, 0 anonymous users