예제 #1
0
    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
예제 #2
0
    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