CompleteURL parses and validates the given URL. It supports general URLs like https://ca.smallstep.com[:port][/path], and incomplete URLs like ca.smallstep.com[:port][/path].
(rawurl string)
| 26 | // URLs like https://ca.smallstep.com[:port][/path], and incomplete URLs like |
| 27 | // ca.smallstep.com[:port][/path]. |
| 28 | func CompleteURL(rawurl string) (string, error) { |
| 29 | u, err := url.Parse(rawurl) |
| 30 | if err != nil { |
| 31 | return "", errors.Wrapf(err, "error parsing url '%s'", rawurl) |
| 32 | } |
| 33 | |
| 34 | // URLs are generally parsed as: |
| 35 | // [scheme:][//[userinfo@]host][/]path[?query][#fragment] |
| 36 | // But URLs that do not start with a slash after the scheme are interpreted as |
| 37 | // scheme:opaque[?query][#fragment] |
| 38 | if u.Opaque == "" { |
| 39 | if u.Scheme == "" { |
| 40 | u.Scheme = "https" |
| 41 | } |
| 42 | if u.Host == "" { |
| 43 | // rawurl looks like ca.smallstep.com or ca.smallstep.com/1.0/sign |
| 44 | if u.Path != "" { |
| 45 | parts := strings.SplitN(u.Path, "/", 2) |
| 46 | u.Host = parts[0] |
| 47 | if len(parts) == 2 { |
| 48 | u.Path = parts[1] |
| 49 | } else { |
| 50 | u.Path = "" |
| 51 | } |
| 52 | return CompleteURL(u.String()) |
| 53 | } |
| 54 | return "", errors.Errorf("error parsing url '%s'", rawurl) |
| 55 | } |
| 56 | return u.String(), nil |
| 57 | } |
| 58 | // scheme:opaque[?query][#fragment] |
| 59 | // rawurl looks like ca.smallstep.com:443 or ca.smallstep.com:443/1.0/sign |
| 60 | return CompleteURL("https://" + rawurl) |
| 61 | } |