diff --git a/baked_in.go b/baked_in.go index ac1c350b..7d993aa5 100644 --- a/baked_in.go +++ b/baked_in.go @@ -1414,6 +1414,15 @@ func isURI(fl FieldLevel) bool { panic(fmt.Sprintf("Bad field type %T", field.Interface())) } +// isFileURL is the helper function for validating if the `path` valid file URL as per RFC8089 +func isFileURL(path string) bool { + if !strings.HasPrefix(path, "file:/") { + return false + } + _, err := url.ParseRequestURI(path) + return err == nil +} + // isURL is the validation function for validating if the current field's value is a valid URL. func isURL(fl FieldLevel) bool { field := fl.Field() @@ -1421,12 +1430,16 @@ func isURL(fl FieldLevel) bool { switch field.Kind() { case reflect.String: - s := field.String() + s := strings.ToLower(field.String()) if len(s) == 0 { return false } + if isFileURL(s) { + return true + } + url, err := url.Parse(s) if err != nil || url.Scheme == "" { return false diff --git a/validator_test.go b/validator_test.go index e2466118..4a08d011 100644 --- a/validator_test.go +++ b/validator_test.go @@ -8139,6 +8139,12 @@ func TestUrl(t *testing.T) { {"./rel/test/dir", false}, {"irc:", false}, {"http://", false}, + {"file://path/to/file.txt", true}, + {"file:///c:/Windows/file.txt", true}, + {"file://localhost/path/to/file.txt", true}, + {"file://localhost/c:/WINDOWS/file.txt", true}, + {"file://", true}, + {"file:////remotehost/path/file.txt", true}, } validate := New()