mirror of
https://github.com/yusing/godoxy.git
synced 2025-06-09 04:52:35 +02:00
remove unnecessary encapsulation, setup branch updated to v0.8
This commit is contained in:
parent
2baeb6a572
commit
276684f076
10 changed files with 60 additions and 94 deletions
|
@ -15,22 +15,14 @@ import (
|
|||
|
||||
type ReverseProxyEntry struct { // real model after validation
|
||||
Raw *route.RawEntry `json:"raw"`
|
||||
|
||||
Alias route.Alias `json:"alias"`
|
||||
Scheme route.Scheme `json:"scheme"`
|
||||
URL net.URL `json:"url"`
|
||||
NoTLSVerify bool `json:"no_tls_verify,omitempty"`
|
||||
PathPatterns []string `json:"path_patterns,omitempty"`
|
||||
HealthCheck *health.HealthCheckConfig `json:"healthcheck,omitempty"`
|
||||
LoadBalance *loadbalance.Config `json:"load_balance,omitempty"`
|
||||
Middlewares map[string]docker.LabelMap `json:"middlewares,omitempty"`
|
||||
|
||||
/* Docker only */
|
||||
Idlewatcher *idlewatcher.Config `json:"idlewatcher,omitempty"`
|
||||
}
|
||||
|
||||
func (rp *ReverseProxyEntry) TargetName() string {
|
||||
return string(rp.Alias)
|
||||
return rp.Raw.Alias
|
||||
}
|
||||
|
||||
func (rp *ReverseProxyEntry) TargetURL() net.URL {
|
||||
|
@ -42,11 +34,11 @@ func (rp *ReverseProxyEntry) RawEntry() *route.RawEntry {
|
|||
}
|
||||
|
||||
func (rp *ReverseProxyEntry) LoadBalanceConfig() *loadbalance.Config {
|
||||
return rp.LoadBalance
|
||||
return rp.Raw.LoadBalance
|
||||
}
|
||||
|
||||
func (rp *ReverseProxyEntry) HealthCheckConfig() *health.HealthCheckConfig {
|
||||
return rp.HealthCheck
|
||||
return rp.Raw.HealthCheck
|
||||
}
|
||||
|
||||
func (rp *ReverseProxyEntry) IdlewatcherConfig() *idlewatcher.Config {
|
||||
|
@ -59,14 +51,12 @@ func validateRPEntry(m *route.RawEntry, s route.Scheme, errs *E.Builder) *Revers
|
|||
cont = docker.DummyContainer
|
||||
}
|
||||
|
||||
lb := m.LoadBalance
|
||||
if lb != nil && lb.Link == "" {
|
||||
lb = nil
|
||||
if m.LoadBalance != nil && m.LoadBalance.Link == "" {
|
||||
m.LoadBalance = nil
|
||||
}
|
||||
|
||||
host := E.Collect(errs, route.ValidateHost, m.Host)
|
||||
port := E.Collect(errs, route.ValidatePort, m.Port)
|
||||
url := E.Collect(errs, url.Parse, fmt.Sprintf("%s://%s:%d", s, host, port))
|
||||
url := E.Collect(errs, url.Parse, fmt.Sprintf("%s://%s:%d", s, m.Host, port))
|
||||
iwCfg := E.Collect(errs, idlewatcher.ValidateConfig, cont)
|
||||
|
||||
if errs.HasError() {
|
||||
|
@ -75,14 +65,7 @@ func validateRPEntry(m *route.RawEntry, s route.Scheme, errs *E.Builder) *Revers
|
|||
|
||||
return &ReverseProxyEntry{
|
||||
Raw: m,
|
||||
Alias: route.Alias(m.Alias),
|
||||
Scheme: s,
|
||||
URL: net.NewURL(url),
|
||||
NoTLSVerify: m.NoTLSVerify,
|
||||
PathPatterns: m.PathPatterns,
|
||||
HealthCheck: m.HealthCheck,
|
||||
LoadBalance: lb,
|
||||
Middlewares: m.Middlewares,
|
||||
Idlewatcher: iwCfg,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,19 +15,17 @@ import (
|
|||
type StreamEntry struct {
|
||||
Raw *route.RawEntry `json:"raw"`
|
||||
|
||||
Alias route.Alias `json:"alias"`
|
||||
Scheme route.StreamScheme `json:"scheme"`
|
||||
URL net.URL `json:"url"`
|
||||
Host route.Host `json:"host,omitempty"`
|
||||
ListenURL net.URL `json:"listening_url"`
|
||||
Port route.StreamPort `json:"port,omitempty"`
|
||||
HealthCheck *health.HealthCheckConfig `json:"healthcheck,omitempty"`
|
||||
|
||||
/* Docker only */
|
||||
Idlewatcher *idlewatcher.Config `json:"idlewatcher,omitempty"`
|
||||
}
|
||||
|
||||
func (s *StreamEntry) TargetName() string {
|
||||
return string(s.Alias)
|
||||
return s.Raw.Alias
|
||||
}
|
||||
|
||||
func (s *StreamEntry) TargetURL() net.URL {
|
||||
|
@ -44,7 +42,7 @@ func (s *StreamEntry) LoadBalanceConfig() *loadbalance.Config {
|
|||
}
|
||||
|
||||
func (s *StreamEntry) HealthCheckConfig() *health.HealthCheckConfig {
|
||||
return s.HealthCheck
|
||||
return s.Raw.HealthCheck
|
||||
}
|
||||
|
||||
func (s *StreamEntry) IdlewatcherConfig() *idlewatcher.Config {
|
||||
|
@ -57,10 +55,10 @@ func validateStreamEntry(m *route.RawEntry, errs *E.Builder) *StreamEntry {
|
|||
cont = docker.DummyContainer
|
||||
}
|
||||
|
||||
host := E.Collect(errs, route.ValidateHost, m.Host)
|
||||
port := E.Collect(errs, route.ValidateStreamPort, m.Port)
|
||||
scheme := E.Collect(errs, route.ValidateStreamScheme, m.Scheme)
|
||||
url := E.Collect(errs, net.ParseURL, fmt.Sprintf("%s://%s:%d", scheme.ListeningScheme, host, port.ProxyPort))
|
||||
url := E.Collect(errs, net.ParseURL, fmt.Sprintf("%s://%s:%d", scheme.ProxyScheme, m.Host, port.ProxyPort))
|
||||
listenURL := E.Collect(errs, net.ParseURL, fmt.Sprintf("%s://:%d", scheme.ListeningScheme, port.ListeningPort))
|
||||
idleWatcherCfg := E.Collect(errs, idlewatcher.ValidateConfig, cont)
|
||||
|
||||
if errs.HasError() {
|
||||
|
@ -69,12 +67,10 @@ func validateStreamEntry(m *route.RawEntry, errs *E.Builder) *StreamEntry {
|
|||
|
||||
return &StreamEntry{
|
||||
Raw: m,
|
||||
Alias: route.Alias(m.Alias),
|
||||
Scheme: *scheme,
|
||||
URL: url,
|
||||
Host: host,
|
||||
ListenURL: listenURL,
|
||||
Port: port,
|
||||
HealthCheck: m.HealthCheck,
|
||||
Idlewatcher: idleWatcherCfg,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,25 +35,23 @@ type (
|
|||
|
||||
l zerolog.Logger
|
||||
}
|
||||
|
||||
SubdomainKey = route.Alias
|
||||
)
|
||||
|
||||
// var globalMux = http.NewServeMux() // TODO: support regex subdomain matching.
|
||||
|
||||
func NewHTTPRoute(entry *entry.ReverseProxyEntry) (impl, E.Error) {
|
||||
var trans *http.Transport
|
||||
if entry.NoTLSVerify {
|
||||
if entry.Raw.NoTLSVerify {
|
||||
trans = gphttp.DefaultTransportNoTLS
|
||||
} else {
|
||||
trans = gphttp.DefaultTransport
|
||||
}
|
||||
|
||||
service := string(entry.Alias)
|
||||
service := entry.TargetName()
|
||||
rp := gphttp.NewReverseProxy(service, entry.URL, trans)
|
||||
|
||||
if len(entry.Middlewares) > 0 {
|
||||
err := middleware.PatchReverseProxy(rp, entry.Middlewares)
|
||||
if len(entry.Raw.Middlewares) > 0 {
|
||||
err := middleware.PatchReverseProxy(rp, entry.Raw.Middlewares)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -63,15 +61,15 @@ func NewHTTPRoute(entry *entry.ReverseProxyEntry) (impl, E.Error) {
|
|||
ReverseProxyEntry: entry,
|
||||
rp: rp,
|
||||
l: logger.With().
|
||||
Str("type", string(entry.Scheme)).
|
||||
Str("name", string(entry.Alias)).
|
||||
Str("type", entry.URL.Scheme).
|
||||
Str("name", service).
|
||||
Logger(),
|
||||
}
|
||||
return r, nil
|
||||
}
|
||||
|
||||
func (r *HTTPRoute) String() string {
|
||||
return string(r.Alias)
|
||||
return r.TargetName()
|
||||
}
|
||||
|
||||
// Start implements*task.TaskStarter.
|
||||
|
@ -85,7 +83,7 @@ func (r *HTTPRoute) Start(providerSubtask *task.Task) E.Error {
|
|||
|
||||
switch {
|
||||
case entry.UseIdleWatcher(r):
|
||||
wakerTask := providerSubtask.Parent().Subtask("waker for " + string(r.Alias))
|
||||
wakerTask := providerSubtask.Parent().Subtask("waker for " + r.TargetName())
|
||||
waker, err := idlewatcher.NewHTTPWaker(wakerTask, r.ReverseProxyEntry, r.rp)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -96,26 +94,27 @@ func (r *HTTPRoute) Start(providerSubtask *task.Task) E.Error {
|
|||
if entry.IsDocker(r) {
|
||||
client, err := docker.ConnectClient(r.Idlewatcher.DockerHost)
|
||||
if err == nil {
|
||||
fallback := monitor.NewHTTPHealthChecker(r.rp.TargetURL, r.HealthCheck)
|
||||
r.HealthMon = monitor.NewDockerHealthMonitor(client, r.Idlewatcher.ContainerID, r.HealthCheck, fallback)
|
||||
fallback := monitor.NewHTTPHealthChecker(r.rp.TargetURL, r.Raw.HealthCheck)
|
||||
r.HealthMon = monitor.NewDockerHealthMonitor(client, r.Idlewatcher.ContainerID, r.Raw.HealthCheck, fallback)
|
||||
r.task.OnCancel("close docker client", client.Close)
|
||||
}
|
||||
}
|
||||
if r.HealthMon == nil {
|
||||
r.HealthMon = monitor.NewHTTPHealthMonitor(r.rp.TargetURL, r.HealthCheck)
|
||||
r.HealthMon = monitor.NewHTTPHealthMonitor(r.rp.TargetURL, r.Raw.HealthCheck)
|
||||
}
|
||||
}
|
||||
|
||||
if r.handler == nil {
|
||||
pathPatterns := r.Raw.PathPatterns
|
||||
switch {
|
||||
case len(r.PathPatterns) == 0:
|
||||
case len(pathPatterns) == 0:
|
||||
r.handler = r.rp
|
||||
case len(r.PathPatterns) == 1 && r.PathPatterns[0] == "/":
|
||||
case len(pathPatterns) == 1 && pathPatterns[0] == "/":
|
||||
r.handler = r.rp
|
||||
default:
|
||||
mux := gphttp.NewServeMux()
|
||||
patErrs := E.NewBuilder("invalid path pattern(s)")
|
||||
for _, p := range r.PathPatterns {
|
||||
for _, p := range pathPatterns {
|
||||
patErrs.Add(mux.HandleFunc(p, r.rp.HandlerFunc))
|
||||
}
|
||||
if err := patErrs.Error(); err != nil {
|
||||
|
@ -136,9 +135,9 @@ func (r *HTTPRoute) Start(providerSubtask *task.Task) E.Error {
|
|||
if entry.UseLoadBalance(r) {
|
||||
r.addToLoadBalancer()
|
||||
} else {
|
||||
routes.SetHTTPRoute(string(r.Alias), r)
|
||||
routes.SetHTTPRoute(r.TargetName(), r)
|
||||
r.task.OnFinished("remove from route table", func() {
|
||||
routes.DeleteHTTPRoute(string(r.Alias))
|
||||
routes.DeleteHTTPRoute(r.TargetName())
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -159,20 +158,21 @@ func (r *HTTPRoute) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||
|
||||
func (r *HTTPRoute) addToLoadBalancer() {
|
||||
var lb *loadbalancer.LoadBalancer
|
||||
l, ok := routes.GetHTTPRoute(r.LoadBalance.Link)
|
||||
cfg := r.Raw.LoadBalance
|
||||
l, ok := routes.GetHTTPRoute(cfg.Link)
|
||||
var linked *HTTPRoute
|
||||
if ok {
|
||||
linked = l.(*HTTPRoute)
|
||||
lb = linked.loadBalancer
|
||||
lb.UpdateConfigIfNeeded(r.LoadBalance)
|
||||
lb.UpdateConfigIfNeeded(cfg)
|
||||
if linked.Raw.Homepage == nil && r.Raw.Homepage != nil {
|
||||
linked.Raw.Homepage = r.Raw.Homepage
|
||||
}
|
||||
} else {
|
||||
lb = loadbalancer.New(r.LoadBalance)
|
||||
lbTask := r.task.Parent().Subtask("loadbalancer " + r.LoadBalance.Link)
|
||||
lb = loadbalancer.New(cfg)
|
||||
lbTask := r.task.Parent().Subtask("loadbalancer " + cfg.Link)
|
||||
lbTask.OnCancel("remove lb from routes", func() {
|
||||
routes.DeleteHTTPRoute(r.LoadBalance.Link)
|
||||
routes.DeleteHTTPRoute(cfg.Link)
|
||||
})
|
||||
if err := lb.Start(lbTask); err != nil {
|
||||
panic(err) // should always return nil
|
||||
|
@ -180,18 +180,18 @@ func (r *HTTPRoute) addToLoadBalancer() {
|
|||
linked = &HTTPRoute{
|
||||
ReverseProxyEntry: &entry.ReverseProxyEntry{
|
||||
Raw: &route.RawEntry{
|
||||
Alias: cfg.Link,
|
||||
Homepage: r.Raw.Homepage,
|
||||
},
|
||||
Alias: route.Alias(lb.Link),
|
||||
},
|
||||
HealthMon: lb,
|
||||
loadBalancer: lb,
|
||||
handler: lb,
|
||||
}
|
||||
routes.SetHTTPRoute(r.LoadBalance.Link, linked)
|
||||
routes.SetHTTPRoute(cfg.Link, linked)
|
||||
}
|
||||
r.loadBalancer = lb
|
||||
r.server = loadbalance.NewServer(r.task.String(), r.rp.TargetURL, r.LoadBalance.Weight, r.handler, r.HealthMon)
|
||||
r.server = loadbalance.NewServer(r.task.String(), r.rp.TargetURL, r.Raw.LoadBalance.Weight, r.handler, r.HealthMon)
|
||||
lb.AddServer(r.server)
|
||||
r.task.OnCancel("remove server from lb", func() {
|
||||
lb.RemoveServer(r.server)
|
||||
|
|
|
@ -325,7 +325,7 @@ func TestStreamDefaultValues(t *testing.T) {
|
|||
a := ExpectType[*entry.StreamEntry](t, en)
|
||||
ExpectEqual(t, a.Scheme.ListeningScheme, T.Scheme("udp"))
|
||||
ExpectEqual(t, a.Scheme.ProxyScheme, T.Scheme("udp"))
|
||||
ExpectEqual(t, a.Host, T.Host(privIP))
|
||||
ExpectEqual(t, a.URL.Hostname(), privIP)
|
||||
ExpectEqual(t, a.Port.ListeningPort, 0)
|
||||
ExpectEqual(t, a.Port.ProxyPort, T.Port(privPort))
|
||||
})
|
||||
|
@ -337,7 +337,7 @@ func TestStreamDefaultValues(t *testing.T) {
|
|||
a := ExpectType[*entry.StreamEntry](t, en)
|
||||
ExpectEqual(t, a.Scheme.ListeningScheme, T.Scheme("udp"))
|
||||
ExpectEqual(t, a.Scheme.ProxyScheme, T.Scheme("udp"))
|
||||
ExpectEqual(t, a.Host, testIP)
|
||||
ExpectEqual(t, a.URL.Hostname(), testIP)
|
||||
ExpectEqual(t, a.Port.ListeningPort, 0)
|
||||
ExpectEqual(t, a.Port.ProxyPort, T.Port(pubPort))
|
||||
})
|
||||
|
|
|
@ -3,7 +3,6 @@ package route
|
|||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/yusing/go-proxy/internal/docker"
|
||||
|
@ -44,7 +43,7 @@ func NewStreamRoute(entry *entry.StreamEntry) (impl, E.Error) {
|
|||
}
|
||||
|
||||
func (r *StreamRoute) String() string {
|
||||
return fmt.Sprintf("stream %s", r.Alias)
|
||||
return "stream " + r.TargetName()
|
||||
}
|
||||
|
||||
// Start implements*task.TaskStarter.
|
||||
|
@ -59,7 +58,7 @@ func (r *StreamRoute) Start(providerSubtask *task.Task) E.Error {
|
|||
|
||||
switch {
|
||||
case entry.UseIdleWatcher(r):
|
||||
wakerTask := providerSubtask.Parent().Subtask("waker for " + string(r.Alias))
|
||||
wakerTask := providerSubtask.Parent().Subtask("waker for " + r.TargetName())
|
||||
waker, err := idlewatcher.NewStreamWaker(wakerTask, r.StreamEntry, r.Stream)
|
||||
if err != nil {
|
||||
r.task.Finish(err)
|
||||
|
@ -71,13 +70,13 @@ func (r *StreamRoute) Start(providerSubtask *task.Task) E.Error {
|
|||
if entry.IsDocker(r) {
|
||||
client, err := docker.ConnectClient(r.Idlewatcher.DockerHost)
|
||||
if err == nil {
|
||||
fallback := monitor.NewRawHealthChecker(r.TargetURL(), r.HealthCheck)
|
||||
r.HealthMon = monitor.NewDockerHealthMonitor(client, r.Idlewatcher.ContainerID, r.HealthCheck, fallback)
|
||||
fallback := monitor.NewRawHealthChecker(r.TargetURL(), r.Raw.HealthCheck)
|
||||
r.HealthMon = monitor.NewDockerHealthMonitor(client, r.Idlewatcher.ContainerID, r.Raw.HealthCheck, fallback)
|
||||
r.task.OnCancel("close docker client", client.Close)
|
||||
}
|
||||
}
|
||||
if r.HealthMon == nil {
|
||||
r.HealthMon = monitor.NewRawHealthMonitor(r.TargetURL(), r.HealthCheck)
|
||||
r.HealthMon = monitor.NewRawHealthMonitor(r.TargetURL(), r.Raw.HealthCheck)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -106,9 +105,9 @@ func (r *StreamRoute) Start(providerSubtask *task.Task) E.Error {
|
|||
|
||||
go r.acceptConnections()
|
||||
|
||||
routes.SetStreamRoute(string(r.Alias), r)
|
||||
routes.SetStreamRoute(r.TargetName(), r)
|
||||
r.task.OnFinished("remove from route table", func() {
|
||||
routes.DeleteStreamRoute(string(r.Alias))
|
||||
routes.DeleteStreamRoute(r.TargetName())
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -45,22 +45,22 @@ func (stream *Stream) Setup() error {
|
|||
|
||||
switch stream.Scheme.ListeningScheme {
|
||||
case "tcp":
|
||||
stream.targetAddr, err = net.ResolveTCPAddr("tcp", fmt.Sprintf("%s:%v", stream.Host, stream.Port.ProxyPort))
|
||||
stream.targetAddr, err = net.ResolveTCPAddr("tcp", stream.URL.Host)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
tcpListener, err := lcfg.Listen(stream.task.Context(), "tcp", fmt.Sprintf(":%v", stream.Port.ListeningPort))
|
||||
tcpListener, err := lcfg.Listen(stream.task.Context(), "tcp", stream.ListenURL.Host)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
stream.Port.ListeningPort = T.Port(tcpListener.Addr().(*net.TCPAddr).Port)
|
||||
stream.listener = types.NetListener(tcpListener)
|
||||
case "udp":
|
||||
stream.targetAddr, err = net.ResolveUDPAddr("udp", fmt.Sprintf("%s:%v", stream.Host, stream.Port.ProxyPort))
|
||||
stream.targetAddr, err = net.ResolveUDPAddr("udp", stream.URL.Host)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
udpListener, err := lcfg.ListenPacket(stream.task.Context(), "udp", fmt.Sprintf(":%v", stream.Port.ListeningPort))
|
||||
udpListener, err := lcfg.ListenPacket(stream.task.Context(), "udp", stream.ListenURL.Host)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
package types
|
||||
|
||||
type Alias string
|
|
@ -1,10 +0,0 @@
|
|||
package types
|
||||
|
||||
type (
|
||||
Host string
|
||||
Subdomain = Alias
|
||||
)
|
||||
|
||||
func ValidateHost[String ~string](s String) (Host, error) {
|
||||
return Host(s), nil
|
||||
}
|
|
@ -33,6 +33,7 @@ type (
|
|||
LoadBalance *loadbalance.Config `json:"load_balance,omitempty" yaml:"load_balance"`
|
||||
Middlewares map[string]docker.LabelMap `json:"middlewares,omitempty" yaml:"middlewares"`
|
||||
Homepage *homepage.Item `json:"homepage,omitempty" yaml:"homepage"`
|
||||
// AccessLog *accesslog.Config `json:"access_log,omitempty" yaml:"access_log"`
|
||||
|
||||
/* Docker only */
|
||||
Container *docker.Container `json:"container,omitempty" yaml:"-"`
|
||||
|
|
|
@ -12,7 +12,7 @@ import (
|
|||
)
|
||||
|
||||
var (
|
||||
branch = common.GetEnvString("BRANCH", "v0.7")
|
||||
branch = common.GetEnvString("BRANCH", "v0.8")
|
||||
baseURL = "https://github.com/yusing/go-proxy/raw/" + branch
|
||||
requiredConfigs = []Config{
|
||||
{common.ConfigBasePath, true, false, ""},
|
||||
|
|
Loading…
Add table
Reference in a new issue