diff --git a/validator/validator.go b/validator/validator.go index bb1b8bd..362d8ec 100644 --- a/validator/validator.go +++ b/validator/validator.go @@ -7,6 +7,7 @@ package validator import ( "encoding/json" "net" + "net/url" "regexp" "strconv" "strings" @@ -123,6 +124,27 @@ func IsPort(str string) bool { return false } +var isUrlRegexMatcher *regexp.Regexp = regexp.MustCompile(`^((ftp|http|https?):\/\/)?(\S+(:\S*)?@)?((([1-9]\d?|1\d\d|2[01]\d|22[0-3])(\.(1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.([0-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(([a-zA-Z0-9]+([-\.][a-zA-Z0-9]+)*)|((www\.)?))?(([a-z\x{00a1}-\x{ffff}0-9]+-?-?)*[a-z\x{00a1}-\x{ffff}0-9]+)(?:\.([a-z\x{00a1}-\x{ffff}]{2,}))?))(:(\d{1,5}))?((\/|\?|#)[^\s]*)?$`) + +// IsUrl check if the string is url. +func IsUrl(str string) bool { + if str == "" || len(str) >= 2083 || len(str) <= 3 || strings.HasPrefix(str, ".") { + return false + } + u, err := url.Parse(str) + if err != nil { + return false + } + if strings.HasPrefix(u.Host, ".") { + return false + } + if u.Host == "" && (u.Path != "" && !strings.Contains(u.Path, ".")) { + return false + } + + return isUrlRegexMatcher.MatchString(str) +} + var isDnsRegexMatcher *regexp.Regexp = regexp.MustCompile(`^[a-zA-Z]([a-zA-Z0-9\-]+[\.]?)*[a-zA-Z0-9]$`) // IsDns check if the string is dns. diff --git a/validator/validator_test.go b/validator/validator_test.go index 6d07bb6..f9f41f9 100644 --- a/validator/validator_test.go +++ b/validator/validator_test.go @@ -160,11 +160,21 @@ func TestIsIpV6(t *testing.T) { assert.Equal(true, IsIpV6("::0:0:0:0:0:0:1")) } +func TestIsUrl(t *testing.T) { + assert := internal.NewAssert(t, "TestIsUrl") + + assert.Equal(true, IsUrl("http://abc.com")) + assert.Equal(true, IsUrl("abc.com")) + assert.Equal(true, IsUrl("a.b.com")) + assert.Equal(false, IsUrl("abc")) +} + func TestIsDns(t *testing.T) { assert := internal.NewAssert(t, "TestIsDns") assert.Equal(true, IsDns("abc.com")) assert.Equal(false, IsDns("a.b.com")) + assert.Equal(false, IsDns("http://abc.com")) } func TestIsEmail(t *testing.T) {