Wiring handlers by hand with repeated set_next calls gets tedious. A small builder takes a list of handlers and links them into a chain, returning the head so callers can dispatch through it.
Implement build_chain(handlers):
Now assembling a pipeline is one call: build_chain([AuthHandler(), AppHandler()]) returns the auth handler already linked to the app.
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):
user = request.get("user")
self.counts[user] = self.counts.get(user, 0) + 1
if self.counts[user] > self.limit:
return {"status": 429, "body": "rate limited"}
return super().handle(request)
def build_chain(handlers):
"""Link each handler to the next and return the head of the chain."""
# TODO: for i in range(len(handlers) - 1): handlers[i].set_next(handlers[i + 1])
# TODO: return handlers[0]
pass
The editor and the test runner need a wide screen. Open this page on a desktop browser and your progress will be waiting.
Wiring handlers by hand with repeated set_next calls gets tedious. A small builder takes a list of handlers and links them into a chain, returning the head so callers can dispatch through it.
Implement build_chain(handlers):
Now assembling a pipeline is one call: build_chain([AuthHandler(), AppHandler()]) returns the auth handler already linked to the app.
Press Run Tests or ββ© to check your solution.