{"record":{"id":"eb69bb1d5586494b","repo":"jeessy2/ddns-go","slug":"v-eb69bb","errorCode":null,"errorMessage":"创建请求失败: %v","messagePattern":"创建请求失败: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"dns/tnethk.go","lineNumber":262,"sourceCode":"\n\treturn strings.Join(finalQuery, \"&\"), nil\n}\n\nfunc (t *Tnethk) request(apiPath string, params map[string]string, method string) ([]byte, error) {\n\t// 生成签名\n\tqueryString, err := t.sign(params, method)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"生成签名失败: %v\", err)\n\t}\n\n\t// 构造完整URL\n\tbaseURL := \"https://www.tnet.hk\"\n\tfullURL := baseURL + apiPath + \"?\" + queryString\n\n\t// 创建HTTP请求\n\treq, err := http.NewRequest(method, fullURL, nil)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"创建请求失败: %v\", err)\n\t}\n\n\t// 设置请求头\n\treq.Header.Set(\"Accept\", \"application/json\")\n\n\t// 发送请求\n\tclient := t.httpClient\n\tresp, err := client.Do(req)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"请求失败: %v\", err)\n\t}\n\tdefer resp.Body.Close()\n\n\t// 读取响应\n\tbody, err := io.ReadAll(resp.Body)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"读取响应失败: %v\", err)\n\t}","sourceCodeStart":244,"sourceCodeEnd":280,"githubUrl":"https://github.com/jeessy2/ddns-go/blob/5874c2e6667c69357ab95079421131104bd3fcae/dns/tnethk.go#L244-L280","documentation":"dns/tnethk.go request() wraps http.NewRequest failures with \"创建请求失败: %v\" (failed to create request). This happens before any network traffic: the method/URL pair is invalid, e.g. a malformed fullURL built from apiPath or the signed query string.","triggerScenarios":"create, modify, or getRecordList calls where baseURL+apiPath+\"?\"+queryString does not parse as a valid URL — e.g. apiPath with spaces/invalid characters or unescaped special characters in signed params.","commonSituations":"Domain or record names containing characters that were not URL-encoded before signing; apiPath typo producing an invalid URL; control characters leaking from config values into parameters.","solutions":["Inspect the wrapped %v error for the URL parse failure detail","Ensure domain/subdomain and record values are URL-escaped before being placed in params","Validate that apiPath and configured domain values contain no spaces or control characters","Sanitize config inputs (trim whitespace, reject invalid hostname characters)"],"exampleFix":"// before\nparams[\"domain\"] = domain.DomainName // may contain unsafe chars\n// after\nparams[\"domain\"] = url.QueryEscape(strings.TrimSpace(domain.DomainName))","handlingStrategy":"validation","validationCode":"// sanitize inputs that end up in the URL\nname := strings.TrimSpace(domain.SubDomain)\nif strings.ContainsAny(name, \" \\t\\r\\n\") {\n\treturn fmt.Errorf(\"invalid subdomain %q\", name)\n}","typeGuard":"func validHost(s string) bool {\n\treturn s != \"\" && net.ParseIP(s) != nil ||\n\t\tregexp.MustCompile(`^[a-zA-Z0-9]([a-zA-Z0-9-]*[a-zA-Z0-9])?$`).MatchString(s)\n}","tryCatchPattern":"if err != nil && strings.Contains(err.Error(), \"创建请求失败\") {\n\treturn fmt.Errorf(\"tnethk: malformed request URL — check domain/param values: %w\", err)\n}","preventionTips":["URL-escape all parameter values before signing","Reject hostnames/IPs with invalid characters at config load","Log the assembled fullURL (redacting secrets) when debugging"],"tags":["http-request","url-validation","config"],"backgroundTag":"invalid-request-url","analyzedSha":"5874c2e6667c69357ab95079421131104bd3fcae","analyzedAt":"2026-09-03T15:41:16.799Z","contentChangedAt":"2026-09-03T15:41:16.799Z","schemaVersion":2},"datasetVersion":"2026-09-11T00:17:11.886Z"}