dev.altai / api.py
prince1604
Add health check endpoint for uptime monitoring
a09c50d
Raw
History Blame
5.21 kB
from flask import Flask, jsonify, request
from flask_cors import CORS
import json
import os
import random
from src.crawler import Crawler
from src.analyzer import ImageAnalyzer
app = Flask(__name__)
CORS(app)
REPORT_FILE = 'seo_report.json'
@app.route('/')
def home():
return "Antigravity API is Running. Use /health to check status."
@app.route('/health')
def health_check():
return jsonify({"status": "alive"}), 200
@app.route('/api/seo-report', methods=['GET', 'POST'])
def get_seo_report():
# Cache variable attached to function to persist state
if not hasattr(get_seo_report, "cache"):
get_seo_report.cache = {"data": None, "mtime": 0}
def get_cached_report():
if not os.path.exists(REPORT_FILE):
return None
current_mtime = os.path.getmtime(REPORT_FILE)
if get_seo_report.cache["data"] is None or current_mtime > get_seo_report.cache["mtime"]:
try:
with open(REPORT_FILE, 'r', encoding='utf-8') as f:
get_seo_report.cache["data"] = json.load(f)
get_seo_report.cache["mtime"] = current_mtime
except Exception as e:
# If read fails, return None or raise
return None
return get_seo_report.cache["data"]
def get_param(name, default):
val = request.args.get(name) or request.form.get(name)
if val is None and request.is_json:
val = request.json.get(name)
return val if val is not None else default
# Global Caching for Domain Crawls (Active Memory Cache)
if not hasattr(get_seo_report, "domain_cache"):
get_seo_report.domain_cache = {}
domain = get_param('domain', None)
limit = int(get_param('limit', 25))
if domain:
# Check Cache (TTL 10 minutes)
cache_key = f"{domain}_{limit}"
cached_item = get_seo_report.domain_cache.get(cache_key)
import time
if cached_item:
timestamp, data = cached_item
# 600 seconds = 10 minutes
if time.time() - timestamp < 600:
print(f"Returning Cached Result for {domain}")
return jsonify(data)
try:
print(f"Starting live scan for: {domain}")
# Initialize Crawler
crawler = Crawler()
# Crawl the domain with the requested limit
site_data, total_discovered, _ = crawler.crawl_domain(domain, max_pages=limit)
if not site_data:
response = {
"summary": {
"total_pages_scanned": 0,
"total_images_found": 0,
"total_images_missing_alt": 0,
"total_pages_discovered": 0
},
"details": []
}
return jsonify(response)
# Analyze Results
analyzer = ImageAnalyzer()
results = analyzer.analyze_site(site_data)
# Add discovery stats
results['summary']['total_pages_discovered'] = total_discovered
results['details_count'] = len(results['details'])
# Save to Cache
get_seo_report.domain_cache[cache_key] = (time.time(), results)
return jsonify(results)
except Exception as e:
return jsonify({"error": f"Scraping failed: {str(e)}"}), 500
if not os.path.exists(REPORT_FILE):
return jsonify({"error": "Report file not found. Please run result logic first."}), 404
try:
data = get_cached_report()
if data is None:
# Fallback if file doesn't exist or read failed
# But if we are here, we passed the os.path.exists check earlier,
# so strictly speaking we should just handle the None case.
# The previous logic had a check for os.path.exists(REPORT_FILE) at line 59.
# We can retain that or rely on get_cached_report returning None.
return jsonify({"error": "Report file not found or unreadable."}), 404
# Get parameters for filtering existing report
# limit is already extracted above
random_param = str(get_param('random', 'true')).lower()
is_random = random_param == 'true'
summary = data.get('summary', {})
details = data.get('details', [])
# Filter details if limit is provided
if limit is not None and limit > 0:
if is_random and limit < len(details):
details = random.sample(details, limit)
else:
details = details[:limit]
response = {
"summary": summary,
"details_count": len(details), # Useful logic for client
"details": details
}
return jsonify(response)
except Exception as e:
return jsonify({"error": f"Failed to read report: {str(e)}"}), 500
if __name__ == '__main__':
# Run on 0.0.0.0 to be accessible if needed, default port 5000
app.run(debug=True, host='0.0.0.0', port=5050)