mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-09-16 23:27:14 +00:00
2730e4d071
* feat(sub): let the panel set the JSON subscription DNS servers A baked routing profile (#6402) carries only the DNS its preset defines, so an operator who wants their own resolvers has to override the whole profile or patch the subscription behind a proxy. Add the subJsonDns setting: either a full xray dns block or a bare array of servers. It wins over the profile's DNS while leaving the profile's routing rules intact, and reaches per-inbound, balancer and info-node documents alike. The value is validated with xray's own schema (internal/xray/dnsconf): a block the client could not load is rejected when the settings are saved and ignored with a warning at request time, instead of being baked into every document. Both the sub server and the settings API share that validator, so a stored value can never be silently dropped. xray's Build() is deliberately not used for validation: it resolves geosite tokens from the geodata files and would reject valid configs whenever those are absent from the panel's working directory. * style(dnsconf): drop the ineffectual initial map assignment golangci's ineffassign flagged the zero-value map whose value both paths overwrite: the object branch now assigns the decoded map directly. * docs(sub): scope the DNS setting to the documents it rewrites The Routing header mirrored to Happ/INCY keeps the routing profile's own resolvers, so the setting description and the header-source comment now say so instead of claiming the profile's DNS is replaced everywhere. Also trims two comments in the new dnsconf package to the repo's two-line cap.
65 lines
2.2 KiB
Go
65 lines
2.2 KiB
Go
package service
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/mhsanaei/3x-ui/v3/internal/web/entity"
|
|
)
|
|
|
|
func TestValidateSubJsonDnsSetting(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
value string
|
|
want string
|
|
wantError string
|
|
}{
|
|
{name: "blank is trimmed", value: " ", want: ""},
|
|
{name: "object passes through", value: ` {"servers": ["1.1.1.1"]} `, want: `{"servers": ["1.1.1.1"]}`},
|
|
{name: "array passes through", value: `["1.1.1.1", "tls://1.0.0.1"]`, want: `["1.1.1.1", "tls://1.0.0.1"]`},
|
|
{name: "object with hosts and strategy", value: `{"hosts":{"a":"b"},"queryStrategy":"UseIPv4","servers":["1.1.1.1"]}`, want: `{"hosts":{"a":"b"},"queryStrategy":"UseIPv4","servers":["1.1.1.1"]}`},
|
|
{name: "malformed JSON is rejected", value: `{"servers": [`, wantError: "JSON subscription DNS is invalid"},
|
|
{name: "broken field type is rejected", value: `{"servers": ["1.1.1.1"], "hosts": 5}`, wantError: "JSON subscription DNS is invalid"},
|
|
{name: "empty server list is rejected", value: `[]`, wantError: "JSON subscription DNS is invalid"},
|
|
{name: "server without address is rejected", value: `[{"skipFallback": true}]`, wantError: "JSON subscription DNS is invalid"},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
settings := &entity.AllSetting{SubJsonDns: tt.value}
|
|
err := validateSubJsonDnsSetting(settings)
|
|
if tt.wantError != "" {
|
|
if err == nil || !strings.Contains(err.Error(), tt.wantError) {
|
|
t.Fatalf("err=%v, want %q", err, tt.wantError)
|
|
}
|
|
return
|
|
}
|
|
if err != nil || settings.SubJsonDns != tt.want {
|
|
t.Fatalf("value=%q err=%v", settings.SubJsonDns, err)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestSubJsonDnsSettingDefaultsAndPersists(t *testing.T) {
|
|
setupSettingTestDB(t)
|
|
s := &SettingService{}
|
|
|
|
settings, err := s.GetAllSetting()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if settings.SubJsonDns != "" {
|
|
t.Fatalf("expected empty default, got %q", settings.SubJsonDns)
|
|
}
|
|
|
|
settings.SubJsonDns = `["https://dns.google/dns-query"]`
|
|
if err := s.UpdateAllSetting(settings, SecretClears{}); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
got, err := s.GetSubJsonDns()
|
|
if err != nil || got != `["https://dns.google/dns-query"]` {
|
|
t.Fatalf("expected the stored DNS list, got %q, err %v", got, err)
|
|
}
|
|
}
|