解析带端口且不带方案的 URL

10 go

我正在尝试在 Go 中解析 URL 并从 URL 中获取主机和方案。但是,在使用端口而不使用方案解析 URL 时,我得到了意外的结果。

u, err := url.ParseRequestURI("hello.com:81")
fmt.Println("host :",u.Host)
fmt.Println("scheme :",u.Scheme)

Run Code Online (Sandbox Code Playgroud)

我得到了意想不到的结果

host :
scheme: hello.com
Run Code Online (Sandbox Code Playgroud)

我想要这个

host : hello.com:80
scheme:
Run Code Online (Sandbox Code Playgroud)

Yur*_*lov 11

如果您需要处理仅包含主机和端口(没有方案和其他参数)的 URL,您可以使用以下代码:

   host, port, err := net.SplitHostPort("hello.com:81")
   fmt.Println("host:", host, "port:", port, "err:", err)
   // output: host: hello.com port: 81 err <nil>
Run Code Online (Sandbox Code Playgroud)

注意SplitHostPort()不适合解析标准 URL(符合[scheme:][//[userinfo@]host][/]path[?query][#fragment]


Nam*_*ess 9

根据 go doc,表示的一般 url 形式为:

[scheme:][//[userinfo@]host][/]path[?query][#fragment]
Run Code Online (Sandbox Code Playgroud)

方案后不以斜杠开头的 URL 被解释为:

scheme:opaque[?query][#fragment]
Run Code Online (Sandbox Code Playgroud)

您的 URL 将被解析为第二种格式。

您可以使用此方法来获得您期望的结果。在函数中,如果 URL 中没有 schema,我们添加它,然后再次解析它以获得预期结果。

func parseRawURL(rawurl string) (domain string, scheme string, err error) {
    u, err := url.ParseRequestURI(rawurl)
    if err != nil || u.Host == "" {
        u, repErr := url.ParseRequestURI("https://" + rawurl)
        if repErr != nil {
            fmt.Printf("Could not parse raw url: %s, error: %v", rawurl, err)
            return
        }
        domain = u.Host
        err = nil
        return
    }

    domain = u.Host
    scheme = u.Scheme
    return
}
Run Code Online (Sandbox Code Playgroud)

你可以在go游乐场尝试一下