LogicGoInfotechSpaces's picture
Integrate FastAI colorization with Firebase auth and Gradio UI - Replace main.py with FastAI implementation - Add Gradio interface for Space UI - Add Firebase authentication to /colorize endpoint - Add curl examples documentation - Update test.py with User-Agent headers
e4599d1
raw
history blame
5.77 kB
import argparse
import io
import json
import logging
import os
import sys
import time
from typing import Optional
import requests
def configure_logging(verbose: bool) -> None:
log_level = logging.DEBUG if verbose else logging.INFO
logging.basicConfig(
level=log_level,
format="%(asctime)s - %(levelname)s - %(message)s"
)
def get_base_url(cli_base_url: Optional[str]) -> str:
if cli_base_url:
return cli_base_url.rstrip("/")
env_base = os.getenv("BASE_URL")
if env_base:
return env_base.rstrip("/")
# Fallback to HF style URL if provided via POSTMAN collection, else localhost
return "http://localhost:7860"
def wait_for_model(base_url: str, timeout_seconds: int = 300) -> None:
deadline = time.time() + timeout_seconds
health_url = f"{base_url}/health"
logging.info("Waiting for model to load at %s", health_url)
last_status = None
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"}
while time.time() < deadline:
try:
resp = requests.get(health_url, headers=headers, timeout=15)
if resp.ok:
data = resp.json()
last_status = data
if data.get("model_loaded"):
logging.info("Model loaded: %s", json.dumps(data))
return
logging.info("Health: %s", json.dumps(data))
else:
logging.warning("Health check HTTP %s", resp.status_code)
except Exception as e:
logging.warning("Health check error: %s", str(e))
time.sleep(3)
raise RuntimeError("Model did not load before timeout. Last health: %s" % (last_status,))
def upload_image(base_url: str, image_path: str, auth_bearer: Optional[str], app_check: Optional[str]) -> dict:
url = f"{base_url}/upload"
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"}
if auth_bearer:
headers["Authorization"] = f"Bearer {auth_bearer}"
if app_check:
headers["X-Firebase-AppCheck"] = app_check
with open(image_path, "rb") as f:
files = {"file": (os.path.basename(image_path), f, "image/jpeg")}
resp = requests.post(url, files=files, headers=headers, timeout=120)
if not resp.ok:
raise RuntimeError("Upload failed: HTTP %s %s" % (resp.status_code, resp.text))
data = resp.json()
logging.info("Upload response: %s", json.dumps(data))
return data
def colorize_image(base_url: str, image_path: str, auth_bearer: Optional[str], app_check: Optional[str]) -> dict:
url = f"{base_url}/colorize"
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"}
if auth_bearer:
headers["Authorization"] = f"Bearer {auth_bearer}"
if app_check:
headers["X-Firebase-AppCheck"] = app_check
with open(image_path, "rb") as f:
files = {"file": (os.path.basename(image_path), f, "image/jpeg")}
resp = requests.post(url, files=files, headers=headers, timeout=900)
if not resp.ok:
raise RuntimeError("Colorize failed: HTTP %s %s" % (resp.status_code, resp.text))
data = resp.json()
logging.info("Colorize response: %s", json.dumps(data))
return data
def download_result(base_url: str, result_id: str, output_path: str, auth_bearer: Optional[str], app_check: Optional[str]) -> None:
url = f"{base_url}/download/{result_id}"
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"}
if auth_bearer:
headers["Authorization"] = f"Bearer {auth_bearer}"
if app_check:
headers["X-Firebase-AppCheck"] = app_check
resp = requests.get(url, headers=headers, stream=True, timeout=300)
if not resp.ok:
raise RuntimeError("Download failed: HTTP %s %s" % (resp.status_code, resp.text))
with open(output_path, "wb") as out:
for chunk in resp.iter_content(chunk_size=8192):
if chunk:
out.write(chunk)
logging.info("Saved colorized image to: %s", output_path)
def main() -> int:
parser = argparse.ArgumentParser(description="End-to-end test for Colorize API")
parser.add_argument("--base-url", type=str, help="API base URL, e.g. https://<space>.hf.space")
parser.add_argument("--image", type=str, required=True, help="Path to input image")
parser.add_argument("--out", type=str, default="colorized_result.jpg", help="Path to save colorized image")
parser.add_argument("--auth", type=str, default=os.getenv("ID_TOKEN", ""), help="Optional Firebase id_token")
parser.add_argument("--app-check", type=str, default=os.getenv("APP_CHECK_TOKEN", ""), help="Optional App Check token")
parser.add_argument("--skip-wait", action="store_true", help="Skip waiting for model to load")
parser.add_argument("--verbose", action="store_true", help="Verbose logging")
args = parser.parse_args()
configure_logging(args.verbose)
base_url = get_base_url(args.base_url)
image_path = args.image
if not os.path.exists(image_path):
logging.error("Image not found: %s", image_path)
return 1
if not args.skip_wait:
try:
wait_for_model(base_url, timeout_seconds=600)
except Exception as e:
logging.warning("Continuing despite health wait failure: %s", str(e))
auth_bearer = args.auth.strip() or None
app_check = args.app_check.strip() or None
try:
upload_resp = upload_image(base_url, image_path, auth_bearer, app_check)
except Exception as e:
logging.error("Upload error: %s", str(e))
return 1
try:
colorize_resp = colorize_image(base_url, image_path, auth_bearer, app_check)
except Exception as e:
logging.error("Colorize error: %s", str(e))
return 1
result_id = colorize_resp.get("result_id")
if not result_id:
logging.error("No result_id in response: %s", json.dumps(colorize_resp))
return 1
try:
download_result(base_url, result_id, args.out, auth_bearer, app_check)
except Exception as e:
logging.error("Download error: %s", str(e))
return 1
logging.info("Test workflow completed successfully.")
return 0
if __name__ == "__main__":
sys.exit(main())