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.