Skip to content

Commit fa60e94

Browse files
vladm-serpapiVlad M
andauthored
Add proper response error formatting (#20)
Co-authored-by: Vlad M <vlad@serpapi.com>
1 parent 3c36029 commit fa60e94

File tree

1 file changed

+45
-6
lines changed

1 file changed

+45
-6
lines changed

src/server.py

Lines changed: 45 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
import json
1212
from typing import Any
1313
import serpapi
14-
import httpx
1514
import logging
1615
from datetime import datetime
1716

@@ -21,6 +20,44 @@
2120
logger = logging.getLogger(__name__)
2221

2322

23+
def extract_error_response(exception) -> str:
24+
"""
25+
Helper function to extract meaningful error information from nested exceptions.
26+
27+
Traverses exception.args[0] chain until it finds a valid .response object,
28+
then attempts to extract JSON from response.json(). Falls back to str(e).
29+
30+
Args:
31+
exception: The exception to process
32+
33+
Returns:
34+
str: Formatted error message with response data if available
35+
"""
36+
current = exception
37+
max_depth = 10
38+
depth = 0
39+
40+
while depth < max_depth:
41+
if hasattr(current, "response") and current.response is not None:
42+
try:
43+
response_data = current.response.json()
44+
return json.dumps(response_data, indent=2)
45+
except (ValueError, AttributeError, TypeError):
46+
try:
47+
return current.response.text
48+
except (AttributeError, TypeError):
49+
pass
50+
51+
if hasattr(current, "args") and current.args and len(current.args) > 0:
52+
current = current.args[0]
53+
depth += 1
54+
else:
55+
break
56+
57+
# Fallback
58+
return str(exception)
59+
60+
2461
class ApiKeyMiddleware(BaseHTTPMiddleware):
2562
async def dispatch(self, request: Request, call_next):
2663
# Skip authentication for healthcheck endpoint
@@ -139,15 +176,17 @@ async def search(params: dict[str, Any] = {}, mode: str = "complete") -> str:
139176

140177
except serpapi.exceptions.HTTPError as e:
141178
if "429" in str(e):
142-
return "Error: Rate limit exceeded. Please try again later."
179+
return f"Error: Rate limit exceeded. Please try again later."
143180
elif "401" in str(e):
144-
return "Error: Invalid SerpApi API key. Check your API key in the path or Authorization header."
181+
return f"Error: Invalid SerpApi API key. Check your API key in the path or Authorization header."
145182
elif "403" in str(e):
146-
return "Error: SerpApi API key forbidden. Verify your subscription and key validity."
183+
return f"Error: SerpApi API key forbidden. Verify your subscription and key validity."
147184
else:
148-
return f"Error: {str(e)}"
185+
error_msg = extract_error_response(e)
186+
return f"Error: {error_msg}"
149187
except Exception as e:
150-
return f"Error: {str(e)}"
188+
error_msg = extract_error_response(e)
189+
return f"Error: {error_msg}"
151190

152191

153192
async def healthcheck_handler(request):

0 commit comments

Comments
 (0)