{"record":{"id":"8753f7d990fc7d8b","repo":"GopeedLab/gopeed","slug":"webhook-url-is-empty","errorCode":null,"errorMessage":"webhook URL is empty","messagePattern":"webhook URL is empty","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/download/webhook.go","lineNumber":101,"sourceCode":"\t\tfor _, urlInterface := range urlsInterface {\n\t\t\tif url, ok := urlInterface.(string); ok && url != \"\" {\n\t\t\t\turls = append(urls, url)\n\t\t\t}\n\t\t}\n\t\tif len(urls) == 0 {\n\t\t\treturn nil\n\t\t}\n\t\treturn urls\n\t}\n\n\treturn nil\n}\n\n// sendWebhookToUrl sends webhook data to a single URL\n// Returns the HTTP status code and any error that occurred\nfunc (d *Downloader) sendWebhookToUrl(url string, data *WebhookData) (int, error) {\n\tif url == \"\" {\n\t\treturn 0, fmt.Errorf(\"webhook URL is empty\")\n\t}\n\n\tjsonData, err := json.Marshal(data)\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\n\tclient := &http.Client{\n\t\tTimeout: webhookTimeout,\n\t}\n\n\treq, err := http.NewRequest(http.MethodPost, url, bytes.NewBuffer(jsonData))\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\treq.Header.Set(\"Content-Type\", \"application/json\")\n\treq.Header.Set(\"User-Agent\", \"Gopeed-Webhook/1.0\")\n","sourceCodeStart":83,"sourceCodeEnd":119,"githubUrl":"https://github.com/GopeedLab/gopeed/blob/7b7327ffb30816273a74b142cccc0bc10c5a4c67/pkg/download/webhook.go#L83-L119","documentation":"Returned by sendWebhookToUrl (webhook.go:99-102) when it is invoked with an empty string as the URL. The internal delivery path (sendWebhooks, webhook.go:147-151) filters empty entries before calling, so in practice this surfaces through the public test endpoint TestWebhookUrl, which the REST API calls with the raw request body (pkg/rest/api.go:416-424). It is a pure input-validation guard: no HTTP request is attempted.","triggerScenarios":"POSTing the webhook-test API with {\"url\": \"\"} or an omitted url field; calling downloader.TestWebhookUrl(\"\") from Go; UI code submitting the test form before the user typed a URL.","commonSituations":"Frontend forms that submit on empty input; automation scripts testing webhook config before filling the URL; whitespace-only URLs pass the empty check but then fail later in http.NewRequest, so trimmed validation upstream is the real fix.","solutions":["Provide the full webhook URL in the test request body","Trim and validate the input client-side before submitting the test call","If integrating the Go API, guard with strings.TrimSpace(url) != \"\" before calling TestWebhookUrl"],"exampleFix":"// before\nerr := downloader.TestWebhookUrl(req.URL) // req.URL == \"\"\n\n// after\nurl := strings.TrimSpace(req.URL)\nif url == \"\" {\n\twriteError(w, \"webhook url is required\")\n\treturn\n}\nerr := downloader.TestWebhookUrl(url)","handlingStrategy":"validation","validationCode":"url := strings.TrimSpace(req.URL)\nif url == \"\" {\n\twriteError(w, \"webhook url is required\")\n\treturn\n}","typeGuard":null,"tryCatchPattern":"if err := downloader.TestWebhookUrl(url); err != nil {\n\tw.WriteHeader(http.StatusBadRequest)\n\tjson.NewEncoder(w).Encode(map[string]string{\"error\": err.Error()})\n}","preventionTips":["Disable the test action until a URL is entered (client-side form validation)","Trim whitespace before validating or submitting webhook URLs","Reject obviously malformed URLs (no scheme/host) before calling the API"],"tags":["webhook","validation","rest-api","config"],"backgroundTag":null,"analyzedSha":"7b7327ffb30816273a74b142cccc0bc10c5a4c67","analyzedAt":"2026-08-16T02:51:03.250Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}