The Rate Limit Handler

Step 4: The Rate Limit Handler

Between auth and the app, real pipelines throttle abusive callers. RateLimitHandler tracks how many times each user has called and rejects them once they exceed a limit.

The init is provided: it stores an injected limit and an empty per-user counter dict self.counts.

Implement RateLimitHandler.handle(request):

  • Read the user with request.get("user").
  • Increment that user's count: self.counts[user] = self.counts.get(user, 0) + 1.
  • If the user's count is now greater than self.limit, return {"status": 429, "body": "rate limited"} and stop the chain.
  • Otherwise pass down with super().handle(request).

Now the full chain is auth then ratelimit then app. With a limit of 1, the first call for a user gets through and the second gets a 429.

Hints
Starter code
class Handler:
    def __init__(self):
        self._next = None

    def set_next(self, handler):
        self._next = handler
        return handler

    def handle(self, request):
        if self._next is not None:
            return self._next.handle(request)
        return None


class AuthHandler(Handler):
    def handle(self, request):
        if request.get("user") is None:
            return {"status": 401, "body": "unauthorized"}
        return super().handle(request)


class AppHandler(Handler):
    def handle(self, request):
        return {"status": 200, "body": "ok:" + request["path"]}


class RateLimitHandler(Handler):
    def __init__(self, limit):
        super().__init__()
        self.limit = limit
        self.counts = {}

    def handle(self, request):
        """Count this user's calls; block over the limit, else pass down."""
        # TODO: read the "user" key off the request and bump that caller's tally
        #   in self.counts, treating a caller you have never seen as zero so far.
        #   A tally that now exceeds self.limit ends the chain with a dict whose
        #   status is 429 and body is "rate limited"; otherwise pass down.
        pass
Write it on a laptop

The editor and the test runner need a wide screen. Open this page on a desktop browser and your progress will be waiting.