Summary: Ref T13008. We haven't hit any issues with this, but I can imagine we might in the future. When one host makes an intracluster request to another host, the `$viewer` ends up as the omnipotent viewer. This viewer isn't logged in, so they'll currently accumulate rate limit points at a high rate. Instead, don't give them any points. These requests are always legitimate, and if they originated from a user request, that request should be the one getting rate limited. Test Plan: Browsed around. Reviewers: amckinley Reviewed By: amckinley Maniphest Tasks: T13008 Differential Revision: https://secure.phabricator.com/D18708
		
			
				
	
	
		
			67 lines
		
	
	
		
			1.6 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			67 lines
		
	
	
		
			1.6 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
<?php
 | 
						|
 | 
						|
final class PhabricatorClientRateLimit
 | 
						|
  extends PhabricatorClientLimit {
 | 
						|
 | 
						|
  protected function getBucketDuration() {
 | 
						|
    return 60;
 | 
						|
  }
 | 
						|
 | 
						|
  protected function getBucketCount() {
 | 
						|
    return 5;
 | 
						|
  }
 | 
						|
 | 
						|
  protected function shouldRejectConnection($score) {
 | 
						|
    $limit = $this->getLimit();
 | 
						|
 | 
						|
    // Reject connections if the average score across all buckets exceeds the
 | 
						|
    // limit.
 | 
						|
    $average_score = $score / $this->getBucketCount();
 | 
						|
 | 
						|
    return ($average_score > $limit);
 | 
						|
  }
 | 
						|
 | 
						|
  protected function getConnectScore() {
 | 
						|
    return 0;
 | 
						|
  }
 | 
						|
 | 
						|
  protected function getPenaltyScore() {
 | 
						|
    return 1;
 | 
						|
  }
 | 
						|
 | 
						|
  protected function getDisconnectScore(array $request_state) {
 | 
						|
    $score = 1;
 | 
						|
 | 
						|
    // If the user was logged in, let them make more requests.
 | 
						|
    if (isset($request_state['viewer'])) {
 | 
						|
      $viewer = $request_state['viewer'];
 | 
						|
      if ($viewer->isOmnipotent()) {
 | 
						|
        // If the viewer was omnipotent, this was an intracluster request or
 | 
						|
        // some other kind of special request, so don't give it any points
 | 
						|
        // toward rate limiting.
 | 
						|
        $score = 0;
 | 
						|
      } else if ($viewer->isLoggedIn()) {
 | 
						|
        // If the viewer was logged in, give them fewer points than if they
 | 
						|
        // were logged out, since this traffic is much more likely to be
 | 
						|
        // legitimate.
 | 
						|
        $score = 0.25;
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    return $score;
 | 
						|
  }
 | 
						|
 | 
						|
  protected function getRateLimitReason($score) {
 | 
						|
    $client_key = $this->getClientKey();
 | 
						|
 | 
						|
    // NOTE: This happens before we load libraries, so we can not use pht()
 | 
						|
    // here.
 | 
						|
 | 
						|
    return
 | 
						|
      "TOO MANY REQUESTS\n".
 | 
						|
      "You (\"{$client_key}\") are issuing too many requests ".
 | 
						|
      "too quickly.\n";
 | 
						|
  }
 | 
						|
 | 
						|
}
 |