mirror of
https://github.com/yusing/godoxy.git
synced 2026-04-27 18:57:04 +02:00
v0.26.0
This commit is contained in:
@@ -9,7 +9,6 @@ import (
|
||||
"fmt"
|
||||
"io/fs"
|
||||
"iter"
|
||||
"net/http"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -18,14 +17,21 @@ import (
|
||||
"github.com/goccy/go-yaml"
|
||||
"github.com/puzpuzpuz/xsync/v4"
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/yusing/godoxy/internal/acl"
|
||||
"github.com/rs/zerolog/log"
|
||||
acl "github.com/yusing/godoxy/internal/acl/types"
|
||||
"github.com/yusing/godoxy/internal/agentpool"
|
||||
"github.com/yusing/godoxy/internal/api"
|
||||
"github.com/yusing/godoxy/internal/autocert"
|
||||
autocertctx "github.com/yusing/godoxy/internal/autocert/types"
|
||||
"github.com/yusing/godoxy/internal/common"
|
||||
config "github.com/yusing/godoxy/internal/config/types"
|
||||
"github.com/yusing/godoxy/internal/entrypoint"
|
||||
entrypointctx "github.com/yusing/godoxy/internal/entrypoint/types"
|
||||
homepage "github.com/yusing/godoxy/internal/homepage/types"
|
||||
"github.com/yusing/godoxy/internal/logging"
|
||||
"github.com/yusing/godoxy/internal/maxmind"
|
||||
"github.com/yusing/godoxy/internal/metrics/systeminfo"
|
||||
"github.com/yusing/godoxy/internal/metrics/uptime"
|
||||
"github.com/yusing/godoxy/internal/notif"
|
||||
route "github.com/yusing/godoxy/internal/route/provider"
|
||||
"github.com/yusing/godoxy/internal/serialization"
|
||||
@@ -40,7 +46,7 @@ type state struct {
|
||||
|
||||
providers *xsync.Map[string, types.RouteProvider]
|
||||
autocertProvider *autocert.Provider
|
||||
entrypoint entrypoint.Entrypoint
|
||||
entrypoint *entrypoint.Entrypoint
|
||||
|
||||
task *task.Task
|
||||
|
||||
@@ -50,14 +56,25 @@ type state struct {
|
||||
tmpLog zerolog.Logger
|
||||
}
|
||||
|
||||
type CriticalError struct {
|
||||
err error
|
||||
}
|
||||
|
||||
func (e CriticalError) Error() string {
|
||||
return e.err.Error()
|
||||
}
|
||||
|
||||
func (e CriticalError) Unwrap() error {
|
||||
return e.err
|
||||
}
|
||||
|
||||
func NewState() config.State {
|
||||
tmpLogBuf := bytes.NewBuffer(make([]byte, 0, 4096))
|
||||
return &state{
|
||||
providers: xsync.NewMap[string, types.RouteProvider](),
|
||||
entrypoint: entrypoint.NewEntrypoint(),
|
||||
task: task.RootTask("config", false),
|
||||
tmpLogBuf: tmpLogBuf,
|
||||
tmpLog: logging.NewLoggerWithFixedLevel(zerolog.InfoLevel, tmpLogBuf),
|
||||
providers: xsync.NewMap[string, types.RouteProvider](),
|
||||
task: task.RootTask("config", false),
|
||||
tmpLogBuf: tmpLogBuf,
|
||||
tmpLog: logging.NewLoggerWithFixedLevel(zerolog.InfoLevel, tmpLogBuf),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,13 +90,7 @@ func SetState(state config.State) {
|
||||
|
||||
cfg := state.Value()
|
||||
config.ActiveState.Store(state)
|
||||
entrypoint.ActiveConfig.Store(&cfg.Entrypoint)
|
||||
homepage.ActiveConfig.Store(&cfg.Homepage)
|
||||
if autocertProvider := state.AutoCertProvider(); autocertProvider != nil {
|
||||
autocert.ActiveProvider.Store(autocertProvider.(*autocert.Provider))
|
||||
} else {
|
||||
autocert.ActiveProvider.Store(nil)
|
||||
}
|
||||
}
|
||||
|
||||
func HasState() bool {
|
||||
@@ -96,7 +107,7 @@ func (state *state) InitFromFile(filename string) error {
|
||||
if errors.Is(err, fs.ErrNotExist) {
|
||||
state.Config = config.DefaultConfig()
|
||||
} else {
|
||||
return err
|
||||
return CriticalError{err}
|
||||
}
|
||||
}
|
||||
return state.Init(data)
|
||||
@@ -105,7 +116,7 @@ func (state *state) InitFromFile(filename string) error {
|
||||
func (state *state) Init(data []byte) error {
|
||||
err := serialization.UnmarshalValidate(data, &state.Config, yaml.Unmarshal)
|
||||
if err != nil {
|
||||
return err
|
||||
return CriticalError{err}
|
||||
}
|
||||
|
||||
g := gperr.NewGroup("config load error")
|
||||
@@ -117,7 +128,9 @@ func (state *state) Init(data []byte) error {
|
||||
// these won't benefit from running on goroutines
|
||||
errs.Add(state.initNotification())
|
||||
errs.Add(state.initACL())
|
||||
errs.Add(state.initEntrypoint())
|
||||
if err := state.initEntrypoint(); err != nil {
|
||||
errs.Add(CriticalError{err})
|
||||
}
|
||||
errs.Add(state.loadRouteProviders())
|
||||
return errs.Error()
|
||||
}
|
||||
@@ -134,8 +147,8 @@ func (state *state) Value() *config.Config {
|
||||
return &state.Config
|
||||
}
|
||||
|
||||
func (state *state) EntrypointHandler() http.Handler {
|
||||
return &state.entrypoint
|
||||
func (state *state) Entrypoint() entrypointctx.Entrypoint {
|
||||
return state.entrypoint
|
||||
}
|
||||
|
||||
func (state *state) ShortLinkMatcher() config.ShortLinkMatcher {
|
||||
@@ -186,10 +199,39 @@ func (state *state) NumProviders() int {
|
||||
}
|
||||
|
||||
func (state *state) FlushTmpLog() {
|
||||
state.tmpLogBuf.WriteTo(os.Stdout)
|
||||
_, _ = state.tmpLogBuf.WriteTo(os.Stdout)
|
||||
state.tmpLogBuf.Reset()
|
||||
}
|
||||
|
||||
func (state *state) StartAPIServers() {
|
||||
// API Handler needs to start after auth is initialized.
|
||||
_, err := server.StartServer(state.task.Subtask("api_server", false), server.Options{
|
||||
Name: "api",
|
||||
HTTPAddr: common.APIHTTPAddr,
|
||||
Handler: api.NewHandler(true),
|
||||
})
|
||||
if err != nil {
|
||||
log.Err(err).Msg("failed to start API server")
|
||||
}
|
||||
|
||||
// Local API Handler is used for unauthenticated access.
|
||||
if common.LocalAPIHTTPAddr != "" {
|
||||
_, err := server.StartServer(state.task.Subtask("local_api_server", false), server.Options{
|
||||
Name: "local_api",
|
||||
HTTPAddr: common.LocalAPIHTTPAddr,
|
||||
Handler: api.NewHandler(false),
|
||||
})
|
||||
if err != nil {
|
||||
log.Err(err).Msg("failed to start local API server")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (state *state) StartMetrics() {
|
||||
systeminfo.Poller.Start(state.task)
|
||||
uptime.Poller.Start(state.task)
|
||||
}
|
||||
|
||||
// initACL initializes the ACL.
|
||||
func (state *state) initACL() error {
|
||||
if !state.ACL.Valid() {
|
||||
@@ -199,7 +241,7 @@ func (state *state) initACL() error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
state.task.SetValue(acl.ContextKey{}, state.ACL)
|
||||
acl.SetCtx(state.task, state.ACL)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -207,6 +249,7 @@ func (state *state) initEntrypoint() error {
|
||||
epCfg := state.Config.Entrypoint
|
||||
matchDomains := state.MatchDomains
|
||||
|
||||
state.entrypoint = entrypoint.NewEntrypoint(state.task, &epCfg)
|
||||
state.entrypoint.SetFindRouteDomains(matchDomains)
|
||||
state.entrypoint.SetNotFoundRules(epCfg.Rules.NotFound)
|
||||
|
||||
@@ -220,6 +263,8 @@ func (state *state) initEntrypoint() error {
|
||||
}
|
||||
}
|
||||
|
||||
entrypointctx.SetCtx(state.task, state.entrypoint)
|
||||
|
||||
errs := gperr.NewBuilder("entrypoint error")
|
||||
errs.Add(state.entrypoint.SetMiddlewares(epCfg.Middlewares))
|
||||
errs.Add(state.entrypoint.SetAccessLogger(state.task, epCfg.AccessLog))
|
||||
@@ -296,6 +341,7 @@ func (state *state) initAutoCert() error {
|
||||
p.PrintCertExpiriesAll()
|
||||
|
||||
state.autocertProvider = p
|
||||
autocertctx.SetCtx(state.task, p)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -309,7 +355,7 @@ func (state *state) initProxmox() error {
|
||||
for _, cfg := range proxmoxCfg {
|
||||
errs.Go(func() error {
|
||||
if err := cfg.Init(state.task.Context()); err != nil {
|
||||
return err.Subject(cfg.URL)
|
||||
return gperr.PrependSubject(err, cfg.URL)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
@@ -333,7 +379,7 @@ func (state *state) loadRouteProviders() error {
|
||||
for _, a := range providers.Agents {
|
||||
agentErrs.Go(func() error {
|
||||
if err := a.Init(state.task.Context()); err != nil {
|
||||
return gperr.PrependSubject(a.String(), err)
|
||||
return gperr.PrependSubject(err, a.String())
|
||||
}
|
||||
agentpool.Add(a)
|
||||
return nil
|
||||
@@ -351,7 +397,7 @@ func (state *state) loadRouteProviders() error {
|
||||
for _, filename := range providers.Files {
|
||||
p, err := route.NewFileProvider(filename)
|
||||
if err != nil {
|
||||
errs.Add(gperr.PrependSubject(filename, err))
|
||||
errs.Add(gperr.PrependSubject(err, filename))
|
||||
return err
|
||||
}
|
||||
registerProvider(p)
|
||||
@@ -376,7 +422,7 @@ func (state *state) loadRouteProviders() error {
|
||||
for _, p := range state.providers.Range {
|
||||
loadErrs.Go(func() error {
|
||||
if err := p.LoadRoutes(); err != nil {
|
||||
return err.Subject(p.String())
|
||||
return gperr.PrependSubject(err, p.String())
|
||||
}
|
||||
resultsMu.Lock()
|
||||
results.Addf("%-"+strconv.Itoa(lenLongestName)+"s %d routes", p.String(), p.NumRoutes())
|
||||
|
||||
Reference in New Issue
Block a user