python / expert
Snippet
Custom Django Middleware with Request/Response Processing Pipeline
Django middleware sits between the web server and your view, processing every request and response. This expert-level middleware implements rate limiting using an in-memory counter, tracks request counts per IP address, blocks excessive requests with HTTP 429, and injects custom headers into responses. The __init__ receives the get_response callable, __call__ processes each request/response pair, and process_exception handles unexpected errors globally.
snippet.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
from django.http import JsonResponsefrom django.utils.deprecation import MiddlewareMixinclass RateLimitMiddleware(MiddlewareMixin):def __init__(self, get_response):self.get_response = get_responseself.request_counts = {}def __call__(self, request):client_ip = request.META.get('REMOTE_ADDR')self.request_counts[client_ip] = self.request_counts.get(client_ip, 0) + 1if self.request_counts[client_ip] > 100:return JsonResponse({'error': 'Rate limit exceeded'}, status=429)response = self.get_response(request)response['X-Request-Count'] = self.request_counts[client_ip]return responsedef process_exception(self, request, exception):return JsonResponse({'error': str(exception)}, status=500)
django
Breakdown
1
from django.utils.deprecation import MiddlewareMixin
Imports MiddlewareMixin for compatibility with Django's middleware framework
2
def __init__(self, get_response):
Initializer receives the next middleware/view in the chain as get_response
3
self.request_counts = {}
In-memory dictionary storing request counts per client IP
4
client_ip = request.META.get('REMOTE_ADDR')
Extracts client IP from request metadata for rate tracking
5
if self.request_counts[client_ip] > 100:
Checks if client has exceeded the rate limit threshold
6
return JsonResponse({'error': 'Rate limit exceeded'}, status=429)
Returns 429 Too Many Requests when limit is exceeded
7
response['X-Request-Count'] = self.request_counts[client_ip]
Injects custom header with current request count into response
8
def process_exception(self, request, exception):
Override to catch and transform unhandled exceptions globally