Refactor CustomSearchService to use updated environment variable names and add search endpoint with error handling
parent
8d9b084a0b
commit
cc9466ab60
|
|
@ -15,14 +15,14 @@ class CustomSearchService:
|
|||
cx: Optional[str] = None,
|
||||
timeout: float = 30.0,
|
||||
):
|
||||
self.api_key = api_key or os.getenv("GOOGLE_CSE_API_KEY")
|
||||
self.cx = cx or os.getenv("GOOGLE_CSE_CX")
|
||||
self.api_key = api_key or os.getenv("GEMINI_API_KEY")
|
||||
self.cx = cx or os.getenv("SEARCH_ENGINE_ID")
|
||||
self.timeout = timeout
|
||||
|
||||
if not self.api_key:
|
||||
raise ValueError("GOOGLE_CSE_API_KEY is not set in environment")
|
||||
raise ValueError("GEMINI_API_KEY is not set in environment")
|
||||
if not self.cx:
|
||||
raise ValueError("GOOGLE_CSE_CX is not set in environment")
|
||||
raise ValueError("SEARCH_ENGINE_ID is not set in environment")
|
||||
|
||||
async def search(
|
||||
self,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,59 @@
|
|||
import logging
|
||||
from typing import Optional
|
||||
from fastapi import APIRouter, HTTPException, Query
|
||||
from fastapi.responses import JSONResponse
|
||||
import httpx
|
||||
|
||||
from .service import CustomSearchService
|
||||
from .serializers import SearchResponse, SearchResultItem
|
||||
|
||||
app_router = APIRouter()
|
||||
|
||||
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@app_router.get("/search", response_model=SearchResponse)
|
||||
async def search_endpoint(
|
||||
q: str = Query(..., description="Search query string"),
|
||||
num: int = Query(10, ge=1, le=10, description="Number of results to return (1-10)"),
|
||||
start: int = Query(1, ge=1, description="Start index for pagination"),
|
||||
):
|
||||
try:
|
||||
service = CustomSearchService()
|
||||
data = await service.search(query=q, num=num, start=start)
|
||||
|
||||
items = [
|
||||
SearchResultItem(
|
||||
title=item.get("title"),
|
||||
link=item.get("link"),
|
||||
displayLink=item.get("displayLink"),
|
||||
snippet=item.get("snippet"),
|
||||
formattedUrl=item.get("formattedUrl"),
|
||||
pagemap=item.get("pagemap"),
|
||||
)
|
||||
for item in data.get("items", [])
|
||||
]
|
||||
|
||||
search_info = data.get("searchInformation", {}) or {}
|
||||
|
||||
return SearchResponse(
|
||||
query=q,
|
||||
total_results=search_info.get("totalResults"),
|
||||
search_time=search_info.get("searchTime"),
|
||||
items=items,
|
||||
raw=data,
|
||||
)
|
||||
|
||||
except ValueError as e:
|
||||
log.error(f"Configuration error: {e}")
|
||||
raise HTTPException(status_code=500, detail=str(e))
|
||||
except httpx.HTTPStatusError as e:
|
||||
log.error(f"Google CSE returned {e.response.status_code}: {e.response.text}")
|
||||
raise HTTPException(status_code=e.response.status_code, detail=e.response.text)
|
||||
except httpx.RequestError as e:
|
||||
log.error(f"Network error calling Google CSE: {e}")
|
||||
raise HTTPException(status_code=502, detail=f"Upstream request failed: {e}")
|
||||
except Exception as e:
|
||||
log.error(f"Unexpected error: {e}")
|
||||
raise HTTPException(status_code=500, detail=str(e))
|
||||
Loading…
Reference in New Issue