def allow_request(self, request, view): # Get the ApiV2Client that made the request and its throttling level auth_method_name = request.successful_authenticator.authentication_method_name if auth_method_name == "OAuth2": self.client = request.auth.client.apiv2_client client_throttle_level = int(self.client.throttling_level) elif auth_method_name == "Token": self.client = request.auth client_throttle_level = int(self.client.throttling_level) elif auth_method_name == "Session": self.client = None client_throttle_level = 1 try: limit_rates = view.throttling_rates_per_level[client_throttle_level] except: # Fallback to basic throttling levels if the view has not defined the throttling rates per level limit_rates = settings.APIV2_BASIC_THROTTLING_RATES_PER_LEVELS[client_throttle_level] # Apply the burst limit rate (the first of the list if there are limit rates. No limit rates means unlimited api usage) if limit_rates: rate = limit_rates[0] # Get burst limit self.rate = rate self.num_requests, self.duration = self.parse_rate(rate) passes_throttle = super(ClientBasedThrottlingBurst, self).allow_request(request, view) if not passes_throttle: msg = "Request was throttled because of exceeding a request limit rate (%s)" % rate if client_throttle_level == 0: # Prevent returning a absurd message like "exceeding a request limit rate (0/minute)" msg = "Request was throttled because the ApiV2 credential has been suspended" raise Throttled(msg=msg, request_info=build_request_info_string_for_error_logging(request)) return True
def allow_request(self, request, view): # Get the ApiV2Client that made the request and its throttling level auth_method_name = request.successful_authenticator.authentication_method_name if auth_method_name == "OAuth2": self.client = request.auth.client.apiv2_client client_throttle_level = int(self.client.throttling_level) elif auth_method_name == "Token": self.client = request.auth client_throttle_level = int(self.client.throttling_level) elif auth_method_name == "Session": self.client = None client_throttle_level = 1 # Get request ip x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR') if x_forwarded_for: self.ip = x_forwarded_for.split(',')[0].strip() else: self.ip = '-' #request.META.get('REMOTE_ADDR') try: limit_rates = view.throttling_rates_per_level[client_throttle_level] except: # Fallback to basic throttling levels if the view has not defined the throttling rates per level limit_rates = settings.APIV2_BASIC_THROTTLING_RATES_PER_LEVELS[client_throttle_level] # Apply the ip limit rate (No limit rates means unlimited api usage) if limit_rates: rate = limit_rates[2] # Get sustained limit self.rate = rate self.num_requests, self.duration = self.parse_rate(rate) if self.rate is None: return True self.key = self.get_cache_key(request, view) if self.key is None: return True self.history = self.cache.get(self.key, []) self.now = self.timer() # Drop any requests from the history which have now passed the # throttle duration while self.history and self.history[-1][0] <= self.now - self.duration: self.history.pop() self.ip_in_history = self.ip in [history_ip for history_now, history_ip in self.history] if self.ip_in_history: return True else: if len(self.history) >= self.num_requests: passes_throttle = self.throttle_failure() else: passes_throttle = self.throttle_success() if not passes_throttle: msg = "Request was throttled because of exceeding the concurrent ip limit rate (%s)" % rate if client_throttle_level == 0: # Prevent returning a absurd message like "exceeding a request limit rate (0/minute)" msg = "Request was throttled because the ApiV2 credential has been suspended" raise Throttled(msg=msg, request_info=build_request_info_string_for_error_logging(request)) return True