go-dev-zprox-0.01/internal/config/config.go
Zeev Diukman 2c7fbd6617 4
2025-03-08 17:50:58 +00:00

241 lines
5 KiB
Go

package config
import (
"regexp"
"strings"
"github.com/zeevdiukman/go-config"
)
const VIPER_NAME string = "config"
const VIPER_TYPE string = "yaml"
const VIPER_PATH string = "./assets/config/."
const SERVICES_KEY string = "http.services"
const ROUTERS_KEY string = "http.routers"
const ENTRYPOINTS_KEY string = "entrypoints"
const TLS_KEY string = "tls.certproviders"
type Config struct {
HTTP *HTTP
TLS *TLS
EntryPoints EntryPoints
}
type HTTP struct {
Routers Routers
Services Services
}
type TLS struct {
CertProviders CertProviders
}
type CertProviders map[string]*CertProvider
type CertProvider struct {
Key string
Cert string
}
type Services map[string]*Service
type Service struct {
URL string
}
type EntryPoints map[string]*EntryPoint
type EntryPoint struct {
Address string
TLS *EntryPointTLS
}
type EntryPointTLS struct {
Enabled bool
}
type Routers map[string]*Router
type Router struct {
EntryPoint string
Service string
Rules *Rules
TLS *RouterTLS
}
type RouterTLS struct {
CertProvider string
}
type Rules struct {
Raw string
Map map[string]*Rule
}
type Rule struct {
Name string
Value string
}
func New() *Config {
c := config.NewConfig(VIPER_NAME, VIPER_TYPE, VIPER_PATH)
c.Load()
appConfig := &Config{
HTTP: &HTTP{
Routers: Routers{},
Services: Services{},
},
TLS: &TLS{
CertProviders: CertProviders{},
},
EntryPoints: EntryPoints{},
}
appConfig.InitRouters(c)
appConfig.InitServices(c)
appConfig.InitEntryPoints(c)
appConfig.InitTLS(c)
return appConfig
}
func (r Routers) ForEach(fn func(routerName string, routerConfig *Router)) {
for k, v := range r {
fn(k, v)
}
}
func (ep EntryPoints) ForEach(fn func(entryPointName string, entryPointConfig *EntryPoint)) {
forEach(ep, fn)
}
func (s Services) ForEach(fn func(serviceName string, serviceConfig *Service)) {
forEach(s, fn)
}
func (c *Config) InitRouters(vConfig *config.Config) {
c.HTTP.Routers = make(Routers)
for k, v := range vConfig.Sub(ROUTERS_KEY).AllSettings() {
val := v.(map[string]any)
var tls string = ""
var services string = ""
var rawRules string = ""
var entryPoint string = ""
if value, ok := val["service"]; ok {
services = value.(string)
}
if value, ok := val["rules"]; ok {
rawRules = value.(string)
}
if value, ok := val["entrypoint"]; ok {
entryPoint = value.(string)
}
if value, ok := val["tls"]; ok {
tls = value.(map[string]any)["certprovider"].(string)
}
rls := &Rules{
Raw: rawRules,
Map: make(map[string]*Rule),
}
r := &Router{
Service: services,
Rules: rls,
EntryPoint: entryPoint,
TLS: &RouterTLS{CertProvider: tls},
}
r.ForRuleFunc("Domain", func(domain string) {
r.Rules.Map["Domain"] = &Rule{
Name: "Domain",
Value: domain,
}
})
r.ForRuleFunc("Path", func(path string) {
r.Rules.Map["Path"] = &Rule{
Name: "Path",
Value: path,
}
})
c.HTTP.Routers[k] = r
}
}
func (c *Config) InitServices(vConfig *config.Config) {
c.HTTP.Services = make(map[string]*Service)
for k, v := range vConfig.Sub(SERVICES_KEY).AllSettings() {
c.HTTP.Services[k] = &Service{
URL: v.(string),
}
}
}
func (c *Config) InitEntryPoints(vConfig *config.Config) {
c.EntryPoints = make(EntryPoints)
for k, v := range vConfig.Sub(ENTRYPOINTS_KEY).AllSettings() {
v := v.(map[string]any)
address := ""
enabled := false
if v, ok := v["tls"]; ok {
if v, ok := v.(map[string]any)["enabled"]; ok {
enabled = v.(bool)
}
}
if value, ok := v["address"]; ok {
address = value.(string)
}
c.EntryPoints[k] = &EntryPoint{
Address: address,
TLS: &EntryPointTLS{
Enabled: enabled,
},
}
}
}
func (c *Config) InitTLS(vConfig *config.Config) {
c.TLS.CertProviders = make(map[string]*CertProvider)
for k, v := range vConfig.Sub(TLS_KEY).AllSettings() {
cert := v.(map[string]any)["cert"].(string)
key := v.(map[string]any)["key"].(string)
c.TLS.CertProviders[k] = &CertProvider{
Cert: cert,
Key: key,
}
}
}
func forEach[K comparable, V comparable](mp map[K]V, fn func(key K, value V)) {
for k, v := range mp {
fn(k, v)
}
}
func (r *Router) ForRuleFunc(ruleName string, fn func(string)) {
rules := r.Rules.Raw
rulesSlice := splitStatementByRegex(rules, "\\(`(.*?)`\\)")
for idx, rule := range rulesSlice {
rule, _ = strings.CutPrefix(rule, ".")
if rule == ruleName {
fn(rulesSlice[idx+1])
}
}
}
func splitStatementByRegex(str string, regx string) []string {
input := str
re := regexp.MustCompile(regx)
matches := re.FindAllStringSubmatch(input, -1)
if len(matches) == 0 {
return []string{str} // Return original if no backticks found
}
result := []string{}
lastIndex := 0
for _, match := range matches {
startIndex := strings.Index(input, match[0])
if startIndex > lastIndex {
result = append(result, input[lastIndex:startIndex])
}
result = append(result, match[1]) // Append the content within backticks
lastIndex = startIndex + len(match[0])
}
if lastIndex < len(input) {
result = append(result, input[lastIndex:])
}
return result
}