144 lines
3.2 KiB
Go
144 lines
3.2 KiB
Go
package pilgrim_conf
|
|
|
|
import (
|
|
"fmt"
|
|
"log"
|
|
"regexp"
|
|
"slices"
|
|
"strings"
|
|
|
|
"mvvasilev.dev/pilgrim/internal/pilgrim_common"
|
|
)
|
|
|
|
const EmptyString = ""
|
|
|
|
type DbDriver string
|
|
|
|
const (
|
|
DbDriver_MySQL DbDriver = "mysql"
|
|
DbDriver_MSSQL DbDriver = "mssql"
|
|
DbDriver_Postgres DbDriver = "postgres"
|
|
DbDriver_Oracle DbDriver = "oracle"
|
|
DbDriver_SQLite DbDriver = "sqlite"
|
|
DbDriver_MariaDB DbDriver = "mariadb"
|
|
)
|
|
|
|
var AvailableDbDrivers []DbDriver = []DbDriver{
|
|
DbDriver_MySQL,
|
|
DbDriver_MSSQL,
|
|
DbDriver_Postgres,
|
|
DbDriver_Oracle,
|
|
DbDriver_SQLite,
|
|
DbDriver_MariaDB,
|
|
}
|
|
|
|
type UrlParts struct {
|
|
Host,
|
|
Port,
|
|
Username,
|
|
Password string
|
|
|
|
Driver DbDriver
|
|
|
|
Segments []string
|
|
Arguments map[string]string
|
|
}
|
|
|
|
const DbUrlRegex = `^(?:([^:\/?#\s]+):\/{2})?(?:([^@\/?#\s]+)@)?([^\/?#\s]+)?(?:\/([^?#\s]*))?(?:[?]([^#\s]+))?\S*$`
|
|
|
|
func ParseDatabaseUrl(url string) UrlParts {
|
|
urlRegex, err := regexp.Compile(DbUrlRegex)
|
|
|
|
if err != nil {
|
|
log.Fatalf("Regex %s could not be compiled", DbUrlRegex) // The developer wrote the regex wrong.
|
|
}
|
|
|
|
parsed := urlRegex.FindAllStringSubmatch(url, -1)
|
|
|
|
if parsed == nil || parsed[0] == nil {
|
|
return UrlParts{}
|
|
}
|
|
|
|
parsedUrl := parsed[0]
|
|
|
|
driver := DbDriver(parsedUrl[1])
|
|
username := ""
|
|
password := ""
|
|
host := ""
|
|
port := ""
|
|
var segments []string
|
|
var arguments map[string]string = make(map[string]string)
|
|
|
|
// Parse username and password ( username:password )
|
|
if parsedUrl[2] != EmptyString && strings.Contains(parsedUrl[2], ":") {
|
|
splitUserAndPass := strings.Split(parsedUrl[2], ":")
|
|
username = splitUserAndPass[0]
|
|
password = splitUserAndPass[1]
|
|
}
|
|
|
|
// Parse host and port ( host:port )
|
|
if parsedUrl[3] != EmptyString && strings.Contains(parsedUrl[3], ":") {
|
|
splitHostAndPort := strings.Split(parsedUrl[3], ":")
|
|
host = splitHostAndPort[0]
|
|
port = splitHostAndPort[1]
|
|
}
|
|
|
|
// Parse segments ( segment1/segment2 )
|
|
if parsedUrl[4] != EmptyString {
|
|
segments = ParseSegments(parsedUrl[4])
|
|
}
|
|
|
|
// Parse arguments ( arg1=value1&arg2=value2 )
|
|
if parsedUrl[5] != EmptyString {
|
|
arguments = ParseArguments(parsedUrl[5])
|
|
}
|
|
|
|
return UrlParts{
|
|
Driver: driver,
|
|
Username: username,
|
|
Password: password,
|
|
Host: host,
|
|
Port: port,
|
|
Segments: segments,
|
|
Arguments: arguments,
|
|
}
|
|
}
|
|
|
|
func ParseSegments(segments string) []string {
|
|
if segments == EmptyString {
|
|
return []string{}
|
|
}
|
|
|
|
return strings.Split(segments, "/")
|
|
}
|
|
|
|
func ParseArguments(arguments string) map[string]string {
|
|
if arguments == EmptyString {
|
|
return make(map[string]string)
|
|
}
|
|
|
|
var argsMap map[string]string = make(map[string]string)
|
|
|
|
splitArguments := strings.Split(arguments, "&")
|
|
|
|
for _, arg := range splitArguments {
|
|
if !strings.Contains(arg, "=") {
|
|
continue
|
|
}
|
|
|
|
splitArgAndValue := strings.Split(arg, "=")
|
|
|
|
argsMap[splitArgAndValue[0]] = splitArgAndValue[1]
|
|
}
|
|
|
|
return argsMap
|
|
}
|
|
|
|
// Returns true if valid, with nil error, or false if invalid, with the validation error
|
|
func (urlParts *UrlParts) Validate() (bool, error) {
|
|
if !slices.Contains(AvailableDbDrivers, DbDriver(urlParts.Driver)) {
|
|
return false, pilgrim_common.PilgrimInvalidError(fmt.Sprintf("URLParts invalid: Provided driver \"%v\" is not currently supported ( must be one of %v )", urlParts.Driver, AvailableDbDrivers))
|
|
}
|
|
|
|
return true, nil
|
|
}
|