refactor(search): improve HTTP error reporting with status code and response detail

This commit is contained in:
Menci
2026-02-26 14:20:01 +08:00
committed by 晨苒
parent 08f5130c66
commit ed90c63888
+45 -4
View File
@@ -149,7 +149,7 @@ func (p *Executor) callBraveSearch(ctx context.Context, configJSON []byte, query
return mcpgw.BuildToolErrorResult(err.Error()), nil
}
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
return mcpgw.BuildToolErrorResult("search request failed"), nil
return buildSearchHTTPError(resp.StatusCode, body), nil
}
var raw struct {
Web struct {
@@ -210,7 +210,7 @@ func (p *Executor) callBingSearch(ctx context.Context, configJSON []byte, query
return mcpgw.BuildToolErrorResult(err.Error()), nil
}
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
return mcpgw.BuildToolErrorResult("search request failed"), nil
return buildSearchHTTPError(resp.StatusCode, body), nil
}
var raw struct {
WebPages struct {
@@ -279,7 +279,7 @@ func (p *Executor) callGoogleSearch(ctx context.Context, configJSON []byte, quer
return mcpgw.BuildToolErrorResult(err.Error()), nil
}
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
return mcpgw.BuildToolErrorResult("search request failed"), nil
return buildSearchHTTPError(resp.StatusCode, body), nil
}
var raw struct {
Items []struct {
@@ -335,7 +335,7 @@ func (p *Executor) callTavilySearch(ctx context.Context, configJSON []byte, quer
return mcpgw.BuildToolErrorResult(err.Error()), nil
}
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
return mcpgw.BuildToolErrorResult("search request failed"), nil
return buildSearchHTTPError(resp.StatusCode, body), nil
}
var raw struct {
Results []struct {
@@ -361,6 +361,47 @@ func (p *Executor) callTavilySearch(ctx context.Context, configJSON []byte, quer
}), nil
}
// buildSearchHTTPError builds an error result for non-2xx search API responses.
// It includes the HTTP status code and attempts to extract a brief error detail
// from the response body (capped at 200 characters to avoid context blowout).
func buildSearchHTTPError(statusCode int, body []byte) map[string]any {
detail := extractJSONErrorMessage(body)
if detail == "" {
detail = strings.TrimSpace(string(body))
}
if len(detail) > 200 {
detail = detail[:200] + "..."
}
if detail != "" {
return mcpgw.BuildToolErrorResult(fmt.Sprintf("search request failed (HTTP %d): %s", statusCode, detail))
}
return mcpgw.BuildToolErrorResult(fmt.Sprintf("search request failed (HTTP %d)", statusCode))
}
// extractJSONErrorMessage probes common JSON error response patterns and returns
// the first human-readable message found, or "" if none.
func extractJSONErrorMessage(body []byte) string {
var obj map[string]any
if json.Unmarshal(body, &obj) != nil {
return ""
}
for _, key := range []string{"error", "message", "detail", "error_message"} {
v, ok := obj[key]
if !ok {
continue
}
switch val := v.(type) {
case string:
return val
case map[string]any:
if msg, ok := val["message"].(string); ok {
return msg
}
}
}
return ""
}
func parseTimeout(configJSON []byte, fallback time.Duration) time.Duration {
cfg := parseConfig(configJSON)
raw, ok := cfg["timeout_seconds"]