Coverage for src / local_deep_research / security / decorators.py: 100%

16 statements  

« prev     ^ index     » next       coverage.py v7.13.5, created at 2026-04-14 23:55 +0000

1""" 

2Request validation decorators for Flask route handlers. 

3""" 

4 

5from functools import wraps 

6 

7from flask import jsonify, request 

8 

9 

10def require_json_body( 

11 *, 

12 error_format="simple", 

13 error_message="Request body must be valid JSON", 

14): 

15 """Decorator that validates request body is a JSON dict. 

16 

17 Returns 400 if the parsed body is not a ``dict``. The decorated function 

18 is responsible for calling ``request.get_json()`` (or ``request.json``) 

19 itself — Flask caches the result so there is no duplicate parsing. 

20 

21 Args: 

22 error_format: Response format on failure. 

23 ``"simple"`` → ``{"error": msg}`` 

24 ``"status"`` → ``{"status": "error", "message": msg}`` 

25 ``"success"`` → ``{"success": False, "error": msg}`` 

26 error_message: The error message string. 

27 """ 

28 

29 def decorator(fn): 

30 @wraps(fn) 

31 def wrapper(*args, **kwargs): 

32 data = request.get_json(silent=True) 

33 if not isinstance(data, dict): 

34 if error_format == "status": 

35 return ( 

36 jsonify({"status": "error", "message": error_message}), 

37 400, 

38 ) 

39 if error_format == "success": 

40 return ( 

41 jsonify({"success": False, "error": error_message}), 

42 400, 

43 ) 

44 # "simple" 

45 return jsonify({"error": error_message}), 400 

46 return fn(*args, **kwargs) 

47 

48 return wrapper 

49 

50 return decorator