I want use React with Yii2 RESTful, i created a users controller like this:
<?php
namespace app\controllers;
use yii\rest\ActiveController;
class UsersController extends ActiveController
{
public $modelClass = 'app\models\User';
}
when open link in browser show my users, when i want use axios
in react, i get error i browser console:
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://localhost/rest/web/users. (Reason: CORS header ‘Access-Control-Allow-Origin’ missing).
but when i check network
in firefox developer tools, i find axios request and it status in 200 and recievies the response correctly.
i try use behaviors
function in my controllers, like this:
public function behaviors()
{
return [
'corsFilter' => [
'class' => \yii\filters\Cors::className(),
'cors' => [
'Origin' => ['*'],
'Access-Control-Request-Method' => ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS'],
'Access-Control-Request-Headers' => ['*'],
],
],
];
}
but get error
Invalid Argument – yii\base\InvalidArgumentException Response content
must not be an array.
how i can fix this?
Update
Updated the answer as the logic implemented was allowing every request to by pass the authentication filters (Thanks to @KalyanHalderRaaz
for pointing out the bug).
There are two things to change
When re-adding the filters it is better to specify which auth you are using.
change the code below
// re-add authentication filter
$behaviors['authenticator'] = $auth;
to the following, i am using BasicAuth
for example.
$behaviors['authenticator'] = [
'class' => yii\filters\auth\HttpBasicAuth::class
];
When adding a beforeAction()
dont forget to wrap the logic in if(parent::beforeAction($action))
otherwise it would authenticate every request as we are just returning true
for every request here and also not calling the parent which would trigger the filters.
Replace the beforeAction()
with the following
public function beforeAction($action)
{
if (parent::beforeAction($action)) {
\Yii::$app->response->format = Response::FORMAT_JSON;
return true;
}
}
Just make sure you are overriding the findIdentityByAccessToken()
in the User identity model
According to docs you should first unset the authenticator
filter in order to add the Cors
filter, so your behavior should look like
public function behaviors() {
$behaviors = parent::behaviors();
// remove authentication filter necessary because we need to
// add CORS filter and it should be added after the CORS
unset($behaviors['authenticator']);
// add CORS filter
$behaviors['corsFilter'] = [
'class' => '\yii\filters\Cors',
'cors' => [
'Origin' => ['*'],
'Access-Control-Request-Method' => ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS'],
'Access-Control-Request-Headers' => ['*'],
],
];
// re-add authentication filter of your choce
$behaviors['authenticator'] = [
'class' => yii\filters\auth\HttpBasicAuth::class
];
// avoid authentication on CORS-pre-flight requests (HTTP OPTIONS method)
$behaviors['authenticator']['except'] = ['options'];
return $behaviors;
}
And you can set the response format to json inside your controller by adding the beforeAction
like below
public function beforeAction($action)
{
if (parent::beforeAction($action)) {
\Yii::$app->response->format = Response::FORMAT_JSON;
return true;
}
}