{"record":{"id":"bbfa86966202c9ad","repo":"siyuan-note/siyuan","slug":"parse-u-failed-s","errorCode":null,"errorMessage":"parse [u] failed: %s","messagePattern":"parse \\[u\\] failed: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/api/network.go","lineNumber":348,"sourceCode":"//\n// Query params:\n//   - `u`: RawURLEncoding base64 of the target URL string.\n//   - `h`: RawURLEncoding base64 of a JSON object map[string][]string.\n//   - `timeout`: The timeout for the request in nanoseconds.\nfunc parseForwardProxyParams(c *gin.Context) (parsedURL *url.URL, headers *http.Header, timeout time.Duration, err error) {\n\tuParam := c.Query(\"u\")\n\tif uParam == \"\" {\n\t\terr = fmt.Errorf(\"missing query param [u]\")\n\t\treturn\n\t}\n\tuBytes, decErr := base64.RawURLEncoding.DecodeString(uParam)\n\tif decErr != nil {\n\t\terr = fmt.Errorf(\"decode [u] failed: %s\", decErr.Error())\n\t\treturn\n\t}\n\tparsedURL, err = url.ParseRequestURI(string(uBytes))\n\tif err != nil {\n\t\terr = fmt.Errorf(\"parse [u] failed: %s\", err.Error())\n\t\treturn\n\t}\n\n\th := http.Header{}\n\theaders = &h\n\thParam := c.Query(\"h\")\n\tif hParam != \"\" {\n\t\thBytes, decErr := base64.RawURLEncoding.DecodeString(hParam)\n\t\tif decErr != nil {\n\t\t\terr = fmt.Errorf(\"decode [h] failed: %s\", decErr.Error())\n\t\t\treturn\n\t\t}\n\t\tvar record map[string][]string\n\t\tif jsonErr := json.Unmarshal(hBytes, &record); jsonErr != nil {\n\t\t\terr = fmt.Errorf(\"parse [h] failed: %s\", jsonErr.Error())\n\t\t\treturn\n\t\t}\n","sourceCodeStart":330,"sourceCodeEnd":366,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/api/network.go#L330-L366","documentation":"After successfully decoding the `u` param, parseForwardProxyParams validates it with url.ParseRequestURI. If the decoded string is not a parseable absolute request URI, the error is \"parse [u] failed: <reason>\". This means base64 was fine but the payload was not a usable URL.","triggerScenarios":"Decoded `u` value that is empty, relative (e.g. \"foo/bar\"), contains spaces or control characters, or lacks a scheme/host form acceptable to ParseRequestURI.","commonSituations":"Encoding the wrong variable (a path instead of a full URL); a client that strips the scheme; URLs containing unencoded whitespace or non-ASCII characters.","solutions":["Ensure the pre-encoding string is a full absolute URL including scheme, e.g. https://host/path","Trim whitespace and remove control characters from the URL before encoding","Percent-encode non-ASCII characters in path/query before base64-encoding","Validate with url.ParseRequestURI in your client before sending"],"exampleFix":"// before\nconst target = \"example.com/api\"; // no scheme -> parse [u] failed\n// after\nconst target = \"https://example.com/api\";","handlingStrategy":"validation","validationCode":"try { new URL(targetUrl); } catch { throw new Error(\"Target must be an absolute http(s) URL\"); }\nif (!/^https?:\\/\\//.test(targetUrl)) throw new Error(\"Target URL must include scheme\");","typeGuard":"function isAbsoluteHttpUrl(s) {\n  try { const u = new URL(s); return u.protocol === \"http:\" || u.protocol === \"https:\"; } catch { return false; }\n}","tryCatchPattern":null,"preventionTips":["Always encode full absolute URLs including the scheme","Trim whitespace and percent-encode non-ASCII characters before encoding"],"tags":["url","validation","proxy","go"],"backgroundTag":"invalid-url-format","analyzedSha":"9f775e8a12daef8255556097396f9b2739078892","analyzedAt":"2026-09-19T03:17:15.984Z","contentChangedAt":"2026-09-19T03:17:15.984Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}