I am in the process of migrating an existing django project to use wagtail CMS.
I am unclear how I can ratelimit using wagtail, I see nothing about it in the documentation.
Take the following example:
Before integrating wagtail, I had a view which would return a privacy policy html page. This was ratelimited using redis, you can see the method decorator and method below
@ratelimit(
key='ip',
rate='15/m',
block=True
)
def show_privacy_policy(request):
context = base_context(request)
return render(
request,
'pages/privacy_policy.html',
context
)
Now this is removed, and I have a more generic wagtail Page which is used to render pages such as terms and conditions or privacy policy, I call this an InfoPage
. The only thing I have defined is my InfoPage model which has a template path attached wagtail/info_page.html
.
class InfoPage(Page):
template = "wagtail/info_page.html"
last_modified_date = models.DateField("Last modified date")
body = RichTextField(features=['bold', 'italic', 'link', 'ul', 'h3'])
content_panels = Page.content_panels + [
FieldPanel('last_modified_date'),
FieldPanel('body')
]
parent_page_types = ['news.Index']
subpage_types = []
This simply just works, and all of my InfoPages are rendered correctly. However, I do not see any way to ratelimit access to these pages. If there is no way to ratelimit, I am susceptible to DDOS attacks and more. What am I missing here? Is there a way to ratelimit access or do I need to take a different approach?
2
Answers
Rather than rate limit, I would suggest using a frontend cache so it is cheap to serve the rendered page. I use Cloudflare with the built-enter link description herein cache invalidator. There are a number of cache invalidators included with the stock Wagtail distro or you could use wagtail-cache from CodeRed.
All Wagtail page objects implement a
serve
method that behaves in the same way as a Django view, accepting a request object and returning a response. The@ratelimit
decorator could most likely be applied here. However, this probably won’t be very effective, since Wagtail has to perform a number of database queries just to find out which page corresponds to a given URL – by the time you’ve arrived at a page object, the request has already consumed a non-trivial amount of server resources.I would recommend applying rate limiting at the web server level – for example, see the Nginx documentation on rate limiting – or externally using a service such as Cloudflare, as @cnk suggests. These options will almost certainly be more security-hardened and better-performing than anything done at the Django / Python application layer.