{"record":{"id":"6cb1f526f5825405","repo":"fish2018/pansou","slug":"s-d-6cb1f5","errorCode":null,"errorMessage":"[%s] 请求返回状态码: %d","messagePattern":"\\[(.+?)\\] 请求返回状态码: (.+?)","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugin/ash/ash.go","lineNumber":99,"sourceCode":"\t// 创建请求\n\treq, err := http.NewRequestWithContext(ctx, \"GET\", searchURL, nil)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"[%s] 创建请求失败: %w\", p.Name(), err)\n\t}\n\t\n\t// 设置请求头\n\tp.setRequestHeaders(req)\n\t\n\t// 发送请求（优化重试）\n\tresp, err := p.doRequestWithRetry(req, client)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"[%s] 搜索请求失败: %w\", p.Name(), err)\n\t}\n\tdefer resp.Body.Close()\n\t\n\t// 检查状态码\n\tif resp.StatusCode != 200 {\n\t\treturn nil, fmt.Errorf(\"[%s] 请求返回状态码: %d\", p.Name(), resp.StatusCode)\n\t}\n\t\n\t// 读取响应（使用有限制的读取，避免读取过大内容）\n\t// ASH页面通常不会太大，限制在2MB以内\n\tlimitReader := io.LimitReader(resp.Body, 2*1024*1024)\n\tbody, err := io.ReadAll(limitReader)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"[%s] 读取响应失败: %w\", p.Name(), err)\n\t}\n\t\n\t// 从HTML中提取JSON数据（直接传递字节，避免字符串转换）\n\tresults, err := p.extractResultsFromBytes(body)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"[%s] 提取搜索结果失败: %w\", p.Name(), err)\n\t}\n\t\n\t// 关键词过滤\n\tfiltered := plugin.FilterResultsByKeyword(results, keyword)","sourceCodeStart":81,"sourceCodeEnd":117,"githubUrl":"https://github.com/fish2018/pansou/blob/beaa56133755a548ebc51b090b3816e2ae044aa6/plugin/ash/ash.go#L81-L117","documentation":"The ASH search endpoint responded, but with a status code other than 200. searchImpl treats any non-200 as a hard failure and reports the code so the caller can react. Body is already closed at this point, so only the status code is available.","triggerScenarios":"After doRequestWithRetry succeeds, resp.StatusCode != 200 — e.g. 403 (blocked/Cloudflare), 429 (rate limited), 404 (path changed), 5xx (server error) — ash.go:99.","commonSituations":"Upstream added WAF/anti-bot protection returning 403; request rate too high causing 429; the site changed its search path causing 404; origin server 5xx during load.","solutions":["Log the status code and retry later if 429/5xx; back off the request rate.","Handle 403 by rotating headers/User-Agent, cookies, or using a proxy/residential IP.","Verify the search URL path is still valid if you get 404 (site layout changed).","Optionally treat the body of non-200 responses as diagnostic info before discarding it."],"exampleFix":"// before\nif resp.StatusCode != 200 {\n    return nil, fmt.Errorf(\"[%s] 请求返回状态码: %d\", p.Name(), resp.StatusCode)\n}\n// after\nif resp.StatusCode != 200 {\n    if resp.StatusCode == http.StatusTooManyRequests {\n        time.Sleep(retryAfterFrom(resp.Header))\n    }\n    io.Copy(io.Discard, io.LimitReader(resp.Body, 4096))\n    return nil, fmt.Errorf(\"[%s] 请求返回状态码: %d\", p.Name(), resp.StatusCode)\n}","handlingStrategy":"retry","validationCode":"// after response\nif resp.StatusCode != 200 { return fmt.Errorf(\"upstream status %d\", resp.StatusCode) }","typeGuard":null,"tryCatchPattern":"var statusErr *StatusError\nif errors.As(err, &statusErr) {\n    switch {\n    case statusErr.Code == 429: backoffAndRetry()\n    case statusErr.Code >= 500: retryLater()\n    default: alertOnBlocked(statusErr.Code)\n    }\n}","preventionTips":["Rate-limit requests to stay under upstream limits","Rotate User-Agent/cookies if WAF-blocked","Alert on recurring 403/429 to detect IP blocking","Verify site path hasn't changed on 404s"],"tags":["http","status-code","upstream","go"],"backgroundTag":"http-non-200-response","analyzedSha":"beaa56133755a548ebc51b090b3816e2ae044aa6","analyzedAt":"2026-09-07T00:31:18.025Z","contentChangedAt":"2026-09-07T00:31:18.025Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}