How To Validate Url In Go
Validation is part of every programmer life, especially when working on backend services, validation must be done right. In this blog post we talk about how to properly validate a URL in Go (Golang).
URL stands for Unique Resource Locator, and is a sub-type of URI (even though many people interchangeably use the two terms). A URL is a reference to a web resource, typically seen as a web address (eg https://golang.org/project/)
Below you can see the structure of a URL, which conforms with he structure of a URI
URI = scheme:[//authority]path[?query][#fragment]
authority = [userinfo@]host[:port]
How do you validate a URL in Go (Golang)?
I’ve always been impressed by the number of native packages in the Go standard library. Also this time we have a package that fulfils our needs. The net/url
package https://golang.org/pkg/net/url/
We can use url.ParseRequestURI
in order to validate our URL
func ParseRequestURI(rawurl string) (*URL, error)
The behaviour is described below
ParseRequestURI parses rawurl into a URL structure. It assumes that rawurl was received in an HTTP request, so the rawurl is interpreted only as an absolute URI or an absolute path. The string rawurl is assumed not to have a #fragment suffix. (Web browsers strip #fragment before sending the URL to a web server.)
Caveat: ParseRequestURI vs Parse
There is also another method that is supposed to be used for Parsing URL strings, but there are some caveats. It allows relative URLs making the validation a bit more loose. It’s url.Parse
func Parse(rawurl string) (*URL, error)
As described on the docs
Parse parses rawurl into a URL structure.
The rawurl may be relative (a path, without a host) or absolute (starting with a scheme). Trying to parse a hostname and path without a scheme is invalid but may not necessarily return an error, due to parsing ambiguities.
Parse URL Example
Let’s see now an example on how to parse and validate a URL in Go using ParseRequestURI
package main
import (
"log"
"net/url"
)
func main() {
u, err := url.ParseRequestURI("hi/there?")
log.Printf("hi/there?: err=%+v url=%+v\n", err, u)
u, err = url.ParseRequestURI("http://golang.cafe/")
log.Printf("hi/there?: err=%+v url=%+v\n", err, u)
u, err = url.ParseRequestURI("http://golang.org/index.html?#page1")
log.Printf("hi/there?: err=%+v url=%+v\n", err, u)
u, err = url.ParseRequestURI("golang.org")
log.Printf("hi/there?: err=%+v url=%+v\n", err, u)
}
Which outputs the following
2009/11/10 23:00:00 hi/there?: err=parse hi/there?: invalid URI for request url=<nil>
2009/11/10 23:00:00 hi/there?: err=<nil> url=http://golang.cafe/
2009/11/10 23:00:00 hi/there?: err=<nil> url=http://golang.org/index.html?#page1
2009/11/10 23:00:00 hi/there?: err=parse golang.org: invalid URI for request url=<nil>