next: upd more
This commit is contained in:
parent
05eec75222
commit
0c64e6cfc6
3
go.mod
3
go.mod
|
@ -4,8 +4,7 @@ go 1.23.3
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/AdguardTeam/dnsproxy v0.73.3
|
github.com/AdguardTeam/dnsproxy v0.73.3
|
||||||
// TODO(a.garipov): !! Update to tag!
|
github.com/AdguardTeam/golibs v0.30.3
|
||||||
github.com/AdguardTeam/golibs v0.30.3-0.20241108140605-ec84c9f86663
|
|
||||||
github.com/AdguardTeam/urlfilter v0.20.0
|
github.com/AdguardTeam/urlfilter v0.20.0
|
||||||
github.com/NYTimes/gziphandler v1.1.1
|
github.com/NYTimes/gziphandler v1.1.1
|
||||||
github.com/ameshkov/dnscrypt/v2 v2.3.0
|
github.com/ameshkov/dnscrypt/v2 v2.3.0
|
||||||
|
|
4
go.sum
4
go.sum
|
@ -1,7 +1,7 @@
|
||||||
github.com/AdguardTeam/dnsproxy v0.73.3 h1:aacr6Wu0ed94DDD+gSB6EwF8nvyq0+DAc7oFOgtgUpA=
|
github.com/AdguardTeam/dnsproxy v0.73.3 h1:aacr6Wu0ed94DDD+gSB6EwF8nvyq0+DAc7oFOgtgUpA=
|
||||||
github.com/AdguardTeam/dnsproxy v0.73.3/go.mod h1:18ssqhDgOCiVIwYmmVuXVM05wSwrzkO2yjKhVRWJX/g=
|
github.com/AdguardTeam/dnsproxy v0.73.3/go.mod h1:18ssqhDgOCiVIwYmmVuXVM05wSwrzkO2yjKhVRWJX/g=
|
||||||
github.com/AdguardTeam/golibs v0.30.3-0.20241108140605-ec84c9f86663 h1:2uhyDq3f4BV48TjXDS0itBU2iwyuWKk1HGLujIJmbd0=
|
github.com/AdguardTeam/golibs v0.30.3 h1:pRxLjMCJ1cZccjZWMMuKxzQQGEpFbmtyj4Tg7nk5rY0=
|
||||||
github.com/AdguardTeam/golibs v0.30.3-0.20241108140605-ec84c9f86663/go.mod h1:Ir9dlHfb8nRQsG3Qgo1zoGL+k1qMbcBtb8tcnsvzdAE=
|
github.com/AdguardTeam/golibs v0.30.3/go.mod h1:Ir9dlHfb8nRQsG3Qgo1zoGL+k1qMbcBtb8tcnsvzdAE=
|
||||||
github.com/AdguardTeam/urlfilter v0.20.0 h1:X32qiuVCVd8WDYCEsbdZKfXMzwdVqrdulamtUi4rmzs=
|
github.com/AdguardTeam/urlfilter v0.20.0 h1:X32qiuVCVd8WDYCEsbdZKfXMzwdVqrdulamtUi4rmzs=
|
||||||
github.com/AdguardTeam/urlfilter v0.20.0/go.mod h1:gjrywLTxfJh6JOkwi9SU+frhP7kVVEZ5exFGkR99qpk=
|
github.com/AdguardTeam/urlfilter v0.20.0/go.mod h1:gjrywLTxfJh6JOkwi9SU+frhP7kVVEZ5exFGkR99qpk=
|
||||||
github.com/NYTimes/gziphandler v1.1.1 h1:ZUDjpQae29j0ryrS0u/B8HZfJBtBQHjqw2rQ2cqUQ3I=
|
github.com/NYTimes/gziphandler v1.1.1 h1:ZUDjpQae29j0ryrS0u/B8HZfJBtBQHjqw2rQ2cqUQ3I=
|
||||||
|
|
|
@ -80,9 +80,8 @@ func (h *signalHandler) writePID(ctx context.Context) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use 8, since most PIDs will fit.
|
pid := os.Getpid()
|
||||||
data := make([]byte, 0, 8)
|
data := strconv.AppendInt(nil, int64(pid), 10)
|
||||||
data = strconv.AppendInt(data, int64(os.Getpid()), 10)
|
|
||||||
data = append(data, '\n')
|
data = append(data, '\n')
|
||||||
|
|
||||||
err := aghos.WriteFile(h.pidFile, data, 0o644)
|
err := aghos.WriteFile(h.pidFile, data, 0o644)
|
||||||
|
@ -92,7 +91,7 @@ func (h *signalHandler) writePID(ctx context.Context) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
h.logger.DebugContext(ctx, "wrote pid", "file", h.pidFile)
|
h.logger.DebugContext(ctx, "wrote pid", "file", h.pidFile, "pid", pid)
|
||||||
}
|
}
|
||||||
|
|
||||||
// reconfigure rereads the configuration file and updates and restarts services.
|
// reconfigure rereads the configuration file and updates and restarts services.
|
||||||
|
|
|
@ -21,7 +21,7 @@ type config struct {
|
||||||
// type check
|
// type check
|
||||||
var _ validator = (*config)(nil)
|
var _ validator = (*config)(nil)
|
||||||
|
|
||||||
// validate returns an error if the configuration structure is invalid.
|
// validate implements the [validator] interface for *config.
|
||||||
func (c *config) validate() (err error) {
|
func (c *config) validate() (err error) {
|
||||||
if c == nil {
|
if c == nil {
|
||||||
return errors.ErrNoValue
|
return errors.ErrNoValue
|
||||||
|
@ -65,7 +65,7 @@ type dnsConfig struct {
|
||||||
// type check
|
// type check
|
||||||
var _ validator = (*dnsConfig)(nil)
|
var _ validator = (*dnsConfig)(nil)
|
||||||
|
|
||||||
// validate returns an error if the DNS configuration structure is invalid.
|
// validate implements the [validator] interface for *dnsConfig.
|
||||||
//
|
//
|
||||||
// TODO(a.garipov): Add more validations.
|
// TODO(a.garipov): Add more validations.
|
||||||
func (c *dnsConfig) validate() (err error) {
|
func (c *dnsConfig) validate() (err error) {
|
||||||
|
@ -74,7 +74,7 @@ func (c *dnsConfig) validate() (err error) {
|
||||||
case c == nil:
|
case c == nil:
|
||||||
return errors.ErrNoValue
|
return errors.ErrNoValue
|
||||||
case c.UpstreamTimeout.Duration <= 0:
|
case c.UpstreamTimeout.Duration <= 0:
|
||||||
return newMustBePositiveError("upstream_timeout", c.UpstreamTimeout)
|
return newErrNotPositive("upstream_timeout", c.UpstreamTimeout)
|
||||||
default:
|
default:
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -94,7 +94,7 @@ type httpConfig struct {
|
||||||
// type check
|
// type check
|
||||||
var _ validator = (*httpConfig)(nil)
|
var _ validator = (*httpConfig)(nil)
|
||||||
|
|
||||||
// validate returns an error if the HTTP configuration structure is invalid.
|
// validate implements the [validator] interface for *httpConfig.
|
||||||
//
|
//
|
||||||
// TODO(a.garipov): Add more validations.
|
// TODO(a.garipov): Add more validations.
|
||||||
func (c *httpConfig) validate() (err error) {
|
func (c *httpConfig) validate() (err error) {
|
||||||
|
@ -102,7 +102,7 @@ func (c *httpConfig) validate() (err error) {
|
||||||
case c == nil:
|
case c == nil:
|
||||||
return errors.ErrNoValue
|
return errors.ErrNoValue
|
||||||
case c.Timeout.Duration <= 0:
|
case c.Timeout.Duration <= 0:
|
||||||
return newMustBePositiveError("timeout", c.Timeout)
|
return newErrNotPositive("timeout", c.Timeout)
|
||||||
default:
|
default:
|
||||||
return c.Pprof.validate()
|
return c.Pprof.validate()
|
||||||
}
|
}
|
||||||
|
@ -114,7 +114,10 @@ type httpPprofConfig struct {
|
||||||
Enabled bool `yaml:"enabled"`
|
Enabled bool `yaml:"enabled"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// validate returns an error if the pprof configuration structure is invalid.
|
// type check
|
||||||
|
var _ validator = (*httpPprofConfig)(nil)
|
||||||
|
|
||||||
|
// validate implements the [validator] interface for *httpPprofConfig.
|
||||||
func (c *httpPprofConfig) validate() (err error) {
|
func (c *httpPprofConfig) validate() (err error) {
|
||||||
if c == nil {
|
if c == nil {
|
||||||
return errors.ErrNoValue
|
return errors.ErrNoValue
|
||||||
|
@ -132,7 +135,7 @@ type logConfig struct {
|
||||||
// type check
|
// type check
|
||||||
var _ validator = (*logConfig)(nil)
|
var _ validator = (*logConfig)(nil)
|
||||||
|
|
||||||
// validate returns an error if the HTTP configuration structure is invalid.
|
// validate implements the [validator] interface for *logConfig.
|
||||||
//
|
//
|
||||||
// TODO(a.garipov): Add more validations.
|
// TODO(a.garipov): Add more validations.
|
||||||
func (c *logConfig) validate() (err error) {
|
func (c *logConfig) validate() (err error) {
|
||||||
|
|
|
@ -21,15 +21,11 @@ type numberOrDuration interface {
|
||||||
constraints.Integer | timeutil.Duration
|
constraints.Integer | timeutil.Duration
|
||||||
}
|
}
|
||||||
|
|
||||||
// newMustBePositiveError returns an error about the value that must be positive
|
// newErrNotPositive returns an error about the value that must be positive but
|
||||||
// but isn't. prop is the name of the property to mention in the error message.
|
// isn't. prop is the name of the property to mention in the error message.
|
||||||
//
|
//
|
||||||
// TODO(a.garipov): Consider moving such helpers to golibs and use in AdGuardDNS
|
// TODO(a.garipov): Consider moving such helpers to golibs and use in AdGuardDNS
|
||||||
// as well.
|
// as well.
|
||||||
func newMustBePositiveError[T numberOrDuration](prop string, v T) (err error) {
|
func newErrNotPositive[T numberOrDuration](prop string, v T) (err error) {
|
||||||
if s, ok := any(v).(fmt.Stringer); ok {
|
return fmt.Errorf("%s: %w, got %v", prop, errors.ErrNotPositive, v)
|
||||||
return fmt.Errorf("%s: %w, got %s", prop, errors.ErrNotPositive, s)
|
|
||||||
}
|
|
||||||
|
|
||||||
return fmt.Errorf("%s: %w, got %d", prop, errors.ErrNotPositive, v)
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,11 @@
|
||||||
package websvc
|
package websvc
|
||||||
|
|
||||||
import "net/http"
|
import (
|
||||||
|
"log/slog"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/AdguardTeam/golibs/netutil/httputil"
|
||||||
|
)
|
||||||
|
|
||||||
// Path pattern constants.
|
// Path pattern constants.
|
||||||
const (
|
const (
|
||||||
|
@ -21,3 +26,48 @@ const (
|
||||||
routePatternPatchV1SettingsDNS = http.MethodPatch + " " + PathPatternV1SettingsDNS
|
routePatternPatchV1SettingsDNS = http.MethodPatch + " " + PathPatternV1SettingsDNS
|
||||||
routePatternPatchV1SettingsHTTP = http.MethodPatch + " " + PathPatternV1SettingsHTTP
|
routePatternPatchV1SettingsHTTP = http.MethodPatch + " " + PathPatternV1SettingsHTTP
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// route registers all necessary handlers in mux.
|
||||||
|
func (svc *Service) route(mux *http.ServeMux) {
|
||||||
|
routes := []struct {
|
||||||
|
handler http.HandlerFunc
|
||||||
|
pattern string
|
||||||
|
isJSON bool
|
||||||
|
}{{
|
||||||
|
handler: svc.handleGetHealthCheck,
|
||||||
|
pattern: routePatternHealthCheck,
|
||||||
|
isJSON: false,
|
||||||
|
}, {
|
||||||
|
handler: http.FileServer(http.FS(svc.frontend)).ServeHTTP,
|
||||||
|
pattern: routePatternFrontend,
|
||||||
|
isJSON: false,
|
||||||
|
}, {
|
||||||
|
handler: svc.handleGetSettingsAll,
|
||||||
|
pattern: routePatternGetV1SettingsAll,
|
||||||
|
isJSON: true,
|
||||||
|
}, {
|
||||||
|
handler: svc.handlePatchSettingsDNS,
|
||||||
|
pattern: routePatternPatchV1SettingsDNS,
|
||||||
|
isJSON: true,
|
||||||
|
}, {
|
||||||
|
handler: svc.handlePatchSettingsHTTP,
|
||||||
|
pattern: routePatternPatchV1SettingsHTTP,
|
||||||
|
isJSON: true,
|
||||||
|
}, {
|
||||||
|
handler: svc.handleGetV1SystemInfo,
|
||||||
|
pattern: routePatternGetV1SystemInfo,
|
||||||
|
isJSON: true,
|
||||||
|
}}
|
||||||
|
|
||||||
|
logMw := httputil.NewLogMiddleware(svc.logger, slog.LevelDebug)
|
||||||
|
for _, r := range routes {
|
||||||
|
var hdlr http.Handler
|
||||||
|
if r.isJSON {
|
||||||
|
hdlr = jsonMw(r.handler)
|
||||||
|
} else {
|
||||||
|
hdlr = r.handler
|
||||||
|
}
|
||||||
|
|
||||||
|
mux.Handle(r.pattern, logMw.Wrap(hdlr))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -83,7 +83,8 @@ func New(c *Config) (svc *Service, err error) {
|
||||||
forceHTTPS: c.ForceHTTPS,
|
forceHTTPS: c.ForceHTTPS,
|
||||||
}
|
}
|
||||||
|
|
||||||
mux := newMux(svc)
|
mux := http.NewServeMux()
|
||||||
|
svc.route(mux)
|
||||||
|
|
||||||
if svc.overrideAddr != (netip.AddrPort{}) {
|
if svc.overrideAddr != (netip.AddrPort{}) {
|
||||||
svc.servers = []*server{newServer(svc.logger, svc.overrideAddr, nil, mux, c.Timeout)}
|
svc.servers = []*server{newServer(svc.logger, svc.overrideAddr, nil, mux, c.Timeout)}
|
||||||
|
@ -160,56 +161,6 @@ func newServer(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// newMux returns a new HTTP request multiplexer for the AdGuard Home web
|
|
||||||
// service.
|
|
||||||
func newMux(svc *Service) (mux *http.ServeMux) {
|
|
||||||
mux = http.NewServeMux()
|
|
||||||
|
|
||||||
routes := []struct {
|
|
||||||
handler http.HandlerFunc
|
|
||||||
pattern string
|
|
||||||
isJSON bool
|
|
||||||
}{{
|
|
||||||
handler: svc.handleGetHealthCheck,
|
|
||||||
pattern: routePatternHealthCheck,
|
|
||||||
isJSON: false,
|
|
||||||
}, {
|
|
||||||
handler: http.FileServer(http.FS(svc.frontend)).ServeHTTP,
|
|
||||||
pattern: routePatternFrontend,
|
|
||||||
isJSON: false,
|
|
||||||
}, {
|
|
||||||
handler: svc.handleGetSettingsAll,
|
|
||||||
pattern: routePatternGetV1SettingsAll,
|
|
||||||
isJSON: true,
|
|
||||||
}, {
|
|
||||||
handler: svc.handlePatchSettingsDNS,
|
|
||||||
pattern: routePatternPatchV1SettingsDNS,
|
|
||||||
isJSON: true,
|
|
||||||
}, {
|
|
||||||
handler: svc.handlePatchSettingsHTTP,
|
|
||||||
pattern: routePatternPatchV1SettingsHTTP,
|
|
||||||
isJSON: true,
|
|
||||||
}, {
|
|
||||||
handler: svc.handleGetV1SystemInfo,
|
|
||||||
pattern: routePatternGetV1SystemInfo,
|
|
||||||
isJSON: true,
|
|
||||||
}}
|
|
||||||
|
|
||||||
logMw := httputil.NewLogMiddleware(svc.logger, slog.LevelDebug)
|
|
||||||
for _, r := range routes {
|
|
||||||
var hdlr http.Handler
|
|
||||||
if r.isJSON {
|
|
||||||
hdlr = jsonMw(r.handler)
|
|
||||||
} else {
|
|
||||||
hdlr = r.handler
|
|
||||||
}
|
|
||||||
|
|
||||||
mux.Handle(r.pattern, logMw.Wrap(hdlr))
|
|
||||||
}
|
|
||||||
|
|
||||||
return mux
|
|
||||||
}
|
|
||||||
|
|
||||||
// addrs returns all addresses on which this server serves the HTTP API. addrs
|
// addrs returns all addresses on which this server serves the HTTP API. addrs
|
||||||
// must not be called simultaneously with Start. If svc was initialized with
|
// must not be called simultaneously with Start. If svc was initialized with
|
||||||
// ":0" addresses, addrs will not return the actual bound ports until Start is
|
// ":0" addresses, addrs will not return the actual bound ports until Start is
|
||||||
|
@ -249,7 +200,7 @@ var _ agh.ServiceWithConfig[*Config] = (*Service)(nil)
|
||||||
// After Start exits, all HTTP servers have tried to start, possibly failing and
|
// After Start exits, all HTTP servers have tried to start, possibly failing and
|
||||||
// writing error messages to the log.
|
// writing error messages to the log.
|
||||||
//
|
//
|
||||||
// TODO(a.garipov): Use the context.
|
// TODO(a.garipov): Use the context for cancelation as well.
|
||||||
func (svc *Service) Start(ctx context.Context) (err error) {
|
func (svc *Service) Start(ctx context.Context) (err error) {
|
||||||
if svc == nil {
|
if svc == nil {
|
||||||
return nil
|
return nil
|
||||||
|
|
Loading…
Reference in New Issue