|
@@ -11,7 +11,7 @@ from sentry.ratelimits import (
|
|
get_rate_limit_key,
|
|
get_rate_limit_key,
|
|
get_rate_limit_value,
|
|
get_rate_limit_value,
|
|
)
|
|
)
|
|
-from sentry.types.ratelimit import RateLimitCategory, RateLimitMeta
|
|
|
|
|
|
+from sentry.types.ratelimit import RateLimitCategory
|
|
|
|
|
|
DEFAULT_ERROR_MESSAGE = (
|
|
DEFAULT_ERROR_MESSAGE = (
|
|
"You are attempting to use this endpoint too frequently. Limit is "
|
|
"You are attempting to use this endpoint too frequently. Limit is "
|
|
@@ -22,8 +22,6 @@ DEFAULT_ERROR_MESSAGE = (
|
|
class RatelimitMiddleware(MiddlewareMixin):
|
|
class RatelimitMiddleware(MiddlewareMixin):
|
|
"""Middleware that applies a rate limit to every endpoint."""
|
|
"""Middleware that applies a rate limit to every endpoint."""
|
|
|
|
|
|
- rate_limit_metadata: RateLimitMeta | None = None
|
|
|
|
-
|
|
|
|
def process_view(self, request: Request, view_func, view_args, view_kwargs) -> Response | None:
|
|
def process_view(self, request: Request, view_func, view_args, view_kwargs) -> Response | None:
|
|
"""Check if the endpoint call will violate."""
|
|
"""Check if the endpoint call will violate."""
|
|
request.will_be_rate_limited = False
|
|
request.will_be_rate_limited = False
|
|
@@ -46,29 +44,25 @@ class RatelimitMiddleware(MiddlewareMixin):
|
|
if rate_limit is None:
|
|
if rate_limit is None:
|
|
return
|
|
return
|
|
|
|
|
|
- self.rate_limit_metadata = above_rate_limit_check(key, rate_limit)
|
|
|
|
- if self.rate_limit_metadata.is_limited:
|
|
|
|
|
|
+ request.rate_limit_metadata = above_rate_limit_check(key, rate_limit)
|
|
|
|
+
|
|
|
|
+ if request.rate_limit_metadata.is_limited:
|
|
request.will_be_rate_limited = True
|
|
request.will_be_rate_limited = True
|
|
enforce_rate_limit = getattr(view_func.view_class, "enforce_rate_limit", False)
|
|
enforce_rate_limit = getattr(view_func.view_class, "enforce_rate_limit", False)
|
|
if enforce_rate_limit:
|
|
if enforce_rate_limit:
|
|
return HttpResponse(
|
|
return HttpResponse(
|
|
{
|
|
{
|
|
"detail": DEFAULT_ERROR_MESSAGE.format(
|
|
"detail": DEFAULT_ERROR_MESSAGE.format(
|
|
- limit=self.rate_limit_metadata.limit,
|
|
|
|
- window=self.rate_limit_metadata.window,
|
|
|
|
|
|
+ limit=request.rate_limit_metadata.limit,
|
|
|
|
+ window=request.rate_limit_metadata.window,
|
|
)
|
|
)
|
|
},
|
|
},
|
|
status=429,
|
|
status=429,
|
|
)
|
|
)
|
|
|
|
|
|
def process_response(self, request: Request, response: Response) -> Response:
|
|
def process_response(self, request: Request, response: Response) -> Response:
|
|
- if self.rate_limit_metadata is not None:
|
|
|
|
- remaining_count = (
|
|
|
|
- self.rate_limit_metadata.limit - self.rate_limit_metadata.current
|
|
|
|
- if not self.rate_limit_metadata.is_limited
|
|
|
|
- else 0
|
|
|
|
- )
|
|
|
|
- response["X-Sentry-Rate-Limit-Remaining"] = remaining_count
|
|
|
|
- response["X-Sentry-Rate-Limit-Limit"] = self.rate_limit_metadata.limit
|
|
|
|
- response["X-Sentry-Rate-Limit-Reset"] = self.rate_limit_metadata.reset_time
|
|
|
|
|
|
+ if hasattr(request, "rate_limit_metadata"):
|
|
|
|
+ response["X-Sentry-Rate-Limit-Remaining"] = request.rate_limit_metadata.remaining
|
|
|
|
+ response["X-Sentry-Rate-Limit-Limit"] = request.rate_limit_metadata.limit
|
|
|
|
+ response["X-Sentry-Rate-Limit-Reset"] = request.rate_limit_metadata.reset_time
|
|
return response
|
|
return response
|