add remote fetch support

This commit is contained in:
iceBear67
2026-05-31 15:46:33 +08:00
parent 56f37faa84
commit 26aa088d58
4 changed files with 316 additions and 3 deletions
+65
View File
@@ -2,11 +2,20 @@ package core
import (
"bytes"
"fmt"
"io"
"net/http"
"os"
"strings"
"time"
"github.com/BurntSushi/toml"
)
// DefaultConfigURL is the default URL for fetching config.
// Set via build flags: go build -ldflags "-X tslink/core.DefaultConfigURL=https://..."
var DefaultConfigURL string
type ForwardRule struct {
Protocol string `toml:"protocol"`
TailscalePort int `toml:"tailscale_port"`
@@ -50,7 +59,16 @@ type Config struct {
Connect map[string][]ConnectRule `toml:"connect"`
}
// LoadConfig loads configuration from a file path or URL.
// If path starts with "http://" or "https://", it fetches the config from the URL.
// Otherwise, it reads from the local file system.
func LoadConfig(path string) (*Config, error) {
// Detect URL
if strings.HasPrefix(path, "http://") || strings.HasPrefix(path, "https://") {
return loadConfigFromURL(path)
}
// File-based loading
cfg := &Config{
Core: Core{
Hostname: "",
@@ -84,3 +102,50 @@ func LoadConfig(path string) (*Config, error) {
return cfg, nil
}
// loadConfigFromURL fetches a TOML config from the given URL and decodes it.
func loadConfigFromURL(url string) (*Config, error) {
client := &http.Client{
Timeout: 30 * time.Second,
}
resp, err := client.Get(url)
if err != nil {
return nil, fmt.Errorf("failed to fetch config from URL %s: %w", url, err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("failed to fetch config from URL %s: unexpected status %d", url, resp.StatusCode)
}
body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, fmt.Errorf("failed to read response body from %s: %w", url, err)
}
cfg := &Config{
Core: Core{
Hostname: "",
Ephemeral: true,
AcceptRoutes: true,
},
Forward: make(map[string][]ForwardRule),
Connect: make(map[string][]ConnectRule),
}
err = toml.Unmarshal(body, cfg)
if err != nil {
return nil, fmt.Errorf("failed to decode TOML config from %s: %w", url, err)
}
if cfg.Core.Hostname == "" {
hostname, err := os.Hostname()
if err != nil {
hostname = "unknown"
}
cfg.Core.Hostname = hostname
}
return cfg, nil
}