mirror of
https://github.com/jazzband/django-axes.git
synced 2026-05-08 15:44:46 +00:00
refactor: update Retry-After header handling in AxesMiddleware and tests
This commit is contained in:
parent
051323166d
commit
4f5bfb8c1c
3 changed files with 21 additions and 23 deletions
|
|
@ -40,19 +40,18 @@ class AxesMiddleware:
|
|||
markcoroutinefunction(self)
|
||||
|
||||
@staticmethod
|
||||
def _set_retry_after_header(
|
||||
response: HttpResponse, request: HttpRequest
|
||||
def set_retry_after_header(request: HttpRequest, response: HttpResponse) -> None:
|
||||
if settings.AXES_ENABLE_RETRY_AFTER_HEADER:
|
||||
response["Retry-After"] = str(int(get_cool_off(request).total_seconds()))
|
||||
|
||||
def build_lockout_response(
|
||||
self,
|
||||
request: HttpRequest,
|
||||
response: HttpResponse,
|
||||
credentials,
|
||||
) -> HttpResponse:
|
||||
if not settings.AXES_ENABLE_RETRY_AFTER_HEADER:
|
||||
return response
|
||||
|
||||
if settings.AXES_LOCKOUT_CALLABLE or settings.AXES_LOCKOUT_URL:
|
||||
return response
|
||||
|
||||
cool_off = get_cool_off(request)
|
||||
if cool_off is not None:
|
||||
response["Retry-After"] = str(int(cool_off.total_seconds()))
|
||||
|
||||
response = get_lockout_response(request, response, credentials) # type: ignore
|
||||
self.set_retry_after_header(request, response)
|
||||
return response
|
||||
|
||||
def __call__(self, request: HttpRequest) -> HttpResponse:
|
||||
|
|
@ -64,8 +63,7 @@ class AxesMiddleware:
|
|||
if settings.AXES_ENABLED:
|
||||
if getattr(request, "axes_locked_out", None):
|
||||
credentials = getattr(request, "axes_credentials", None)
|
||||
response = get_lockout_response(request, response, credentials) # type: ignore
|
||||
response = self._set_retry_after_header(response, request)
|
||||
response = self.build_lockout_response(request, response, credentials)
|
||||
|
||||
return response
|
||||
|
||||
|
|
@ -76,10 +74,9 @@ class AxesMiddleware:
|
|||
if getattr(request, "axes_locked_out", None):
|
||||
credentials = getattr(request, "axes_credentials", None)
|
||||
response = await sync_to_async(
|
||||
get_lockout_response, thread_sensitive=True
|
||||
self.build_lockout_response, thread_sensitive=True
|
||||
)(
|
||||
request, response, credentials
|
||||
) # type: ignore
|
||||
response = self._set_retry_after_header(response, request)
|
||||
)
|
||||
|
||||
return response
|
||||
|
|
|
|||
|
|
@ -91,8 +91,7 @@ The following ``settings.py`` options are available for customizing Axes behavio
|
|||
.. note::
|
||||
If ``AXES_ENABLE_RETRY_AFTER_HEADER`` is enabled and ``AXES_COOLOFF_TIME`` is configured,
|
||||
``AxesMiddleware`` adds a ``Retry-After`` HTTP header (`RFC 7231 <https://datatracker.ietf.org/doc/html/rfc7231#section-7.1.3>`_)
|
||||
with the cool-off duration in seconds. This header is not added for redirects
|
||||
(``AXES_LOCKOUT_URL``) or custom lockout responses (``AXES_LOCKOUT_CALLABLE``).
|
||||
with the cool-off duration in seconds for lockout responses.
|
||||
|
||||
The configuration option precedences for the access attempt monitoring are:
|
||||
|
||||
|
|
|
|||
|
|
@ -74,27 +74,29 @@ class MiddlewareTestCase(AxesTestCase):
|
|||
|
||||
@override_settings(
|
||||
AXES_COOLOFF_TIME=timedelta(seconds=120),
|
||||
AXES_ENABLE_RETRY_AFTER_HEADER=True,
|
||||
AXES_LOCKOUT_URL="https://example.com",
|
||||
)
|
||||
def test_lockout_redirect_response_does_not_set_retry_after_header(self):
|
||||
def test_lockout_redirect_response_sets_retry_after_header(self):
|
||||
def get_response(request):
|
||||
request.axes_locked_out = True
|
||||
return HttpResponse()
|
||||
|
||||
response = AxesMiddleware(get_response)(self.request)
|
||||
self.assertFalse(response.has_header("Retry-After"))
|
||||
self.assertEqual(response["Retry-After"], "120")
|
||||
|
||||
@override_settings(
|
||||
AXES_COOLOFF_TIME=timedelta(seconds=120),
|
||||
AXES_ENABLE_RETRY_AFTER_HEADER=True,
|
||||
AXES_LOCKOUT_CALLABLE="tests.test_middleware.get_custom_lockout_response",
|
||||
)
|
||||
def test_lockout_callable_response_does_not_set_retry_after_header(self):
|
||||
def test_lockout_callable_response_sets_retry_after_header(self):
|
||||
def get_response(request):
|
||||
request.axes_locked_out = True
|
||||
return HttpResponse()
|
||||
|
||||
response = AxesMiddleware(get_response)(self.request)
|
||||
self.assertFalse(response.has_header("Retry-After"))
|
||||
self.assertEqual(response["Retry-After"], "120")
|
||||
|
||||
@override_settings(AXES_USERNAME_CALLABLE="tests.test_middleware.get_username")
|
||||
def test_lockout_response_with_axes_callable_username(self):
|
||||
|
|
|
|||
Loading…
Reference in a new issue