{"record":{"id":"ccbe2d446961f26a","repo":"fish2018/pansou","slug":"http-403-forbidden-ccbe2d","errorCode":null,"errorMessage":"HTTP 403 Forbidden - 需要重新登录","messagePattern":"HTTP 403 Forbidden - 需要重新登录","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugin/gying/gying.go","lineNumber":2492,"sourceCode":"\t\t\t\tpreview := string(body)\n\t\t\t\tif len(preview) > 300 {\n\t\t\t\t\tpreview = preview[:300] + \"...\"\n\t\t\t\t}\n\t\t\t\tfmt.Printf(\"[Gying] 403响应内容: %s\\n\", preview)\n\t\t\t}\n\t\t}\n\t\treturn nil, fmt.Errorf(\"HTTP 403 Forbidden - 可能需要重新登录\")\n\t}\n\n\t// 2. 提取 _obj.search JSON\n\tmatches := searchDataPattern.FindSubmatch(body)\n\n\tif DebugLog {\n\t\tfmt.Printf(\"[Gying] 正则匹配结果: 找到 %d 个匹配\\n\", len(matches))\n\t}\n\n\tif isLoginShell(body) {\n\t\treturn nil, fmt.Errorf(\"HTTP 403 Forbidden - 需要重新登录\")\n\t}\n\n\tif len(matches) < 2 {\n\t\tif DebugLog {\n\t\t\tfmt.Printf(\"[Gying] ❌ 未找到 _obj.search JSON数据\\n\")\n\n\t\t\t// 尝试查找是否有其他模式\n\t\t\tif strings.Contains(string(body), \"_obj.search\") {\n\t\t\t\tfmt.Printf(\"[Gying] 但是Body中包含 '_obj.search' 字符串\\n\")\n\t\t\t} else {\n\t\t\t\tfmt.Printf(\"[Gying] Body中不包含 '_obj.search' 字符串\\n\")\n\t\t\t}\n\t\t}\n\t\treturn nil, fmt.Errorf(\"未找到搜索结果数据\")\n\t}\n\n\tif DebugLog {\n\t\tjsonStr := string(matches[1])","sourceCodeStart":2474,"sourceCodeEnd":2510,"githubUrl":"https://github.com/fish2018/pansou/blob/beaa56133755a548ebc51b090b3816e2ae044aa6/plugin/gying/gying.go#L2474-L2510","documentation":"The search response body passed isLoginShell(body) — i.e. it looks like the login page shell rather than search results. The plugin interprets this as the server having redirected to login because the session is invalid, and reports it as a 403-like condition requiring re-login.","triggerScenarios":"searchWithScraper gets HTTP 200 but the HTML is the login shell (session silently invalidated); the code detects isLoginShell(body) and returns this error before attempting JSON extraction.","commonSituations":"Site logs out sessions server-side ( kicked by concurrent login ); cookies cleared/rotated; site redirects unauthenticated requests to the login page instead of returning 403.","solutions":["Re-login to refresh the session cookie (the plugin's 403-recovery path handles this).","Avoid using the same account from multiple clients that invalidate each other's sessions.","Persist cookies across restarts so sessions are reused while valid.","Verify credentials are still valid in case the account was logged out everywhere."],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"results, err := p.Search(keyword)\nif err != nil && strings.Contains(err.Error(), \"需要重新登录\") {\n    if rlErr := p.reloginUser(user); rlErr != nil {\n        return rlErr\n    }\n    results, err = p.Search(keyword)\n}","preventionTips":["Use one session per account — concurrent logins may invalidate each other.","Re-login proactively when cookies are older than the site's session TTL.","Persist and reload cookies to detect staleness early."],"tags":["session-expired","login-redirect","authentication"],"backgroundTag":"authentication-required","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"}