40
votes

Is there any function in a standard package in GO that allows to validate a URL?

I have not found anything on my initial search, and I would prefer not to resort to regex checking.

4

4 Answers

93
votes

Yep, url.ParseRequestURI returns an error if the URL is not valid, not an absolute url, etc etc. url.Parse returns valid on almost anything...

import "net/url"

...


u, err := url.ParseRequestURI("http://google.com/")
if err != nil {
   panic(err)
}

The above example will not fail, but these will:

u, err := url.ParseRequestURI("http//google.com")

u, err := url.ParseRequestURI("google.com")

u, err := url.ParseRequestURI("/foo/bar")
29
votes

The accepted answer allows empty http:// and relative urls like /foo/bar. If you want a stricter check, this will reject those:

import "net/url"

func IsUrl(str string) bool {
    u, err := url.Parse(str)
    return err == nil && u.Scheme != "" && u.Host != ""
}

Example: https://play.golang.org/p/JngFarWPF2-

Which came from this answer: https://stackoverflow.com/a/25747925/744298

7
votes

This helped me understand how the standard library url.Parse method works, hope it helps some of you as well. Notice that all these values never throw an error.

package main

import (
    "fmt"
    "net/url"
)

func main() {
    urls := []string{
        "https",
        "https://",
        "",
        "http://www",
        "http://www.dumpsters.com",
        "https://www.dumpsters.com:443",
        "/testing-path",
        "testing-path",
        "alskjff#?asf//dfas",
    }
    for _, u := range urls {
        val, err := url.Parse(u)
        scheme := val.Scheme
        host := val.Host
        hostname := val.Hostname()
        path := val.Path
        fmt.Println("val        : "+u+" : ", val)
        fmt.Println("error      : "+u+" : ", err)
        fmt.Println("scheme     : "+u+" : ", scheme)
        fmt.Println("host       : "+u+" : ", host)
        fmt.Println("hostname   : "+u+" : ", hostname)
        fmt.Println("path       : "+u+" : ", path)
        fmt.Println()
    }
}

The results

val        : https :  https
error      : https :  <nil>
scheme     : https :
host       : https :
hostname   : https :
path       : https :  https

val        : https:// :  https:
error      : https:// :  <nil>
scheme     : https:// :  https
host       : https:// :
hostname   : https:// :
path       : https:// :

val        :  :
error      :  :  <nil>
scheme     :  :
host       :  :
hostname   :  :
path       :  :

val        : http://www :  http://www
error      : http://www :  <nil>
scheme     : http://www :  http
host       : http://www :  www
hostname   : http://www :  www
path       : http://www :

val        : http://www.dumpsters.com :  http://www.dumpsters.com
error      : http://www.dumpsters.com :  <nil>
scheme     : http://www.dumpsters.com :  http
host       : http://www.dumpsters.com :  www.dumpsters.com
hostname   : http://www.dumpsters.com :  www.dumpsters.com
path       : http://www.dumpsters.com :

val        : https://www.dumpsters.com:443 :  https://www.dumpsters.com:443
error      : https://www.dumpsters.com:443 :  <nil>
scheme     : https://www.dumpsters.com:443 :  https
host       : https://www.dumpsters.com:443 :  www.dumpsters.com:443
hostname   : https://www.dumpsters.com:443 :  www.dumpsters.com
path       : https://www.dumpsters.com:443 :

val        : /testing-path :  /testing-path
error      : /testing-path :  <nil>
scheme     : /testing-path :
host       : /testing-path :
hostname   : /testing-path :
path       : /testing-path :  /testing-path

val        : testing-path :  testing-path
error      : testing-path :  <nil>
scheme     : testing-path :
host       : testing-path :
hostname   : testing-path :
path       : testing-path :  testing-path

val        : alskjff#?asf//dfas :  alskjff#?asf//dfas
error      : alskjff#?asf//dfas :  <nil>
scheme     : alskjff#?asf//dfas :
host       : alskjff#?asf//dfas :
hostname   : alskjff#?asf//dfas :
path       : alskjff#?asf//dfas :  alskjff
0
votes
func IsUrl(str string) bool {
    url, err := url.ParseRequestURI(str)
    if err != nil {
        log.Info(err.Error())
        return false
    }

    address := net.ParseIP(url.Host)
    log.Infow("url-info", "host", address)

    if address == nil {
        log.Infow("url-info", "host", url.Host)

        return  strings.Contains(url.Host, ".") 
    }

    return true
}
func Test_IsAllowUrl(t *testing.T) {
    assert.True(t, IsUrl("http://google.com"))
    assert.True(t, IsUrl("http://w.com/cn"))
    assert.True(t, IsUrl("http://192.158.0.1:90"))
    assert.False(t, IsUrl("http://w"))
    assert.False(t, IsUrl("fsw"))
    assert.False(t, IsUrl("http://192.158.1/1"))

}

the last "http:/192.158.1/1" not pass. may be should match all allow domains,but will be to complex https://www.iana.org/domains/root/db