Files
drip/internal/shared/utils/subdomain.go

67 lines
1.5 KiB
Go

package utils
import (
"crypto/rand"
"math/big"
"regexp"
)
const (
// SubdomainChars defines the allowed characters for subdomain generation
SubdomainChars = "abcdefghijklmnopqrstuvwxyz0123456789"
// DefaultSubdomainLength is the default length of generated subdomains
DefaultSubdomainLength = 6
)
var subdomainRegex = regexp.MustCompile(`^[a-z0-9][a-z0-9-]{1,61}[a-z0-9]$`)
// GenerateSubdomain generates a random subdomain
func GenerateSubdomain(length int) string {
if length <= 0 {
length = DefaultSubdomainLength
}
result := make([]byte, length)
charsLen := big.NewInt(int64(len(SubdomainChars)))
for i := 0; i < length; i++ {
num, err := rand.Int(rand.Reader, charsLen)
if err != nil {
// Fallback to simple random if crypto/rand fails
result[i] = SubdomainChars[i%len(SubdomainChars)]
continue
}
result[i] = SubdomainChars[num.Int64()]
}
return string(result)
}
// ValidateSubdomain checks if a subdomain is valid
func ValidateSubdomain(subdomain string) bool {
if len(subdomain) < 3 || len(subdomain) > 63 {
return false
}
return subdomainRegex.MatchString(subdomain)
}
// IsReserved checks if a subdomain is reserved
func IsReserved(subdomain string) bool {
reserved := map[string]bool{
"www": true,
"api": true,
"admin": true,
"app": true,
"mail": true,
"ftp": true,
"blog": true,
"shop": true,
"status": true,
"health": true,
"test": true,
"dev": true,
"staging": true,
}
return reserved[subdomain]
}