@@ -1465,29 +1465,49 @@ func isURI(fl FieldLevel) bool {
14651465func isURL (fl FieldLevel ) bool {
14661466 field := fl .Field ()
14671467
1468+ var s string
1469+ var uri * url.URL
1470+ var ok bool
1471+
14681472 switch field .Kind () {
14691473 case reflect .String :
1474+ s = strings .ToLower (field .String ())
1475+ case reflect .Struct :
1476+ var u url.URL
1477+ if u , ok = field .Interface ().(url.URL ); ! ok {
1478+ panic (fmt .Sprintf ("Bad field type %s" , field .Type ()))
1479+ }
1480+ uri = & u
1481+ default :
1482+ var stringer fmt.Stringer
1483+ if stringer , ok = field .Interface ().(fmt.Stringer ); ! ok {
1484+ panic (fmt .Sprintf ("Bad field type %s" , field .Type ()))
1485+ }
1486+ s = stringer .String ()
1487+ }
14701488
1471- s := strings .ToLower (field .String ())
1489+ if len (s ) == 0 && uri == nil {
1490+ return false
1491+ }
14721492
1473- if len (s ) == 0 {
1493+ if uri == nil {
1494+ var err error
1495+ if uri , err = url .Parse (s ); err != nil {
14741496 return false
14751497 }
1498+ }
14761499
1477- url , err := url .Parse (s )
1478- if err != nil || url .Scheme == "" {
1479- return false
1480- }
1481- isFileScheme := url .Scheme == "file"
1500+ if uri .Scheme == "" {
1501+ return false
1502+ }
14821503
1483- if (isFileScheme && (len (url .Path ) == 0 || url .Path == "/" )) || (! isFileScheme && len (url .Host ) == 0 && len (url .Fragment ) == 0 && len (url .Opaque ) == 0 ) {
1484- return false
1485- }
1504+ isFileScheme := uri .Scheme == "file"
14861505
1487- return true
1506+ if (isFileScheme && (len (uri .Path ) == 0 || uri .Path == "/" )) || (! isFileScheme && len (uri .Host ) == 0 && len (uri .Fragment ) == 0 && len (uri .Opaque ) == 0 ) {
1507+ return false
14881508 }
14891509
1490- panic ( fmt . Sprintf ( "Bad field type %s" , field . Type ()))
1510+ return true
14911511}
14921512
14931513// isHttpURL is the validation function for validating if the current field's value is a valid HTTP(s) URL.
@@ -1497,20 +1517,32 @@ func isHttpURL(fl FieldLevel) bool {
14971517 }
14981518
14991519 field := fl .Field ()
1520+ var s string
1521+ var ok bool
15001522 switch field .Kind () {
15011523 case reflect .String :
1524+ s = strings .ToLower (field .String ())
1525+ case reflect .Struct :
1526+ var u url.URL
15021527
1503- s := strings .ToLower (field .String ())
1504-
1505- url , err := url .Parse (s )
1506- if err != nil || url .Host == "" {
1507- return false
1528+ if u , ok = field .Interface ().(url.URL ); ! ok {
1529+ panic (fmt .Sprintf ("Bad field type %s" , field .Type ()))
1530+ }
1531+ s = u .String ()
1532+ default :
1533+ if stringer , ok := fl .Field ().Interface ().(fmt.Stringer ); ok {
1534+ s = stringer .String ()
1535+ } else {
1536+ panic (fmt .Sprintf ("Bad field type %s" , field .Type ()))
15081537 }
1538+ }
15091539
1510- return url .Scheme == "http" || url .Scheme == "https"
1540+ url , err := url .Parse (s )
1541+ if err != nil || url .Host == "" {
1542+ return false
15111543 }
15121544
1513- panic ( fmt . Sprintf ( "Bad field type %s" , field . Type ()))
1545+ return url . Scheme == "http" || url . Scheme == "https"
15141546}
15151547
15161548// isUrnRFC2141 is the validation function for validating if the current field's value is a valid URN as per RFC 2141.
0 commit comments