-
Notifications
You must be signed in to change notification settings - Fork 4
/
url.go
111 lines (94 loc) · 2.85 KB
/
url.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
// SPDX-License-Identifier: Apache-2.0
// SPDX-FileCopyrightText: 2024-Present Defense Unicorns
package helpers
import (
"fmt"
"net"
"net/url"
"os"
"path"
"regexp"
"strconv"
)
// Nonstandard URL schemes or prefixes
const (
OCIURLPrefix = "oci://"
SGETURLPrefix = "sget://"
SGETURLScheme = "sget"
IPV4Localhost = "127.0.0.1"
)
// IsURL is a helper function to check if a URL is valid.
func IsURL(source string) bool {
parsedURL, err := url.Parse(source)
return err == nil && parsedURL.Scheme != "" && parsedURL.Host != ""
}
// IsOCIURL returns true if the given URL is an OCI URL.
func IsOCIURL(source string) bool {
parsedURL, err := url.Parse(source)
return err == nil && parsedURL.Scheme == "oci"
}
// DoHostnamesMatch returns a boolean indicating if the hostname of two different URLs are the same.
func DoHostnamesMatch(url1 string, url2 string) (bool, error) {
parsedURL1, err := url.Parse(url1)
if err != nil {
return false, fmt.Errorf("unable to parse the url (%s): %w", url1, err)
}
parsedURL2, err := url.Parse(url2)
if err != nil {
return false, fmt.Errorf("unable to parse the url (%s): %w", url2, err)
}
return parsedURL1.Hostname() == parsedURL2.Hostname(), nil
}
// ExtractBasePathFromURL returns filename from URL string
func ExtractBasePathFromURL(urlStr string) (string, error) {
if !IsURL(urlStr) {
return "", fmt.Errorf("%s is not a valid URL", urlStr)
}
parsedURL, err := url.Parse(urlStr)
if err != nil {
return "", err
}
filename := path.Base(parsedURL.Path)
return filename, nil
}
// IsValidHostName returns a boolean indicating if the hostname of the host machine is valid according to https://www.ietf.org/rfc/rfc1123.txt.
func IsValidHostName() bool {
// Quick & dirty character validation instead of a complete RFC validation since the OS is already allowing it
hostname, err := os.Hostname()
if err != nil {
return false
}
return validHostname(hostname)
}
func validHostname(hostname string) bool {
// Explanation: https://regex101.com/r/zUGqjP/1/
rfcDomain := regexp.MustCompile(`^[a-zA-Z0-9\-.]+$`)
// Explanation: https://regex101.com/r/vPGnzR/1/
localhost := regexp.MustCompile(`\.?localhost$`)
isValid := rfcDomain.MatchString(hostname)
if isValid {
isValid = !localhost.MatchString(hostname)
}
return isValid
}
// GetAvailablePort retrieves an available port on the host machine. This delegates the port selection to the golang net
// library by starting a server and then checking the port that the server is using.
func GetAvailablePort() (int, error) {
l, err := net.Listen("tcp", ":0")
if err != nil {
return 0, err
}
defer func(l net.Listener) {
// ignore this error because it won't help us to tell the user
_ = l.Close()
}(l)
_, p, err := net.SplitHostPort(l.Addr().String())
if err != nil {
return 0, err
}
port, err := strconv.Atoi(p)
if err != nil {
return 0, err
}
return port, err
}