abinazebinoy commited on
Commit
091223d
·
1 Parent(s): 91db04e

refactor(analyze): use shared json_safe.sanitize()

Browse files

Replaces the module-level _sanitize() definition with an import from
the new shared module. All existing call sites unchanged (imported
under the same local name).

Files changed (1) hide show
  1. backend/api/routes/analyze.py +1 -33
backend/api/routes/analyze.py CHANGED
@@ -8,8 +8,6 @@ from slowapi import Limiter
8
  from slowapi.util import get_remote_address
9
  import hashlib
10
  import time
11
- import math as _math
12
- import numpy as _np
13
  from typing import List
14
 
15
  from backend.services.image_forensics import ImageForensics
@@ -20,41 +18,11 @@ from backend.core.cache import forensics_cache
20
  from backend.services.metrics_collector import record_analysis
21
  from backend.core.audit_log import log_analysis
22
  from backend.core.config import settings
 
23
 
24
  logger = setup_logger(__name__)
25
 
26
 
27
- def _sanitize(obj):
28
- """Recursively replace NaN/Infinity floats with 0.0 (F-8, F-27).
29
-
30
- json.dumps() happily emits the literal tokens NaN/Infinity, which
31
- are not valid per RFC 8259 and many non-Python JSON parsers reject
32
- outright. Division-by-zero guards throughout the signal detectors
33
- (e.g. "+ 1e-8" denominators in several cosine-similarity calcs)
34
- mean a signal can legitimately produce a non-finite float.
35
-
36
- This single shared helper replaces the two near-duplicate copies
37
- that used to live inline in analyze_image() -- one for the
38
- cache-miss path, one for the cache-hit path (_sanitize_hit) -- which
39
- is exactly the kind of drift risk this project has been bitten by
40
- before (see F-4). It is now called ONCE, immediately after
41
- generate_forensic_report() returns and before the report is cached,
42
- sent to any webhook, or written to the audit log -- previously all
43
- three saw the raw, unsanitized report, and only the direct HTTP
44
- response (sanitized too late, right before returning) was
45
- guaranteed clean.
46
- """
47
- if isinstance(obj, _np.generic):
48
- return obj.item()
49
- if isinstance(obj, float):
50
- return 0.0 if (_math.isnan(obj) or _math.isinf(obj)) else obj
51
- if isinstance(obj, dict):
52
- return {k: _sanitize(v) for k, v in obj.items()}
53
- if isinstance(obj, list):
54
- return [_sanitize(v) for v in obj]
55
- return obj
56
-
57
-
58
  def _correct_exif_orientation(file_bytes: bytes) -> bytes:
59
  """Apply EXIF orientation before all forensic analysis.
60
 
 
8
  from slowapi.util import get_remote_address
9
  import hashlib
10
  import time
 
 
11
  from typing import List
12
 
13
  from backend.services.image_forensics import ImageForensics
 
18
  from backend.services.metrics_collector import record_analysis
19
  from backend.core.audit_log import log_analysis
20
  from backend.core.config import settings
21
+ from backend.utils.json_safe import sanitize as _sanitize
22
 
23
  logger = setup_logger(__name__)
24
 
25
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
26
  def _correct_exif_orientation(file_bytes: bytes) -> bytes:
27
  """Apply EXIF orientation before all forensic analysis.
28