"""Generic, leak-free handlers for breaker-open (503) and rate-limit (429).""" from flask import Flask, Response from owsresponse import response from owsresponse.adaptors.flask import flaskify from werkzeug.exceptions import TooManyRequests from core.hardening.breaker import CircuitBreakerError def register_hardening_error_handlers(app: Flask) -> None: """Register generic 503 (breaker) and 429 (rate-limit) handlers on the app. Both render a fixed message so the circuit/resource name and the rate-limit policy string never reach the client. """ @app.errorhandler(CircuitBreakerError) def _breaker_open(_e: CircuitBreakerError) -> Response: return flaskify( response.create_error_response( message='service temporarily unavailable', status=503, code='error', ) ) @app.errorhandler(TooManyRequests) def _rate_limited(_e: TooManyRequests) -> Response: # The default handler would render the limit policy string; this stays generic. # Catching TooManyRequests also covers flask_limiter's RateLimitExceeded subclass. return flaskify( response.create_error_response( message='rate limit exceeded', status=429, code='error', ) )