cconnected.
Understand the pattern. Find your own way.Find your starting point
Your learning feed/Idea 175 of 218
Ideas this builds on
Low-level design175 / 218

Chain of responsibility: pass a request along

Picture

First check whether its shape is valid. Then check permission. Finally call the business operation.

Predict

Should a denied request continue to the final operation?

Walk through the small example

No. Correct. Rejection must stop this chain before the protected action.

Mental model and complete Python solution

The chain consists of validation handlers. Each raises to stop processing or returns to let the next handler run. The dispatcher invokes the business action only after every check passes. More general chains can stop after a handler produces a result. Middleware is a related structure; wrappers with before-and-after behavior also resemble decorators. The example assumes request identity has already been authenticated elsewhere.

What the function promises: Requests are dictionaries with a nonempty string action and a trusted allowed flag. This is a control-flow demonstration, not a real authentication or authorization scheme.

def validate(request):
    if not isinstance(request.get("action"), str) or not request["action"]:
        raise ValueError("Missing action")

def authorize(request):
    if request.get("allowed") is not True:
        raise PermissionError("Action denied")

def dispatch(request, handlers, action):
    for handler in handlers:
        handler(request)
    return action(request)

calls = []
result = dispatch({"action": "save", "allowed": True},
                  [validate, authorize], lambda r: calls.append(r["action"]))
assert calls == ["save"]
try:
    dispatch({"action": "save", "allowed": False},
             [validate, authorize], lambda r: calls.append(r["action"]))
except PermissionError:
    pass
assert calls == ["save"]

Work and storage: O(number of handlers) dispatch overhead plus each handler’s own work.

When to recognize it: Each handler decides whether to reject or forward. Keep that decision visible instead of scattering checks across callers.

Check before applying it: Handler order and trust boundaries matter. Client-provided permission claims are not authorization.

Change one rule

A client supplies its own allowed=true field. Is that a trustworthy permission decision?

See what changes

No. The authorization handler must derive permission from trusted identity and server-side policy. The demonstration flag is explicitly not a production security design.

Connect

Agree on a small promise: Every handler needs an explicit input, failure, and continuation contract.

Make an API safe to call again: An API boundary composes validation, authorization, and business handling.