{"record":{"id":"effdec31c6b1f14d","repo":"fish2018/pansou","slug":"s-token-http-d","errorCode":null,"errorMessage":"[%s] token请求HTTP状态错误: %d","messagePattern":"\\[(.+?)\\] token请求HTTP状态错误: (.+?)","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugin/xys/xys.go","lineNumber":168,"sourceCode":"\t}\n\n\t// 设置完整的请求头\n\treq.Header.Set(\"User-Agent\", UserAgent)\n\treq.Header.Set(\"Accept\", \"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8\")\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(\"Upgrade-Insecure-Requests\", \"1\")\n\treq.Header.Set(\"Cache-Control\", \"max-age=0\")\n\treq.Header.Set(\"Referer\", BaseURL+\"/\")\n\n\tresp, err := p.doRequestWithRetry(req, client)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"[%s] token请求失败: %w\", p.Name(), err)\n\t}\n\tdefer resp.Body.Close()\n\n\tif resp.StatusCode != 200 {\n\t\treturn \"\", fmt.Errorf(\"[%s] token请求HTTP状态错误: %d\", p.Name(), resp.StatusCode)\n\t}\n\n\t// 解析HTML提取token\n\tdoc, err := goquery.NewDocumentFromReader(resp.Body)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"[%s] 解析token页面HTML失败: %w\", p.Name(), err)\n\t}\n\n\t// 查找script标签中的DToken定义\n\tvar token string\n\tdoc.Find(\"script\").Each(func(i int, s *goquery.Selection) {\n\t\tscriptContent := s.Text()\n\t\tif strings.Contains(scriptContent, \"DToken\") {\n\t\t\t// 使用正则表达式提取token\n\t\t\tre := regexp.MustCompile(`const\\s+DToken\\s*=\\s*\"([^\"]+)\"`)\n\t\t\tmatches := re.FindStringSubmatch(scriptContent)\n\t\t\tif len(matches) > 1 {\n\t\t\t\ttoken = matches[1]","sourceCodeStart":150,"sourceCodeEnd":186,"githubUrl":"https://github.com/fish2018/pansou/blob/beaa56133755a548ebc51b090b3816e2ae044aa6/plugin/xys/xys.go#L150-L186","documentation":"getToken rejects the token page response when its HTTP status is not 200. The plugin strictly requires a 200 HTML page from which to scrape DToken; any redirect landing on an error page, anti-bot challenge, or 5xx triggers this error. The status code is embedded in the message for diagnosis.","triggerScenarios":"doRequestWithRetry succeeded but resp.StatusCode != 200 (e.g. 403 from WAF/anti-bot, 302 followed to a captcha page, 502/503 from an overloaded upstream).","commonSituations":"Site upgraded anti-bot measures (Cloudflare challenge page); IP rate-limited or banned; region blocking returning 403; upstream outage returning 502/503; User-Agent header blacklisted.","solutions":["Log the status code and response body snippet to identify what the server actually returned (challenge page vs error)","Check for IP bans/rate limits; reduce request frequency or rotate proxy/IP","Update the User-Agent and browser-like headers in getToken to a current browser value","Handle redirects/captcha endpoints explicitly if the site introduced an anti-bot interstitial"],"exampleFix":"null","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"var httpErr *HTTPStatusError\nif errors.As(err, &httpErr) && (httpErr.Code == 403 || httpErr.Code == 429) {\n    time.Sleep(backoff)\n    return retryWithFreshIP()\n}","preventionTips":["Keep User-Agent and browser headers up to date with real browser values","Rate-limit requests to avoid WAF/anti-bot triggers","Treat non-200 bodies as diagnostic: log a snippet for triage","Use a cookie jar so the client keeps any anti-bot cookies issued"],"tags":["http","http-status","anti-bot","upstream"],"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"}