2025-03-15 19:03:22 +02:00
package pilgrim_conf
2024-10-25 23:57:19 +03:00
import (
"fmt"
"log"
"regexp"
"slices"
"strings"
)
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 , PilgrimInvalidError ( fmt . Sprintf ( "URLParts invalid: Provided driver %v is not currently supported ( must be one of %v )" , urlParts . Driver , AvailableDbDrivers ) )
}
return true , nil
}