From d90b715ca7ae421c50d14094fdddf6a32cec1480 Mon Sep 17 00:00:00 2001 From: Eljees <3.14hell@gmail.com> Date: Wed, 28 Oct 2026 14:21:03 +0300 Subject: [PATCH 1/2] Query every balancer tag passed to api bi --- main/commands/all/api/balancer_info.go | 21 ++++---- main/commands/all/api/balancer_info_test.go | 58 +++++++++++++++++++++ 2 files changed, 69 insertions(+), 10 deletions(-) create mode 100644 main/commands/all/api/balancer_info_test.go diff --git a/main/commands/all/api/balancer_info.go b/main/commands/all/api/balancer_info.go index cabc66d98380..97ab9f7ba772 100644 --- a/main/commands/all/api/balancer_info.go +++ b/main/commands/all/api/balancer_info.go @@ -47,18 +47,19 @@ func executeBalancerInfo(cmd *base.Command, args []string) { conn, ctx, close := dialAPIServer() defer close() client := routerService.NewRoutingServiceClient(conn) - r := &routerService.GetBalancerInfoRequest{Tag: unnamedArgs[0]} - resp, err := client.GetBalancerInfo(ctx, r) - if err != nil { - base.Fatalf("failed to get health information: %s", err) - } + for _, tag := range unnamedArgs { + r := &routerService.GetBalancerInfoRequest{Tag: tag} + resp, err := client.GetBalancerInfo(ctx, r) + if err != nil { + base.Fatalf("failed to get health information: %s", err) + } - if apiJSON { - showJSONResponse(resp) - return + if apiJSON { + showJSONResponse(resp) + } else { + showBalancerInfo(resp.Balancer) + } } - - showBalancerInfo(resp.Balancer) } func showBalancerInfo(b *routerService.BalancerMsg) { diff --git a/main/commands/all/api/balancer_info_test.go b/main/commands/all/api/balancer_info_test.go new file mode 100644 index 000000000000..8f4feb1836d5 --- /dev/null +++ b/main/commands/all/api/balancer_info_test.go @@ -0,0 +1,58 @@ +package api + +import ( + "context" + "net" + "slices" + "testing" + + "google.golang.org/grpc" + + routerService "github.com/xtls/xray-core/app/router/command" + "github.com/xtls/xray-core/main/commands/base" +) + +type balancerInfoRecorder struct { + routerService.UnimplementedRoutingServiceServer + tags chan string +} + +func (s *balancerInfoRecorder) GetBalancerInfo(_ context.Context, request *routerService.GetBalancerInfoRequest) (*routerService.GetBalancerInfoResponse, error) { + s.tags <- request.Tag + return &routerService.GetBalancerInfoResponse{Balancer: &routerService.BalancerMsg{}}, nil +} + +func TestBalancerInfoMultipleTags(t *testing.T) { + serverAddr, timeout, jsonOutput := apiServerAddrPtr, apiTimeout, apiJSON + t.Cleanup(func() { apiServerAddrPtr, apiTimeout, apiJSON = serverAddr, timeout, jsonOutput }) + for _, mode := range []string{"text", "json"} { + t.Run(mode, func(t *testing.T) { + listener, err := net.Listen("tcp", "127.0.0.1:0") + if err != nil { + t.Fatal(err) + } + recorder := &balancerInfoRecorder{tags: make(chan string, 2)} + server := grpc.NewServer() + routerService.RegisterRoutingServiceServer(server, recorder) + stopped := make(chan struct{}) + go func() { + defer close(stopped) + server.Serve(listener) + }() + t.Cleanup(func() { server.Stop(); <-stopped }) + + args := []string{"--server=" + listener.Addr().String()} + if mode == "json" { + args = append(args, "--json") + } + executeBalancerInfo(&base.Command{}, append(args, "a", "b")) + var got []string + for len(recorder.tags) > 0 { + got = append(got, <-recorder.tags) + } + if !slices.Equal(got, []string{"a", "b"}) { + t.Fatalf("queried tags = %v, want [a b]", got) + } + }) + } +} From 13afff00fec4fc1713600ec2a4c5734fe9c76081 Mon Sep 17 00:00:00 2001 From: RPRX <63339210+RPRX@users.noreply.github.com> Date: Sat, 31 Oct 2026 07:17:44 +0000 Subject: [PATCH 2/2] Delete main/commands/all/api/balancer_info_test.go --- main/commands/all/api/balancer_info_test.go | 58 --------------------- 1 file changed, 58 deletions(-) delete mode 100644 main/commands/all/api/balancer_info_test.go diff --git a/main/commands/all/api/balancer_info_test.go b/main/commands/all/api/balancer_info_test.go deleted file mode 100644 index 8f4feb1836d5..000000000000 --- a/main/commands/all/api/balancer_info_test.go +++ /dev/null @@ -1,58 +0,0 @@ -package api - -import ( - "context" - "net" - "slices" - "testing" - - "google.golang.org/grpc" - - routerService "github.com/xtls/xray-core/app/router/command" - "github.com/xtls/xray-core/main/commands/base" -) - -type balancerInfoRecorder struct { - routerService.UnimplementedRoutingServiceServer - tags chan string -} - -func (s *balancerInfoRecorder) GetBalancerInfo(_ context.Context, request *routerService.GetBalancerInfoRequest) (*routerService.GetBalancerInfoResponse, error) { - s.tags <- request.Tag - return &routerService.GetBalancerInfoResponse{Balancer: &routerService.BalancerMsg{}}, nil -} - -func TestBalancerInfoMultipleTags(t *testing.T) { - serverAddr, timeout, jsonOutput := apiServerAddrPtr, apiTimeout, apiJSON - t.Cleanup(func() { apiServerAddrPtr, apiTimeout, apiJSON = serverAddr, timeout, jsonOutput }) - for _, mode := range []string{"text", "json"} { - t.Run(mode, func(t *testing.T) { - listener, err := net.Listen("tcp", "127.0.0.1:0") - if err != nil { - t.Fatal(err) - } - recorder := &balancerInfoRecorder{tags: make(chan string, 2)} - server := grpc.NewServer() - routerService.RegisterRoutingServiceServer(server, recorder) - stopped := make(chan struct{}) - go func() { - defer close(stopped) - server.Serve(listener) - }() - t.Cleanup(func() { server.Stop(); <-stopped }) - - args := []string{"--server=" + listener.Addr().String()} - if mode == "json" { - args = append(args, "--json") - } - executeBalancerInfo(&base.Command{}, append(args, "a", "b")) - var got []string - for len(recorder.tags) > 0 { - got = append(got, <-recorder.tags) - } - if !slices.Equal(got, []string{"a", "b"}) { - t.Fatalf("queried tags = %v, want [a b]", got) - } - }) - } -}