コード例 #1
0
 def test_window_and_concurrent_limit(self):
     """Test that if there is a window limit and a concurrent limit, the
     FIXED_WINDOW limit takes precedence"""
     return_val = above_rate_limit_check("xar", RateLimit(0, 100, 0),
                                         "request_uid")
     assert return_val.rate_limit_type == RateLimitType.FIXED_WINDOW
     assert return_val.concurrent_remaining is None
コード例 #2
0
    def test_above_rate_limit_check(self):
        with freeze_time("2000-01-01"):
            expected_reset_time = int(time() + 100)
            return_val = above_rate_limit_check("foo", RateLimit(10, 100),
                                                "request_uid")
            assert return_val == RateLimitMeta(
                rate_limit_type=RateLimitType.NOT_LIMITED,
                current=1,
                limit=10,
                window=100,
                reset_time=expected_reset_time,
                remaining=9,
                concurrent_limit=None,
                concurrent_requests=None,
            )
            for i in range(10):
                return_val = above_rate_limit_check("foo", RateLimit(10, 100),
                                                    f"request_uid{i}")
            assert return_val == RateLimitMeta(
                rate_limit_type=RateLimitType.FIXED_WINDOW,
                current=11,
                limit=10,
                window=100,
                reset_time=expected_reset_time,
                remaining=0,
                concurrent_limit=None,
                concurrent_requests=None,
            )

            for i in range(10):
                return_val = above_rate_limit_check("bar",
                                                    RateLimit(120, 100, 9),
                                                    f"request_uid{i}")
            assert return_val == RateLimitMeta(
                rate_limit_type=RateLimitType.CONCURRENT,
                current=10,
                limit=120,
                window=100,
                reset_time=expected_reset_time,
                remaining=110,
                concurrent_limit=9,
                concurrent_requests=9,
            )
コード例 #3
0
 def test_above_rate_limit_check(self):
     with freeze_time("2000-01-01"):
         expected_reset_time = int(time() + 100)
         return_val = above_rate_limit_check("foo", RateLimit(10, 100))
         assert return_val == RateLimitMeta(
             is_limited=False,
             current=1,
             limit=10,
             window=100,
             reset_time=expected_reset_time,
             remaining=9,
         )
         for _ in range(10):
             return_val = above_rate_limit_check("foo", RateLimit(10, 100))
         assert return_val == RateLimitMeta(
             is_limited=True,
             current=11,
             limit=10,
             window=100,
             reset_time=expected_reset_time,
             remaining=0,
         )
コード例 #4
0
    def process_view(self, request: Request, view_func, view_args,
                     view_kwargs) -> Response | None:
        """Check if the endpoint call will violate."""
        try:
            # TODO: put these fields into their own object
            request.will_be_rate_limited = False
            request.rate_limit_category = None
            request.rate_limit_uid = uuid.uuid4().hex
            request.rate_limit_key = get_rate_limit_key(view_func, request)
            if request.rate_limit_key is None:
                return
            category_str = request.rate_limit_key.split(":", 1)[0]
            request.rate_limit_category = category_str

            rate_limit = get_rate_limit_value(
                http_method=request.method,
                endpoint=view_func.view_class,
                category=RateLimitCategory(category_str),
            )
            if rate_limit is None:
                return

            request.rate_limit_metadata = above_rate_limit_check(
                request.rate_limit_key, rate_limit, request.rate_limit_uid)
            # TODO: also limit by concurrent window once we have the data
            rate_limit_cond = (request.rate_limit_metadata.rate_limit_type !=
                               RateLimitType.NOT_LIMITED
                               if ENFORCE_CONCURRENT_RATE_LIMITS else
                               request.rate_limit_metadata.rate_limit_type
                               == RateLimitType.FIXED_WINDOW)
            if rate_limit_cond:
                request.will_be_rate_limited = True
                enforce_rate_limit = getattr(view_func.view_class,
                                             "enforce_rate_limit", False)
                if enforce_rate_limit:
                    return HttpResponse(
                        {
                            "detail":
                            DEFAULT_ERROR_MESSAGE.format(
                                limit=request.rate_limit_metadata.limit,
                                window=request.rate_limit_metadata.window,
                            )
                        },
                        status=429,
                    )
        except Exception:
            logging.exception(
                "Error during rate limiting, failing open. THIS SHOULD NOT HAPPEN"
            )
コード例 #5
0
    def process_view(self, request: Request, view_func, view_args,
                     view_kwargs) -> Response | None:
        """Check if the endpoint call will violate."""
        request.will_be_rate_limited = False
        request.rate_limit_category = None

        key = get_rate_limit_key(view_func, request)
        if key is None:
            return
        category_str = key.split(":", 1)[0]
        request.rate_limit_category = category_str

        rate_limit = get_rate_limit_value(
            http_method=request.method,
            endpoint=view_func.view_class,
            category=RateLimitCategory(category_str),
        )
        if rate_limit is None:
            return

        request.rate_limit_metadata = above_rate_limit_check(key, rate_limit)

        if request.rate_limit_metadata.is_limited:
            request.will_be_rate_limited = True
            enforce_rate_limit = getattr(view_func.view_class,
                                         "enforce_rate_limit", False)
            if enforce_rate_limit:
                return HttpResponse(
                    {
                        "detail":
                        DEFAULT_ERROR_MESSAGE.format(
                            limit=request.rate_limit_metadata.limit,
                            window=request.rate_limit_metadata.window,
                        )
                    },
                    status=429,
                )
コード例 #6
0
 def do_request():
     uid = uuid.uuid4().hex
     meta = above_rate_limit_check("foo", RateLimit(10, 1, 3), uid)
     sleep(0.2)
     finish_request("foo", uid)
     return meta
コード例 #7
0
 def test_above_rate_limit_check(self):
     return_val = above_rate_limit_check("foo", RateLimit(10, 100))
     assert return_val == dict(is_limited=False,
                               current=1,
                               limit=10,
                               window=100)