1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\web;
use Yii;
use yii\base\ActionEvent;
use yii\base\Behavior;
/**
* VerbFilter is an action filter that filters by HTTP request methods.
*
* It allows to define allowed HTTP request methods for each action and will throw
* an HTTP 405 error when the method is not allowed.
*
* To use VerbFilter, declare it in the `behaviors()` method of your controller class.
* For example, the following declarations will define a typical set of allowed
* request methods for REST CRUD actions.
*
* ~~~
* public function behaviors()
* {
* return [
* 'verbs' => [
* 'class' => \yii\web\VerbFilter::className(),
* 'actions' => [
* 'index' => ['get'],
* 'view' => ['get'],
* 'create' => ['get', 'post'],
* 'update' => ['get', 'put', 'post'],
* 'delete' => ['post', 'delete'],
* ],
* ],
* ];
* }
* ~~~
*
* @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.7
* @author Carsten Brandt <mail@cebe.cc>
* @since 2.0
*/
class VerbFilter extends Behavior
{
/**
* @var array this property defines the allowed request methods for each action.
* For each action that should only support limited set of request methods
* you add an entry with the action id as array key and an array of
* allowed methods (e.g. GET, HEAD, PUT) as the value.
* If an action is not listed all request methods are considered allowed.
*
* You can use '*' to stand for all actions. When an action is explicitly
* specified, it takes precedence over the specification given by '*'.
*
* For example,
*
* ~~~
* [
* 'create' => ['get', 'post'],
* 'update' => ['get', 'put', 'post'],
* 'delete' => ['post', 'delete'],
* '*' => ['get'],
* ]
* ~~~
*/
public $actions = [];
/**
* Declares event handlers for the [[owner]]'s events.
* @return array events (array keys) and the corresponding event handler methods (array values).
*/
public function events()
{
return [Controller::EVENT_BEFORE_ACTION => 'beforeAction'];
}
/**
* @param ActionEvent $event
* @return boolean
* @throws HttpException when the request method is not allowed.
*/
public function beforeAction($event)
{
$action = $event->action->id;
if (isset($this->actions[$action])) {
$verbs = $this->actions[$action];
} elseif (isset($this->actions['*'])) {
$verbs = $this->actions['*'];
} else {
return $event->isValid;
}
$verb = Yii::$app->getRequest()->getMethod();
$allowed = array_map('strtoupper', $verbs);
if (!in_array($verb, $allowed)) {
$event->isValid = false;
// http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.7
Yii::$app->getResponse()->getHeaders()->set('Allow', implode(', ', $allowed));
throw new MethodNotAllowedHttpException('Method Not Allowed. This url can only handle the following request methods: ' . implode(', ', $allowed) . '.');
}
return $event->isValid;
}
}