This commit is contained in:
afjcjsbx 2026-03-18 20:20:27 +01:00
parent 845d0f0a4a
commit 3c5276a9ac
2 changed files with 14 additions and 5 deletions

View file

@ -926,12 +926,16 @@ func (t *WebFetchTool) Execute(ctx context.Context, args map[string]any) *ToolRe
return nil, nil, fmt.Errorf("request failed: %w", doErr)
}
resp.Body = http.MaxBytesReader(nil, resp.Body, t.fetchLimitBytes)
defer resp.Body.Close()
b, readErr := io.ReadAll(resp.Body)
return resp, b, readErr
}
resp, body, err := doFetch(userAgent)
if resp != nil && resp.Body != nil {
defer resp.Body.Close()
}
if err != nil {
var maxBytesErr *http.MaxBytesError
if errors.As(err, &maxBytesErr) {
@ -943,11 +947,16 @@ func (t *WebFetchTool) Execute(ctx context.Context, args map[string]any) *ToolRe
// Cloudflare (and similar WAFs) signal bot challenges with 403 + cf-mitigated: challenge.
// Retry once with an honest User-Agent that identifies picoclaw, which some
// operators explicitly allow-list for AI assistants.
if resp.StatusCode == http.StatusForbidden && resp.Header.Get("cf-mitigated") == "challenge" {
if resp.StatusCode == http.StatusForbidden && resp.Header.Get("Cf-Mitigated") == "challenge" {
logger.DebugCF("tool", "Cloudflare challenge detected, retrying with honest User-Agent",
map[string]any{"url": urlStr})
honestUA := fmt.Sprintf(userAgentHonest, config.Version)
if resp2, body2, err2 := doFetch(honestUA); err2 == nil {
resp2, body2, err2 := doFetch(honestUA)
if resp2 != nil && resp2.Body != nil {
defer resp2.Body.Close()
}
if err2 == nil {
resp, body = resp2, body2
} else {
var maxBytesErr *http.MaxBytesError

View file

@ -1084,7 +1084,7 @@ func TestWebFetchTool_CloudflareChallenge_RetryWithHonestUA(t *testing.T) {
if requestCount == 1 {
// First request: simulate Cloudflare challenge
w.Header().Set("cf-mitigated", "challenge")
w.Header().Set("Cf-Mitigated", "challenge")
w.Header().Set("Content-Type", "text/html")
w.WriteHeader(http.StatusForbidden)
w.Write([]byte("<html><body>Cloudflare challenge</body></html>"))
@ -1158,7 +1158,7 @@ func TestWebFetchTool_CloudflareChallenge_RetryFailsToo(t *testing.T) {
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Always return CF challenge regardless of UA
w.Header().Set("cf-mitigated", "challenge")
w.Header().Set("Cf-Mitigated", "challenge")
w.Header().Set("Content-Type", "text/html")
w.WriteHeader(http.StatusForbidden)
w.Write([]byte("<html><body>still blocked</body></html>"))