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

  1. Prefix the URL with 'http://' or 'https://' before calling HTTPRequest.
  2. If you accept user/agent input, normalize it with url.Parse and force/reject the scheme upstream.
  3. 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

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


AI-assisted analysis of siyuan-note/siyuan@251596fc0d (2026-08-12). Data as JSON: /api/errors/2c4003f237009bdc. Report an issue: GitHub.