我正在尝试使用Go的标准库来验证URL。这就是我的代码当前的样子。
import (
"fmt"
"net/url"
)
func isValidURL(tocheck string) bool {
_, err := url.ParseRequestURI(tocheck)
return err == nil
}
func main() {
fmt.Println(isValidURL("google.com")) //returns false, expected true
fmt.Println(isValidURL("www.google.com")) //returns false, expected true
fmt.Println(isValidURL("google")) //returns false, expected false
fmt.Println(isValidURL("/google")) //returns true, expected false
}
尽管前两个示例为true,但所有三个示例均打印为false。然后,我尝试将https://
附加到不以它们开头的URL的开头,但是随后,像https://aaaa
这样的所有内容都被解析为有效。我该怎么做才能确保仅在URL有效时才返回true?
答案 0 :(得分:5)
其中大多数是域名。 https://aaaa
是有效的网址。 /google
不是URL,但ParseRequestURI
可以接受,因为它也接受绝对路径。
“ 原始网址仅解释为绝对URI 或绝对路径 ”
当您询问ParseRequestURI
时,您是在要求对绝对URL或绝对路径进行严格的语法检查。绝对路径类似于/foo/bar
。 RFC 3986涵盖了什么是绝对URL,什么不是绝对URL。 URI的基本语法是这样。
URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
hier-part = "//" authority path-abempty
/ path-absolute
/ path-rootless
/ path-empty
“绝对URL”表示path
部分是绝对路径或为空,因此上面的path-abempty
或path-absolute
。 http
和https
网址只能是绝对网址。 foo:bar/baz
是相对URL的示例。
这是一个例子。
foo://example.com:8042/over/there?name=ferret#nose
\_/ \______________/\_________/ \_________/ \__/
| | | | |
scheme authority path query fragment
| _____________________|__
/ \ / \
urn:example:animal:ferret:nose
google.com
没有scheme
,因此它不是URL。 https://aaaa
有一个方案https
和一个hier-part
,//aaaa
,因此它是一个URL。它没有query
或fragement
,但它们是可选的。
显然,这有点宽泛。在现实世界中,您需要缩小要求。通常就像...
ParseRequestURI
来实现,因为它也可以是绝对路径。url.Scheme
。这将丢弃绝对路径。url.Host
。以及您可能要执行的其他任何检查,以限制您认为有效的URL。
因此您的完整支票可能看起来像...
package main
import (
"fmt"
"net"
"net/url"
"errors"
)
func isValidURL(tocheck string) (bool, error) {
// Check it's an Absolute URL or absolute path
uri, err := url.ParseRequestURI(tocheck)
if err != nil {
return false, err
}
// Check it's an acceptable scheme
switch uri.Scheme {
case "http":
case "https":
default:
return false, errors.New("Invalid scheme")
}
// Check it's a valid domain name
_,err = net.LookupHost(uri.Host)
if err != nil {
return false, err
}
return true, nil
}
func main() {
// False, no scheme
fmt.Println(isValidURL("/google"))
// True, good scheme, good domain
fmt.Println(isValidURL("https://google.com"))
// False, bad domain
fmt.Println(isValidURL("http://halghalghlakdjfl.blarg"))
}
答案 1 :(得分:3)
您将域名与URL混淆了,域名只是URL的一部分。
有效的域示例为:www.google.com
,localhost
和a.b.c.a.google.com
。
为了使URL有效,方案/协议部分(通常为https://
)必须存在,请参阅syntax at Wikipedia for an easy explanation。
http://aaa
是有效网址,其规则与http://localhost
有效