From cc9466ab608879b32be440076b8ca4a8bdc250e5 Mon Sep 17 00:00:00 2001 From: "bahawal.baloch" Date: Thu, 14 May 2026 15:53:21 +0500 Subject: [PATCH] Refactor CustomSearchService to use updated environment variable names and add search endpoint with error handling --- custom_search_api/service.py | 8 ++--- custom_search_api/views.py | 59 ++++++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+), 4 deletions(-) create mode 100644 custom_search_api/views.py diff --git a/custom_search_api/service.py b/custom_search_api/service.py index 39b7d71..0d98f9d 100644 --- a/custom_search_api/service.py +++ b/custom_search_api/service.py @@ -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, diff --git a/custom_search_api/views.py b/custom_search_api/views.py new file mode 100644 index 0000000..e68ab2c --- /dev/null +++ b/custom_search_api/views.py @@ -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))