mirror of
https://gitcode.com/JianFeeeee/webui4frpc.git
synced 2026-09-20 08:57:55 +00:00
- store: Local 增加 customDomains/subdomain/locations/hostHeaderRewrite/httpHeaders/basicAuth;Remote 增加 vhostHttpPort;migrate() 补列;CRUD 读写(JSOm 编解码) - render: http/https proxy 输出 customDomains/subdomain/locations/hostHeaderRewrite/httpHeaders/basicAuth - main: renderRemote 透传 M2 字段(customDomains 逗号拆分 splitCSV) - web: LocalNode 折叠 HTTP 路由高级区;RemoteNode vhostHTTPPort;StatusView 显示 HTTP 访问端口 - 测试: TestRenderHTTPAdvanced / TestRenderHTTPSUsesCustomDomains;端到端 PUT canvas→config 验证通过
159 lines
5.0 KiB
Go
159 lines
5.0 KiB
Go
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)
|
|
}
|
|
}
|