This commit is contained in:
Zeev Diukman 2025-03-08 17:50:58 +00:00
parent b4088175a2
commit 2c7fbd6617
7 changed files with 227 additions and 16 deletions

52
.air.toml Normal file
View file

@ -0,0 +1,52 @@
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","yaml","yml","toml"]
include_file = [".air.toml"]
kill_delay = "0.5s"
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

BIN
_tmp/main Executable file

Binary file not shown.

View file

@ -3,21 +3,35 @@ http:
keycloak:
entryPoint: https
service: keycloak
rules: Domain(`keycloak.z.com`).Path(`/`)
rules: Domain(`keycloak.z.com`).PathPrefix(`/)
tls:
certProvider: default
app1:
# app1:
# entryPoint: https
# service: app1
# rules: Domain(`app1.z.com`).Path(`/`)
# tls:
# certProvider: default
# app2:
# entryPoint: https
# service: app2
# rules: Domain(`app2.z.com`).PathPrefix(`/test/`)
# tls:
# certProvider: default
aaa:
entryPoint: https
service: app1
rules: Domain(`app1.z.com`).Path(`/`)
tls:
certProvider: default
app2:
rules: Domain(`a.z.com`).PathPrefix(`/`)
bbb:
entryPoint: https
service: app2
rules: Domain(`app2.z.com`).Path(`/`)
tls:
certProvider: default
rules: Domain(`a.z.com`).PathPrefix(`/app2/`)
# ccc:
# entryPoint: https
# service: keycloak
# rules: Domain(`a.z.com`).PathPrefix(`/`)
services:
keycloak: http://192.168.10.2:8080
@ -29,6 +43,8 @@ entryPoints:
address: :443
tls:
enabled: true
http:
address: :80
tls:
certProviders:

View file

@ -65,7 +65,7 @@ type Rule struct {
Value string
}
func NewConfig() *Config {
func New() *Config {
c := config.NewConfig(VIPER_NAME, VIPER_TYPE, VIPER_PATH)
c.Load()

151
main.go
View file

@ -1,8 +1,14 @@
package main
import (
"net/http"
"net/url"
"github.com/zeevdiukman/go-helper"
"github.com/zeevdiukman/go-reverseproxy"
"github.com/zeevdiukman/go-router"
"github.com/zeevdiukman/go-zgate"
"github.com/zeevdiukman/go-zgate/pkg/config"
)
// main is the entry point of the z application.
@ -10,13 +16,150 @@ import (
// configures routers, and starts the servers. It also starts test HTTP servers
// for demonstration purposes.
func main() {
helper.Clear()
helper.AppRunner(true, func() {
helper.Clear()
zGate := zgate.New()
zGate.BuildActiveEntryPoints()
zGate.BuildRouters()
zGate.ListenAndServe()
//Enetry points building
zGate.Config.EntryPoints.ForEach(func(entryPointName string, entryPointConfig *config.EntryPoint) {
v, ok := isOKv(zGate.ActiveEntryPoints, entryPointName)
if ok && v {
port := zgate.StrAddressPortToInt(entryPointConfig.Address)
newEntryPoint := zGate.EntryPoints.NewEntryPoint(entryPointName)
newEntryPoint.Server.Port(port).Name(entryPointName)
newEntryPoint.Server.Router(newEntryPoint.Router)
if ok && entryPointConfig.TLS.Enabled {
zGate.EntryPoints[entryPointName].IsTLS = true
}
}
})
//Routers building
zGate.Config.HTTP.Routers.ForEach(func(rName string, rConfig *config.Router) {
epName := rConfig.EntryPoint
serviceName := rConfig.Service
isActive, _ := isOKv(zGate.ActiveEntryPoints, epName)
isEpExist := isOK(zGate.EntryPoints, epName)
isServiceExist := isOK(zGate.Config.HTTP.Services, serviceName)
ok := isActive && isEpExist && isServiceExist
if ok {
entryPoint := zGate.EntryPoints[rConfig.EntryPoint]
if _, ok := entryPoint.HostRouters[rName]; !ok {
entryPoint.HostRouters = make(map[string]*router.DomainRouter)
}
applyMap := make(map[string]string)
rulesAvailable := []string{
"Domain",
"Path",
"PathPrefix",
}
for _, ruleName := range rulesAvailable {
applyMap[ruleName] = rConfig.Rules.Get(ruleName)
}
revereProxyHandler := zGate.NewReverseProxy(rConfig.Service)
revereProxyHandler.Director = func(r *http.Request) {
r = reverseproxy.StripPrefix(r, applyMap["PathPrefix"])
r = r.WithContext(zGate.Context)
host := zGate.Config.HTTP.Services[rConfig.Service].URL
target, _ := url.Parse(host)
targetQuery := target.RawQuery
r.URL.Scheme = target.Scheme
r.URL.Host = target.Host
r.URL.Path, r.URL.RawPath = reverseproxy.JoinURLPath(target, r.URL)
if targetQuery == "" || r.URL.RawQuery == "" {
r.URL.RawQuery = targetQuery + r.URL.RawQuery
} else {
r.URL.RawQuery = targetQuery + "&" + r.URL.RawQuery
}
}
route1 := entryPoint.Router.NewRoute()
subRouter := route1.Host(applyMap["Domain"]).Subrouter()
subRouter.PathPrefix(applyMap["PathPrefix"]).Handler(revereProxyHandler)
// subRouter.NewRoute().Handler(revereProxyHandler)
// readyRouter.MatcherFunc(func(r *http.Request, rm *mux.RouteMatch) bool {
// return r.URL.Path == applyMap["PathPrefix"]
// }).Handler(revereProxyHandler)
// }
// readyRouter.PathPrefix(applyMap["Path"]).Handler(revereProxyHandler)
zGate.EntryPoints[rConfig.EntryPoint].Router = entryPoint.Router
// }
// if applyMap["Domain"] && applyMap["Path"] {
// serviceURL := zGate.Config.HTTP.Services[rConfig.Service].URL
// reverseProxy := reverseproxy.New(zGate.Context, serviceURL)
// domain := rConfig.Rules.Map["Domain"].Value
// hostRouter = entryPoint.Router.NewDomainRouter(domain,"Path")
// pathPrefix := rConfig.Rules.Map["Path"].Value
// hostRouter.Path(pathPrefix).Handler(reverseProxy)
// zGate.EntryPoints[rConfig.EntryPoint].HostRouters[rName] = hostRouter
// }
}
})
zGate.EntryPoints.ForEach(func(epNAme string, zGateEntryPoint *zgate.EntryPoint) {
if zGateEntryPoint.IsTLS {
zGateEntryPoint.Server.CertKey(zgate.CERTS_PATH, "z.com.cert.pem", "z.com.key.pem")
go zGateEntryPoint.Server.ListenAndServeTLS()
} else {
go zGateEntryPoint.Server.ListenAndServe()
}
/*
//TODO: TLS per domain
// isTLS := false
// zGate.Config.HTTP.Routers.ForEach(func(rName string, rConfig *config.Router) {
// rEntryPoint := rConfig.EntryPoint
// ep, isEpConfOK := isOK(zGate.Config.EntryPoints, rEntryPoint)
// activeEp, isActiveEpOK := isOK(zGate.ActiveEntryPoints, rEntryPoint)
// if isEpConfOK && isActiveEpOK && ep.TLS.Enabled && epNAme == rEntryPoint && activeEp {
// isTLS = true
// }
// })
// zGate.Config.HTTP.Routers.ForEach(func(rName string, rConfig *config.Router) {
// rEntryPoint := rConfig.EntryPoint
// ep, ok := isOK(zGate.Config.EntryPoints, rEntryPoint)
// if ok && ep.TLS.Enabled && epNAme == rEntryPoint {
// isTLS = true
// }
// })
// zGateEntryPoint.Server.ConnState = func(c net.Conn, cs http.ConnState) {
// msg1 := c.RemoteAddr().String()
// msg2 := "Connection state: " + strconv.Itoa(int(cs))
// fmt.Println(msg1 + "\n" + msg2)
// fmt.Println("=======================")
// log.Println()
// }
*/
})
helper.StartTestHTTPServer(3001, "app1")
helper.StartTestHTTPServer(3002, "app2")
})
}
func isOKv[K comparable, V comparable](mp map[K]V, key K) (V, bool) {
if v, ok := mp[key]; ok {
return v, true
} else {
return v, false
}
}
func isOK[K comparable, V comparable](mp map[K]V, key K) bool {
if _, ok := mp[key]; ok {
return true
} else {
return false
}
}

File diff suppressed because one or more lines are too long

BIN
tmp/main

Binary file not shown.