# main.py from fastapi import FastAPI, Depends, HTTPException, Security from fastapi.security import APIKeyHeader from fastapi.middleware.cors import CORSMiddleware from fastapi import Request, Query from fastapi.templating import Jinja2Templates from fastapi import File, UploadFile from fastapi.responses import FileResponse from fastapi.responses import Response from pydantic import BaseModel from serpapi import GoogleSearch import os app = FastAPI(title="SerpApi Research Backend") app.add_middleware( CORSMiddleware, allow_origins=["*"], allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) # Security setup api_key_header = APIKeyHeader(name="X-API-Key") SERPAPI_KEY = os.getenv("SERPAPI_SECRET") # Set in Hugging Face secrets class SearchQuery(BaseModel): query: str engine: str = "google" num_results: int = 10 def get_serpapi_client(): if not SERPAPI_KEY: raise HTTPException( status_code=500, detail="SerpApi configuration missing" ) return GoogleSearch({"api_key": SERPAPI_KEY}) def verify_api_key(api_key: str = Security(api_key_header)): print("api_key: " + api_key) if api_key != os.getenv("API_SECRET_KEY"): raise HTTPException( status_code=401, detail="Invalid API key" ) return True templates = Jinja2Templates(directory=".") @app.get("/") def read_root(request: Request): return templates.TemplateResponse("index.html", {"request": request}) @app.post("/search") async def perform_search( search_query: SearchQuery, _: bool = Depends(verify_api_key) ): try: #client = get_serpapi_client() params = { "q": search_query.query, "engine": search_query.engine, "num": search_query.num_results, "api_key": SERPAPI_KEY } # Initialize GoogleSearch with parameters search = GoogleSearch(params) # Fetch results as a dictionary results = search.get_dict() #results = client.get_dict(params) return { "organic_results": results.get("organic_results", []), "related_searches": results.get("related_searches", []) } except Exception as e: raise HTTPException( status_code=500, detail=f"Search failed: {str(e)}" ) @app.get("/health") async def health_check(): return {"status": "operational"}