feat: Add per-site debug toggle for HTML dump control

- Add debug_enabled field to SearchSite model
- Update schemas and API routes to allow debug toggle
- Add debug toggle button on site cards in Admin UI
- Only dump HTML when debug is enabled for the site (except for critical errors like Amazon blocking)
- Add API endpoints to list/delete debug files per site domain
- Add button to clear debug files for individual sites
This commit is contained in:
Claude committed 2025-11-24 08:01:39 +00:00
1 parent 7243bcfaa1
commit e62117f9b9
7 files changed
+157 -17

No files matched your search

+67 -4
View File
@@ -75,19 +75,82 @@ def delete_debug_dump(filename: str):
"""Delete a specific debug dump file"""
if not os.path.exists(DEBUG_DIR):
raise HTTPException(status_code=404, detail="Debug directory not found")
filepath = os.path.join(DEBUG_DIR, filename)
# Security check: prevent directory traversal
if not os.path.abspath(filepath).startswith(os.path.abspath(DEBUG_DIR)):
raise HTTPException(status_code=403, detail="Access denied")
if not os.path.isfile(filepath):
raise HTTPException(status_code=404, detail="File not found")
try:
os.remove(filepath)
return {"message": "File deleted"}
except Exception as e:
logger.error(f"Error deleting debug dump {filename}: {e}")
raise HTTPException(status_code=500, detail=str(e))
@router.get("/dumps/site/{domain}", response_model=List[DebugFile])
def list_debug_dumps_by_site(domain: str):
"""List debug dump files for a specific site domain"""
if not os.path.exists(DEBUG_DIR):
return []
# Clean domain for comparison (remove www. if present)
clean_domain = domain.lower().strip()
if clean_domain.startswith("www."):
clean_domain = clean_domain[4:]
files = []
try:
for filename in os.listdir(DEBUG_DIR):
# Check if filename starts with the domain
filename_lower = filename.lower()
# Handle both formats: domain_query_timestamp.html and amazon.fr_query_timestamp.html
if filename_lower.startswith(clean_domain) or filename_lower.startswith(clean_domain.replace(".", "_")):
filepath = os.path.join(DEBUG_DIR, filename)
if os.path.isfile(filepath):
stat = os.stat(filepath)
files.append(DebugFile(
filename=filename,
size=stat.st_size,
created_at=stat.st_ctime,
created_at_formatted=datetime.fromtimestamp(stat.st_ctime).strftime("%Y-%m-%d %H:%M:%S")
))
# Sort by creation time (newest first)
files.sort(key=lambda x: x.created_at, reverse=True)
return files
except Exception as e:
logger.error(f"Error listing debug dumps for site {domain}: {e}")
raise HTTPException(status_code=500, detail=str(e))
@router.delete("/dumps/site/{domain}")
def delete_debug_dumps_by_site(domain: str):
"""Delete all debug dump files for a specific site domain"""
if not os.path.exists(DEBUG_DIR):
return {"message": "No files found", "deleted": 0}
# Clean domain for comparison
clean_domain = domain.lower().strip()
if clean_domain.startswith("www."):
clean_domain = clean_domain[4:]
deleted_count = 0
try:
for filename in os.listdir(DEBUG_DIR):
filename_lower = filename.lower()
if filename_lower.startswith(clean_domain) or filename_lower.startswith(clean_domain.replace(".", "_")):
filepath = os.path.join(DEBUG_DIR, filename)
if os.path.isfile(filepath):
os.remove(filepath)
deleted_count += 1
return {"message": f"{deleted_count} file(s) deleted", "deleted": deleted_count}
except Exception as e:
logger.error(f"Error deleting debug dumps for site {domain}: {e}")
raise HTTPException(status_code=500, detail=str(e))