{"record":{"id":"a73fba8cab4dc2bb","repo":"fish2018/pansou","slug":"s-s-d-d","errorCode":null,"errorMessage":"[%s] %s网盘第%d页返回状态码: %d","messagePattern":"\\[(.+?)\\] (.+?)网盘第(.+?)页返回状态码: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugin/haisou/haisou.go","lineNumber":347,"sourceCode":"\t}\n\n\t// 设置请求头\n\treq.Header.Set(\"User-Agent\", \"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36\")\n\treq.Header.Set(\"Accept\", \"application/json, text/plain, */*\")\n\treq.Header.Set(\"Accept-Language\", \"zh-CN,zh;q=0.9,en;q=0.8\")\n\treq.Header.Set(\"Connection\", \"keep-alive\")\n\treq.Header.Set(\"Referer\", \"https://haisou.cc/\")\n\n\t// 发送HTTP请求（带重试机制）\n\tresp, err := p.doRequestWithRetry(req, client)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"[%s] %s网盘第%d页请求失败: %w\", p.Name(), panType, pageNo, err)\n\t}\n\tdefer resp.Body.Close()\n\n\t// 检查状态码\n\tif resp.StatusCode != 200 {\n\t\treturn nil, fmt.Errorf(\"[%s] %s网盘第%d页返回状态码: %d\", p.Name(), panType, pageNo, resp.StatusCode)\n\t}\n\n\t// 读取响应体\n\tbody, err := io.ReadAll(resp.Body)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"[%s] %s网盘第%d页读取响应失败: %w\", p.Name(), panType, pageNo, err)\n\t}\n\n\t// 解析响应\n\tvar apiResp SearchAPIResponse\n\tif err := json.Unmarshal(body, &apiResp); err != nil {\n\t\treturn nil, fmt.Errorf(\"[%s] %s网盘第%d页JSON解析失败: %w\", p.Name(), panType, pageNo, err)\n\t}\n\n\t// 检查API响应状态\n\tif apiResp.Code != 0 {\n\t\treturn nil, fmt.Errorf(\"[%s] %s网盘第%d页API错误: %s\", p.Name(), panType, pageNo, apiResp.Msg)\n\t}","sourceCodeStart":329,"sourceCodeEnd":365,"githubUrl":"https://github.com/fish2018/pansou/blob/beaa56133755a548ebc51b090b3816e2ae044aa6/plugin/haisou/haisou.go#L329-L365","documentation":"After a successful round-trip, fetchSearchPage checks resp.StatusCode and throws this error for anything other than 200, embedding the plugin name, pan type, page number, and actual status code. It means the haisou API answered but rejected the request — e.g. 403/429 anti-bot or rate limiting, 404 after an endpoint change, or 5xx server trouble.","triggerScenarios":"Calling fetchSearchPage when the API returns a non-200 status: request missing expected headers/cookies, too-frequent requests triggering 429/403, endpoint path changed (404), or server-side errors (5xx).","commonSituations":"Site updated its API and moved/renamed endpoints; aggressive polling causing rate limits; IP blocked by WAF returning 403; maintenance windows returning 502/503.","solutions":["Log the status code and body to identify whether it's 403/404/429/5xx.","Back off and retry for 429/5xx; reduce request rate.","Update the search URL and required headers if the API changed (compare with browser DevTools).","Use a session with proper cookies/headers if the site now requires them."],"exampleFix":"// before\nif resp.StatusCode != 200 {\n    return nil, fmt.Errorf(\"...返回状态码: %d\", resp.StatusCode)\n}\n// after\nif resp.StatusCode == http.StatusTooManyRequests {\n    time.Sleep(retryAfterBackoff(resp.Header.Get(\"Retry-After\")))\n    return p.fetchSearchPage(panType, keyword, pageNo) // retry once\n} else if resp.StatusCode != 200 {\n    return nil, fmt.Errorf(\"...返回状态码: %d\", resp.StatusCode)\n}","handlingStrategy":"retry","validationCode":"// honor rate limiting proactively\nif resp.StatusCode == http.StatusTooManyRequests || resp.StatusCode == http.StatusForbidden {\n    return fmt.Errorf(\"throttled (status %d); back off before retrying\", resp.StatusCode)\n}","typeGuard":"func isThrottled(err error) bool { return err != nil && (strings.Contains(err.Error(), \"429\") || strings.Contains(err.Error(), \"403\")) }","tryCatchPattern":"items, err := fetchSearchPage(panType, keyword, pageNo)\nif isThrottled(err) {\n    select {\n    case <-time.After(rateLimitBackoff):\n    case <-ctx.Done():\n        return ctx.Err()\n    }\n    items, err = fetchSearchPage(panType, keyword, pageNo)\n}","preventionTips":["Rate-limit requests per pan type and add jitter between pages.","Log response bodies for non-200s to detect API/WAF changes quickly.","Mirror expected headers/cookies from browser DevTools requests.","Pin and monitor the endpoint path so 404s from API changes are caught early."],"tags":["http","status-code","rate-limit","upstream"],"backgroundTag":"http-error-status","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"}