Exercise 2: Swapping Middleware Registration Order — Possible Solution ==================================================================== THE MIDDLEWARES ------------------------------ def auth_middleware(request, next_): request.state.setdefault('trace', []).append('auth check') if request.environ.get('HTTP_X_API_KEY') != 'secret123': request.state['trace'].append('auth REJECTED') return Response(f"401, trace={request.state['trace']}", status=401) return next_(request) def logging_middleware(request, next_): request.state.setdefault('trace', []).append('logging before') response = next_(request) request.state['trace'].append('logging after') return response TWO REAL Apps, TWO REAL ORDERS ------------------------------ orig_app = App() orig_app.use(auth_middleware) orig_app.use(logging_middleware) orig_app.add_route('GET', '/', traced_handler) swapped_app = App() swapped_app.use(logging_middleware) swapped_app.use(auth_middleware) swapped_app.add_route('GET', '/', traced_handler) VERIFIED, REAL RESULTS (both requests sent with no X-Api-Key header) ------------------------------ orig_app (auth, then logging): 401, trace=['auth check', 'auth REJECTED'] swapped_app (logging, then auth): 401, trace=['logging before', 'auth check', 'auth REJECTED'] WHAT ACTUALLY CHANGES ------------------------------ In the original order, logging_middleware sits INSIDE auth_middleware in the real nested chain, so auth's own short-circuit return never even reaches it - 'logging before' never appears in the trace at all. In the swapped order, logging_middleware sits OUTSIDE auth_middleware, so its own "before next_()" code genuinely runs first, before auth_middleware ever gets a chance to reject the request - confirmed directly by 'logging before' appearing as the real first trace entry. In neither order does 'logging after' ever appear, since auth_middleware's own short-circuit return means logging_middleware's own call to next_() is never reached in either arrangement, and so its own "after" line has nothing to run after. WHY THIS WORKS AS AN ANSWER ------------------------------ It builds two real, independently configured App instances rather than reasoning about the swap abstractly, sends the identical real unauthenticated request to both, and reads the answer directly out of request.state's own recorded trace - confirming registration order is a genuine, observable behavior difference, not just a theoretical one.