mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-09-14 02:12:11 +03:00
* 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.
49 lines
1.4 KiB
Go
49 lines
1.4 KiB
Go
package sub
|
|
|
|
import (
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
)
|
|
|
|
// The panel setting must survive the controller wiring, not just the service
|
|
// API: sub.go passes it as a controller option.
|
|
func TestJsonEndpointServesPanelDnsServers(t *testing.T) {
|
|
seedSubDB(t)
|
|
seedSubInbound(t, "s1", "tcpin", 4910, 1, dnsTestStream)
|
|
gin.SetMode(gin.TestMode)
|
|
|
|
router := gin.New()
|
|
NewSUBController(
|
|
router.Group("/"),
|
|
WithSUBJsonEnabled(true),
|
|
WithSUBJsonAlwaysArray(true),
|
|
WithSUBJsonDns(`["https://dns.google/dns-query", "tls://1.1.1.1"]`),
|
|
)
|
|
|
|
req := httptest.NewRequest(http.MethodGet, "http://sub.example.com/json/s1", nil)
|
|
resp := httptest.NewRecorder()
|
|
router.ServeHTTP(resp, req)
|
|
|
|
if resp.Code != http.StatusOK {
|
|
t.Fatalf("status = %d, want 200; body=%s", resp.Code, resp.Body.String())
|
|
}
|
|
docs := parseSubJsonDocs(t, resp.Body.String())
|
|
if len(docs) != 1 {
|
|
t.Fatalf("docs = %d, want 1", len(docs))
|
|
}
|
|
servers, _ := docDnsBlock(t, docs[0])["servers"].([]any)
|
|
if len(servers) != 2 || servers[0] != "https://dns.google/dns-query" || servers[1] != "tls://1.1.1.1" {
|
|
t.Fatalf("dns servers = %v", servers)
|
|
}
|
|
if _, hasTemplate := docDnsBlock(t, docs[0])["tag"]; hasTemplate {
|
|
t.Fatalf("template dns keys leaked: %v", docDnsBlock(t, docs[0]))
|
|
}
|
|
if body := resp.Body.String(); strings.Contains(body, "8.8.8.8") {
|
|
t.Fatalf("template resolver survived the override:\n%s", body)
|
|
}
|
|
}
|