Keep getting the cors issue.
Have already tried the following:
adding code you can see in the image in yii2
have installed the Cors Plugin in firefox
API URL : http://thisisbig.ae/advanced/backend/web/customersapi/update/?id=2
In the back-end ( Yii2 ), needed to override the verbs() function in the controller and add 'OPTIONS' for the 'update' value
protected function verbs()
{
return [
'index' => ['GET', 'HEAD'],
'view' => ['GET', 'HEAD'],
'create' => ['POST'],
'update' => ['PUT', 'PATCH','OPTIONS'],
'delete' => ['DELETE'],
];
}
Use a behavior to define this
public function behaviors()
{
return [
'verbs' => [
'class' => \yii\filters\VerbFilter::className(),
'actions' => [
'index' => ['GET'],
'view' => ['GET'],
'create' => ['GET', 'POST'],
'update' => ['GET', 'PUT', 'POST'],
'delete' => ['POST', 'DELETE'],
],
],
];
}
You can also use CORS filter by attaching it as a behavior to a controller or module, like the following,
public function behaviors()
{
return [
'corsFilter' => [
'class' => \yii\filters\Cors::className(),
],
];
}
you can also use CORS filter to restrict parameters, like this,
public function behaviors()
{
return [
'corsFilter' => [
'class' => \yii\filters\Cors::className(),
'cors' => [
// restrict access to
'Origin' => ['http://www.myserver.com', 'https://www.myserver.com'],
// Allow only POST and PUT methods
'Access-Control-Request-Method' => ['POST', 'PUT'],
// Allow only headers 'X-Wsse'
'Access-Control-Request-Headers' => ['X-Wsse'],
// Allow credentials (cookies, authorization headers, etc.) to be exposed to the browser
'Access-Control-Allow-Credentials' => true,
// Allow OPTIONS caching
'Access-Control-Max-Age' => 3600,
// Allow the X-Pagination-Current-Page header to be exposed to the browser.
'Access-Control-Expose-Headers' => ['X-Pagination-Current-Page'],
],
],
];
}
Related
I have an issue with the CORS header not being added to the response. I'm using the 'cors' from the package \yii\filters\Cors
Basically, I'm doing this :
class ApiController extends ActiveController
{
public function behaviors()
{
return array_merge(parent::behaviors(), [
// For cross-domain AJAX request
'corsFilter' => [
'class' => 'yii\filters\Cors',
'cors' => [
'Origin' => ['*'], // Restrict access to domains
'Access-Control-Max-Age' => 3600, // Cache (seconds)
'Access-Control-Allow-Origin' => true,
'Access-Control-Expose-Headers' => ['*'],
'Access-Control-Request-Headers' => ['*'],
'Access-Control-Allow-Credentials' => true,
'Access-Control-Request-Method' => ['POST', 'HEAD', 'DELETE', 'PUT', 'GET', 'OPTIONS'],
],
],
]);
}
}
And I still have the same result as without applying this method.. No CORS headers are added to the Response of the OPTIONS query to my endpoint.
Anyone else having/had that issue ?
You can try allow origin as well:
public static function allowedDomains()
{
return [
// '*', // star allows all domains
'http://localhost:4200',
];
}
public function behaviors()
{
return array_merge(parent::behaviors(), [
// For cross-domain AJAX request
'verbs' => [
'class' => VerbFilter::className(),
'actions' => [
'stats' => ['GET'],
],
],
'corsFilter' => [
'class' => \yii\filters\Cors::className(),
'cors' => [
// restrict access to domains:
'Origin' => static::allowedDomains(),
'Access-Control-Request-Method' => ['POST', 'GET', 'DELETE', 'PUT', 'OPTIONS'],
'Access-Control-Allow-Credentials' => true,
'Access-Control-Allow-Headers' => ['*'],
'Access-Control-Allow-Origin' => ['*'],
'Access-Control-Max-Age' => 3600, // Cache (seconds)
],
],
]);
}
I want to declare a method actionViewSlug($slug) in ScholarshipController in Yii2 REST api, My method is showing Not Found that too not in REST manner i.e. JSON.
Here is my Url Config for ScholarshipController
[
'class' => 'yii\rest\UrlRule',
'controller' => ['scholarship'],
'extraPatterns' => [
'POST filters' => 'filters',
'GET {slug}' => 'view-slug',
],
'tokens' => [
'{slug}' => '<slug>'
],
],
This is behaviors() function in ScholarshipController
public function behaviors()
{
return [
[
'class' => 'yii\filters\ContentNegotiator',
'only' => ['view', 'index', 'filters', 'view-slug'], // in a controller
// if in a module, use the following IDs for user actions
// 'only' => ['user/view', 'user/index']
'formats' => [
'application/json' => Response::FORMAT_JSON,
],
],
'corsFilter' => [
'class' => \yii\filters\Cors::className(),
'cors' => [
'Origin' => ['*'],
'Access-Control-Request-Method' => ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS'],
'Access-Control-Request-Headers' => ['*'],
'Access-Control-Allow-Credentials' => null,
'Access-Control-Max-Age' => 86400,
'Access-Control-Expose-Headers' => [],
],
],
];
}
Try this URL rule may it should help you.
But befor proceeding with this rule I want to clear you if you are using a module for rest API you must need to define your module ID too in rule either using prefix or direct
[
'class' => 'yii\rest\UrlRule',
'controller' => '<moduleID>/scholarships',
'tokens' => [
'{slug}' => '<slug>',
],
'extraPatterns' => [
'GET,HEAD {slug}' => 'view-slug',
]
],
and where is youe actionViewSlug($slug);
It is good if you share your controller code too. It's simple to use slug with different actions. One more thing here I would like to know why you are defining viewSlug action? Why you are not using the existing view action with slug?
Thanks
i'm adding a verb to the verbs behaviors to only allow POST request for some action and if the request not a POST it should return method not allowed but this is not working it return 404 not found response not 405 Not allowed response when i'm sending a GET request instead of POST please any help
i set in my REST control the behaviors like this
public function behaviors()
{
$behaviors = parent::behaviors();
$behaviors['authenticator'] = [
'class' => CompositeAuth::className(),
'except' => ['login'],
'authMethods' => [
HttpBearerAuth::className(),
],
];
$behaviors['verbs'] = [
'class' => \yii\filters\VerbFilter::className(),
'actions' => [
//'index' => ['get'],
'login' => ['post', 'put'],
'view' => ['get'],
//'create' => ['get', 'post'],
'update' => ['put'],
//'delete' => ['post', 'delete'],
'delete' => [''],
'test', ['post']
],
];
return $behaviors;
}
in the main.php
'urlManager' => [
'enablePrettyUrl' => true,
'enableStrictParsing' => true,
'showScriptName' => false,
'rules' => [
[
'class' => 'yii\rest\UrlRule',
'controller' => ['v1/vendor'],
'extraPatterns' => [
'POST,PUT login' => 'login',
'POST logout' => 'logout',
'POST test' => 'test'
],
'tokens' => [
'{id}' => '<id:\\w+>'
]
],
],
]
so when i test and sent GET request to
GET localhost/mywebsite/api/web/v1/vendors/test
it return 404 not 405 status please any help
'extraPatterns' => [
...
'test' => 'test'
]
From Yii2 guideline routing: pretty url, strict parsing always throw \yii\web\NotFound\HttpException.
You can update the controller's beforeAction:
public function beforeAction() {
if (Yii::$app->getRequest()->getMethod() != 'POST') {
throw new \yii\web\MethodNotAllowedHttpException('Only allow POST request');
}
}
I am building an API in Yii2 and have added CORS and authentication. This works fine for all Create/Read/Update/Delete actions but not for custom actions. Has anyone experienced this before?
URL manager:
['class' => 'yii\rest\UrlRule', 'controller' => 'api/v1/user', 'pluralize' => false],
Controller behaviors:
public function behaviors()
{
return ArrayHelper::merge([
'corsFilter' => [
'class' => Cors::className(),
],
[
'class' => HttpBearerAuth::className(),
'except' => ['options',
'login',
],
],
], parent::behaviors()
);
}
As mentioned, actions for CRUD are fine but a custom action such as http://domain.com/user/test will respond with a 401 Unauthorised response.
Is it not possible to get CORS and auth to work together on custom actions?
Edit: I should add that the issue (401) occurs only when a browser makes the OPTIONS request. Normal requests (curl,Postman) are not affected. The issue seems to occur with the RESTful,Cors,Auth combination.
try this:
public function behaviors()
{
$behaviors = parent::behaviors();
unset($behaviors['authenticator']);
$behaviors['corsFilter'] = [
'class' => Cors::className(),
'cors' => [
'Origin' => ['*'],
'Access-Control-Request-Method' => ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS'],
'Access-Control-Request-Headers' => ['*'],
'Access-Control-Allow-Credentials' => true,
],
];
$behaviors['authenticator'] = [
'class' => HttpBearerAuth::className(),
'except' => ['options','login'],
];
return $behaviors;
}
It will unset the default authenticator implemented by the parent controller to be sure that cors is treated first. Then we force cors to allow credentials before implementing your own authenticator.
The other thing that may raise that Unauthorized error is a not-found or wrong Options response as a browser request it first to get a list of allowed verbs. You may check that list in its headers response within your browser's network tab.
The general rule is when you ask your browser to perform a sensible verb like PUT, DELETE or POST to any url it may first send an OPTIONS request to that same url (check this) to check if that verb is allowed before sending the real request. So Yii should be configured to respond to all those OPTIONS verbs by performing the correct redirections.
The default CRUD actions implemented by ActiveController are using those default patterns:
'PUT,PATCH {id}' => 'update',
'DELETE {id}' => 'delete',
'GET,HEAD {id}' => 'view',
'POST' => 'create',
'GET,HEAD' => 'index',
'{id}' => 'options',
'' => 'options',
So whatever configurations you did implement in urlManager['rules'] be sure to not override the last 2 of them and if you are using custom patterns always remember to include its equivalent options verbs like in this example:
[
'class' => 'yii\rest\UrlRule',
'controller' => ['account' => 'auth/account'],
'patterns' => [
'POST,HEAD login' => 'login',
'POST,HEAD signup' => 'signup',
'POST req-reset-pass' => 'request-password-reset',
'POST reset-pass' => 'reset-password',
// OPTTIONS VERBS
'OPTIONS login' => 'options',
'OPTIONS signup' => 'options',
'OPTIONS req-reset-pass' => 'options',
'OPTIONS reset-pass' => 'options',
]
],
The same applies when adding custom patterns within extraPatterns.
The Options action is implemented by default in ActiveController. it's code can be seen here.
In case you are extending a different controller than ActiveController like maybe \yii\rest\Controller be sure to manually include it:
public function actions()
{
$actions = parent::actions();
$actions['options'] = [
'class' => 'yii\rest\OptionsAction',
// optional:
'collectionOptions' => ['GET', 'POST', 'HEAD', 'OPTIONS'],
'resourceOptions' => ['GET', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS'],
];
return $actions;
}
Just move your corsFilter block above the authenticator block like this:
public function behaviors()
{
return [
'corsFilter' => [
'class' => \yii\filters\Cors::className(),
],
'authenticator' => [
'class' => HttpBearerAuth::className(),
],
'contentNegotiator' => [
'class' => ContentNegotiator::className(),
'formats' => [
'application/json' => Response::FORMAT_JSON,
],
],
];
}
I have a backend project on my ssl server, like ssl.mybackend.com, with following:
class FormController extends Controller
{
public function behaviors()
{
return [
'access' => [
'class' => AccessControl::className(),
'rules' => [
[
'actions' => ['index', 'delete', 'view', 'create'],
'allow' => true,
'roles' => ['#'], //only authorized users
],
[
'actions'=> ['create-order'],
'allow'=>true //change all users to "myfrontend.com"
]
],
],
];
}
I need to grant an access to create-order action only to my frontend website.
I am not sure if it's possible to do with AccessControl and appreciate if you could advise other solutions.
If you want to use ajax calls from frontend on another domain, you should use corsFilter instead. Example from documentation:
public function behaviors()
{
return [
'corsFilter' => [
'class' => \yii\filters\Cors::className(),
'cors' => [
// restrict access to
'Origin' => ['http://www.myserver.com', 'https://www.myserver.com'],
'Access-Control-Request-Method' => ['POST', 'PUT'],
// Allow only POST and PUT methods
'Access-Control-Request-Headers' => ['X-Wsse'],
// Allow only headers 'X-Wsse'
'Access-Control-Allow-Credentials' => true,
// Allow OPTIONS caching
'Access-Control-Max-Age' => 3600,
// Allow the X-Pagination-Current-Page header to be exposed to the browser.
'Access-Control-Expose-Headers' => ['X-Pagination-Current-Page'],
],
],
];
}
Cross Origin Resource Sharing in Yii2