Merge pull request #26441 from edx/feanil/make_rate_limit_errors_429s
Make rate limit errors 429s instead of 403s
This commit is contained in:
@@ -2805,7 +2805,7 @@ class TestInstructorAPILevelsDataDump(SharedModuleStoreTestCase, LoginEnrollment
|
||||
# other users of the lms.
|
||||
with freeze_time(base_time + datetime.timedelta(minutes=1)):
|
||||
response = self.client.post(url, {})
|
||||
assert response.status_code == 403
|
||||
assert response.status_code == 429
|
||||
|
||||
with freeze_time(base_time + datetime.timedelta(minutes=5)):
|
||||
response = self.client.post(url, {})
|
||||
|
||||
@@ -9,11 +9,13 @@
|
||||
import mimetypes
|
||||
|
||||
from django.conf import settings
|
||||
from django.http import Http404, HttpResponseNotFound, HttpResponseServerError
|
||||
from django.http import Http404, HttpResponse, HttpResponseNotFound, HttpResponseServerError
|
||||
from django.shortcuts import redirect
|
||||
from django.template import TemplateDoesNotExist
|
||||
from django.utils.safestring import mark_safe
|
||||
from django.views.decorators.csrf import ensure_csrf_cookie
|
||||
from django.views.defaults import permission_denied
|
||||
from ratelimit.exceptions import Ratelimited
|
||||
from mako.exceptions import TopLevelLookupException
|
||||
|
||||
from common.djangoapps.edxmako.shortcuts import render_to_response, render_to_string
|
||||
@@ -92,12 +94,32 @@ def render_press_release(request, slug):
|
||||
return resp
|
||||
|
||||
|
||||
@fix_crum_request
|
||||
def render_403(request, exception=None):
|
||||
"""
|
||||
Render the permission_denied template unless it's a ratelimit exception in which case use the rate limit template.
|
||||
"""
|
||||
if isinstance(exception, Ratelimited):
|
||||
return render_429(request, exception)
|
||||
|
||||
return permission_denied(request, exception)
|
||||
|
||||
|
||||
@fix_crum_request
|
||||
def render_404(request, exception): # lint-amnesty, pylint: disable=unused-argument
|
||||
request.view_name = '404'
|
||||
return HttpResponseNotFound(render_to_string('static_templates/404.html', {}, request=request))
|
||||
|
||||
|
||||
@fix_crum_request
|
||||
def render_429(request, exception=None): # lint-amnesty, pylint: disable=unused-argument
|
||||
"""
|
||||
Render the rate limit template as an HttpResponse.
|
||||
"""
|
||||
request.view_name = '429'
|
||||
return HttpResponse(render_to_string('static_templates/429.html', {}, request=request), status=429)
|
||||
|
||||
|
||||
@fix_crum_request
|
||||
def render_500(request):
|
||||
return HttpResponseServerError(render_to_string('static_templates/server-error.html', {}, request=request))
|
||||
|
||||
26
lms/templates/static_templates/429.html
Normal file
26
lms/templates/static_templates/429.html
Normal file
@@ -0,0 +1,26 @@
|
||||
<%page expression_filter="h"/>
|
||||
<%namespace name='static' file='../static_content.html'/>
|
||||
<%!
|
||||
from django.utils.translation import ugettext as _
|
||||
from openedx.core.djangolib.markup import HTML, Text
|
||||
%>
|
||||
<%inherit file="../main.html" />
|
||||
|
||||
<%block name="pagetitle">${_("Too Many Requests")}</%block>
|
||||
|
||||
<main id="main" aria-label="Content" tabindex="-1">
|
||||
<section class="outside-app">
|
||||
<h1>
|
||||
<%block name="pageheader">${page_header or _("Too Many Requests")}</%block>
|
||||
</h1>
|
||||
<p>
|
||||
<%block name="pagecontent">
|
||||
% if page_content:
|
||||
${page_content}
|
||||
% else:
|
||||
${Text(_('Your request has been rate-limited. Please try again later.'))}
|
||||
% endif
|
||||
</%block>
|
||||
</p>
|
||||
</section>
|
||||
</main>
|
||||
@@ -7,6 +7,7 @@ from django.conf import settings
|
||||
from django.conf.urls import include, url
|
||||
from django.conf.urls.static import static
|
||||
from django.contrib.admin import autodiscover as django_autodiscover
|
||||
from django.urls import path
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.views.generic.base import RedirectView
|
||||
from edx_api_doc_tools import make_docs_urls
|
||||
@@ -69,7 +70,9 @@ if settings.DEBUG or settings.FEATURES.get('ENABLE_DJANGO_ADMIN_SITE'):
|
||||
# Custom error pages
|
||||
# These are used by Django to render these error codes. Do not remove.
|
||||
# pylint: disable=invalid-name
|
||||
handler403 = static_template_view_views.render_403
|
||||
handler404 = static_template_view_views.render_404
|
||||
handler429 = static_template_view_views.render_429
|
||||
handler500 = static_template_view_views.render_500
|
||||
|
||||
notification_prefs_urls = [
|
||||
@@ -198,6 +201,10 @@ urlpatterns = [
|
||||
),
|
||||
url(r'^api/discounts/', include(('openedx.features.discounts.urls', 'openedx.features.discounts'),
|
||||
namespace='api_discounts')),
|
||||
path('403', handler403),
|
||||
path('404', handler404),
|
||||
path('429', handler429),
|
||||
path('500', handler500),
|
||||
]
|
||||
|
||||
if settings.FEATURES.get('ENABLE_MOBILE_REST_API'):
|
||||
|
||||
@@ -137,7 +137,7 @@ class LoginAndRegistrationTest(ThirdPartyAuthTestMixin, UrlResetMixin, ModuleSto
|
||||
|
||||
# then the rate limiter should kick in and give a HttpForbidden response
|
||||
response = self.client.get(login_url)
|
||||
self.assertEqual(response.status_code, 403)
|
||||
self.assertEqual(response.status_code, 429)
|
||||
|
||||
# now reset the time to 6 mins from now in future in order to unblock
|
||||
reset_time = datetime.now(UTC) + timedelta(seconds=361)
|
||||
|
||||
Reference in New Issue
Block a user