siyuan-note/siyuan · error
URL must start with http:// or https://
Error message
URL must start with http:// or https://
What it means
Returned by HTTPRequest when url.Parse fails for the input, or succeeds but yields a scheme that is neither http nor https. The check is the first validation in HTTPRequest and rejects mailto:, file:, ftp:, data:, and other schemes before any network activity.
Source
Thrown at kernel/util/httprequest.go:63
return errors.New("failed to resolve host: " + err.Error())
}
for _, ip := range ips {
// 与 SSRFSafeDialer 共用 isPrivateIP,覆盖 NAT64、6to4、Teredo 等 IPv6 过渡地址。
if isPrivateIP(ip) {
return errors.New("access to private/internal IP is prohibited")
}
}
return nil
}
// HTTPRequest 发起一次通用 HTTP 调用,供智能体 http_request 工具使用。
// 与 WebFetch 不同:本函数不做 HTML→Markdown 转换,文本类响应(含 JSON/XML)原样返回,
// 便于智能体直接消费 REST API 的 JSON 输出。method 取值:GET/POST/PUT/DELETE/PATCH。
// 返回的 text 为响应正文(文本类)或落盘后的文件路径(二进制类)。
func HTTPRequest(method, rawURL string, headers map[string]string, body string) (statusCode int, contentType string, text string, err error) {
u, err := url.Parse(rawURL)
if err != nil || (u.Scheme != "http" && u.Scheme != "https") {
return 0, "", "", errors.New("URL must start with http:// or https://")
}
if u.Host == "" {
return 0, "", "", errors.New("URL has no host")
}
if serr := CheckHostSSRF(u.Hostname()); serr != nil {
return 0, "", "", serr
}
method = strings.ToUpper(strings.TrimSpace(method))
if method == "" {
method = "GET"
}
request := httpclient.NewBrowserRequest()
for k, v := range headers {
request.SetHeader(k, v)
}View on GitHub (pinned to 251596fc0d)
Solutions
- Prefix the URL with 'http://' or 'https://' before calling HTTPRequest.
- If you accept user/agent input, normalize it with url.Parse and force/reject the scheme upstream.
- Use a different code path for non-HTTP schemes (e.g. kernel file APIs for file://).
Example fix
// before
util.HTTPRequest("GET", rawURL, nil, "")
// after
u, err := url.Parse(rawURL)
if err != nil || (u.Scheme != "http" && u.Scheme != "https") {
if u != nil && u.Host != "" {
rawURL = "https://" + rawURL
} else {
return errors.New("a full http(s) URL is required")
}
}
util.HTTPRequest("GET", rawURL, nil, "") Defensive patterns
Strategy: validation
Validate before calling
func validHTTPURL(raw string) bool {
u, err := url.Parse(raw)
return err == nil && (u.Scheme == "http" || u.Scheme == "https")
} Prevention
- Normalize agent/user URLs to force an http(s) scheme before calling HTTPRequest.
- Reject mailto:, file:, ftp:, data: at the input boundary.
When it happens
Trigger: Calling util.HTTPRequest with a URL that is unparseable, has no scheme, or uses a non-http(s) scheme (file://, ftp://, mailto:, data:, javascript:, ws://).
Common situations: An agent passed a bare hostname ('example.com') without a scheme; a copy-paste included a file:// or mailto: link; the URL was constructed by string concatenation that dropped the scheme; a WebSocket ws:// URL fed to the HTTP tool.
Related errors
- URL has no host
- parse [u] failed: %s
- response too large
- Failed to update agent session permission
- missing query param [u]
AI-assisted analysis of siyuan-note/siyuan@251596fc0d (2026-08-12).
Data as JSON: /api/errors/2c4003f237009bdc.
Report an issue: GitHub.