mirror of
https://github.com/AdguardTeam/AdGuardHome.git
synced 2026-10-12 02:01:26 +00:00
Pull request 2735: ADG-12585-imp-code
Squashed commit of the following:
commit 43ed1e377b74ea65d1bc6e1d811aaba9d8816d67
Author: Maksim Kazantsev <[email protected]>
Date: Thu Jul 30 15:52:37 2026 +0300
home: imp code;
commit 8d524f9c57d203263cb0f5c820e1a7c882d72b82
Merge: 384140ac5 66360530c
Author: Maksim Kazantsev <[email protected]>
Date: Thu Jul 30 15:50:16 2026 +0300
Merge branch 'master' into ADG-12585-imp-code
commit 384140ac57092d4f200114d4098789e1928a62ef
Author: Maksim Kazantsev <[email protected]>
Date: Thu Jul 30 15:37:15 2026 +0300
updater: fix race; filtering: imp tests; aghtest: fix docs;
commit b2194f76d4ddd992efc06ccc86525629b7191450
Author: Maksim Kazantsev <[email protected]>
Date: Thu Jul 30 14:49:35 2026 +0300
updater: imp tests; home: imp todo;
commit 2b88612d6716bede9b7edb5fe42051438507b4bb
Author: Maksim Kazantsev <[email protected]>
Date: Thu Jul 30 13:39:49 2026 +0300
all: imp code;
commit d4d52fb73adba9b8fe9c2602a28c6347309d3a41
Author: Maksim Kazantsev <[email protected]>
Date: Wed Jul 29 15:43:54 2026 +0300
home: imp contracts and fix potential panic;
commit 8212df493935010c94d52e73b9295b134b6b63c8
Author: Maksim Kazantsev <[email protected]>
Date: Wed Jul 29 15:23:37 2026 +0300
home: imp code;
This commit is contained in:
@@ -33,13 +33,12 @@ func HostToIPs(host string) (ipv4, ipv6 netip.Addr) {
|
||||
}
|
||||
|
||||
// StartHTTPServer is a helper that starts the HTTP server, which is configured
|
||||
// to return data on every request, and returns the client and server URL.
|
||||
func StartHTTPServer(tb testing.TB, data []byte) (c *http.Client, u *url.URL) {
|
||||
// to handle HTTP requests with the given handler. It then returns the client
|
||||
// and server URL.
|
||||
func StartHTTPServer(tb testing.TB, handler http.Handler) (c *http.Client, u *url.URL) {
|
||||
tb.Helper()
|
||||
|
||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
|
||||
_, _ = w.Write(data)
|
||||
}))
|
||||
srv := httptest.NewServer(handler)
|
||||
tb.Cleanup(srv.Close)
|
||||
|
||||
u, err := url.Parse(srv.URL)
|
||||
|
||||
@@ -8,8 +8,10 @@ import (
|
||||
"io"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"net/url"
|
||||
"testing"
|
||||
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/agh"
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/aghalg"
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/aghtest"
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/filtering"
|
||||
@@ -39,44 +41,49 @@ type rewriteUpdateJSON struct {
|
||||
Update rewriteJSON `json:"update"`
|
||||
}
|
||||
|
||||
// URLs for the rewrite HTTP API.
|
||||
const (
|
||||
listURL = "/control/rewrite/list"
|
||||
addURL = "/control/rewrite/add"
|
||||
deleteURL = "/control/rewrite/delete"
|
||||
updateURL = "/control/rewrite/update"
|
||||
)
|
||||
|
||||
// Messages for the rewrite HTTP API.
|
||||
const (
|
||||
decodeMsg = "json.Decode: json: cannot unmarshal string into Go value of type"
|
||||
decodeErrorMsg = decodeMsg + " filtering.rewriteEntryJSON\n"
|
||||
decodeUpdateErrorMsg = decodeMsg + " filtering.rewriteUpdateJSON\n"
|
||||
)
|
||||
|
||||
// TODO(m.kazantsev): Improve maintainability.
|
||||
// Test domains.
|
||||
const (
|
||||
exampleDomain = "example.local"
|
||||
exampleAnswer = "example.rewrite"
|
||||
oneDomain = "one.local"
|
||||
oneAnswer = "one.rewrite"
|
||||
disabledDomain = "disabled.local"
|
||||
disabledAnswer = "disabled.rewrite"
|
||||
addDomain = "add.local"
|
||||
addAnswer = "add.rewrite"
|
||||
updDomain = "upd.local"
|
||||
updAnswer = "upd.rewrite"
|
||||
invDomain = "inv.local"
|
||||
invAnswer = "inv.rewrite"
|
||||
invalidDomain = "invalid_domain"
|
||||
)
|
||||
|
||||
// testRewrites is a common rewrites list for tests.
|
||||
var testRewrites = []*rewriteJSON{
|
||||
newRewriteJSON(exampleDomain, exampleAnswer, aghalg.NBTrue),
|
||||
newRewriteJSON(oneDomain, oneAnswer, aghalg.NBTrue),
|
||||
newRewriteJSON(disabledDomain, disabledAnswer, aghalg.NBFalse),
|
||||
}
|
||||
|
||||
func TestDNSFilter_HandleRewriteHTTP(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
const (
|
||||
exampleDomain = "example.local"
|
||||
exampleAnswer = "example.rewrite"
|
||||
oneDomain = "one.local"
|
||||
oneAnswer = "one.rewrite"
|
||||
disabledDomain = "disabled.local"
|
||||
disabledAnswer = "disabled.rewrite"
|
||||
addDomain = "add.local"
|
||||
addAnswer = "add.rewrite"
|
||||
updDomain = "upd.local"
|
||||
updAnswer = "upd.rewrite"
|
||||
invDomain = "inv.local"
|
||||
invAnswer = "inv.rewrite"
|
||||
invalidDomain = "invalid_domain"
|
||||
)
|
||||
|
||||
testRewrites := []*rewriteJSON{
|
||||
newRewriteJSON(exampleDomain, exampleAnswer, aghalg.NBTrue),
|
||||
newRewriteJSON(oneDomain, oneAnswer, aghalg.NBTrue),
|
||||
newRewriteJSON(disabledDomain, disabledAnswer, aghalg.NBFalse),
|
||||
}
|
||||
|
||||
testRewritesJSON, mErr := json.Marshal(testRewrites)
|
||||
rewritesJSON, mErr := json.Marshal(testRewrites)
|
||||
require.NoError(t, mErr)
|
||||
|
||||
testCases := []struct {
|
||||
@@ -85,7 +92,7 @@ func TestDNSFilter_HandleRewriteHTTP(t *testing.T) {
|
||||
url string
|
||||
method string
|
||||
wantList []*rewriteJSON
|
||||
wantBody string
|
||||
wantBody []byte
|
||||
wantConfMod bool
|
||||
wantStatus int
|
||||
}{{
|
||||
@@ -95,7 +102,7 @@ func TestDNSFilter_HandleRewriteHTTP(t *testing.T) {
|
||||
reqData: nil,
|
||||
wantConfMod: false,
|
||||
wantStatus: http.StatusOK,
|
||||
wantBody: string(testRewritesJSON) + "\n",
|
||||
wantBody: append(rewritesJSON, '\n'),
|
||||
wantList: testRewrites,
|
||||
}, {
|
||||
name: "add_enabled_null",
|
||||
@@ -104,7 +111,7 @@ func TestDNSFilter_HandleRewriteHTTP(t *testing.T) {
|
||||
reqData: rewriteJSON{Domain: addDomain, Answer: addAnswer},
|
||||
wantConfMod: true,
|
||||
wantStatus: http.StatusOK,
|
||||
wantBody: "",
|
||||
wantBody: []byte{},
|
||||
wantList: append(
|
||||
testRewrites,
|
||||
newRewriteJSON(addDomain, addAnswer, aghalg.NBTrue),
|
||||
@@ -120,7 +127,7 @@ func TestDNSFilter_HandleRewriteHTTP(t *testing.T) {
|
||||
},
|
||||
wantConfMod: true,
|
||||
wantStatus: http.StatusOK,
|
||||
wantBody: "",
|
||||
wantBody: []byte{},
|
||||
wantList: append(
|
||||
testRewrites,
|
||||
newRewriteJSON(addDomain, addAnswer, aghalg.NBFalse),
|
||||
@@ -136,35 +143,11 @@ func TestDNSFilter_HandleRewriteHTTP(t *testing.T) {
|
||||
},
|
||||
wantConfMod: true,
|
||||
wantStatus: http.StatusOK,
|
||||
wantBody: "",
|
||||
wantBody: []byte{},
|
||||
wantList: append(
|
||||
testRewrites,
|
||||
newRewriteJSON(addDomain, addAnswer, aghalg.NBTrue),
|
||||
),
|
||||
}, {
|
||||
name: "add_error",
|
||||
url: addURL,
|
||||
method: http.MethodPost,
|
||||
reqData: "invalid_json",
|
||||
wantConfMod: false,
|
||||
wantStatus: http.StatusBadRequest,
|
||||
wantBody: decodeErrorMsg,
|
||||
wantList: testRewrites,
|
||||
}, {
|
||||
name: "add_error_invalid_cname",
|
||||
url: addURL,
|
||||
method: http.MethodPost,
|
||||
reqData: rewriteJSON{
|
||||
Domain: addDomain,
|
||||
Answer: invalidDomain,
|
||||
Enabled: aghalg.NBTrue,
|
||||
},
|
||||
wantConfMod: false,
|
||||
wantStatus: http.StatusBadRequest,
|
||||
wantBody: `normalizing: invalid CNAME target "` + invalidDomain + `": bad domain name ` +
|
||||
`"` + invalidDomain + `": bad top-level domain name label "` + invalidDomain +
|
||||
`": bad top-level domain name label rune '_'` + "\n",
|
||||
wantList: testRewrites,
|
||||
}, {
|
||||
name: "delete",
|
||||
url: deleteURL,
|
||||
@@ -172,20 +155,11 @@ func TestDNSFilter_HandleRewriteHTTP(t *testing.T) {
|
||||
reqData: rewriteJSON{Domain: oneDomain, Answer: oneAnswer},
|
||||
wantConfMod: true,
|
||||
wantStatus: http.StatusOK,
|
||||
wantBody: "",
|
||||
wantBody: []byte{},
|
||||
wantList: []*rewriteJSON{
|
||||
newRewriteJSON(exampleDomain, exampleAnswer, aghalg.NBTrue),
|
||||
newRewriteJSON(disabledDomain, disabledAnswer, aghalg.NBFalse),
|
||||
},
|
||||
}, {
|
||||
name: "delete_error",
|
||||
url: deleteURL,
|
||||
method: http.MethodPost,
|
||||
reqData: "invalid_json",
|
||||
wantConfMod: false,
|
||||
wantStatus: http.StatusBadRequest,
|
||||
wantBody: decodeErrorMsg,
|
||||
wantList: testRewrites,
|
||||
}, {
|
||||
name: "update_enabled_null",
|
||||
url: updateURL,
|
||||
@@ -196,7 +170,7 @@ func TestDNSFilter_HandleRewriteHTTP(t *testing.T) {
|
||||
},
|
||||
wantConfMod: true,
|
||||
wantStatus: http.StatusOK,
|
||||
wantBody: "",
|
||||
wantBody: []byte{},
|
||||
wantList: []*rewriteJSON{
|
||||
newRewriteJSON(exampleDomain, exampleAnswer, aghalg.NBTrue),
|
||||
newRewriteJSON(updDomain, updAnswer, aghalg.NBTrue),
|
||||
@@ -216,7 +190,7 @@ func TestDNSFilter_HandleRewriteHTTP(t *testing.T) {
|
||||
},
|
||||
wantConfMod: true,
|
||||
wantStatus: http.StatusOK,
|
||||
wantBody: "",
|
||||
wantBody: []byte{},
|
||||
wantList: []*rewriteJSON{
|
||||
newRewriteJSON(exampleDomain, exampleAnswer, aghalg.NBTrue),
|
||||
newRewriteJSON(updDomain, updAnswer, aghalg.NBFalse),
|
||||
@@ -232,21 +206,86 @@ func TestDNSFilter_HandleRewriteHTTP(t *testing.T) {
|
||||
},
|
||||
wantConfMod: true,
|
||||
wantStatus: http.StatusOK,
|
||||
wantBody: "",
|
||||
wantBody: []byte{},
|
||||
wantList: []*rewriteJSON{
|
||||
newRewriteJSON(exampleDomain, exampleAnswer, aghalg.NBTrue),
|
||||
newRewriteJSON(updDomain, updAnswer, aghalg.NBTrue),
|
||||
newRewriteJSON(disabledDomain, disabledAnswer, aghalg.NBFalse),
|
||||
},
|
||||
}}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
confModCh := make(chan struct{}, 1)
|
||||
pt := testutil.NewPanicT(t)
|
||||
confModifier := &aghtest.ConfigModifier{}
|
||||
confModifier.OnApply = func(_ context.Context) {
|
||||
require.Truef(pt, tc.wantConfMod, "config modified has been fired")
|
||||
testutil.RequireSend(pt, confModCh, struct{}{}, testTimeout)
|
||||
}
|
||||
|
||||
cl, baseURL := setupTestFiltering(t, confModifier)
|
||||
|
||||
respBody, status := executeRequest(t, cl, baseURL, tc.method, tc.url, tc.reqData)
|
||||
|
||||
if tc.wantConfMod {
|
||||
testutil.RequireReceive(t, confModCh, testTimeout)
|
||||
}
|
||||
|
||||
assert.Equal(t, tc.wantStatus, status)
|
||||
assert.Equal(t, tc.wantBody, respBody)
|
||||
assertRewritesList(t, cl, baseURL, tc.wantList)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestDNSFilter_HandleRewriteHTTP_errors(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
pt := testutil.NewPanicT(t)
|
||||
confModifier := &aghtest.ConfigModifier{}
|
||||
confModifier.OnApply = func(_ context.Context) {
|
||||
require.Truef(pt, false, "config modified has been fired")
|
||||
}
|
||||
|
||||
testCases := []struct {
|
||||
reqData any
|
||||
name string
|
||||
url string
|
||||
method string
|
||||
wantBody []byte
|
||||
}{{
|
||||
name: "add_error",
|
||||
url: addURL,
|
||||
method: http.MethodPost,
|
||||
reqData: "invalid_json",
|
||||
wantBody: []byte(decodeErrorMsg),
|
||||
}, {
|
||||
name: "update_error",
|
||||
url: updateURL,
|
||||
method: http.MethodPut,
|
||||
reqData: "invalid_json",
|
||||
wantConfMod: false,
|
||||
wantStatus: http.StatusBadRequest,
|
||||
wantBody: decodeUpdateErrorMsg,
|
||||
wantList: testRewrites,
|
||||
name: "add_error_invalid_cname",
|
||||
url: addURL,
|
||||
method: http.MethodPost,
|
||||
reqData: rewriteJSON{
|
||||
Domain: addDomain,
|
||||
Answer: invalidDomain,
|
||||
Enabled: aghalg.NBTrue,
|
||||
},
|
||||
wantBody: []byte(`normalizing: invalid CNAME target "` + invalidDomain + `": bad domain name ` +
|
||||
`"` + invalidDomain + `": bad top-level domain name label "` + invalidDomain +
|
||||
`": bad top-level domain name label rune '_'` + "\n"),
|
||||
}, {
|
||||
name: "delete_error",
|
||||
url: deleteURL,
|
||||
method: http.MethodPost,
|
||||
reqData: "invalid_json",
|
||||
wantBody: []byte(decodeErrorMsg),
|
||||
}, {
|
||||
name: "update_error",
|
||||
url: updateURL,
|
||||
method: http.MethodPut,
|
||||
reqData: "invalid_json",
|
||||
wantBody: []byte(decodeUpdateErrorMsg),
|
||||
}, {
|
||||
name: "update_error_target",
|
||||
url: updateURL,
|
||||
@@ -255,96 +294,117 @@ func TestDNSFilter_HandleRewriteHTTP(t *testing.T) {
|
||||
Target: rewriteJSON{Domain: invDomain, Answer: invAnswer},
|
||||
Update: rewriteJSON{Domain: updDomain, Answer: updAnswer},
|
||||
},
|
||||
wantConfMod: false,
|
||||
wantStatus: http.StatusBadRequest,
|
||||
wantBody: "target rule not found\n",
|
||||
wantList: testRewrites,
|
||||
wantBody: []byte("target rule not found\n"),
|
||||
}}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
confModCh := make(chan struct{})
|
||||
reqCh := make(chan struct{})
|
||||
cl, base := setupTestFiltering(t, confModifier)
|
||||
respBody, status := executeRequest(t, cl, base, tc.method, tc.url, tc.reqData)
|
||||
|
||||
pt := testutil.NewPanicT(t)
|
||||
handlers := make(map[string]http.Handler)
|
||||
confModifier := &aghtest.ConfigModifier{}
|
||||
confModifier.OnApply = func(_ context.Context) {
|
||||
require.Truef(pt, tc.wantConfMod, "config modified has been fired")
|
||||
testutil.RequireSend(pt, confModCh, struct{}{}, testTimeout)
|
||||
}
|
||||
|
||||
d, err := filtering.New(&filtering.Config{
|
||||
Logger: testLogger,
|
||||
ConfModifier: confModifier,
|
||||
HTTPReg: &aghtest.Registrar{
|
||||
OnRegister: func(_, url string, handler http.HandlerFunc) {
|
||||
handlers[url] = handler
|
||||
},
|
||||
},
|
||||
Rewrites: rewriteEntriesToLegacyRewrites(testRewrites),
|
||||
}, nil)
|
||||
require.NoError(t, err)
|
||||
t.Cleanup(d.Close)
|
||||
|
||||
d.RegisterFilteringHandlers()
|
||||
require.NotEmpty(t, handlers)
|
||||
require.Contains(t, handlers, listURL)
|
||||
require.Contains(t, handlers, tc.url)
|
||||
|
||||
var body io.Reader
|
||||
if tc.reqData != nil {
|
||||
data, rErr := json.Marshal(tc.reqData)
|
||||
require.NoError(t, rErr)
|
||||
|
||||
body = bytes.NewReader(data)
|
||||
}
|
||||
|
||||
r := httptest.NewRequest(tc.method, tc.url, body)
|
||||
w := httptest.NewRecorder()
|
||||
|
||||
go func() {
|
||||
handlers[tc.url].ServeHTTP(w, r)
|
||||
|
||||
testutil.RequireSend(pt, reqCh, struct{}{}, testTimeout)
|
||||
}()
|
||||
|
||||
if tc.wantConfMod {
|
||||
testutil.RequireReceive(t, confModCh, testTimeout)
|
||||
}
|
||||
|
||||
testutil.RequireReceive(t, reqCh, testTimeout)
|
||||
assert.Equal(t, tc.wantStatus, w.Code)
|
||||
|
||||
respBody, err := io.ReadAll(w.Body)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, []byte(tc.wantBody), respBody)
|
||||
|
||||
assertRewritesList(t, handlers[listURL], tc.wantList)
|
||||
assert.Equal(t, http.StatusBadRequest, status)
|
||||
assert.Equal(t, tc.wantBody, respBody)
|
||||
assertRewritesList(t, cl, base, testRewrites)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// assertRewritesList checks if rewrites list equals the list received from the
|
||||
// handler by listURL.
|
||||
func assertRewritesList(tb testing.TB, handler http.Handler, wantList []*rewriteJSON) {
|
||||
func assertRewritesList(tb testing.TB, cl *http.Client, base *url.URL, wantList []*rewriteJSON) {
|
||||
tb.Helper()
|
||||
|
||||
r := httptest.NewRequest(http.MethodGet, listURL, nil)
|
||||
w := httptest.NewRecorder()
|
||||
full := base.ResolveReference(&url.URL{Path: listURL})
|
||||
ctx := testutil.ContextWithTimeout(tb, testTimeout)
|
||||
r, err := http.NewRequestWithContext(ctx, http.MethodGet, full.String(), nil)
|
||||
require.NoError(tb, err)
|
||||
|
||||
handler.ServeHTTP(w, r)
|
||||
require.Equal(tb, http.StatusOK, w.Code)
|
||||
resp, err := cl.Do(r)
|
||||
require.NoError(tb, err)
|
||||
defer func() {
|
||||
require.NoError(tb, resp.Body.Close())
|
||||
}()
|
||||
|
||||
require.Equal(tb, http.StatusOK, resp.StatusCode)
|
||||
|
||||
var actual []*rewriteJSON
|
||||
err := json.NewDecoder(w.Body).Decode(&actual)
|
||||
err = json.NewDecoder(resp.Body).Decode(&actual)
|
||||
require.NoError(tb, err)
|
||||
|
||||
assert.Equal(tb, wantList, actual)
|
||||
}
|
||||
|
||||
// setupTestFiltering creates the test environment with the filtering DNS filter
|
||||
// and returns the HTTP client and server URL for making requests.
|
||||
func setupTestFiltering(
|
||||
tb testing.TB,
|
||||
confModifier agh.ConfigModifier,
|
||||
) (cl *http.Client, base *url.URL) {
|
||||
tb.Helper()
|
||||
|
||||
mux := http.NewServeMux()
|
||||
|
||||
d, err := filtering.New(&filtering.Config{
|
||||
Logger: testLogger,
|
||||
ConfModifier: confModifier,
|
||||
HTTPReg: &aghtest.Registrar{
|
||||
OnRegister: func(_, urlPath string, handler http.HandlerFunc) {
|
||||
mux.Handle(urlPath, handler)
|
||||
},
|
||||
},
|
||||
Rewrites: rewriteEntriesToLegacyRewrites(testRewrites),
|
||||
}, nil)
|
||||
require.NoError(tb, err)
|
||||
tb.Cleanup(d.Close)
|
||||
|
||||
d.RegisterFilteringHandlers()
|
||||
|
||||
cl, base = aghtest.StartHTTPServer(tb, mux)
|
||||
|
||||
return cl, base
|
||||
}
|
||||
|
||||
// executeRequest prepares and executes an HTTP request against the given
|
||||
// client and base URL, returning the response body and status code.
|
||||
func executeRequest(
|
||||
tb testing.TB,
|
||||
client *http.Client,
|
||||
base *url.URL,
|
||||
method string,
|
||||
path string,
|
||||
reqData any,
|
||||
) (respBody []byte, status int) {
|
||||
tb.Helper()
|
||||
|
||||
var body io.Reader
|
||||
if reqData != nil {
|
||||
data, rErr := json.Marshal(reqData)
|
||||
require.NoError(tb, rErr)
|
||||
|
||||
body = bytes.NewReader(data)
|
||||
}
|
||||
|
||||
fullURL := base.ResolveReference(&url.URL{Path: path})
|
||||
ctx := testutil.ContextWithTimeout(tb, testTimeout)
|
||||
r, err := http.NewRequestWithContext(ctx, method, fullURL.String(), body)
|
||||
require.NoError(tb, err)
|
||||
|
||||
resp, err := client.Do(r)
|
||||
require.NoError(tb, err)
|
||||
defer func() {
|
||||
require.NoError(tb, resp.Body.Close())
|
||||
}()
|
||||
|
||||
respBody, err = io.ReadAll(resp.Body)
|
||||
require.NoError(tb, err)
|
||||
|
||||
status = resp.StatusCode
|
||||
|
||||
return respBody, status
|
||||
}
|
||||
|
||||
// rewriteEntriesToLegacyRewrites gets legacy rewrites from json entries.
|
||||
func rewriteEntriesToLegacyRewrites(entries []*rewriteJSON) (rw []*filtering.LegacyRewrite) {
|
||||
for _, entry := range entries {
|
||||
|
||||
@@ -179,6 +179,10 @@ func (web *webAPI) handleStatus(w http.ResponseWriter, r *http.Request) {
|
||||
func (web *webAPI) registerControlHandlers() {
|
||||
mux := web.conf.mux
|
||||
|
||||
web.httpReg.Register(http.MethodGet, "/control/tls/status", web.handleTLSStatus)
|
||||
web.httpReg.Register(http.MethodPost, "/control/tls/configure", web.handleTLSConfigure)
|
||||
web.httpReg.Register(http.MethodPost, "/control/tls/validate", web.handleTLSValidate)
|
||||
|
||||
mux.Handle(
|
||||
"/control/version.json",
|
||||
web.postInstallHandler(http.HandlerFunc(web.handleVersionJSON)),
|
||||
|
||||
@@ -570,7 +570,6 @@ func (web *webAPI) finalizeInstall(
|
||||
web.conf.BindAddr = netip.AddrPortFrom(req.Web.IP, req.Web.Port)
|
||||
|
||||
web.registerControlHandlers()
|
||||
web.registerTLSHandlers()
|
||||
|
||||
aghhttp.OK(ctx, l, w)
|
||||
|
||||
|
||||
+12
-10
@@ -109,7 +109,6 @@ func initDNS(
|
||||
|
||||
err = initDNSServer(
|
||||
ctx,
|
||||
baseLogger,
|
||||
dnsforward.DNSCreateParams{
|
||||
Logger: baseLogger,
|
||||
DNSFilter: globalContext.filters,
|
||||
@@ -135,26 +134,28 @@ func initDNS(
|
||||
return nil
|
||||
}
|
||||
|
||||
// initDNSServer initializes the [context.dnsServer]. tlsMgr and l must not be
|
||||
// nil. Other arguments, including params fields, are allowed to be nil if you
|
||||
// want to use only the internal proxy. It also must not be called unless
|
||||
// [config] and [globalContext] are initialized.
|
||||
// initDNSServer initializes the [context.dnsServer]. To only use the internal
|
||||
// proxy, none of the arguments are required, but params must be valid and
|
||||
// tlsMgr must not be nil. In other cases all the arguments also must not be
|
||||
// nil. It also must not be called unless [config] and [globalContext] are
|
||||
// initialized.
|
||||
func initDNSServer(
|
||||
ctx context.Context,
|
||||
l *slog.Logger,
|
||||
params dnsforward.DNSCreateParams,
|
||||
httpReg aghhttp.Registrar,
|
||||
tlsMgr *tlsManager,
|
||||
confModifier agh.ConfigModifier,
|
||||
) (err error) {
|
||||
globalContext.dnsServer, err = dnsforward.NewServer(params)
|
||||
// TODO(m.kazantsev): Investigate if the server should be closed in case of
|
||||
// error and consider removing this defer.
|
||||
defer func() {
|
||||
if err != nil {
|
||||
closeDNSServer(ctx)
|
||||
}
|
||||
}()
|
||||
if err != nil {
|
||||
return fmt.Errorf("dnsforward.NewServer: %w", err)
|
||||
return fmt.Errorf("creating new dns server: %w", err)
|
||||
}
|
||||
|
||||
globalContext.clients.clientChecker = globalContext.dnsServer
|
||||
@@ -164,26 +165,27 @@ func initDNSServer(
|
||||
config.Clients.Sources,
|
||||
tlsMgr.extendedTLSConfig(),
|
||||
config.HTTPConfig.DoH,
|
||||
tlsMgr,
|
||||
params.TLSConfigProvider,
|
||||
httpReg,
|
||||
globalContext.clients.storage,
|
||||
confModifier,
|
||||
)
|
||||
if err != nil {
|
||||
return fmt.Errorf("newServerConfig: %w", err)
|
||||
return fmt.Errorf("creating new dns server config: %w", err)
|
||||
}
|
||||
|
||||
// Try to prepare the server with disabled private RDNS resolution if it
|
||||
// failed to prepare as is. See TODO on [dnsforward.PrivateRDNSError].
|
||||
err = globalContext.dnsServer.Prepare(ctx, dnsConf)
|
||||
if _, ok := errors.AsType[*dnsforward.PrivateRDNSError](err); ok {
|
||||
l := params.Logger
|
||||
l.WarnContext(ctx, "private rdns resolution failed; disabling", slogutil.KeyError, err)
|
||||
|
||||
dnsConf.UsePrivateRDNS = false
|
||||
err = globalContext.dnsServer.Prepare(ctx, dnsConf)
|
||||
}
|
||||
if err != nil {
|
||||
return fmt.Errorf("dnsServer.Prepare: %w", err)
|
||||
return fmt.Errorf("preparing dns server: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
+10
-6
@@ -1408,12 +1408,16 @@ func cmdlineUpdate(
|
||||
//
|
||||
// TODO(e.burkov): We could probably initialize the internal resolver
|
||||
// separately.
|
||||
params := dnsforward.DNSCreateParams{
|
||||
Logger: l,
|
||||
TLSConfigProvider: tlsMgr,
|
||||
}
|
||||
|
||||
err := initDNSServer(ctx, l, params, nil, tlsMgr, agh.EmptyConfigModifier{})
|
||||
err := initDNSServer(
|
||||
ctx,
|
||||
dnsforward.DNSCreateParams{
|
||||
Logger: l,
|
||||
TLSConfigProvider: tlsMgr,
|
||||
},
|
||||
nil,
|
||||
tlsMgr,
|
||||
agh.EmptyConfigModifier{},
|
||||
)
|
||||
fatalOnError(err)
|
||||
|
||||
l.InfoContext(ctx, "performing update via cli")
|
||||
|
||||
@@ -291,7 +291,6 @@ func newWebAPI(ctx context.Context, conf *webAPIConfig) (w *webAPI) {
|
||||
mux.Handle("/install.html", w.preInstallHandler(clientFS))
|
||||
w.registerInstallHandlers()
|
||||
} else {
|
||||
w.registerTLSHandlers()
|
||||
w.registerControlHandlers()
|
||||
}
|
||||
|
||||
@@ -558,15 +557,6 @@ func startPprof(baseLogger *slog.Logger, port uint16) {
|
||||
}()
|
||||
}
|
||||
|
||||
// registerTLSHandlers registers HTTP handlers for TLS configuration.
|
||||
//
|
||||
// TODO(m.kazantsev): Consider uniting with registerControlHandlers.
|
||||
func (web *webAPI) registerTLSHandlers() {
|
||||
web.httpReg.Register(http.MethodGet, "/control/tls/status", web.handleTLSStatus)
|
||||
web.httpReg.Register(http.MethodPost, "/control/tls/configure", web.handleTLSConfigure)
|
||||
web.httpReg.Register(http.MethodPost, "/control/tls/validate", web.handleTLSValidate)
|
||||
}
|
||||
|
||||
// handleTLSStatus is the handler for the GET /control/tls/status HTTP API.
|
||||
func (web *webAPI) handleTLSStatus(w http.ResponseWriter, r *http.Request) {
|
||||
tlsConf := web.tlsManager.extendedTLSConfig()
|
||||
|
||||
@@ -111,7 +111,14 @@ func TestUpdater_VersionInfo_others(t *testing.T) {
|
||||
"download_linux_mips_softfloat": "https://static.adtidy.org/adguardhome/beta/AdGuardHome_linux_mips_softfloat.tar.gz"
|
||||
}`
|
||||
|
||||
fakeClient, fakeURL := aghtest.StartHTTPServer(t, []byte(jsonData))
|
||||
handler := http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
|
||||
pt := testutil.NewPanicT(t)
|
||||
|
||||
_, err := w.Write([]byte(jsonData))
|
||||
require.NoError(pt, err)
|
||||
})
|
||||
|
||||
fakeClient, fakeURL := aghtest.StartHTTPServer(t, handler)
|
||||
fakeURL = fakeURL.JoinPath("adguardhome", version.ChannelBeta, "version.json")
|
||||
|
||||
testCases := []struct {
|
||||
|
||||
@@ -2,6 +2,7 @@ package updater
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"path/filepath"
|
||||
@@ -55,7 +56,14 @@ func TestUpdater_internal(t *testing.T) {
|
||||
pkgData, err := os.ReadFile(filepath.Join("testdata", tc.archiveName))
|
||||
require.NoError(t, err)
|
||||
|
||||
fakeClient, fakeURL := aghtest.StartHTTPServer(t, pkgData)
|
||||
handler := http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
|
||||
pt := testutil.NewPanicT(t)
|
||||
|
||||
_, werr := w.Write(pkgData)
|
||||
require.NoError(pt, werr)
|
||||
})
|
||||
|
||||
fakeClient, fakeURL := aghtest.StartHTTPServer(t, handler)
|
||||
fakeURL = fakeURL.JoinPath(tc.archiveName)
|
||||
|
||||
u := NewUpdater(&Config{
|
||||
|
||||
Reference in New Issue
Block a user