{"record":{"id":"53818b861b718583","repo":"fish2018/pansou","slug":"s-token-w","errorCode":null,"errorMessage":"[%s] 创建token请求失败: %w","messagePattern":"\\[(.+?)\\] 创建token请求失败: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugin/xys/xys.go","lineNumber":149,"sourceCode":"\t\t\t\tif p.debugMode {\n\t\t\t\t\tlog.Printf(\"[XYS] 使用缓存的token\")\n\t\t\t\t}\n\t\t\t\treturn tokenCache.Token, nil\n\t\t\t}\n\t\t}\n\t}\n\n\t// 构建请求URL\n\ttokenURL := fmt.Sprintf(\"%s%s?wd=%s&mode=undefined&stype=undefined\",\n\t\tBaseURL, TokenPath, url.QueryEscape(keyword))\n\n\t// 创建带超时的上下文\n\tctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)\n\tdefer cancel()\n\n\treq, err := http.NewRequestWithContext(ctx, \"GET\", tokenURL, nil)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"[%s] 创建token请求失败: %w\", p.Name(), err)\n\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 {","sourceCodeStart":131,"sourceCodeEnd":167,"githubUrl":"https://github.com/fish2018/pansou/blob/beaa56133755a548ebc51b090b3816e2ae044aa6/plugin/xys/xys.go#L131-L167","documentation":"getToken wraps the error from http.NewRequestWithContext when building the GET request to the site's token page. The plugin needs a DToken scraped from an HTML page before it can search; if the request object itself cannot be constructed (bad URL, invalid method/ctx combination) the token fetch is aborted and the wrapped error is returned up through searchImpl. This is a pre-flight construction failure, not a network failure.","triggerScenarios":"http.NewRequestWithContext(ctx, \"GET\", tokenURL, nil) returns a non-nil err — in practice a malformed or unparseable tokenURL (e.g. control characters, unparseable scheme) since method/ctx are constants here.","commonSituations":"BaseURL or token URL constant corrupted by an edit or config substitution; URL built with unescaped user input containing newlines/control chars; Go stdlib rejecting an invalid URL string.","solutions":["Print/log the tokenURL value and validate it with url.Parse before calling http.NewRequestWithContext","Check that BaseURL/tokenURL constants in plugin/xys/xys.go are intact and correctly formatted (https://host/path)","If the URL is derived from user input, sanitize/escape it (strings.ContainsAny for control chars, url.QueryEscape)"],"exampleFix":"// before\nreq, err := http.NewRequestWithContext(ctx, \"GET\", tokenURL, nil)\nif err != nil {\n    return \"\", fmt.Errorf(\"[%s] 创建token请求失败: %w\", p.Name(), err)\n}\n// after\nu, perr := url.Parse(tokenURL)\nif perr != nil {\n    return \"\", fmt.Errorf(\"[%s] invalid token URL %q: %w\", p.Name(), tokenURL, perr)\n}\nreq, err := http.NewRequestWithContext(ctx, \"GET\", u.String(), nil)\nif err != nil {\n    return \"\", fmt.Errorf(\"[%s] 创建token请求失败: %w\", p.Name(), err)\n}","handlingStrategy":"validation","validationCode":"u, err := url.Parse(tokenURL)\nif err != nil || u.Scheme == \"\" || u.Host == \"\" {\n    return fmt.Errorf(\"invalid token URL: %v\", err)\n}","typeGuard":null,"tryCatchPattern":"if err != nil {\n    var ue *url.Error\n    if errors.As(err, &ue) {\n        log.Printf(\"bad token URL %q: %v\", ue.URL, ue.Err)\n    }\n    return fallbackSearch()\n}","preventionTips":["Always validate URLs composed from constants/config with url.Parse before use","Never interpolate unsanitized user input into URLs; use url.QueryEscape","Pin BaseURL/tokenURL in tests so accidental edits fail CI"],"tags":["http","request-construction","invalid-url"],"backgroundTag":"invalid-url","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"}