import os import secrets import shutil from pathlib import Path from fastapi import FastAPI, UploadFile, File, Depends, HTTPException, status from fastapi.staticfiles import StaticFiles from fastapi.security import HTTPBasic, HTTPBasicCredentials from dotenv import load_dotenv # Load .env for local dev (ignored by Hugging Face) load_dotenv() app = FastAPI(title="Image Upload API for Hugging Face Spaces") # Auth setup security = HTTPBasic() ADMIN_USERNAME = os.getenv("ADMIN_USERNAME") ADMIN_PASSWORD = os.getenv("ADMIN_PASSWORD") # Upload dir UPLOAD_DIR = "/tmp/images" Path(UPLOAD_DIR).mkdir(parents=True, exist_ok=True) # Auth dependency def verify_admin(credentials: HTTPBasicCredentials = Depends(security)): correct_user = secrets.compare_digest(credentials.username, ADMIN_USERNAME) correct_pass = secrets.compare_digest(credentials.password, ADMIN_PASSWORD) if not (correct_user and correct_pass): raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail="Invalid credentials", headers={"WWW-Authenticate": "Basic"}, ) return credentials.username @app.get("/") def read_root(): return {"message": "Welcome to the Hugging Face Image Upload API!"} @app.post("/upload") def upload_image(file: UploadFile = File(...), username: str = Depends(verify_admin)): file_ext = Path(file.filename).suffix safe_name = file.filename.replace(" ", "_") dest_path = Path(UPLOAD_DIR) / safe_name with open(dest_path, "wb") as out_file: shutil.copyfileobj(file.file, out_file) return { "message": "Image uploaded successfully.", "filename": safe_name, "url": f"/images/{safe_name}" } # Serve images statically app.mount("/images", StaticFiles(directory=UPLOAD_DIR), name="images")