共计 5573 个字符,预计需要花费 14 分钟才能阅读完成。
前言
在理论开发过程中,有时候会遇到 URL 的校验问题,其实我也是间接调用了第三方库,然而也引发了一个思考,Go 语言中有哪些办法去验证一个字符串是否满足 URL 格局呢?
URL 代表惟一资源定位符,是 URI 的子类型(只管许多人能够调换应用这两个术语)。URL 是对网络资源的援用,通常被视为网址(例如 https://golang.org
)。
上面你能够看到一个 URL 的构造,它合乎 URI 的构造
URI = scheme:[//authority]path[?query][#fragment]
authority = [userinfo@]host[:port]
官网 URL 包
在 Golang 中利用 url.ParseRequestURI
能够简略验证咱们的 URL。
func ParseRequestURI(rawurl string) (*URL, error)
ParseRequestURI 将 rawurl 解析成 URL 构造。它假设在 HTTP 申请中接管到 rawurl,因而 rawurl 仅被解释为相对 URI 或绝对路径。假设字符串 rawurl 没有 #fragment 后缀。(Web 浏览器在将 URL 发送到 Web 服务器之前去除 #fragment。)
ParseRequestURI 与 Parse
还有另一种办法应该用于解析 URL 字符串,但有一些注意事项。它容许绝对 URL 使验证更加宽松。它是 url.Parse
func Parse(rawurl string) (*URL, error)
如文档中所述:
Parse 将 rawurl 解析成 URL 构造。
rawurl 能够是绝对的(门路,没有主机)或相对的(以计划结尾)。尝试在没有计划的状况下解析主机名和门路是有效的,但因为解析歧义,不肯定会返回谬误。
比方如下的例子:
package main
import (
"fmt"
"net/url"
)
func main() {
str := "//yuzhou1u.com"
var validURL bool
_, err := url.Parse(str)
if err != nil {fmt.Println(err)
validURL = false
} else {validURL = true}
fmt.Printf("%s is a valid URL : %v \n", str, validURL)
}
应用 ParseRequestURI
在 Google 解决办法的时候,依据这篇教程中 How to check if a string is a valid URL in Golang? 提供的办法,写了一个函数:
func isValidUrl(u1 string) bool {_, err := url.ParseRequestURI(u1)
if err != nil {return false}
u, err := url.Parse(u1)
if err != nil || u.Scheme == ""|| u.Host =="" {return false}
// Check if the URL has a valid scheme (http or https)
if u.Scheme != "http" && u.Scheme != "https" {return false}
return true
}
应用这个办法也有个缺点,如果是多个 schema:https
,也是查看不进去的,例如上面的示例:
package main
import (
"fmt"
"net/url"
)
func main() {fmt.Println(isValidUrl("testURL"))
fmt.Println(isValidUrl("test.test/"))
fmt.Println(isValidUrl("http://goglang.org"))
fmt.Println(isValidUrl("https://goglang.org"))
fmt.Println(isValidUrl("https://https://https://../google.com"))
}
func isValidUrl(u1 string) bool {_, err := url.ParseRequestURI(u1)
if err != nil {return false}
u, err := url.Parse(u1)
if err != nil || u.Scheme == ""|| u.Host =="" {return false}
// Check if the URL has a valid scheme (http or https)
if u.Scheme != "http" && u.Scheme != "https" {return false}
return true
}
运行后果如图:
应用 url-verifier
包
装置:go get -u github.com/davidmytton/url-verifier
package main
import (
"fmt"
urlverifier "github.com/davidmytton/url-verifier"
)
func main() {
url := "https://https://https://../google.com"
verifier := urlverifier.NewVerifier()
ret, err := verifier.Verify(url)
if err != nil {fmt.Errorf("Error: %s", err)
}
fmt.Printf("Result: %+v\n", ret)
}
运行后果:
前面在钻研这部分 verifier.go
源码时,发现这个用了 govalidator
这个包,如图:
于是,咱们何不间接应用 govalidator
包来判断一个字符串是否是 URL 呢?
应用 govalidator
包
govalidator
是一个针对字符串、构造体和汇合的验证器和包。基于 validator.js。
GitHub 地址:https://github.com/asaskevich/govalidator,目前播种了 5.7k 的 star
装置:go get github.com/asaskevich/govalidator
package main
import (
"fmt"
"github.com/asaskevich/govalidator"
)
func main() {
str := "https://https://https://../google.com"
validURL := govalidator.IsURL(str)
fmt.Printf("%s is a valid URL : %v \n", str, validURL)
}
运行后果如下:
正则表达式匹配
原本想本人写正则表达式匹配的,而后发现 govalidator
包的作者背地的原理也是用了正则表达式的,
而后就偷懒了,间接把他源码中的局部汇合到一个 main.go
函数中:
package main
import (
"fmt"
"net/url"
"regexp"
"strings"
"unicode/utf8"
)
const (URLSchema string = `((ftp|tcp|udp|wss?|https?):\/\/)`
URLUsername string = `(\S+(:\S*)?@)`
URLPath string = `((\/|\?|#)[^\s]*)`
URLPort string = `(:(\d{1,5}))`
URLIP string = `([1-9]\d?|1\d\d|2[01]\d|22[0-3]|24\d|25[0-5])(\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])){2}(?:\.([0-9]\d?|1\d\d|2[0-4]\d|25[0-5]))`
IP string = `(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))`
URLSubdomain string = `((www\.)|([a-zA-Z0-9]+([-_\.]?[a-zA-Z0-9])*[a-zA-Z0-9]\.[a-zA-Z0-9]+))`
URL = `^` + URLSchema + `?` + URLUsername + `?` + `((` + URLIP + `|(\[` + IP + `\])|(([a-zA-Z0-9]([a-zA-Z0-9-_]+)?[a-zA-Z0-9]([-\.][a-zA-Z0-9]+)*)|(` + URLSubdomain + `?))?(([a-zA-Z\x{00a1}-\x{ffff}0-9]+-?-?)*[a-zA-Z\x{00a1}-\x{ffff}0-9]+)(?:\.([a-zA-Z\x{00a1}-\x{ffff}]{1,}))?))\.?` + URLPort + `?` + URLPath + `?$`
/*MaxURLRuneCount : maxima cantidad de runas por contar*/
MaxURLRuneCount = 2083
/*MinURLRuneCount : minima cantidad de runas por contar*/
MinURLRuneCount = 3
)
var rxURL = regexp.MustCompile(URL)
// IsURL checks if the string is an URL.
func IsURL(str string) bool {if str == ""|| utf8.RuneCountInString(str) >= MaxURLRuneCount || len(str) <= MinURLRuneCount || strings.HasPrefix(str,".") {return false}
strTemp := str
if strings.Contains(str, ":") && !strings.Contains(str, "://") {
// support no indicated urlscheme but with colon for port number
// http:// is appended so url.Parse will succeed, strTemp used so it does not impact rxURL.MatchString
strTemp = "http://" + str
}
u, err := url.Parse(strTemp)
if err != nil {return false}
if strings.HasPrefix(u.Host, ".") {return false}
if u.Host == ""&& (u.Path !="" && !strings.Contains(u.Path, ".")) {return false}
return rxURL.MatchString(str)
}
func main() {fmt.Println(IsURL("testURL"))
fmt.Println(IsURL("test.test/"))
fmt.Println(IsURL("http://goglang.org"))
fmt.Println(IsURL("https://goglang.org"))
fmt.Println(IsURL("https://https://https://../google.com"))
}
运行后果:
除了校验 URL,这个包还提供了泛滥的字符串校验办法,例如校验邮箱、信用卡格局、IP…
总结
数据校验是每个程序员日常开发过程的一部分,尤其是在从事后端服务时,数据验证必须严格,放弃正确。
在这篇文章中,咱们探讨了如何在 Go 语言中正确验证一个字符串是否是 URL,当然利用了官网包和优良的第三方包,在理论过程中,可能咱们为了简便会间接应用他人开发好的工具,然而在学习过程中,无妨也去思考他人实现的原理,结合实际业务须要,进而扩大成本人的工具包。
心愿本文能对你有所帮忙,如果喜爱本文,能够点个关注.
下一篇文章见!宇宙古今无有穷期,毕生不过顷刻,当思奋争。
参考链接:
- url-verifier: A Go library for URL validation and verification: does this URL actually work?
- How To Validate Url In Go
- govalidator: [Go] Package of validators and sanitizers for strings, numerics, slices and structs