mirror of
				https://github.com/yiisoft/yii2.git
				synced 2025-10-31 10:39:59 +08:00 
			
		
		
		
	
		
			
				
	
	
		
			67 lines
		
	
	
		
			3.0 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
			
		
		
	
	
			67 lines
		
	
	
		
			3.0 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
| Rate Limiting
 | |
| =============
 | |
| 
 | |
| To prevent abuse, you should consider adding *rate limiting* to your APIs. For example, you may want to limit the API usage
 | |
| of each user to be at most 100 API calls within a period of 10 minutes. If too many requests are received from a user
 | |
| within the stated period of the time, a response with status code 429 (meaning "Too Many Requests") should be returned.
 | |
| 
 | |
| To enable rate limiting, the [[yii\web\User::identityClass|user identity class]] should implement [[yii\filters\RateLimitInterface]].
 | |
| This interface requires implementation of three methods:
 | |
| 
 | |
| * `getRateLimit()`: returns the maximum number of allowed requests and the time period (e.g., `[100, 600]` means there can be at most 100 API calls within 600 seconds).
 | |
| * `loadAllowance()`: returns the number of remaining requests allowed and the corresponding UNIX timestamp
 | |
|   when the rate limit was last checked.
 | |
| * `saveAllowance()`: saves both the number of remaining requests allowed and the current UNIX timestamp.
 | |
| 
 | |
| You may want to use two columns in the user table to record the allowance and timestamp information. With those defined,
 | |
| then `loadAllowance()` and `saveAllowance()` can be implemented to read and save the values
 | |
| of the two columns corresponding to the current authenticated user. To improve performance, you may also
 | |
| consider storing these pieces of information in a cache or NoSQL storage.
 | |
| 
 | |
| Implementation in the `User` model could look like the following:
 | |
| 
 | |
| ```php
 | |
| public function getRateLimit($request, $action)
 | |
| {
 | |
|     return [$this->rateLimit, 1]; // $rateLimit requests per second
 | |
| }
 | |
| 
 | |
| public function loadAllowance($request, $action)
 | |
| {
 | |
|     return [$this->allowance, $this->allowance_updated_at];
 | |
| }
 | |
| 
 | |
| public function saveAllowance($request, $action, $allowance, $timestamp)
 | |
| {
 | |
|     $this->allowance = $allowance;
 | |
|     $this->allowance_updated_at = $timestamp;
 | |
|     $this->save();
 | |
| }
 | |
| ```
 | |
| 
 | |
| Once the identity class implements the required interface, Yii will automatically use [[yii\filters\RateLimiter]]
 | |
| configured as an action filter for [[yii\rest\Controller]] to perform rate limiting check. The rate limiter
 | |
| will throw a [[yii\web\TooManyRequestsHttpException]] when the rate limit is exceeded. 
 | |
| 
 | |
| You may configure the rate limiter
 | |
| as follows in your REST controller classes:
 | |
| 
 | |
| ```php
 | |
| public function behaviors()
 | |
| {
 | |
|     $behaviors = parent::behaviors();
 | |
|     $behaviors['rateLimiter']['enableRateLimitHeaders'] = false;
 | |
|     return $behaviors;
 | |
| }
 | |
| ```
 | |
| 
 | |
| When rate limiting is enabled, by default every response will be sent with the following HTTP headers containing
 | |
| the current rate limiting information:
 | |
| 
 | |
| * `X-Rate-Limit-Limit`, the maximum number of requests allowed with a time period
 | |
| * `X-Rate-Limit-Remaining`, the number of remaining requests in the current time period
 | |
| * `X-Rate-Limit-Reset`, the number of seconds to wait in order to get the maximum number of allowed requests
 | |
| 
 | |
| You may disable these headers by configuring [[yii\filters\RateLimiter::enableRateLimitHeaders]] to be `false`,
 | |
| as shown in the above code example.
 | 
