feat(config): support loading configuration from URL

https://github.com/fatedier/frp/issues/4853
This commit introduces the capability to load configuration files directly from an HTTP or HTTPS URL, in addition to local file paths.

A new helper function, `readBytesFromPath`, is implemented to handle both remote and local file retrieval. This function replaces direct calls to `os.ReadFile` in the configuration loading logic, providing greater flexibility for deploying and managing frp configurations.
pull/4855/head
heskdx 2025-06-27 14:48:59 +08:00
parent c777891f75
commit 058fe0b6e5
2 changed files with 38 additions and 3 deletions

View File

@ -16,6 +16,9 @@ package legacy
import (
"bytes"
"fmt"
"io"
"net/http"
"os"
"strings"
"text/template"
@ -45,6 +48,21 @@ func GetValues() *Values {
}
}
func readBytesFromPath(path string) ([]byte, error) {
if strings.HasPrefix(path, "http://") || strings.HasPrefix(path, "https://") {
resp, err := http.Get(path)
if err != nil {
return nil, err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("failed to fetch config from url %s, status code: %d", path, resp.StatusCode)
}
return io.ReadAll(resp.Body)
}
return os.ReadFile(path)
}
func RenderContent(in []byte) (out []byte, err error) {
tmpl, errRet := template.New("frp").Parse(string(in))
if errRet != nil {
@ -64,7 +82,7 @@ func RenderContent(in []byte) (out []byte, err error) {
func GetRenderedConfFromFile(path string) (out []byte, err error) {
var b []byte
b, err = os.ReadFile(path)
b, err = readBytesFromPath(path)
if err != nil {
return
}

View File

@ -18,6 +18,8 @@ import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"os"
"path/filepath"
"strings"
@ -36,6 +38,21 @@ import (
"github.com/fatedier/frp/pkg/util/util"
)
func readBytesFromPath(path string) ([]byte, error) {
if strings.HasPrefix(path, "http://") || strings.HasPrefix(path, "https://") {
resp, err := http.Get(path)
if err != nil {
return nil, err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("failed to fetch config from url %s, status code: %d", path, resp.StatusCode)
}
return io.ReadAll(resp.Body)
}
return os.ReadFile(path)
}
var glbEnvs map[string]string
func init() {
@ -72,7 +89,7 @@ func DetectLegacyINIFormat(content []byte) bool {
}
func DetectLegacyINIFormatFromFile(path string) bool {
b, err := os.ReadFile(path)
b, err := readBytesFromPath(path)
if err != nil {
return false
}
@ -96,7 +113,7 @@ func RenderWithTemplate(in []byte, values *Values) ([]byte, error) {
}
func LoadFileContentWithTemplate(path string, values *Values) ([]byte, error) {
b, err := os.ReadFile(path)
b, err := readBytesFromPath(path)
if err != nil {
return nil, err
}