platform: modularize api/gui, add docs-tests-web foundation, and refresh root config

This commit is contained in:
beckline
2026-03-26 22:40:54 +03:00
parent 0e2d7f61ea
commit 6a56d734c2
562 changed files with 70151 additions and 16423 deletions

View File

@@ -0,0 +1,74 @@
package app
import (
"encoding/json"
"net/netip"
"os"
"strings"
"time"
egressutilpkg "selective-vpn-api/app/egressutil"
)
func egressIPEndpoints() []string {
return egressutilpkg.IPEndpoints(os.Getenv("SVPN_EGRESS_IP_ENDPOINTS"))
}
func egressGeoEndpointsForIP(ip string) []string {
return egressutilpkg.GeoEndpointsForIP(os.Getenv("SVPN_EGRESS_GEO_ENDPOINTS"), ip)
}
func egressLimitEndpointsForNetns(in []string) []string {
maxN := envInt("SVPN_EGRESS_NETNS_MAX_ENDPOINTS", 1)
return egressutilpkg.LimitEndpoints(in, maxN)
}
func egressJoinErrorsCompact(errs []string) string {
return egressutilpkg.JoinErrorsCompact(errs)
}
func egressSingBoxSOCKSProxyURL(client TransportClient) string {
if client.Kind != TransportClientSingBox {
return ""
}
path := transportSingBoxConfigPath(client)
if strings.TrimSpace(path) == "" {
return ""
}
data, err := os.ReadFile(path)
if err != nil || len(data) == 0 {
return ""
}
var root map[string]any
if err := json.Unmarshal(data, &root); err != nil {
return ""
}
return egressutilpkg.ParseSingBoxSOCKSProxyURL(root)
}
func egressInterfaceBindAddress(iface string) string {
iface = strings.TrimSpace(iface)
if iface == "" {
return ""
}
stdout, _, code, err := runCommandTimeout(1500*time.Millisecond, "ip", "-4", "-o", "addr", "show", "dev", iface, "scope", "global")
if err != nil || code != 0 {
return ""
}
for _, line := range strings.Split(stdout, "\n") {
fields := strings.Fields(strings.TrimSpace(line))
for i := 0; i < len(fields); i++ {
if fields[i] != "inet" || i+1 >= len(fields) {
continue
}
ip := strings.TrimSpace(fields[i+1])
if slash := strings.Index(ip, "/"); slash > 0 {
ip = ip[:slash]
}
if addr, err := netip.ParseAddr(ip); err == nil && addr.Is4() {
return addr.String()
}
}
}
return ""
}