package render import ( "encoding/json" "testing" "webui4frpc/internal/store" ) func TestRenderTCPProxy(t *testing.T) { remote := store.Remote{Name: "srv", IP: "1.2.3.4", Port: 7000, Token: "secret"} data, err := Render(remote, []Proxy{ {Name: "web", Type: "tcp", LocalIP: "127.0.0.1", LocalPort: 8080, RemotePort: 8080}, }) if err != nil { t.Fatal(err) } var cfg Config if err := json.Unmarshal(data, &cfg); err != nil { t.Fatal(err) } if cfg.ServerAddr != "1.2.3.4" || cfg.Auth.Token != "secret" { t.Fatalf("cfg = %+v", cfg) } if len(cfg.Proxies) != 1 || cfg.Proxies[0].RemotePort != 8080 { t.Fatalf("proxies = %+v", cfg.Proxies) } } func TestRenderDuplicateServiceGetsPortSuffix(t *testing.T) { remote := store.Remote{Name: "srv", IP: "1.2.3.4", Port: 7000} proxy := []Proxy{ {Name: "web", Type: "tcp", LocalIP: "127.0.0.1", LocalPort: 8080, RemotePort: 8080}, {Name: "web", Type: "tcp", LocalIP: "127.0.0.1", LocalPort: 8080, RemotePort: 8081}, } data, err := Render(remote, proxy) if err != nil { t.Fatal(err) } var cfg Config _ = json.Unmarshal(data, &cfg) if len(cfg.Proxies) != 2 { t.Fatalf("proxies = %+v", cfg.Proxies) } if cfg.Proxies[1].Name != "web-8081" { t.Fatalf("second proxy name = %q", cfg.Proxies[1].Name) } } func TestRenderTransportAdvanced(t *testing.T) { remote := store.Remote{ Name: "srv", IP: "1.2.3.4", Port: 7000, Token: "secret", TransportProtocol: "kcp", TransportTLS: true, TransportPool: 3, TransportTLSServerName: "frps.local", } data, err := Render(remote, []Proxy{ {Name: "web", Type: "tcp", LocalIP: "127.0.0.1", LocalPort: 8080, RemotePort: 8080, UseEncryption: true, UseCompression: true, BandwidthLimit: "1MB", PoolCount: 2, Metadatas: map[string]string{"env": "prod"}, Annotations: map[string]string{"owner": "ops"}}, }) if err != nil { t.Fatal(err) } var cfg Config if err := json.Unmarshal(data, &cfg); err != nil { t.Fatal(err) } if cfg.Transport.Protocol != "kcp" { t.Fatalf("transport.protocol = %q, want kcp", cfg.Transport.Protocol) } if cfg.Transport.TLS == nil || !cfg.Transport.TLS.Enable || cfg.Transport.TLS.ServerName != "frps.local" { t.Fatalf("transport.tls = %+v", cfg.Transport.TLS) } if cfg.Transport.PoolCount != 3 { t.Fatalf("transport.poolCount = %d, want 3", cfg.Transport.PoolCount) } p := cfg.Proxies[0] if !p.UseEncryption || !p.UseCompression || p.BandwidthLimit != "1MB" || p.PoolCount != 2 { t.Fatalf("proxy advanced fields = %+v", p) } if p.Metadatas["env"] != "prod" || p.Annotations["owner"] != "ops" { t.Fatalf("proxy metadatas/annotations = %+v", p) } } func TestRenderTransportOmittedWhenEmpty(t *testing.T) { remote := store.Remote{Name: "srv", IP: "1.2.3.4", Port: 7000} data, err := Render(remote, []Proxy{ {Name: "web", Type: "tcp", LocalIP: "127.0.0.1", LocalPort: 8080, RemotePort: 8080}, }) if err != nil { t.Fatal(err) } var cfg Config if err := json.Unmarshal(data, &cfg); err != nil { t.Fatal(err) } if cfg.Transport.Protocol != "" || cfg.Transport.TLS != nil || cfg.Transport.PoolCount != 0 { t.Fatalf("transport should be empty, got %+v", cfg.Transport) } if cfg.Proxies[0].UseEncryption || cfg.Proxies[0].BandwidthLimit != "" { t.Fatalf("proxy advanced should be empty, got %+v", cfg.Proxies[0]) } } func TestRenderHTTPAdvanced(t *testing.T) { remote := store.Remote{Name: "srv", IP: "1.2.3.4", Port: 7000, Token: "secret"} data, err := Render(remote, []Proxy{ {Name: "web", Type: "http", LocalIP: "127.0.0.1", LocalPort: 8080, CustomDomains: []string{"app.example.com"}, Locations: []string{"/api", "/admin"}, HostHeaderRewrite: "backend.internal", HTTPHeaders: map[string]string{"X-Custom": "val"}, BasicAuthUser: "user", BasicAuthPassword: "pass"}, }) if err != nil { t.Fatal(err) } var cfg Config if err := json.Unmarshal(data, &cfg); err != nil { t.Fatal(err) } p := cfg.Proxies[0] if p.CustomDomains[0] != "app.example.com" { t.Fatalf("customDomains = %+v", p.CustomDomains) } if len(p.Locations) != 2 || p.Locations[0] != "/api" { t.Fatalf("locations = %+v", p.Locations) } if p.HostHeaderRewrite != "backend.internal" { t.Fatalf("hostHeaderRewrite = %q", p.HostHeaderRewrite) } if p.HTTPHeaders["X-Custom"] != "val" { t.Fatalf("httpHeaders = %+v", p.HTTPHeaders) } if p.HTTPBasicAuth == nil || p.HTTPBasicAuth.User != "user" || p.HTTPBasicAuth.Password != "pass" { t.Fatalf("basicAuth = %+v", p.HTTPBasicAuth) } } func TestRenderHTTPSUsesCustomDomains(t *testing.T) { remote := store.Remote{Name: "srv", IP: "1.2.3.4", Port: 7000} data, err := Render(remote, []Proxy{ {Name: "secure", Type: "https", LocalIP: "127.0.0.1", LocalPort: 8443, CustomDomains: []string{"secure.example.com"}}, }) if err != nil { t.Fatal(err) } var cfg Config _ = json.Unmarshal(data, &cfg) p := cfg.Proxies[0] if p.RemotePort != 0 { t.Fatalf("https proxy should not set remotePort, got %d", p.RemotePort) } if len(p.CustomDomains) != 1 || p.CustomDomains[0] != "secure.example.com" { t.Fatalf("customDomains = %+v", p.CustomDomains) } }