3
This commit is contained in:
parent
7fe2b621e8
commit
f3e476a6c3
9 changed files with 458 additions and 130 deletions
52
.air.toml
52
.air.toml
|
|
@ -1,52 +0,0 @@
|
||||||
root = "."
|
|
||||||
testdata_dir = "testdata"
|
|
||||||
tmp_dir = "tmp"
|
|
||||||
|
|
||||||
[build]
|
|
||||||
args_bin = []
|
|
||||||
bin = "./tmp/main"
|
|
||||||
cmd = "go build -o ./tmp/main ."
|
|
||||||
delay = 1000
|
|
||||||
exclude_dir = ["assets", "tmp", "vendor", "testdata"]
|
|
||||||
exclude_file = []
|
|
||||||
exclude_regex = ["_test.go"]
|
|
||||||
exclude_unchanged = false
|
|
||||||
follow_symlink = false
|
|
||||||
full_bin = ""
|
|
||||||
include_dir = []
|
|
||||||
include_ext = ["go", "tpl", "tmpl", "html"]
|
|
||||||
include_file = []
|
|
||||||
kill_delay = "0s"
|
|
||||||
log = "build-errors.log"
|
|
||||||
poll = false
|
|
||||||
poll_interval = 0
|
|
||||||
post_cmd = []
|
|
||||||
pre_cmd = []
|
|
||||||
rerun = false
|
|
||||||
rerun_delay = 500
|
|
||||||
send_interrupt = false
|
|
||||||
stop_on_error = false
|
|
||||||
|
|
||||||
[color]
|
|
||||||
app = ""
|
|
||||||
build = "yellow"
|
|
||||||
main = "magenta"
|
|
||||||
runner = "green"
|
|
||||||
watcher = "cyan"
|
|
||||||
|
|
||||||
[log]
|
|
||||||
main_only = false
|
|
||||||
silent = false
|
|
||||||
time = false
|
|
||||||
|
|
||||||
[misc]
|
|
||||||
clean_on_exit = false
|
|
||||||
|
|
||||||
[proxy]
|
|
||||||
app_port = 0
|
|
||||||
enabled = false
|
|
||||||
proxy_port = 0
|
|
||||||
|
|
||||||
[screen]
|
|
||||||
clear_on_rebuild = false
|
|
||||||
keep_scroll = true
|
|
||||||
|
|
@ -1,20 +1,37 @@
|
||||||
http:
|
http:
|
||||||
routers:
|
routers:
|
||||||
keycloak:
|
keycloak:
|
||||||
|
entryPoint: https
|
||||||
service: keycloak
|
service: keycloak
|
||||||
rules: Host(keycloak.z.com).Path(`/`)
|
rules: Domain(`keycloak.z.com`).Path(`/`)
|
||||||
|
tls:
|
||||||
|
certProvider: default
|
||||||
app1:
|
app1:
|
||||||
service: app1_srv
|
entryPoint: https
|
||||||
rules: Host(`app1.z.com`).Path(`/`)
|
service: app1
|
||||||
|
rules: Domain(`app1.z.com`).Path(`/`)
|
||||||
|
tls:
|
||||||
|
certProvider: default
|
||||||
app2:
|
app2:
|
||||||
service: app2_srv
|
entryPoint: https
|
||||||
rules: Host(`app2.z.com`).Path(`/`)
|
service: app2
|
||||||
|
rules: Domain(`app2.z.com`).Path(`/`)
|
||||||
|
tls:
|
||||||
|
certProvider: default
|
||||||
|
|
||||||
services:
|
services:
|
||||||
keycloak: http://192.168.10.2:8080
|
keycloak: http://192.168.10.2:8080
|
||||||
app1_srv: http://192.168.10.2:3001
|
app1: http://192.168.10.2:3001
|
||||||
app2_srv: http://192.168.10.2:3002
|
app2: http://192.168.10.2:3002
|
||||||
|
|
||||||
entryPoints:
|
entryPoints:
|
||||||
https:
|
https:
|
||||||
address: :443
|
address: :443
|
||||||
|
tls:
|
||||||
|
enabled: true
|
||||||
|
|
||||||
|
tls:
|
||||||
|
certProviders:
|
||||||
|
default:
|
||||||
|
key: ./assets/certs/z.com.key.pem
|
||||||
|
cert: ./assets/certs/z.com.cert.pem
|
||||||
7
go.mod
7
go.mod
|
|
@ -1,15 +1,18 @@
|
||||||
module z/zprox
|
module github.com/zeevdiukman/zprox
|
||||||
|
|
||||||
go 1.24.0
|
go 1.24.0
|
||||||
|
|
||||||
|
require github.com/gookit/goutil v0.6.18 // indirect
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
github.com/zeevdiukman/go-interpreter v0.0.0-20250305163450-43423a7e8ba7
|
||||||
github.com/zeevdiukman/go-reverseproxy v0.0.0-20250305093102-9882ad3edb31
|
github.com/zeevdiukman/go-reverseproxy v0.0.0-20250305093102-9882ad3edb31
|
||||||
github.com/zeevdiukman/go-router v0.0.0-20250305093130-650cd1d241f5
|
github.com/zeevdiukman/go-router v0.0.0-20250305093130-650cd1d241f5
|
||||||
|
github.com/zeevdiukman/go-server v0.0.0-20250305093228-f3ab0096fcba
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/fsnotify/fsnotify v1.7.0 // indirect
|
github.com/fsnotify/fsnotify v1.7.0 // indirect
|
||||||
github.com/gookit/goutil v0.6.18 // indirect
|
|
||||||
github.com/gorilla/mux v1.8.1 // indirect
|
github.com/gorilla/mux v1.8.1 // indirect
|
||||||
github.com/hashicorp/hcl v1.0.0 // indirect
|
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||||
github.com/magiconair/properties v1.8.7 // indirect
|
github.com/magiconair/properties v1.8.7 // indirect
|
||||||
|
|
|
||||||
4
go.sum
4
go.sum
|
|
@ -63,10 +63,14 @@ github.com/zeevdiukman/go-config v0.0.0-20250305101848-6cef80370123 h1:AYl8UZu7+
|
||||||
github.com/zeevdiukman/go-config v0.0.0-20250305101848-6cef80370123/go.mod h1:oK8ESatUsIFPpj/p/0iMW3HPs8+97F52O40xjotcY64=
|
github.com/zeevdiukman/go-config v0.0.0-20250305101848-6cef80370123/go.mod h1:oK8ESatUsIFPpj/p/0iMW3HPs8+97F52O40xjotcY64=
|
||||||
github.com/zeevdiukman/go-helper v0.0.0-20250305091316-396bd5057e2f h1:1UyqJ/MzVw+Oxl8kryguBsObG7qVw+IhlKTE/HhpLGE=
|
github.com/zeevdiukman/go-helper v0.0.0-20250305091316-396bd5057e2f h1:1UyqJ/MzVw+Oxl8kryguBsObG7qVw+IhlKTE/HhpLGE=
|
||||||
github.com/zeevdiukman/go-helper v0.0.0-20250305091316-396bd5057e2f/go.mod h1:buB5zo+BkiM7kNOI2o33rmXBSlnjH1zpN0DtgNDbnCc=
|
github.com/zeevdiukman/go-helper v0.0.0-20250305091316-396bd5057e2f/go.mod h1:buB5zo+BkiM7kNOI2o33rmXBSlnjH1zpN0DtgNDbnCc=
|
||||||
|
github.com/zeevdiukman/go-interpreter v0.0.0-20250305163450-43423a7e8ba7 h1:3iW+LgqdYt9OvhcFX5aK3eI5Kr9Ue/wTpiZqBFEWMT8=
|
||||||
|
github.com/zeevdiukman/go-interpreter v0.0.0-20250305163450-43423a7e8ba7/go.mod h1:fofniVuiVQ022IcHdrRsO67GXj2jIp/D8K+DP7APUrQ=
|
||||||
github.com/zeevdiukman/go-reverseproxy v0.0.0-20250305093102-9882ad3edb31 h1:OaOVvayXo4yf/gg8/IuZzGnFxTXEXGOVXiNVxPC0OgM=
|
github.com/zeevdiukman/go-reverseproxy v0.0.0-20250305093102-9882ad3edb31 h1:OaOVvayXo4yf/gg8/IuZzGnFxTXEXGOVXiNVxPC0OgM=
|
||||||
github.com/zeevdiukman/go-reverseproxy v0.0.0-20250305093102-9882ad3edb31/go.mod h1:RAFNKzQy/q2eDB/2WI88dHuiVC8Qqp6iAPDZ+btXACk=
|
github.com/zeevdiukman/go-reverseproxy v0.0.0-20250305093102-9882ad3edb31/go.mod h1:RAFNKzQy/q2eDB/2WI88dHuiVC8Qqp6iAPDZ+btXACk=
|
||||||
github.com/zeevdiukman/go-router v0.0.0-20250305093130-650cd1d241f5 h1:ssP7N61mi0MLfnaH/ob7xOlu+prPwULl0nZ2hPw/QdE=
|
github.com/zeevdiukman/go-router v0.0.0-20250305093130-650cd1d241f5 h1:ssP7N61mi0MLfnaH/ob7xOlu+prPwULl0nZ2hPw/QdE=
|
||||||
github.com/zeevdiukman/go-router v0.0.0-20250305093130-650cd1d241f5/go.mod h1:wY15gRD14GOWs8j6bazZypGkMfCbSdr5cQK77MwzReA=
|
github.com/zeevdiukman/go-router v0.0.0-20250305093130-650cd1d241f5/go.mod h1:wY15gRD14GOWs8j6bazZypGkMfCbSdr5cQK77MwzReA=
|
||||||
|
github.com/zeevdiukman/go-server v0.0.0-20250305093228-f3ab0096fcba h1:BHG0fbASaIBXr+JyIaIt+/x1MIH+wAB5MTj2VQ1nlnU=
|
||||||
|
github.com/zeevdiukman/go-server v0.0.0-20250305093228-f3ab0096fcba/go.mod h1:HQARDR3c1btC+vNSDekVtC1KM/tVFrJqr3yGrPN3pbo=
|
||||||
go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE=
|
go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE=
|
||||||
go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
||||||
go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI=
|
go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI=
|
||||||
|
|
|
||||||
241
internal/config/config.go
Normal file
241
internal/config/config.go
Normal file
|
|
@ -0,0 +1,241 @@
|
||||||
|
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 NewConfig() *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
|
||||||
|
}
|
||||||
43
internal/interpreter/interpreter.go
Normal file
43
internal/interpreter/interpreter.go
Normal file
|
|
@ -0,0 +1,43 @@
|
||||||
|
package interpreter
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/zeevdiukman/go-interpreter"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Interp struct {
|
||||||
|
*interpreter.Interpreter
|
||||||
|
}
|
||||||
|
|
||||||
|
func New() *Interp {
|
||||||
|
interp := &Interp{interpreter.New()}
|
||||||
|
|
||||||
|
return interp
|
||||||
|
}
|
||||||
|
func (interp *Interp) PathAction(rules string, fn func(fn interpreter.Function)) {
|
||||||
|
name := "router_rules"
|
||||||
|
|
||||||
|
regx := interp.Regex(name, "\\(`(.*?)`\\)")
|
||||||
|
interp.Func(name, func(args ...any) string {
|
||||||
|
// argsStmntName := args[0].(string)
|
||||||
|
argsPathAction := args[0].(func(string))
|
||||||
|
interp.AddStatment(name, rules).SplitStatementByRegex(regx)
|
||||||
|
interp.Statments.ForEach(func(stmnt *interpreter.Statment) {
|
||||||
|
if stmnt.Name == name {
|
||||||
|
for idx, splitVal := range stmnt.RegexSplit {
|
||||||
|
splitVal, _ = strings.CutPrefix(splitVal, ".")
|
||||||
|
switch splitVal {
|
||||||
|
case "Path":
|
||||||
|
{
|
||||||
|
path := stmnt.RegexSplit[idx+1]
|
||||||
|
argsPathAction(path)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return ""
|
||||||
|
})
|
||||||
|
interp.Funcs[name].Function()
|
||||||
|
}
|
||||||
204
main.go
204
main.go
|
|
@ -1,11 +1,34 @@
|
||||||
|
/*
|
||||||
|
Example:
|
||||||
|
|
||||||
|
rp1 := reverseproxy.New(ctx, "http://localhost:8080")
|
||||||
|
rp2 := reverseproxy.New(ctx, "http://localhost:3001")
|
||||||
|
rp3 := reverseproxy.New(ctx, "http://localhost:3002")
|
||||||
|
router := router.NewRouter()
|
||||||
|
pr1 := router.NewHostRouter("keycloak.z.com")
|
||||||
|
pr1.Handler(rp1)
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
s := server.New().Name("proxy1").Port(443).Router(router)
|
||||||
|
s.CertKey(CERTS_PATH, "z.com.cert.pem", "z.com.key.pem")
|
||||||
|
err := s.ListenAndServeTLS()
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err.Error())
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
*/
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"context"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/gookit/goutil/dump"
|
|
||||||
"github.com/zeevdiukman/go-config"
|
|
||||||
"github.com/zeevdiukman/go-helper"
|
"github.com/zeevdiukman/go-helper"
|
||||||
|
"github.com/zeevdiukman/go-reverseproxy"
|
||||||
|
"github.com/zeevdiukman/go-router"
|
||||||
|
"github.com/zeevdiukman/go-server"
|
||||||
|
"github.com/zeevdiukman/zprox/internal/config"
|
||||||
)
|
)
|
||||||
|
|
||||||
// type ReverseProxy struct {
|
// type ReverseProxy struct {
|
||||||
|
|
@ -16,78 +39,127 @@ import (
|
||||||
|
|
||||||
const CERTS_PATH string = "./assets/certs/"
|
const CERTS_PATH string = "./assets/certs/"
|
||||||
|
|
||||||
|
type App struct {
|
||||||
|
// Routers struct {
|
||||||
|
// Maps map[string]*router.HostRouter
|
||||||
|
// }
|
||||||
|
// map[string]*router.HostRouter
|
||||||
|
// Rules map[string]map[string]string
|
||||||
|
// Services map[string]string
|
||||||
|
DomainRouters DomainRouters
|
||||||
|
EntryPoints EntryPoints
|
||||||
|
}
|
||||||
|
|
||||||
|
type DomainRouters map[string]*router.DomainRouter
|
||||||
|
type EntryPoints map[string]*EntryPoint
|
||||||
|
type EntryPoint struct {
|
||||||
|
*server.Server
|
||||||
|
*router.Router
|
||||||
|
HostRouters HostRouters
|
||||||
|
}
|
||||||
|
type HostRouters map[string]*router.DomainRouter
|
||||||
|
|
||||||
|
func New() *App {
|
||||||
|
return &App{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ep EntryPoints) ForEach(f func(string, *EntryPoint)) {
|
||||||
|
forEach(ep, f)
|
||||||
|
}
|
||||||
|
|
||||||
|
func forEach[K comparable, V any](mp map[K]V, f func(K, V)) {
|
||||||
|
for k, v := range mp {
|
||||||
|
f(k, v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// main is the entry point of the z application.
|
||||||
|
// It initializes and configures the application, sets up entry points,
|
||||||
|
// configures routers, and starts the servers. It also starts test HTTP servers
|
||||||
|
// for demonstration purposes.
|
||||||
func main() {
|
func main() {
|
||||||
helper.AppRunner(true, func() {
|
helper.AppRunner(true, func() {
|
||||||
// ctx := context.Background()
|
helper.Clear()
|
||||||
c := config.NewConfig("config", "yaml", "./assets/config")
|
ctx := context.Background()
|
||||||
c.Load()
|
app := New()
|
||||||
|
conf := config.NewConfig()
|
||||||
|
activeEntryPoints := make(map[string]bool)
|
||||||
|
conf.EntryPoints.ForEach(func(entryPointName string, entryPointConfig *config.EntryPoint) {
|
||||||
|
conf.HTTP.Routers.ForEach(func(rName string, rConfig *config.Router) {
|
||||||
|
if rConfig.EntryPoint == entryPointName {
|
||||||
|
activeEntryPoints[entryPointName] = true
|
||||||
|
|
||||||
// routersMap := make(map[string]*router.HostRouter)
|
|
||||||
routersMap := make(map[string]map[string]string)
|
|
||||||
|
|
||||||
firstPart, subKeys := c.GetSubKeys("http.routers", false)
|
|
||||||
subKeys.ForEach(func(idx int, key config.Key) {
|
|
||||||
fullKey := helper.AddDotBetween(firstPart, string(key))
|
|
||||||
p := key.GetKeyPartByLevel(0)
|
|
||||||
name := string(p)
|
|
||||||
|
|
||||||
fmt.Println(name + ":")
|
|
||||||
if _, ok := routersMap[string(name)]; !ok {
|
|
||||||
routersMap[string(name)] = make(map[string]string)
|
|
||||||
}
|
|
||||||
|
|
||||||
key.ForEach(func(idx int, part config.KeyPart, isFirst bool) {
|
|
||||||
if !isFirst {
|
|
||||||
field := string(part)
|
|
||||||
|
|
||||||
val := c.Get(fullKey).(string)
|
|
||||||
|
|
||||||
routersMap[string(name)][field] = val
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// router.NewHostRouter("keycloak.z.com")
|
|
||||||
// router.NewHostRouter("keycloak.z.com").Handler(proxy)
|
|
||||||
|
|
||||||
})
|
})
|
||||||
dump.Println(routersMap)
|
conf.EntryPoints.ForEach(func(entryPointName string, entryPointConfig *config.EntryPoint) {
|
||||||
|
if isUsed, ok := activeEntryPoints[entryPointName]; ok && isUsed {
|
||||||
|
if _, ok := app.EntryPoints[entryPointName]; !ok {
|
||||||
|
app.EntryPoints = make(map[string]*EntryPoint)
|
||||||
|
}
|
||||||
|
r := router.NewRouter()
|
||||||
|
_, portStr, _ := strings.Cut(entryPointConfig.Address, ":")
|
||||||
|
port, _ := strconv.Atoi(portStr)
|
||||||
|
s := server.New().Name(entryPointName).Port(port)
|
||||||
|
s.Router(r)
|
||||||
|
app.EntryPoints[entryPointName] = &EntryPoint{
|
||||||
|
Server: s,
|
||||||
|
Router: r,
|
||||||
|
HostRouters: make(map[string]*router.DomainRouter),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
conf.HTTP.Routers.ForEach(func(rName string, rConfig *config.Router) {
|
||||||
|
if isUsed, ok := activeEntryPoints[rConfig.EntryPoint]; ok && isUsed {
|
||||||
|
domain := rConfig.Rules.Map["Domain"].Value
|
||||||
|
serviceURL := conf.HTTP.Services[rConfig.Service].URL
|
||||||
|
if _, ok := app.EntryPoints[rConfig.EntryPoint]; ok {
|
||||||
|
entryPoint := app.EntryPoints[rConfig.EntryPoint]
|
||||||
|
if _, ok := entryPoint.HostRouters[domain]; !ok {
|
||||||
|
entryPoint.HostRouters = make(map[string]*router.DomainRouter)
|
||||||
|
}
|
||||||
|
rpHandler := reverseproxy.New(ctx, serviceURL)
|
||||||
|
r := app.EntryPoints[rConfig.EntryPoint].Router
|
||||||
|
hostRouter := r.NewDomainRouter(domain)
|
||||||
|
hostRouter.Handler(rpHandler)
|
||||||
|
app.EntryPoints[rConfig.EntryPoint].HostRouters[domain] = hostRouter
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
app.EntryPoints.ForEach(func(s string, ep *EntryPoint) {
|
||||||
|
conf.HTTP.Routers.ForEach(func(rName string, rConfig *config.Router) {
|
||||||
|
if s == rConfig.EntryPoint {
|
||||||
|
|
||||||
// proxy := reverseproxy.New(ctx, name)
|
}
|
||||||
|
})
|
||||||
/*******************************************************************************/
|
ep.CertKey(CERTS_PATH, "z.com.cert.pem", "z.com.key.pem")
|
||||||
|
go ep.ListenAndServeTLS()
|
||||||
// z := zgate.NewGate()
|
})
|
||||||
// z.NewEntryPoint("https")
|
|
||||||
// z.EntryPoints["https"].Port(443).CertKey(CERTS_PATH, "z.com.cert.pem", "z.com.key.pem")
|
|
||||||
|
|
||||||
// if err := c.Load(); err != nil {
|
|
||||||
// log.Fatalln("Error:", err.Error())
|
|
||||||
// }
|
|
||||||
/*-------------------------------------------------*/
|
|
||||||
// rp1 := reverseproxy.New(ctx, "http://localhost:8080")
|
|
||||||
// rp2 := reverseproxy.New(ctx, "http://localhost:3001")
|
|
||||||
// rp3 := reverseproxy.New(ctx, "http://localhost:3002")
|
|
||||||
|
|
||||||
// router := router.NewRouter()
|
|
||||||
// pr1 := router.NewHostRouter("keycloak.z.com")
|
|
||||||
// pr1.Handler(rp1)
|
|
||||||
// pr2 := router.NewHostRouter("app1.z.com")
|
|
||||||
// pr2.Handler(rp2)
|
|
||||||
// pr3 := router.NewHostRouter("app2.z.com")
|
|
||||||
// pr3.Handler(rp3)
|
|
||||||
|
|
||||||
// go func() {
|
|
||||||
// s := server.New().Name("proxy1").Port(443).Router(router)
|
|
||||||
// s.CertKey(CERTS_PATH, "z.com.cert.pem", "z.com.key.pem")
|
|
||||||
// err := s.ListenAndServeTLS()
|
|
||||||
// if err != nil {
|
|
||||||
// log.Println(err.Error())
|
|
||||||
// }
|
|
||||||
// }()
|
|
||||||
/*-------------------------------------------------*/
|
|
||||||
helper.StartTestHTTPServer(3001, "app1")
|
helper.StartTestHTTPServer(3001, "app1")
|
||||||
helper.StartTestHTTPServer(3002, "app2")
|
helper.StartTestHTTPServer(3002, "app2")
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// func main() {
|
||||||
|
// Test()
|
||||||
|
// }
|
||||||
|
func Test() {
|
||||||
|
ctx := context.Background()
|
||||||
|
conf := config.NewConfig()
|
||||||
|
rp1 := reverseproxy.New(ctx, conf.HTTP.Services["keycloak"].URL)
|
||||||
|
rp2 := reverseproxy.New(ctx, conf.HTTP.Services["app1"].URL)
|
||||||
|
rp3 := reverseproxy.New(ctx, conf.HTTP.Services["app2"].URL)
|
||||||
|
|
||||||
|
r := router.NewRouter()
|
||||||
|
r.NewDomainRouter(conf.HTTP.Routers["keycloak"].Rules.Map["Domain"].Value).Handler(rp1)
|
||||||
|
r.NewDomainRouter(conf.HTTP.Routers["app1"].Rules.Map["Domain"].Value).Handler(rp2)
|
||||||
|
r.NewDomainRouter(conf.HTTP.Routers["app2"].Rules.Map["Domain"].Value).Handler(rp3)
|
||||||
|
|
||||||
|
s := server.New().Name("proxy1").Port(443).Router(r)
|
||||||
|
s.CertKey(CERTS_PATH, "z.com.cert.pem", "z.com.key.pem")
|
||||||
|
go s.ListenAndServeTLS()
|
||||||
|
helper.StartTestHTTPServer(3001, "app1")
|
||||||
|
helper.StartTestHTTPServer(3002, "app2")
|
||||||
|
select {}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1
|
exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1
|
||||||
BIN
tmp/main
BIN
tmp/main
Binary file not shown.
Loading…
Reference in a new issue