How to Mock X-RateLimit Headers in Python

This code creates a local HTTP server that mimics rate limit headers (X-RateLimit-Limit, Remaining, Reset, Update) and returns 429 responses when the limit is exceeded.

Medium Python 3.9+ Aug 9, 2026 API design & gRPC 13 views 0 copies

Python code

55 lines
Python 3.9+
import time
import threading
from http.server import BaseHTTPRequestHandler, HTTPServer


class RateLimitHandler(BaseHTTPRequestHandler):
    RATE_LIMIT = 5          # max requests allowed
    WINDOW_SECONDS = 60     # per time window

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.request_count = 0
        self.window_start = time.time()
        self.lock = threading.Lock()

    def _reset_if_needed(self):
        now = time.time()
        if now - self.window_start >= self.WINDOW_SECONDS:
            self.window_start = now
            self.request_count = 0

    def do_GET(self):
        with self.lock:
            self._reset_if_needed()
            self.request_count += 1
            remaining = max(0, self.RATE_LIMIT - self.request_count)
            reset_epoch = int(self.window_start + self.WINDOW_SECONDS)
            update_epoch = int(self.window_start)

            if self.request_count > self.RATE_LIMIT:
                self.send_response(429)
                self.send_header("X-RateLimit-Limit", str(self.RATE_LIMIT))
                self.send_header("X-RateLimit-Remaining", "0")
                self.send_header("X-RateLimit-Reset", str(reset_epoch))
                self.send_header("X-RateLimit-Update", str(update_epoch))
                self.end_headers()
                self.wfile.write(b"Rate limit exceeded")
            else:
                self.send_response(200)
                self.send_header("X-RateLimit-Limit", str(self.RATE_LIMIT))
                self.send_header("X-RateLimit-Remaining", str(remaining))
                self.send_header("X-RateLimit-Reset", str(reset_epoch))
                self.send_header("X-RateLimit-Update", str(update_epoch))
                self.end_headers()
                self.wfile.write(b"Request accepted")


def run_server():
    server = HTTPServer(("127.0.0.1", 8000), RateLimitHandler)
    print("Mock rate-limited server on http://127.0.0.1:8000")
    server.serve_forever()


if __name__ == "__main__":
    run_server()

Output

stdout
When you run the server and make requests, the first 5 requests return 200 with headers like:
X-RateLimit-Limit: 5
X-RateLimit-Remaining: 4
...then subsequent requests return 429 with X-RateLimit-Remaining: 0. The server prints: "Mock rate-limited server on http://127.0.0.1:8000" to the console.

How it works

The handler uses a rolling window to track requests. Each request updates the count and calculates remaining requests. When the limit is exceeded, it sends a 429 status with the rate limit headers. The _reset_if_needed method clears the count after the time window expires. The lock ensures thread safety since the server may handle multiple connections. Headers provide standard rate limit info for client-side logic.

Common mistakes

  • Forgetting to call `end_headers()` before writing the body
  • Not resetting the window correctly when time goes backwards
  • Using `int(time.time())` for the reset header instead of the window start plus window seconds
  • Incrementing the count before checking the limit, causing off-by-one errors

Variations

  1. Use a decorator or middleware in a framework like Flask to add rate limit headers
  2. Store request counts in a dictionary keyed by IP address for per-client limits

Real-world use cases

  • Testing client-side handling of rate limit responses in development without hitting a real API.
  • Simulating API rate limits in integration tests for backoff and retry logic.
  • Building a mock server for API documentation examples or local development environments.

Sponsored

Run this sample

Open the browser IDE to tweak the example and see results without installing anything.

Open editor

More from API design & gRPC

Related tutorials and quizzes for this topic.