VerbFilter.php 3.1 KB
Newer Older
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
<?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()
 * {
Alexander Makarov committed
27 28
 *     return [
 *         'verbs' => [
29
 *             'class' => \yii\web\VerbFilter::className(),
Alexander Makarov committed
30 31 32 33 34 35 36 37 38
 *             'actions' => [
 *                 'index'  => ['get'],
 *                 'view'   => ['get'],
 *                 'create' => ['get', 'post'],
 *                 'update' => ['get', 'put', 'post'],
 *                 'delete' => ['post', 'delete'],
 *             ],
 *         ],
 *     ];
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
 * }
 * ~~~
 *
 * @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.
54 55 56 57 58 59 60 61 62 63 64 65 66 67
	 *
	 * 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'],
	 * ]
	 * ~~~
68
	 */
Alexander Makarov committed
69
	public $actions = [];
70 71 72 73 74 75 76 77


	/**
	 * Declares event handlers for the [[owner]]'s events.
	 * @return array events (array keys) and the corresponding event handler methods (array values).
	 */
	public function events()
	{
Alexander Makarov committed
78
		return [Controller::EVENT_BEFORE_ACTION => 'beforeAction'];
79 80 81 82 83
	}

	/**
	 * @param ActionEvent $event
	 * @return boolean
Qiang Xue committed
84
	 * @throws HttpException when the request method is not allowed.
85 86 87 88 89
	 */
	public function beforeAction($event)
	{
		$action = $event->action->id;
		if (isset($this->actions[$action])) {
90 91 92 93 94
			$verbs = $this->actions[$action];
		} elseif (isset($this->actions['*'])) {
			$verbs = $this->actions['*'];
		} else {
			return $event->isValid;
95
		}
96 97 98

		$verb = Yii::$app->getRequest()->getMethod();
		$allowed = array_map('strtoupper', $verbs);
peeradach001 committed
99
		if (!in_array($verb, $allowed)) {
100 101 102
			$event->isValid = false;
			// http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.7
			Yii::$app->getResponse()->getHeaders()->set('Allow', implode(', ', $allowed));
103
			throw new MethodNotAllowedHttpException('Method Not Allowed. This url can only handle the following request methods: ' . implode(', ', $allowed) . '.');
104 105
		}

106 107 108
		return $event->isValid;
	}
}