Learn the concept
A backend handler translates HTTP into application behavior. Keep its responsibilities small: authenticate, parse and validate, call domain logic, and convert the result into a response. Framework-specific routing should not contain all of your business rules.
Build and test the domain function first. A framework adapter can then expose it as an endpoint. This makes it possible to test behavior without opening a port. Status codes should reflect the contract; do not return a successful status with an unexplained error string for every failure.
Bound input sizes and avoid leaking stack traces or secrets in public responses. Internal logs can retain a request ID and failure stage. A beginner can practice the boundary with a plain function before selecting a web framework for deployment.
Run and inspect
def handle(payload):
if not isinstance(payload, dict): return 400, {"error": "Object required"}
text = payload.get("text")
if not isinstance(text, str) or not text.strip():
return 400, {"error": "Text required"}
return 200, {"length": len(text.strip())}
assert handle({"text": " hello "}) == (200, {"length": 5})
assert handle({})[0] == 400
Your exercise
Extend the handler with a maximum input length and a fake dependency that can time out. Keep dependency failures separate from validation errors.
Check your understanding
Invalid requests never call the dependency, and public error responses contain no internal traceback.