mirror of
https://github.com/yusing/godoxy.git
synced 2025-06-09 13:02:33 +02:00
v0.5: (BREAKING) simplified config format, improved output formatting, fixed docker watcher
This commit is contained in:
parent
719693deb7
commit
5be8659a99
34 changed files with 165 additions and 343 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -14,3 +14,5 @@ log/
|
||||||
go.work.sum
|
go.work.sum
|
||||||
|
|
||||||
!src/config/
|
!src/config/
|
||||||
|
|
||||||
|
todo.md
|
4
go.work
4
go.work
|
@ -1,3 +1,5 @@
|
||||||
go 1.22
|
go 1.22.0
|
||||||
|
|
||||||
|
toolchain go1.22.6
|
||||||
|
|
||||||
use ./src
|
use ./src
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||||
"title": "go-proxy providers file",
|
"title": "go-proxy providers file",
|
||||||
"anyOf": [
|
"oneOf": [
|
||||||
{
|
{
|
||||||
"type": "object"
|
"type": "object"
|
||||||
},
|
},
|
||||||
|
@ -16,7 +16,7 @@
|
||||||
"properties": {
|
"properties": {
|
||||||
"scheme": {
|
"scheme": {
|
||||||
"title": "Proxy scheme (http, https, tcp, udp)",
|
"title": "Proxy scheme (http, https, tcp, udp)",
|
||||||
"anyOf": [
|
"oneOf": [
|
||||||
{
|
{
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"enum": [
|
"enum": [
|
||||||
|
@ -101,7 +101,7 @@
|
||||||
"then": {
|
"then": {
|
||||||
"properties": {
|
"properties": {
|
||||||
"port": {
|
"port": {
|
||||||
"anyOf": [
|
"oneOf": [
|
||||||
{
|
{
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"pattern": "^[0-9]{1,5}$",
|
"pattern": "^[0-9]{1,5}$",
|
||||||
|
@ -118,7 +118,7 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"path": {
|
"path": {
|
||||||
"anyOf": [
|
"oneOf": [
|
||||||
{
|
{
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "Proxy path"
|
"description": "Proxy path"
|
||||||
|
|
|
@ -6,6 +6,7 @@ import (
|
||||||
|
|
||||||
U "github.com/yusing/go-proxy/api/v1/utils"
|
U "github.com/yusing/go-proxy/api/v1/utils"
|
||||||
"github.com/yusing/go-proxy/config"
|
"github.com/yusing/go-proxy/config"
|
||||||
|
PT "github.com/yusing/go-proxy/proxy/fields"
|
||||||
R "github.com/yusing/go-proxy/route"
|
R "github.com/yusing/go-proxy/route"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -23,20 +24,20 @@ func CheckHealth(cfg *config.Config, w http.ResponseWriter, r *http.Request) {
|
||||||
U.HandleErr(w, r, U.ErrNotFound("target", target), http.StatusNotFound)
|
U.HandleErr(w, r, U.ErrNotFound("target", target), http.StatusNotFound)
|
||||||
return
|
return
|
||||||
case *R.HTTPRoute:
|
case *R.HTTPRoute:
|
||||||
path := r.FormValue("path")
|
path, err := PT.NewPath(r.FormValue("path"))
|
||||||
if path == "" {
|
if err.IsNotNil() {
|
||||||
U.HandleErr(w, r, U.ErrMissingKey("path"), http.StatusBadRequest)
|
U.HandleErr(w, r, err, http.StatusBadRequest)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
sr, hasSr := route.GetSubroute(path)
|
sr, hasSr := route.GetSubroute(path)
|
||||||
if !hasSr {
|
if !hasSr {
|
||||||
U.HandleErr(w, r, U.ErrNotFound("path", path), http.StatusNotFound)
|
U.HandleErr(w, r, U.ErrNotFound("path", string(path)), http.StatusNotFound)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ok = U.IsSiteHealthy(sr.TargetURL.String())
|
ok = U.IsSiteHealthy(sr.TargetURL.String())
|
||||||
case *R.StreamRoute:
|
case *R.StreamRoute:
|
||||||
ok = U.IsStreamHealthy(
|
ok = U.IsStreamHealthy(
|
||||||
route.Scheme.ProxyScheme.String(),
|
string(route.Scheme.ProxyScheme),
|
||||||
fmt.Sprintf("%s:%v", route.Host, route.Port.ProxyPort),
|
fmt.Sprintf("%s:%v", route.Host, route.Port.ProxyPort),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@ import (
|
||||||
|
|
||||||
func HandleErr(w http.ResponseWriter, r *http.Request, err error, code ...int) {
|
func HandleErr(w http.ResponseWriter, r *http.Request, err error, code ...int) {
|
||||||
err = E.From(err).Subjectf("%s %s", r.Method, r.URL)
|
err = E.From(err).Subjectf("%s %s", r.Method, r.URL)
|
||||||
logrus.WithField("?", "api").Error(err)
|
logrus.WithField("module", "api").Error(err)
|
||||||
if len(code) > 0 {
|
if len(code) > 0 {
|
||||||
http.Error(w, err.Error(), code[0])
|
http.Error(w, err.Error(), code[0])
|
||||||
return
|
return
|
||||||
|
|
|
@ -28,4 +28,4 @@ var providersGenMap = map[string]ProviderGenerator{
|
||||||
ProviderDuckdns: providerGenerator(duckdns.NewDefaultConfig, duckdns.NewDNSProviderConfig),
|
ProviderDuckdns: providerGenerator(duckdns.NewDefaultConfig, duckdns.NewDNSProviderConfig),
|
||||||
}
|
}
|
||||||
|
|
||||||
var Logger = logrus.WithField("?", "autocert")
|
var Logger = logrus.WithField("module", "autocert")
|
||||||
|
|
|
@ -255,4 +255,4 @@ func providerGenerator[CT any, PT challenge.Provider](
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var logger = logrus.WithField("?", "autocert")
|
var logger = logrus.WithField("module", "autocert")
|
||||||
|
|
|
@ -32,14 +32,15 @@ type Config struct {
|
||||||
|
|
||||||
func New() (*Config, E.NestedError) {
|
func New() (*Config, E.NestedError) {
|
||||||
cfg := &Config{
|
cfg := &Config{
|
||||||
l: logrus.WithField("?", "config"),
|
l: logrus.WithField("module", "config"),
|
||||||
reader: U.NewFileReader(common.ConfigPath),
|
reader: U.NewFileReader(common.ConfigPath),
|
||||||
watcher: W.NewFileWatcher(common.ConfigFileName),
|
watcher: W.NewFileWatcher(common.ConfigFileName),
|
||||||
reloadReq: make(chan struct{}),
|
reloadReq: make(chan struct{}, 1),
|
||||||
}
|
}
|
||||||
if err := cfg.load(); err.IsNotNil() {
|
if err := cfg.load(); err.IsNotNil() {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
cfg.startProviders()
|
||||||
cfg.watchChanges()
|
cfg.watchChanges()
|
||||||
return cfg, E.Nil()
|
return cfg, E.Nil()
|
||||||
}
|
}
|
||||||
|
@ -200,7 +201,7 @@ func (cfg *Config) load() E.NestedError {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
warnings := E.NewBuilder("errors validating config")
|
warnings := E.NewBuilder("errors loading config")
|
||||||
|
|
||||||
cfg.l.Debug("starting autocert")
|
cfg.l.Debug("starting autocert")
|
||||||
ap, err := autocert.NewConfig(&model.AutoCert).GetProvider()
|
ap, err := autocert.NewConfig(&model.AutoCert).GetProvider()
|
||||||
|
@ -211,7 +212,7 @@ func (cfg *Config) load() E.NestedError {
|
||||||
}
|
}
|
||||||
cfg.autocertProvider = ap
|
cfg.autocertProvider = ap
|
||||||
|
|
||||||
cfg.l.Debug("starting providers")
|
cfg.l.Debug("loading providers")
|
||||||
cfg.proxyProviders = F.NewMap[string, *PR.Provider]()
|
cfg.proxyProviders = F.NewMap[string, *PR.Provider]()
|
||||||
for _, filename := range model.Providers.Files {
|
for _, filename := range model.Providers.Files {
|
||||||
p := PR.NewFileProvider(filename)
|
p := PR.NewFileProvider(filename)
|
||||||
|
@ -221,12 +222,7 @@ func (cfg *Config) load() E.NestedError {
|
||||||
p := PR.NewDockerProvider(name, dockerHost)
|
p := PR.NewDockerProvider(name, dockerHost)
|
||||||
cfg.proxyProviders.Set(p.GetName(), p)
|
cfg.proxyProviders.Set(p.GetName(), p)
|
||||||
}
|
}
|
||||||
cfg.proxyProviders.EachKV(func(name string, p *PR.Provider) {
|
cfg.l.Debug("loaded providers")
|
||||||
if err := p.StartAllRoutes(); err.IsNotNil() {
|
|
||||||
warnings.Add(E.Failure("start routes").Subject(p).With(err))
|
|
||||||
}
|
|
||||||
})
|
|
||||||
cfg.l.Debug("started providers")
|
|
||||||
|
|
||||||
cfg.value = model
|
cfg.value = model
|
||||||
|
|
||||||
|
@ -257,5 +253,5 @@ func (cfg *Config) startProviders() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cfg *Config) stopProviders() {
|
func (cfg *Config) stopProviders() {
|
||||||
cfg.controlProviders("stop", (*PR.Provider).StopAllRoutes)
|
cfg.controlProviders("stop routes", (*PR.Provider).StopAllRoutes)
|
||||||
}
|
}
|
||||||
|
|
|
@ -91,4 +91,4 @@ var clientOptEnvHost = []client.Opt{
|
||||||
client.WithAPIVersionNegotiation(),
|
client.WithAPIVersionNegotiation(),
|
||||||
}
|
}
|
||||||
|
|
||||||
var logger = logrus.WithField("?", "docker")
|
var logger = logrus.WithField("module", "docker")
|
||||||
|
|
34
src/go.mod
34
src/go.mod
|
@ -1,22 +1,24 @@
|
||||||
module github.com/yusing/go-proxy
|
module github.com/yusing/go-proxy
|
||||||
|
|
||||||
go 1.22
|
go 1.22.0
|
||||||
|
|
||||||
|
toolchain go1.22.6
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/docker/cli v27.1.2+incompatible
|
github.com/docker/cli v27.2.1+incompatible
|
||||||
github.com/docker/docker v27.1.2+incompatible
|
github.com/docker/docker v27.2.1+incompatible
|
||||||
github.com/fsnotify/fsnotify v1.7.0
|
github.com/fsnotify/fsnotify v1.7.0
|
||||||
github.com/go-acme/lego/v4 v4.17.4
|
github.com/go-acme/lego/v4 v4.18.0
|
||||||
github.com/santhosh-tekuri/jsonschema v1.2.4
|
github.com/santhosh-tekuri/jsonschema v1.2.4
|
||||||
github.com/sirupsen/logrus v1.9.3
|
github.com/sirupsen/logrus v1.9.3
|
||||||
golang.org/x/net v0.28.0
|
golang.org/x/net v0.29.0
|
||||||
gopkg.in/yaml.v3 v3.0.1
|
gopkg.in/yaml.v3 v3.0.1
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/Microsoft/go-winio v0.6.2 // indirect
|
github.com/Microsoft/go-winio v0.6.2 // indirect
|
||||||
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
|
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
|
||||||
github.com/cloudflare/cloudflare-go v0.101.0 // indirect
|
github.com/cloudflare/cloudflare-go v0.104.0 // indirect
|
||||||
github.com/containerd/log v0.1.0 // indirect
|
github.com/containerd/log v0.1.0 // indirect
|
||||||
github.com/distribution/reference v0.6.0 // indirect
|
github.com/distribution/reference v0.6.0 // indirect
|
||||||
github.com/docker/go-connections v0.5.0 // indirect
|
github.com/docker/go-connections v0.5.0 // indirect
|
||||||
|
@ -28,25 +30,25 @@ require (
|
||||||
github.com/goccy/go-json v0.10.3 // indirect
|
github.com/goccy/go-json v0.10.3 // indirect
|
||||||
github.com/gogo/protobuf v1.3.2 // indirect
|
github.com/gogo/protobuf v1.3.2 // indirect
|
||||||
github.com/google/go-querystring v1.1.0 // indirect
|
github.com/google/go-querystring v1.1.0 // indirect
|
||||||
github.com/miekg/dns v1.1.61 // indirect
|
github.com/miekg/dns v1.1.62 // indirect
|
||||||
github.com/moby/docker-image-spec v1.3.1 // indirect
|
github.com/moby/docker-image-spec v1.3.1 // indirect
|
||||||
github.com/moby/term v0.5.0 // indirect
|
github.com/moby/term v0.5.0 // indirect
|
||||||
github.com/morikuni/aec v1.0.0 // indirect
|
github.com/morikuni/aec v1.0.0 // indirect
|
||||||
github.com/opencontainers/go-digest v1.0.0 // indirect
|
github.com/opencontainers/go-digest v1.0.0 // indirect
|
||||||
github.com/opencontainers/image-spec v1.1.0 // indirect
|
github.com/opencontainers/image-spec v1.1.0 // indirect
|
||||||
github.com/pkg/errors v0.9.1 // indirect
|
github.com/pkg/errors v0.9.1 // indirect
|
||||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 // indirect
|
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.55.0 // indirect
|
||||||
go.opentelemetry.io/otel v1.28.0 // indirect
|
go.opentelemetry.io/otel v1.30.0 // indirect
|
||||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.24.0 // indirect
|
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.24.0 // indirect
|
||||||
go.opentelemetry.io/otel/metric v1.28.0 // indirect
|
go.opentelemetry.io/otel/metric v1.30.0 // indirect
|
||||||
go.opentelemetry.io/otel/sdk v1.24.0 // indirect
|
go.opentelemetry.io/otel/sdk v1.24.0 // indirect
|
||||||
go.opentelemetry.io/otel/trace v1.28.0 // indirect
|
go.opentelemetry.io/otel/trace v1.30.0 // indirect
|
||||||
golang.org/x/crypto v0.26.0 // indirect
|
golang.org/x/crypto v0.27.0 // indirect
|
||||||
golang.org/x/mod v0.20.0 // indirect
|
golang.org/x/mod v0.21.0 // indirect
|
||||||
golang.org/x/sync v0.8.0 // indirect
|
golang.org/x/sync v0.8.0 // indirect
|
||||||
golang.org/x/sys v0.24.0 // indirect
|
golang.org/x/sys v0.25.0 // indirect
|
||||||
golang.org/x/text v0.17.0 // indirect
|
golang.org/x/text v0.18.0 // indirect
|
||||||
golang.org/x/time v0.6.0 // indirect
|
golang.org/x/time v0.6.0 // indirect
|
||||||
golang.org/x/tools v0.24.0 // indirect
|
golang.org/x/tools v0.25.0 // indirect
|
||||||
gotest.tools/v3 v3.5.1 // indirect
|
gotest.tools/v3 v3.5.1 // indirect
|
||||||
)
|
)
|
||||||
|
|
60
src/go.sum
60
src/go.sum
|
@ -4,8 +4,8 @@ github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERo
|
||||||
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
|
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
|
||||||
github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=
|
github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=
|
||||||
github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
|
github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
|
||||||
github.com/cloudflare/cloudflare-go v0.101.0 h1:SXWNSEDkbdY84iFIZGyTdWQwDfd98ljv0/4UubpleBQ=
|
github.com/cloudflare/cloudflare-go v0.104.0 h1:R/lB0dZupaZbOgibAH/BRrkFbZ6Acn/WsKg2iX2xXuY=
|
||||||
github.com/cloudflare/cloudflare-go v0.101.0/go.mod h1:xXQHnoXKR48JlWbFS42i2al3nVqimVhcYvKnIdXLw9g=
|
github.com/cloudflare/cloudflare-go v0.104.0/go.mod h1:pfUQ4PIG4ISI0/Mmc21Bp86UnFU0ktmPf3iTgbSL+cM=
|
||||||
github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I=
|
github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I=
|
||||||
github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo=
|
github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
@ -13,10 +13,10 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk=
|
github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk=
|
||||||
github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
|
github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
|
||||||
github.com/docker/cli v27.1.2+incompatible h1:nYviRv5Y+YAKx3dFrTvS1ErkyVVunKOhoweCTE1BsnI=
|
github.com/docker/cli v27.2.1+incompatible h1:U5BPtiD0viUzjGAjV1p0MGB8eVA3L3cbIrnyWmSJI70=
|
||||||
github.com/docker/cli v27.1.2+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
|
github.com/docker/cli v27.2.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
|
||||||
github.com/docker/docker v27.1.2+incompatible h1:AhGzR1xaQIy53qCkxARaFluI00WPGtXn0AJuoQsVYTY=
|
github.com/docker/docker v27.2.1+incompatible h1:fQdiLfW7VLscyoeYEBz7/J8soYFDZV1u6VW6gJEjNMI=
|
||||||
github.com/docker/docker v27.1.2+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
github.com/docker/docker v27.2.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||||
github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c=
|
github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c=
|
||||||
github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc=
|
github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc=
|
||||||
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
|
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
|
||||||
|
@ -25,8 +25,8 @@ github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2
|
||||||
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||||
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
|
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
|
||||||
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
|
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
|
||||||
github.com/go-acme/lego/v4 v4.17.4 h1:h0nePd3ObP6o7kAkndtpTzCw8shOZuWckNYeUQwo36Q=
|
github.com/go-acme/lego/v4 v4.18.0 h1:2hH8KcdRBSb+p5o9VZIm61GAOXYALgILUCSs1Q+OYsk=
|
||||||
github.com/go-acme/lego/v4 v4.17.4/go.mod h1:dU94SvPNqimEeb7EVilGGSnS0nU1O5Exir0pQ4QFL4U=
|
github.com/go-acme/lego/v4 v4.18.0/go.mod h1:Blkg3izvXpl3zxk7WKngIuwR2I/hvYVP3vRnvgBp7m8=
|
||||||
github.com/go-jose/go-jose/v4 v4.0.4 h1:VsjPI33J0SB9vQM6PLmNjoHqMQNGPiZ0rHL7Ni7Q6/E=
|
github.com/go-jose/go-jose/v4 v4.0.4 h1:VsjPI33J0SB9vQM6PLmNjoHqMQNGPiZ0rHL7Ni7Q6/E=
|
||||||
github.com/go-jose/go-jose/v4 v4.0.4/go.mod h1:NKb5HO1EZccyMpiZNbdUw/14tiXNyUJh188dfnMCAfc=
|
github.com/go-jose/go-jose/v4 v4.0.4/go.mod h1:NKb5HO1EZccyMpiZNbdUw/14tiXNyUJh188dfnMCAfc=
|
||||||
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||||
|
@ -51,8 +51,8 @@ github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
|
||||||
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
|
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
|
||||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||||
github.com/miekg/dns v1.1.61 h1:nLxbwF3XxhwVSm8g9Dghm9MHPaUZuqhPiGL+675ZmEs=
|
github.com/miekg/dns v1.1.62 h1:cN8OuEF1/x5Rq6Np+h1epln8OiyPWV+lROx9LxcGgIQ=
|
||||||
github.com/miekg/dns v1.1.61/go.mod h1:mnAarhS3nWaW+NVP2wTkYVIZyHNJ098SJZUki3eykwQ=
|
github.com/miekg/dns v1.1.62/go.mod h1:mvDlcItzm+br7MToIKqkglaGhlFMHJ9DTNNWONWXbNQ=
|
||||||
github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0=
|
github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0=
|
||||||
github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo=
|
github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo=
|
||||||
github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0=
|
github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0=
|
||||||
|
@ -79,37 +79,37 @@ github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsT
|
||||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 h1:4K4tsIXefpVJtvA/8srF4V4y0akAoPHkIslgAkjixJA=
|
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.55.0 h1:ZIg3ZT/aQ7AfKqdwp7ECpOK6vHqquXXuyTjIO8ZdmPs=
|
||||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0/go.mod h1:jjdQuTGVsXV4vSs+CJ2qYDeDPf9yIJV23qlIzBm73Vg=
|
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.55.0/go.mod h1:DQAwmETtZV00skUwgD6+0U89g80NKsJE3DCKeLLPQMI=
|
||||||
go.opentelemetry.io/otel v1.28.0 h1:/SqNcYk+idO0CxKEUOtKQClMK/MimZihKYMruSMViUo=
|
go.opentelemetry.io/otel v1.30.0 h1:F2t8sK4qf1fAmY9ua4ohFS/K+FUuOPemHUIXHtktrts=
|
||||||
go.opentelemetry.io/otel v1.28.0/go.mod h1:q68ijF8Fc8CnMHKyzqL6akLO46ePnjkgfIMIjUIX9z4=
|
go.opentelemetry.io/otel v1.30.0/go.mod h1:tFw4Br9b7fOS+uEao81PJjVMjW/5fvNCbpsDIXqP0pc=
|
||||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.24.0 h1:t6wl9SPayj+c7lEIFgm4ooDBZVb01IhLB4InpomhRw8=
|
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.24.0 h1:t6wl9SPayj+c7lEIFgm4ooDBZVb01IhLB4InpomhRw8=
|
||||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.24.0/go.mod h1:iSDOcsnSA5INXzZtwaBPrKp/lWu/V14Dd+llD0oI2EA=
|
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.24.0/go.mod h1:iSDOcsnSA5INXzZtwaBPrKp/lWu/V14Dd+llD0oI2EA=
|
||||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.24.0 h1:Xw8U6u2f8DK2XAkGRFV7BBLENgnTGX9i4rQRxJf+/vs=
|
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.24.0 h1:Xw8U6u2f8DK2XAkGRFV7BBLENgnTGX9i4rQRxJf+/vs=
|
||||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.24.0/go.mod h1:6KW1Fm6R/s6Z3PGXwSJN2K4eT6wQB3vXX6CVnYX9NmM=
|
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.24.0/go.mod h1:6KW1Fm6R/s6Z3PGXwSJN2K4eT6wQB3vXX6CVnYX9NmM=
|
||||||
go.opentelemetry.io/otel/metric v1.28.0 h1:f0HGvSl1KRAU1DLgLGFjrwVyismPlnuU6JD6bOeuA5Q=
|
go.opentelemetry.io/otel/metric v1.30.0 h1:4xNulvn9gjzo4hjg+wzIKG7iNFEaBMX00Qd4QIZs7+w=
|
||||||
go.opentelemetry.io/otel/metric v1.28.0/go.mod h1:Fb1eVBFZmLVTMb6PPohq3TO9IIhUisDsbJoL/+uQW4s=
|
go.opentelemetry.io/otel/metric v1.30.0/go.mod h1:aXTfST94tswhWEb+5QjlSqG+cZlmyXy/u8jFpor3WqQ=
|
||||||
go.opentelemetry.io/otel/sdk v1.24.0 h1:YMPPDNymmQN3ZgczicBY3B6sf9n62Dlj9pWD3ucgoDw=
|
go.opentelemetry.io/otel/sdk v1.24.0 h1:YMPPDNymmQN3ZgczicBY3B6sf9n62Dlj9pWD3ucgoDw=
|
||||||
go.opentelemetry.io/otel/sdk v1.24.0/go.mod h1:KVrIYw6tEubO9E96HQpcmpTKDVn9gdv35HoYiQWGDFg=
|
go.opentelemetry.io/otel/sdk v1.24.0/go.mod h1:KVrIYw6tEubO9E96HQpcmpTKDVn9gdv35HoYiQWGDFg=
|
||||||
go.opentelemetry.io/otel/trace v1.28.0 h1:GhQ9cUuQGmNDd5BTCP2dAvv75RdMxEfTmYejp+lkx9g=
|
go.opentelemetry.io/otel/trace v1.30.0 h1:7UBkkYzeg3C7kQX8VAidWh2biiQbtAKjyIML8dQ9wmc=
|
||||||
go.opentelemetry.io/otel/trace v1.28.0/go.mod h1:jPyXzNPg6da9+38HEwElrQiHlVMTnVfM3/yv2OlIHaI=
|
go.opentelemetry.io/otel/trace v1.30.0/go.mod h1:5EyKqTzzmyqB9bwtCCq6pDLktPK6fmGf/Dph+8VI02o=
|
||||||
go.opentelemetry.io/proto/otlp v1.1.0 h1:2Di21piLrCqJ3U3eXGCTPHE9R8Nh+0uglSnOyxikMeI=
|
go.opentelemetry.io/proto/otlp v1.1.0 h1:2Di21piLrCqJ3U3eXGCTPHE9R8Nh+0uglSnOyxikMeI=
|
||||||
go.opentelemetry.io/proto/otlp v1.1.0/go.mod h1:GpBHCBWiqvVLDqmHZsoMM3C5ySeKTC7ej/RNTae6MdY=
|
go.opentelemetry.io/proto/otlp v1.1.0/go.mod h1:GpBHCBWiqvVLDqmHZsoMM3C5ySeKTC7ej/RNTae6MdY=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw=
|
golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A=
|
||||||
golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54=
|
golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70=
|
||||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
golang.org/x/mod v0.20.0 h1:utOm6MM3R3dnawAiJgn0y+xvuYRsm1RKM/4giyfDgV0=
|
golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0=
|
||||||
golang.org/x/mod v0.20.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
|
||||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||||
golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE=
|
golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo=
|
||||||
golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg=
|
golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0=
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
@ -119,20 +119,20 @@ golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5h
|
||||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg=
|
golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34=
|
||||||
golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc=
|
golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224=
|
||||||
golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
|
golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
|
||||||
golang.org/x/time v0.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U=
|
golang.org/x/time v0.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U=
|
||||||
golang.org/x/time v0.6.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
golang.org/x/time v0.6.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||||
golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24=
|
golang.org/x/tools v0.25.0 h1:oFU9pkj/iJgs+0DT+VMHrx+oBKs/LJMV+Uvg78sl+fE=
|
||||||
golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ=
|
golang.org/x/tools v0.25.0/go.mod h1:/vtpO8WL1N9cQC3FN5zPqb//fRXskFHbLKk4OW1Q7rg=
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
|
|
@ -20,13 +20,14 @@ import (
|
||||||
R "github.com/yusing/go-proxy/route"
|
R "github.com/yusing/go-proxy/route"
|
||||||
"github.com/yusing/go-proxy/server"
|
"github.com/yusing/go-proxy/server"
|
||||||
F "github.com/yusing/go-proxy/utils/functional"
|
F "github.com/yusing/go-proxy/utils/functional"
|
||||||
|
W "github.com/yusing/go-proxy/watcher"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
runtime.GOMAXPROCS(runtime.NumCPU())
|
runtime.GOMAXPROCS(runtime.NumCPU())
|
||||||
|
|
||||||
args := common.GetArgs()
|
args := common.GetArgs()
|
||||||
l := logrus.WithField("?", "init")
|
l := logrus.WithField("module", "main")
|
||||||
|
|
||||||
if common.IsDebug {
|
if common.IsDebug {
|
||||||
logrus.SetLevel(logrus.DebugLevel)
|
logrus.SetLevel(logrus.DebugLevel)
|
||||||
|
@ -69,6 +70,7 @@ func main() {
|
||||||
|
|
||||||
onShutdown.Add(func() {
|
onShutdown.Add(func() {
|
||||||
docker.CloseAllClients()
|
docker.CloseAllClients()
|
||||||
|
W.StopAllFileWatchers()
|
||||||
cfg.Dispose()
|
cfg.Dispose()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
package proxy
|
package proxy
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"strconv"
|
|
||||||
|
|
||||||
E "github.com/yusing/go-proxy/error"
|
E "github.com/yusing/go-proxy/error"
|
||||||
M "github.com/yusing/go-proxy/models"
|
M "github.com/yusing/go-proxy/models"
|
||||||
|
@ -39,7 +39,7 @@ func NewEntry(m *M.ProxyEntry) (any, E.NestedError) {
|
||||||
if scheme.IsStream() {
|
if scheme.IsStream() {
|
||||||
return validateStreamEntry(m)
|
return validateStreamEntry(m)
|
||||||
}
|
}
|
||||||
return validateEntry(m, *scheme)
|
return validateEntry(m, scheme)
|
||||||
}
|
}
|
||||||
|
|
||||||
func validateEntry(m *M.ProxyEntry, s T.Scheme) (*Entry, E.NestedError) {
|
func validateEntry(m *M.ProxyEntry, s T.Scheme) (*Entry, E.NestedError) {
|
||||||
|
@ -55,7 +55,7 @@ func validateEntry(m *M.ProxyEntry, s T.Scheme) (*Entry, E.NestedError) {
|
||||||
if err.IsNotNil() {
|
if err.IsNotNil() {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
url, err := E.Check(url.Parse(s.String() + "://" + host.String() + ":" + strconv.Itoa(int(port))))
|
url, err := E.Check(url.Parse(fmt.Sprintf("%s://%s:%d", s, host, port)))
|
||||||
if err.IsNotNil() {
|
if err.IsNotNil() {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,11 +6,11 @@ import (
|
||||||
F "github.com/yusing/go-proxy/utils/functional"
|
F "github.com/yusing/go-proxy/utils/functional"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Alias struct{ F.Stringable }
|
type Alias string
|
||||||
type Aliases struct{ *F.Slice[Alias] }
|
type Aliases struct{ *F.Slice[Alias] }
|
||||||
|
|
||||||
func NewAlias(s string) Alias {
|
func NewAlias(s string) Alias {
|
||||||
return Alias{F.NewStringable(s)}
|
return Alias(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewAliases(s string) Aliases {
|
func NewAliases(s string) Aliases {
|
||||||
|
|
|
@ -2,19 +2,11 @@ package fields
|
||||||
|
|
||||||
import (
|
import (
|
||||||
E "github.com/yusing/go-proxy/error"
|
E "github.com/yusing/go-proxy/error"
|
||||||
F "github.com/yusing/go-proxy/utils/functional"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Host struct{ F.Stringable }
|
type Host string
|
||||||
type Subdomain = Alias
|
type Subdomain = Alias
|
||||||
|
|
||||||
func NewHost(s string) (Host, E.NestedError) {
|
func NewHost(s string) (Host, E.NestedError) {
|
||||||
return Host{F.NewStringable(s)}, E.Nil()
|
return Host(s), E.Nil()
|
||||||
}
|
|
||||||
|
|
||||||
func (h Host) Subdomain() (*Subdomain, E.NestedError) {
|
|
||||||
if i := h.IndexRune(':'); i != -1 {
|
|
||||||
return &Subdomain{h.SubStr(0, i)}, E.Nil()
|
|
||||||
}
|
|
||||||
return nil, E.Invalid("host", h)
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,14 +2,13 @@ package fields
|
||||||
|
|
||||||
import (
|
import (
|
||||||
E "github.com/yusing/go-proxy/error"
|
E "github.com/yusing/go-proxy/error"
|
||||||
F "github.com/yusing/go-proxy/utils/functional"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Path struct{ F.Stringable }
|
type Path string
|
||||||
|
|
||||||
func NewPath(s string) (Path, E.NestedError) {
|
func NewPath(s string) (Path, E.NestedError) {
|
||||||
if s == "" || s[0] == '/' {
|
if s == "" || s[0] == '/' {
|
||||||
return Path{F.NewStringable(s)}, E.Nil()
|
return Path(s), E.Nil()
|
||||||
}
|
}
|
||||||
return Path{}, E.Invalid("path", s).With("must be empty or start with '/'")
|
return "", E.Invalid("path", s).With("must be empty or start with '/'")
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,25 +1,24 @@
|
||||||
package fields
|
package fields
|
||||||
|
|
||||||
import (
|
import (
|
||||||
F "github.com/yusing/go-proxy/utils/functional"
|
|
||||||
E "github.com/yusing/go-proxy/error"
|
E "github.com/yusing/go-proxy/error"
|
||||||
)
|
)
|
||||||
|
|
||||||
type PathMode struct{ F.Stringable }
|
type PathMode string
|
||||||
|
|
||||||
func NewPathMode(pm string) (PathMode, E.NestedError) {
|
func NewPathMode(pm string) (PathMode, E.NestedError) {
|
||||||
switch pm {
|
switch pm {
|
||||||
case "", "forward":
|
case "", "forward":
|
||||||
return PathMode{F.NewStringable(pm)}, E.Nil()
|
return PathMode(pm), E.Nil()
|
||||||
default:
|
default:
|
||||||
return PathMode{}, E.Invalid("path mode", pm)
|
return "", E.Invalid("path mode", pm)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p PathMode) IsRemove() bool {
|
func (p PathMode) IsRemove() bool {
|
||||||
return p.String() == ""
|
return p == ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p PathMode) IsForward() bool {
|
func (p PathMode) IsForward() bool {
|
||||||
return p.String() == "forward"
|
return p == "forward"
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,20 +4,19 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
E "github.com/yusing/go-proxy/error"
|
E "github.com/yusing/go-proxy/error"
|
||||||
F "github.com/yusing/go-proxy/utils/functional"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Scheme struct{ F.Stringable }
|
type Scheme string
|
||||||
|
|
||||||
func NewScheme(s string) (*Scheme, E.NestedError) {
|
func NewScheme(s string) (Scheme, E.NestedError) {
|
||||||
switch s {
|
switch s {
|
||||||
case "http", "https", "tcp", "udp":
|
case "http", "https", "tcp", "udp":
|
||||||
return &Scheme{F.NewStringable(s)}, E.Nil()
|
return Scheme(s), E.Nil()
|
||||||
}
|
}
|
||||||
return nil, E.Invalid("scheme", s)
|
return "", E.Invalid("scheme", s)
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewSchemeFromPort(p string) (*Scheme, E.NestedError) {
|
func NewSchemeFromPort(p string) (Scheme, E.NestedError) {
|
||||||
var s string
|
var s string
|
||||||
switch {
|
switch {
|
||||||
case strings.ContainsRune(p, ':'):
|
case strings.ContainsRune(p, ':'):
|
||||||
|
@ -27,11 +26,11 @@ func NewSchemeFromPort(p string) (*Scheme, E.NestedError) {
|
||||||
default:
|
default:
|
||||||
s = "http"
|
s = "http"
|
||||||
}
|
}
|
||||||
return &Scheme{F.NewStringable(s)}, E.Nil()
|
return Scheme(s), E.Nil()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s Scheme) IsHTTP() bool { return s.String() == "http" }
|
func (s Scheme) IsHTTP() bool { return s == "http" }
|
||||||
func (s Scheme) IsHTTPS() bool { return s.String() == "https" }
|
func (s Scheme) IsHTTPS() bool { return s == "https" }
|
||||||
func (s Scheme) IsTCP() bool { return s.String() == "tcp" }
|
func (s Scheme) IsTCP() bool { return s == "tcp" }
|
||||||
func (s Scheme) IsUDP() bool { return s.String() == "udp" }
|
func (s Scheme) IsUDP() bool { return s == "udp" }
|
||||||
func (s Scheme) IsStream() bool { return s.IsTCP() || s.IsUDP() }
|
func (s Scheme) IsStream() bool { return s.IsTCP() || s.IsUDP() }
|
||||||
|
|
|
@ -1,14 +1,15 @@
|
||||||
package fields
|
package fields
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
E "github.com/yusing/go-proxy/error"
|
E "github.com/yusing/go-proxy/error"
|
||||||
)
|
)
|
||||||
|
|
||||||
type StreamScheme struct {
|
type StreamScheme struct {
|
||||||
ListeningScheme *Scheme `json:"listening"`
|
ListeningScheme Scheme `json:"listening"`
|
||||||
ProxyScheme *Scheme `json:"proxy"`
|
ProxyScheme Scheme `json:"proxy"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewStreamScheme(s string) (ss *StreamScheme, err E.NestedError) {
|
func NewStreamScheme(s string) (ss *StreamScheme, err E.NestedError) {
|
||||||
|
@ -31,12 +32,12 @@ func NewStreamScheme(s string) (ss *StreamScheme, err E.NestedError) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s StreamScheme) String() string {
|
func (s StreamScheme) String() string {
|
||||||
return s.ListeningScheme.String() + " -> " + s.ProxyScheme.String()
|
return fmt.Sprintf("%s -> %s", s.ListeningScheme, s.ProxyScheme)
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsCoherent checks if the ListeningScheme and ProxyScheme of the StreamScheme are equal.
|
// IsCoherent checks if the ListeningScheme and ProxyScheme of the StreamScheme are equal.
|
||||||
//
|
//
|
||||||
// It returns a boolean value indicating whether the ListeningScheme and ProxyScheme are equal.
|
// It returns a boolean value indicating whether the ListeningScheme and ProxyScheme are equal.
|
||||||
func (s StreamScheme) IsCoherent() bool {
|
func (s StreamScheme) IsCoherent() bool {
|
||||||
return *s.ListeningScheme == *s.ProxyScheme
|
return s.ListeningScheme == s.ProxyScheme
|
||||||
}
|
}
|
||||||
|
|
|
@ -100,8 +100,8 @@ func (p *DockerProvider) getEntriesFromLabels(container *types.Container, client
|
||||||
|
|
||||||
// init entries map for all aliases
|
// init entries map for all aliases
|
||||||
aliases.ForEach(func(a PT.Alias) {
|
aliases.ForEach(func(a PT.Alias) {
|
||||||
entries.Set(a.String(), &M.ProxyEntry{
|
entries.Set(string(a), &M.ProxyEntry{
|
||||||
Alias: a.String(),
|
Alias: string(a),
|
||||||
Host: clientHost,
|
Host: clientHost,
|
||||||
Port: fmt.Sprint(defaultPort),
|
Port: fmt.Sprint(defaultPort),
|
||||||
})
|
})
|
||||||
|
|
|
@ -40,13 +40,15 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
func newProvider(name string, t ProviderType) *Provider {
|
func newProvider(name string, t ProviderType) *Provider {
|
||||||
return &Provider{
|
p := &Provider{
|
||||||
name: name,
|
name: name,
|
||||||
t: t,
|
t: t,
|
||||||
routes: R.NewRoutes(),
|
routes: R.NewRoutes(),
|
||||||
reloadReqCh: make(chan struct{}, 1),
|
reloadReqCh: make(chan struct{}, 1),
|
||||||
l: logrus.WithField("provider", name),
|
|
||||||
}
|
}
|
||||||
|
p.l = logrus.WithField("provider", p)
|
||||||
|
|
||||||
|
return p
|
||||||
}
|
}
|
||||||
func NewFileProvider(filename string) *Provider {
|
func NewFileProvider(filename string) *Provider {
|
||||||
name := path.Base(filename)
|
name := path.Base(filename)
|
||||||
|
@ -72,7 +74,7 @@ func (p *Provider) GetType() ProviderType {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Provider) String() string {
|
func (p *Provider) String() string {
|
||||||
return fmt.Sprintf("%s (%s provider)", p.name, p.t)
|
return fmt.Sprintf("%s: %s", p.t, p.name)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Provider) StartAllRoutes() E.NestedError {
|
func (p *Provider) StartAllRoutes() E.NestedError {
|
||||||
|
@ -103,25 +105,22 @@ func (p *Provider) StartAllRoutes() E.NestedError {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Provider) StopAllRoutes() E.NestedError {
|
func (p *Provider) StopAllRoutes() E.NestedError {
|
||||||
defer p.routes.Clear()
|
|
||||||
|
|
||||||
if p.watcherCancel != nil {
|
if p.watcherCancel != nil {
|
||||||
p.watcherCancel()
|
p.watcherCancel()
|
||||||
}
|
}
|
||||||
errors := E.NewBuilder("errors stopping routes for provider %q", p.name)
|
errors := E.NewBuilder("errors stopping routes for provider %q", p.name)
|
||||||
nStopped := 0
|
nStopped := 0
|
||||||
|
nFailed := 0
|
||||||
p.routes.EachKVParallel(func(alias string, r R.Route) {
|
p.routes.EachKVParallel(func(alias string, r R.Route) {
|
||||||
if err := r.Stop(); err.IsNotNil() {
|
if err := r.Stop(); err.IsNotNil() {
|
||||||
errors.Add(err.Subject(r))
|
errors.Add(err.Subject(r))
|
||||||
|
nFailed++
|
||||||
} else {
|
} else {
|
||||||
nStopped++
|
nStopped++
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
if err := errors.Build(); err.IsNotNil() {
|
p.l.Infof("%d routes stopped, %d failed", nStopped, nFailed)
|
||||||
return err
|
return errors.Build()
|
||||||
}
|
|
||||||
p.l.Infof("%d routes stopped", nStopped)
|
|
||||||
return E.Nil()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Provider) ReloadRoutes() {
|
func (p *Provider) ReloadRoutes() {
|
||||||
|
@ -146,7 +145,7 @@ func (p *Provider) GetCurrentRoutes() *R.Routes {
|
||||||
|
|
||||||
func (p *Provider) watchEvents() {
|
func (p *Provider) watchEvents() {
|
||||||
events, errs := p.watcher.Events(p.watcherCtx)
|
events, errs := p.watcher.Events(p.watcherCtx)
|
||||||
l := logrus.WithField("?", "watcher")
|
l := p.l.WithField("module", "watcher")
|
||||||
|
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
|
@ -156,12 +155,15 @@ func (p *Provider) watchEvents() {
|
||||||
if !ok {
|
if !ok {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
l.Infof("watcher event: %v", event)
|
l.Infof("watcher event: %s", event)
|
||||||
p.reloadReqCh <- struct{}{}
|
p.reloadReqCh <- struct{}{}
|
||||||
case err, ok := <-errs:
|
case err, ok := <-errs:
|
||||||
if !ok {
|
if !ok {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if err.Is(context.Canceled) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
l.Errorf("watcher error: %s", err)
|
l.Errorf("watcher error: %s", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -175,17 +177,15 @@ func (p *Provider) loadRoutes() E.NestedError {
|
||||||
}
|
}
|
||||||
p.routes = R.NewRoutes()
|
p.routes = R.NewRoutes()
|
||||||
|
|
||||||
errors := E.NewBuilder("errors loading routes from provider %q", p.name)
|
errors := E.NewBuilder("errors loading routes from %s", p)
|
||||||
entries.EachKV(func(a string, e *M.ProxyEntry) {
|
entries.EachKV(func(a string, e *M.ProxyEntry) {
|
||||||
e.Alias = a
|
e.Alias = a
|
||||||
r, err := R.NewRoute(e)
|
r, err := R.NewRoute(e)
|
||||||
if err.IsNotNil() {
|
if err.IsNotNil() {
|
||||||
errors.Add(err.Subject(a))
|
errors.Add(err.Subject(a))
|
||||||
p.l.Debugf("failed to load route: %s, %s", a, err)
|
|
||||||
} else {
|
} else {
|
||||||
p.routes.Set(a, r)
|
p.routes.Set(a, r)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
p.l.Debugf("loaded %d routes from %d entries", p.routes.Size(), entries.Size())
|
|
||||||
return errors.Build()
|
return errors.Build()
|
||||||
}
|
}
|
||||||
|
|
|
@ -535,4 +535,4 @@ func IsPrint(s string) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
var logger = logrus.WithField("?", "http")
|
var logger = logrus.WithField("module", "http")
|
||||||
|
|
|
@ -1,102 +0,0 @@
|
||||||
package proxy
|
|
||||||
|
|
||||||
// import (
|
|
||||||
// "net/http"
|
|
||||||
// "net/url"
|
|
||||||
// "os"
|
|
||||||
// "reflect"
|
|
||||||
// "testing"
|
|
||||||
// "time"
|
|
||||||
// )
|
|
||||||
|
|
||||||
// var proxy Entry
|
|
||||||
// var proxyUrl, _ = url.Parse("http://127.0.0.1:8181")
|
|
||||||
// var proxyServer = NewServer(ServerOptions{
|
|
||||||
// Name: "proxy",
|
|
||||||
// HTTPAddr: ":8080",
|
|
||||||
// Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
// NewReverseProxy(proxyUrl, &http.Transport{}, &proxy).ServeHTTP(w, r)
|
|
||||||
// }),
|
|
||||||
// })
|
|
||||||
|
|
||||||
// var testServer = NewServer(ServerOptions{
|
|
||||||
// Name: "test",
|
|
||||||
// HTTPAddr: ":8181",
|
|
||||||
// Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
// h := r.Header
|
|
||||||
// for k, vv := range h {
|
|
||||||
// for _, v := range vv {
|
|
||||||
// w.Header().Add(k, v)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// w.WriteHeader(http.StatusOK)
|
|
||||||
// }),
|
|
||||||
// })
|
|
||||||
|
|
||||||
// var httpClient = http.DefaultClient
|
|
||||||
|
|
||||||
// func TestMain(m *testing.M) {
|
|
||||||
// proxyServer.Start()
|
|
||||||
// testServer.Start()
|
|
||||||
// time.Sleep(100 * time.Millisecond)
|
|
||||||
// code := m.Run()
|
|
||||||
// proxyServer.Stop()
|
|
||||||
// testServer.Stop()
|
|
||||||
// os.Exit(code)
|
|
||||||
// }
|
|
||||||
|
|
||||||
// func TestSetHeader(t *testing.T) {
|
|
||||||
// hWant := http.Header{"X-Test": []string{"foo", "bar"}, "X-Test2": []string{"baz"}}
|
|
||||||
// proxy = Entry{
|
|
||||||
// Alias: "test",
|
|
||||||
// Scheme: "http",
|
|
||||||
// Host: "127.0.0.1",
|
|
||||||
// Port: "8181",
|
|
||||||
// SetHeaders: hWant,
|
|
||||||
// }
|
|
||||||
// req, err := http.NewRequest("HEAD", "http://127.0.0.1:8080", nil)
|
|
||||||
// if err != nil {
|
|
||||||
// t.Fatal(err)
|
|
||||||
// }
|
|
||||||
// resp, err := httpClient.Do(req)
|
|
||||||
// if err != nil {
|
|
||||||
// t.Fatal(err)
|
|
||||||
// }
|
|
||||||
// hGot := resp.Header
|
|
||||||
// t.Log("headers: ", hGot)
|
|
||||||
// for k, v := range hWant {
|
|
||||||
// if !reflect.DeepEqual(hGot[k], v) {
|
|
||||||
// t.Errorf("header %s: expected %v, got %v", k, v, hGot[k])
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// func TestHideHeader(t *testing.T) {
|
|
||||||
// hHide := []string{"X-Test", "X-Test2"}
|
|
||||||
// proxy = Entry{
|
|
||||||
// Alias: "test",
|
|
||||||
// Scheme: "http",
|
|
||||||
// Host: "127.0.0.1",
|
|
||||||
// Port: "8181",
|
|
||||||
// HideHeaders: hHide,
|
|
||||||
// }
|
|
||||||
// req, err := http.NewRequest("HEAD", "http://127.0.0.1:8080", nil)
|
|
||||||
// for _, k := range hHide {
|
|
||||||
// req.Header.Set(k, "foo")
|
|
||||||
// }
|
|
||||||
// if err != nil {
|
|
||||||
// t.Fatal(err)
|
|
||||||
// }
|
|
||||||
// resp, err := httpClient.Do(req)
|
|
||||||
// if err != nil {
|
|
||||||
// t.Fatal(err)
|
|
||||||
// }
|
|
||||||
// hGot := resp.Header
|
|
||||||
// t.Log("headers: ", hGot)
|
|
||||||
// for _, v := range hHide {
|
|
||||||
// _, ok := hGot[v]
|
|
||||||
// if ok {
|
|
||||||
// t.Errorf("header %s: expected hidden, got %v", v, hGot[v])
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
|
@ -26,17 +26,15 @@ type (
|
||||||
}
|
}
|
||||||
|
|
||||||
HTTPSubroute struct {
|
HTTPSubroute struct {
|
||||||
TargetURL URL `json:"targetURL"`
|
TargetURL *URL `json:"targetURL"`
|
||||||
Path PathKey `json:"path"`
|
Path PathKey `json:"path"`
|
||||||
|
|
||||||
proxy *P.ReverseProxy
|
proxy *P.ReverseProxy
|
||||||
}
|
}
|
||||||
|
|
||||||
URL struct {
|
URL url.URL
|
||||||
*url.URL
|
PathKey = PT.Path
|
||||||
}
|
SubdomainKey = PT.Alias
|
||||||
PathKey = string
|
|
||||||
SubdomainKey = string
|
|
||||||
HTTPSubroutes = map[PathKey]HTTPSubroute
|
HTTPSubroutes = map[PathKey]HTTPSubroute
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -53,25 +51,25 @@ func NewHTTPRoute(entry *P.Entry) (*HTTPRoute, E.NestedError) {
|
||||||
rp := P.NewReverseProxy(entry.URL, tr, entry)
|
rp := P.NewReverseProxy(entry.URL, tr, entry)
|
||||||
|
|
||||||
httpRoutes.Lock()
|
httpRoutes.Lock()
|
||||||
|
defer httpRoutes.Unlock()
|
||||||
|
|
||||||
var r *HTTPRoute
|
var r *HTTPRoute
|
||||||
r, ok := httpRoutes.UnsafeGet(entry.Alias.String())
|
r, ok := httpRoutes.UnsafeGet(entry.Alias)
|
||||||
if !ok {
|
if !ok {
|
||||||
r = &HTTPRoute{
|
r = &HTTPRoute{
|
||||||
Alias: entry.Alias,
|
Alias: entry.Alias,
|
||||||
Subroutes: make(HTTPSubroutes),
|
Subroutes: make(HTTPSubroutes),
|
||||||
mux: http.NewServeMux(),
|
mux: http.NewServeMux(),
|
||||||
}
|
}
|
||||||
httpRoutes.UnsafeSet(entry.Alias.String(), r)
|
httpRoutes.UnsafeSet(entry.Alias, r)
|
||||||
}
|
}
|
||||||
|
|
||||||
path := entry.Path.String()
|
path := entry.Path
|
||||||
if _, exists := r.Subroutes[path]; exists {
|
if _, exists := r.Subroutes[path]; exists {
|
||||||
httpRoutes.Unlock()
|
|
||||||
return nil, E.Duplicated("path", path)
|
return nil, E.Duplicated("path", path)
|
||||||
}
|
}
|
||||||
r.mux.HandleFunc(path, rp.ServeHTTP)
|
r.mux.HandleFunc(string(path), rp.ServeHTTP)
|
||||||
if err := recover(); err != nil {
|
if err := recover(); err != nil {
|
||||||
httpRoutes.Unlock()
|
|
||||||
switch t := err.(type) {
|
switch t := err.(type) {
|
||||||
case error:
|
case error:
|
||||||
// NOTE: likely path pattern error
|
// NOTE: likely path pattern error
|
||||||
|
@ -82,7 +80,7 @@ func NewHTTPRoute(entry *P.Entry) (*HTTPRoute, E.NestedError) {
|
||||||
}
|
}
|
||||||
|
|
||||||
sr := HTTPSubroute{
|
sr := HTTPSubroute{
|
||||||
TargetURL: URL{entry.URL},
|
TargetURL: (*URL)(entry.URL),
|
||||||
proxy: rp,
|
proxy: rp,
|
||||||
Path: path,
|
Path: path,
|
||||||
}
|
}
|
||||||
|
@ -102,21 +100,20 @@ func NewHTTPRoute(entry *P.Entry) (*HTTPRoute, E.NestedError) {
|
||||||
}
|
}
|
||||||
|
|
||||||
r.Subroutes[path] = sr
|
r.Subroutes[path] = sr
|
||||||
httpRoutes.Unlock()
|
|
||||||
return r, E.Nil()
|
return r, E.Nil()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *HTTPRoute) String() string {
|
func (r *HTTPRoute) String() string {
|
||||||
return fmt.Sprintf("%s (reverse proxy)", r.Alias)
|
return string(r.Alias)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *HTTPRoute) Start() E.NestedError {
|
func (r *HTTPRoute) Start() E.NestedError {
|
||||||
httpRoutes.Set(r.Alias.String(), r)
|
httpRoutes.Set(r.Alias, r)
|
||||||
return E.Nil()
|
return E.Nil()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *HTTPRoute) Stop() E.NestedError {
|
func (r *HTTPRoute) Stop() E.NestedError {
|
||||||
httpRoutes.Delete(r.Alias.String())
|
httpRoutes.Delete(r.Alias)
|
||||||
return E.Nil()
|
return E.Nil()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,7 +122,11 @@ func (r *HTTPRoute) GetSubroute(path PathKey) (HTTPSubroute, bool) {
|
||||||
return sr, ok
|
return sr, ok
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u URL) MarshalText() (text []byte, err error) {
|
func (u *URL) String() string {
|
||||||
|
return (*url.URL)(u).String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *URL) MarshalText() (text []byte, err error) {
|
||||||
return []byte(u.String()), nil
|
return []byte(u.String()), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -144,7 +145,7 @@ func ProxyHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
func findMux(host string, path PathKey) (*http.ServeMux, error) {
|
func findMux(host string, path PathKey) (*http.ServeMux, error) {
|
||||||
sd := strings.Split(host, ".")[0]
|
sd := strings.Split(host, ".")[0]
|
||||||
if r, ok := httpRoutes.UnsafeGet(sd); ok {
|
if r, ok := httpRoutes.UnsafeGet(PT.Alias(sd)); ok {
|
||||||
return r.mux, nil
|
return r.mux, nil
|
||||||
}
|
}
|
||||||
return nil, E.NotExists("route", fmt.Sprintf("subdomain: %s, path: %s", sd, path))
|
return nil, E.NotExists("route", fmt.Sprintf("subdomain: %s, path: %s", sd, path))
|
||||||
|
|
|
@ -39,18 +39,18 @@ func NewStreamRoute(entry *P.StreamEntry) (*StreamRoute, E.NestedError) {
|
||||||
wg: sync.WaitGroup{},
|
wg: sync.WaitGroup{},
|
||||||
stopCh: make(chan struct{}, 1),
|
stopCh: make(chan struct{}, 1),
|
||||||
connCh: make(chan any),
|
connCh: make(chan any),
|
||||||
l: logger.WithField("alias", entry.Alias),
|
|
||||||
}
|
}
|
||||||
if entry.Scheme.ListeningScheme.IsTCP() {
|
if entry.Scheme.ListeningScheme.IsTCP() {
|
||||||
base.StreamImpl = NewTCPRoute(base)
|
base.StreamImpl = NewTCPRoute(base)
|
||||||
} else {
|
} else {
|
||||||
base.StreamImpl = NewUDPRoute(base)
|
base.StreamImpl = NewUDPRoute(base)
|
||||||
}
|
}
|
||||||
|
base.l = logrus.WithField("route", base.StreamImpl)
|
||||||
return base, E.Nil()
|
return base, E.Nil()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *StreamRoute) String() string {
|
func (r *StreamRoute) String() string {
|
||||||
return fmt.Sprintf("%s (%v stream)", r.Alias, r.Scheme)
|
return fmt.Sprintf("%s-stream: %s", r.Scheme, r.Alias)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *StreamRoute) Start() E.NestedError {
|
func (r *StreamRoute) Start() E.NestedError {
|
||||||
|
@ -131,5 +131,3 @@ func (r *StreamRoute) grHandleConnections() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var logger = logrus.WithField("?", "stream")
|
|
||||||
|
|
|
@ -53,7 +53,7 @@ func (route *TCPRoute) Handle(c interface{}) error {
|
||||||
serverAddr := fmt.Sprintf("%s:%v", route.Host, route.Port.ProxyPort)
|
serverAddr := fmt.Sprintf("%s:%v", route.Host, route.Port.ProxyPort)
|
||||||
dialer := &net.Dialer{}
|
dialer := &net.Dialer{}
|
||||||
|
|
||||||
serverConn, err := dialer.DialContext(ctx, route.Scheme.ProxyScheme.String(), serverAddr)
|
serverConn, err := dialer.DialContext(ctx, string(route.Scheme.ProxyScheme), serverAddr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,15 +36,15 @@ func NewUDPRoute(base *StreamRoute) StreamImpl {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (route *UDPRoute) Setup() error {
|
func (route *UDPRoute) Setup() error {
|
||||||
laddr, err := net.ResolveUDPAddr(route.Scheme.ListeningScheme.String(), fmt.Sprintf(":%v", route.Port.ProxyPort))
|
laddr, err := net.ResolveUDPAddr(string(route.Scheme.ListeningScheme), fmt.Sprintf(":%v", route.Port.ProxyPort))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
source, err := net.ListenUDP(route.Scheme.ListeningScheme.String(), laddr)
|
source, err := net.ListenUDP(string(route.Scheme.ListeningScheme), laddr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
raddr, err := net.ResolveUDPAddr(route.Scheme.ProxyScheme.String(), fmt.Sprintf("%s:%v", route.Host, route.Port.ProxyPort))
|
raddr, err := net.ResolveUDPAddr(string(route.Scheme.ProxyScheme), fmt.Sprintf("%s:%v", route.Host, route.Port.ProxyPort))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
source.Close()
|
source.Close()
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -158,4 +158,4 @@ func redirectToTLSHandler(port string) http.HandlerFunc {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var logger = logrus.WithField("?", "server")
|
var logger = logrus.WithField("module", "server")
|
||||||
|
|
|
@ -1,68 +0,0 @@
|
||||||
package functional
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Stringable struct{ string }
|
|
||||||
|
|
||||||
func NewStringable(v any) Stringable {
|
|
||||||
switch vv := v.(type) {
|
|
||||||
case string:
|
|
||||||
return Stringable{vv}
|
|
||||||
case fmt.Stringer:
|
|
||||||
return Stringable{vv.String()}
|
|
||||||
default:
|
|
||||||
return Stringable{fmt.Sprint(vv)}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s Stringable) String() string {
|
|
||||||
return s.string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s Stringable) Len() int {
|
|
||||||
return len(s.string)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s Stringable) MarshalText() (text []byte, err error) {
|
|
||||||
return []byte(s.string), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s Stringable) SubStr(start int, end int) Stringable {
|
|
||||||
return Stringable{s.string[start:end]}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s Stringable) HasPrefix(p Stringable) bool {
|
|
||||||
return len(s.string) >= len(p.string) && s.string[0:len(p.string)] == p.string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s Stringable) HasSuffix(p Stringable) bool {
|
|
||||||
return len(s.string) >= len(p.string) && s.string[len(s.string)-len(p.string):] == p.string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s Stringable) IsEmpty() bool {
|
|
||||||
return len(s.string) == 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s Stringable) IndexRune(r rune) int {
|
|
||||||
return strings.IndexRune(s.string, r)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s Stringable) ToInt() (int, error) {
|
|
||||||
return strconv.Atoi(s.string)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s Stringable) Split(sep string) []Stringable {
|
|
||||||
return Stringables(strings.Split(s.string, sep))
|
|
||||||
}
|
|
||||||
|
|
||||||
func Stringables(ss []string) []Stringable {
|
|
||||||
ret := make([]Stringable, len(ss))
|
|
||||||
for i, s := range ss {
|
|
||||||
ret[i] = Stringable{s}
|
|
||||||
}
|
|
||||||
return ret
|
|
||||||
}
|
|
|
@ -4,7 +4,7 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/docker/docker/api/types"
|
"github.com/docker/docker/api/types/events"
|
||||||
"github.com/docker/docker/api/types/filters"
|
"github.com/docker/docker/api/types/filters"
|
||||||
D "github.com/yusing/go-proxy/docker"
|
D "github.com/yusing/go-proxy/docker"
|
||||||
E "github.com/yusing/go-proxy/error"
|
E "github.com/yusing/go-proxy/error"
|
||||||
|
@ -30,14 +30,14 @@ func (w *DockerWatcher) Events(ctx context.Context) (<-chan Event, <-chan E.Nest
|
||||||
var err E.NestedError
|
var err E.NestedError
|
||||||
for range 3 {
|
for range 3 {
|
||||||
cl, err = D.ConnectClient(w.host)
|
cl, err = D.ConnectClient(w.host)
|
||||||
if err.IsNotNil() {
|
if err.IsNil() {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
errCh <- E.From(err)
|
errCh <- E.From(err)
|
||||||
time.Sleep(1 * time.Second)
|
time.Sleep(1 * time.Second)
|
||||||
}
|
}
|
||||||
if err.IsNotNil() {
|
if err.IsNotNil() {
|
||||||
errCh <- E.Failure("connect to docker")
|
errCh <- E.Failure("connecting to docker")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,14 +50,8 @@ func (w *DockerWatcher) Events(ctx context.Context) (<-chan Event, <-chan E.Nest
|
||||||
errCh <- E.From(<-cErrCh)
|
errCh <- E.From(<-cErrCh)
|
||||||
return
|
return
|
||||||
case msg := <-cEventCh:
|
case msg := <-cEventCh:
|
||||||
containerName, ok := msg.Actor.Attributes["name"]
|
|
||||||
if !ok {
|
|
||||||
// NOTE: should not happen
|
|
||||||
// but if it happens, just ignore it
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
eventCh <- Event{
|
eventCh <- Event{
|
||||||
ActorName: containerName,
|
ActorName: msg.Actor.Attributes["name"],
|
||||||
Action: ActionModified,
|
Action: ActionModified,
|
||||||
}
|
}
|
||||||
case err := <-cErrCh:
|
case err := <-cErrCh:
|
||||||
|
@ -79,7 +73,7 @@ func (w *DockerWatcher) Events(ctx context.Context) (<-chan Event, <-chan E.Nest
|
||||||
return eventCh, errCh
|
return eventCh, errCh
|
||||||
}
|
}
|
||||||
|
|
||||||
var dwOptions = types.EventsOptions{Filters: filters.NewArgs(
|
var dwOptions = events.ListOptions{Filters: filters.NewArgs(
|
||||||
filters.Arg("type", "container"),
|
filters.Arg("type", "container"),
|
||||||
filters.Arg("event", "start"),
|
filters.Arg("event", "start"),
|
||||||
filters.Arg("event", "die"), // 'stop' already triggering 'die'
|
filters.Arg("event", "die"), // 'stop' already triggering 'die'
|
||||||
|
|
|
@ -16,7 +16,7 @@ const (
|
||||||
ActionCreated Action = "CREATED"
|
ActionCreated Action = "CREATED"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (e *Event) String() string {
|
func (e Event) String() string {
|
||||||
return fmt.Sprintf("%s %s", e.ActorName, e.Action)
|
return fmt.Sprintf("%s %s", e.ActorName, e.Action)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,10 @@ func NewFileWatcher(filename string) Watcher {
|
||||||
return &fileWatcher{filename: filename}
|
return &fileWatcher{filename: filename}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func StopAllFileWatchers() {
|
||||||
|
fwHelper.close()
|
||||||
|
}
|
||||||
|
|
||||||
func (f *fileWatcher) Events(ctx context.Context) (<-chan Event, <-chan E.NestedError) {
|
func (f *fileWatcher) Events(ctx context.Context) (<-chan Event, <-chan E.NestedError) {
|
||||||
return fwHelper.Add(ctx, f)
|
return fwHelper.Add(ctx, f)
|
||||||
}
|
}
|
||||||
|
|
|
@ -129,4 +129,4 @@ func (h *fileWatcherHelper) start() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var fsLogger = logrus.WithField("?", "fsnotify")
|
var fsLogger = logrus.WithField("module", "fsnotify")
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
0.5.0-beta2
|
0.5.0-beta4
|
Loading…
Add table
Reference in a new issue