{"record":{"id":"0f5786cfe8559a36","repo":"siyuan-note/siyuan","slug":"missing-query-param-u","errorCode":null,"errorMessage":"missing query param [u]","messagePattern":"missing query param \\[u\\]","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/api/network.go","lineNumber":338,"sourceCode":"\tdialer := util.SSRFSafeDialer(timeout)\n\n\tclient := req.C()\n\tclient.SetTimeout(timeout)\n\tclient.SetDial(dialer.DialContext)\n\tclient.SetRedirectPolicy(req.MaxRedirectPolicy(3))\n\treturn client\n}\n\n// parseForwardProxyParams decodes the `u` and `h` query parameters.\n//\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)","sourceCodeStart":320,"sourceCodeEnd":356,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/api/network.go#L320-L356","documentation":"parseForwardProxyParams handles SiYuan's forward-proxy endpoint. The target URL must be supplied as query param `u`, base64 (RawURLEncoding) encoded. When `u` is absent or empty the handler aborts with \"missing query param [u]\" before doing any network work.","triggerScenarios":"Calling a forward-proxy API route (e.g. /api/network/forwardProxy) without the `u` query parameter, or with `u=` empty.","commonSituations":"Hand-constructed curl/browser requests to the proxy endpoint; a client integration that forgot to encode the target URL; older plugin code written against a changed API surface.","solutions":["Add the `u` query parameter containing base64.RawURLEncoding of the target URL string","Ensure the value is RawURLEncoding (no padding, - and _ alphabet), not StdEncoding","Reproduce the encoding the frontend uses (search forwardProxy in app/src) and mirror it in your client"],"exampleFix":"// before\nfetch(\"/api/network/forwardProxy?url=https://example.com\")\n// after\nconst u = base64urlEncode(\"https://example.com\");\nfetch(\"/api/network/forwardProxy?u=\" + u)","handlingStrategy":"validation","validationCode":"if (!params.u) throw new Error(\"forwardProxy requires the u query param (base64url of target URL)\");","typeGuard":null,"tryCatchPattern":"try {\n  await fetch(\"/api/network/forwardProxy?\" + qs);\n} catch (e) {\n  if (String(e.msg).includes(\"missing query param\")) fixParamEncoding();\n}","preventionTips":["Always build proxy requests through a helper that enforces the u param","Keep a single base64url encoding utility shared by all callers"],"tags":["http","query-param","proxy","go"],"backgroundTag":"missing-required-argument","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"}