wip
This commit is contained in:
parent
c7438fd2fd
commit
369c545647
@ -54,7 +54,7 @@ func (svr *Service) apiReload(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
newCommonCfg, err := config.LoadClientCommonConf(content)
|
||||
newCommonCfg, err := config.UnmarshalClientConfFromIni(content)
|
||||
if err != nil {
|
||||
res.Code = 400
|
||||
res.Msg = err.Error()
|
||||
@ -62,7 +62,7 @@ func (svr *Service) apiReload(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
pxyCfgs, visitorCfgs, err := config.LoadClientBasicConf(svr.cfg.User, content, newCommonCfg.Start)
|
||||
pxyCfgs, visitorCfgs, err := config.LoadAllConfFromIni(svr.cfg.User, content, newCommonCfg.Start)
|
||||
if err != nil {
|
||||
res.Code = 400
|
||||
res.Msg = err.Error()
|
||||
|
@ -131,7 +131,7 @@ func handleSignal(svr *client.Service) {
|
||||
|
||||
func parseClientCommonCfg(fileType int, source interface{}) (cfg config.ClientCommonConf, err error) {
|
||||
if fileType == CfgFileTypeIni {
|
||||
cfg, err = config.LoadClientCommonConf(source)
|
||||
cfg, err = config.UnmarshalClientConfFromIni(source)
|
||||
} else if fileType == CfgFileTypeCmd {
|
||||
cfg, err = parseClientCommonCfgFromCmd()
|
||||
}
|
||||
@ -147,7 +147,7 @@ func parseClientCommonCfg(fileType int, source interface{}) (cfg config.ClientCo
|
||||
}
|
||||
|
||||
func parseClientCommonCfgFromCmd() (cfg config.ClientCommonConf, err error) {
|
||||
cfg = config.DefaultClientConf()
|
||||
cfg = config.GetDefaultClientConf()
|
||||
|
||||
strs := strings.Split(serverAddr, ":")
|
||||
if len(strs) < 2 {
|
||||
@ -183,24 +183,25 @@ func parseClientCommonCfgFromCmd() (cfg config.ClientCommonConf, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func runClient(cfgFilePath string) error {
|
||||
content, err := config.GetRenderedConfFromFile(cfgFilePath)
|
||||
func runClient(cfgFilePath string) (err error) {
|
||||
var content string
|
||||
content, err = config.GetRenderedConfFromFile(cfgFilePath)
|
||||
if err != nil {
|
||||
return err
|
||||
return
|
||||
}
|
||||
|
||||
cfg, err := parseClientCommonCfg(CfgFileTypeIni, content)
|
||||
if err != nil {
|
||||
return err
|
||||
return
|
||||
}
|
||||
|
||||
pxyCfgs, visitorCfgs, err := config.LoadClientBasicConf(cfg.User, content, cfg.Start)
|
||||
pxyCfgs, visitorCfgs, err := config.LoadAllConfFromIni(cfg.User, content, cfg.Start)
|
||||
if err != nil {
|
||||
return err
|
||||
return
|
||||
}
|
||||
|
||||
err = startService(cfg, pxyCfgs, visitorCfgs, cfgFilePath)
|
||||
return err
|
||||
return
|
||||
}
|
||||
|
||||
func startService(
|
||||
|
@ -104,10 +104,9 @@ var rootCmd = &cobra.Command{
|
||||
|
||||
var cfg config.ServerCommonConf
|
||||
var err error
|
||||
|
||||
if cfgFile != "" {
|
||||
log.Info("frps uses config file: %s", cfgFile)
|
||||
var content []byte
|
||||
var content string
|
||||
content, err = config.GetRenderedConfFromFile(cfgFile)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -138,7 +137,7 @@ func Execute() {
|
||||
|
||||
func parseServerCommonCfg(fileType int, source interface{}) (cfg config.ServerCommonConf, err error) {
|
||||
if fileType == CfgFileTypeIni {
|
||||
cfg, err = config.LoadServerCommonConf(source)
|
||||
cfg, err = config.UnmarshalServerConfFromIni(source)
|
||||
} else if fileType == CfgFileTypeCmd {
|
||||
cfg, err = parseServerCommonCfgFromCmd()
|
||||
}
|
||||
@ -154,7 +153,7 @@ func parseServerCommonCfg(fileType int, source interface{}) (cfg config.ServerCo
|
||||
}
|
||||
|
||||
func parseServerCommonCfgFromCmd() (cfg config.ServerCommonConf, err error) {
|
||||
cfg = config.DefaultServerConf()
|
||||
cfg = config.GetDefaultServerConf()
|
||||
|
||||
cfg.BindAddr = bindAddr
|
||||
cfg.BindPort = bindPort
|
||||
|
@ -177,7 +177,7 @@ use_compression = true
|
||||
http_user = admin
|
||||
http_pwd = admin
|
||||
# if domain for frps is frps.com, then you can access [web01] proxy by URL http://test.frps.com
|
||||
sub_domain = web01
|
||||
subdomain = web01
|
||||
custom_domains = web02.yourdomain.com
|
||||
# locations is only available for http type
|
||||
locations = /,/pic
|
||||
|
121
pkg/config/bandwidth.go
Normal file
121
pkg/config/bandwidth.go
Normal file
@ -0,0 +1,121 @@
|
||||
// Copyright 2019 fatedier, fatedier@gmail.com
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package config
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
MB = 1024 * 1024
|
||||
KB = 1024
|
||||
)
|
||||
|
||||
type BandwidthQuantity struct {
|
||||
s string // MB or KB
|
||||
|
||||
i int64 // bytes
|
||||
}
|
||||
|
||||
func NewBandwidthQuantity(s string) (BandwidthQuantity, error) {
|
||||
q := BandwidthQuantity{}
|
||||
err := q.UnmarshalString(s)
|
||||
if err != nil {
|
||||
return q, err
|
||||
}
|
||||
return q, nil
|
||||
}
|
||||
|
||||
func MustBandwidthQuantity(s string) BandwidthQuantity {
|
||||
q := BandwidthQuantity{}
|
||||
err := q.UnmarshalString(s)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return q
|
||||
}
|
||||
|
||||
func (q *BandwidthQuantity) Equal(u *BandwidthQuantity) bool {
|
||||
if q == nil && u == nil {
|
||||
return true
|
||||
}
|
||||
if q != nil && u != nil {
|
||||
return q.i == u.i
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (q *BandwidthQuantity) String() string {
|
||||
return q.s
|
||||
}
|
||||
|
||||
func (q *BandwidthQuantity) UnmarshalString(s string) error {
|
||||
s = strings.TrimSpace(s)
|
||||
if s == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
var (
|
||||
base int64
|
||||
f float64
|
||||
err error
|
||||
)
|
||||
if strings.HasSuffix(s, "MB") {
|
||||
base = MB
|
||||
fstr := strings.TrimSuffix(s, "MB")
|
||||
f, err = strconv.ParseFloat(fstr, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else if strings.HasSuffix(s, "KB") {
|
||||
base = KB
|
||||
fstr := strings.TrimSuffix(s, "KB")
|
||||
f, err = strconv.ParseFloat(fstr, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
return errors.New("unit not support")
|
||||
}
|
||||
|
||||
q.s = s
|
||||
q.i = int64(f * float64(base))
|
||||
return nil
|
||||
}
|
||||
|
||||
func (q *BandwidthQuantity) UnmarshalJSON(b []byte) error {
|
||||
if len(b) == 4 && string(b) == "null" {
|
||||
return nil
|
||||
}
|
||||
|
||||
var str string
|
||||
err := json.Unmarshal(b, &str)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return q.UnmarshalString(str)
|
||||
}
|
||||
|
||||
func (q *BandwidthQuantity) MarshalJSON() ([]byte, error) {
|
||||
return []byte("\"" + q.s + "\""), nil
|
||||
}
|
||||
|
||||
func (q *BandwidthQuantity) Bytes() int64 {
|
||||
return q.i
|
||||
}
|
40
pkg/config/bandwidth_test.go
Normal file
40
pkg/config/bandwidth_test.go
Normal file
@ -0,0 +1,40 @@
|
||||
// Copyright 2019 fatedier, fatedier@gmail.com
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package config
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
type Wrap struct {
|
||||
B BandwidthQuantity `json:"b"`
|
||||
Int int `json:"int"`
|
||||
}
|
||||
|
||||
func TestBandwidthQuantity(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
var w Wrap
|
||||
err := json.Unmarshal([]byte(`{"b":"1KB","int":5}`), &w)
|
||||
assert.NoError(err)
|
||||
assert.EqualValues(1*KB, w.B.Bytes())
|
||||
|
||||
buf, err := json.Marshal(&w)
|
||||
assert.NoError(err)
|
||||
assert.Equal(`{"b":"1KB","int":5}`, string(buf))
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
// Copyright 2016 fatedier, fatedier@gmail.com
|
||||
// Copyright 2020 The frp Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@ -26,7 +26,7 @@ import (
|
||||
)
|
||||
|
||||
// GetDefaultClientConf returns a client configuration with default values.
|
||||
func DefaultClientConf() ClientCommonConf {
|
||||
func GetDefaultClientConf() ClientCommonConf {
|
||||
return ClientCommonConf{
|
||||
ClientConfig: auth.GetDefaultClientConf(),
|
||||
ServerAddr: "0.0.0.0",
|
||||
@ -87,7 +87,7 @@ func (cfg *ClientCommonConf) Check() error {
|
||||
}
|
||||
|
||||
// Supported sources including: string(file path), []byte, Reader interface.
|
||||
func LoadClientCommonConf(source interface{}) (ClientCommonConf, error) {
|
||||
func UnmarshalClientConfFromIni(source interface{}) (ClientCommonConf, error) {
|
||||
f, err := ini.LoadSources(ini.LoadOptions{
|
||||
Insensitive: false,
|
||||
InsensitiveSections: false,
|
||||
@ -105,7 +105,7 @@ func LoadClientCommonConf(source interface{}) (ClientCommonConf, error) {
|
||||
return ClientCommonConf{}, err
|
||||
}
|
||||
|
||||
common := DefaultClientConf()
|
||||
common := GetDefaultClientConf()
|
||||
err = s.MapTo(&common)
|
||||
if err != nil {
|
||||
return ClientCommonConf{}, err
|
||||
@ -118,7 +118,7 @@ func LoadClientCommonConf(source interface{}) (ClientCommonConf, error) {
|
||||
|
||||
// if len(startProxy) is 0, start all
|
||||
// otherwise just start proxies in startProxy map
|
||||
func LoadClientBasicConf(
|
||||
func LoadAllConfFromIni(
|
||||
prefix string,
|
||||
source interface{},
|
||||
start []string,
|
||||
|
@ -1,3 +1,17 @@
|
||||
// Copyright 2020 The frp Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package config
|
||||
|
||||
import (
|
||||
@ -277,7 +291,7 @@ func Test_LoadClientCommonConf(t *testing.T) {
|
||||
UDPPacketSize: 1509,
|
||||
}
|
||||
|
||||
common, err := LoadClientCommonConf(testClientBytesWithFull)
|
||||
common, err := UnmarshalClientConfFromIni(testClientBytesWithFull)
|
||||
assert.NoError(err)
|
||||
assert.Equal(expected, common)
|
||||
}
|
||||
@ -446,7 +460,7 @@ func Test_LoadClientBasicConf(t *testing.T) {
|
||||
},
|
||||
},
|
||||
HTTPProxySpec: HTTPProxySpec{
|
||||
DomainSpec: DomainSpec{
|
||||
DomainConf: DomainConf{
|
||||
CustomDomains: []string{"web02.yourdomain.com"},
|
||||
SubDomain: "web01",
|
||||
},
|
||||
@ -472,7 +486,7 @@ func Test_LoadClientBasicConf(t *testing.T) {
|
||||
ProxyProtocolVersion: "v2",
|
||||
},
|
||||
HTTPSProxySpec: HTTPSProxySpec{
|
||||
DomainSpec: DomainSpec{
|
||||
DomainConf: DomainConf{
|
||||
CustomDomains: []string{"web02.yourdomain.com"},
|
||||
SubDomain: "web01",
|
||||
},
|
||||
@ -516,7 +530,7 @@ func Test_LoadClientBasicConf(t *testing.T) {
|
||||
},
|
||||
},
|
||||
TCPMuxProxySpec: TCPMuxProxySpec{
|
||||
DomainSpec: DomainSpec{
|
||||
DomainConf: DomainConf{
|
||||
CustomDomains: []string{"tunnel1"},
|
||||
SubDomain: "",
|
||||
},
|
||||
@ -609,7 +623,7 @@ func Test_LoadClientBasicConf(t *testing.T) {
|
||||
},
|
||||
},
|
||||
HTTPSProxySpec: HTTPSProxySpec{
|
||||
DomainSpec: DomainSpec{
|
||||
DomainConf: DomainConf{
|
||||
CustomDomains: []string{"test.yourdomain.com"},
|
||||
},
|
||||
},
|
||||
@ -629,7 +643,7 @@ func Test_LoadClientBasicConf(t *testing.T) {
|
||||
},
|
||||
},
|
||||
HTTPProxySpec: HTTPProxySpec{
|
||||
DomainSpec: DomainSpec{
|
||||
DomainConf: DomainConf{
|
||||
CustomDomains: []string{"test.yourdomain.com"},
|
||||
},
|
||||
},
|
||||
@ -661,7 +675,7 @@ func Test_LoadClientBasicConf(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
proxyActual, visitorActual, err := LoadClientBasicConf(testUser, testClientBytesWithFull, nil)
|
||||
proxyActual, visitorActual, err := LoadAllConfFromIni(testUser, testClientBytesWithFull, nil)
|
||||
assert.NoError(err)
|
||||
assert.Equal(proxyExpected, proxyActual)
|
||||
assert.Equal(visitorExpected, visitorActual)
|
||||
|
1014
pkg/config/proxy.go
1014
pkg/config/proxy.go
File diff suppressed because it is too large
Load Diff
@ -1,3 +1,17 @@
|
||||
// Copyright 2020 The frp Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package config
|
||||
|
||||
import (
|
||||
@ -171,7 +185,7 @@ func Test_Proxy_UnmarshalFromIni(t *testing.T) {
|
||||
},
|
||||
},
|
||||
HTTPProxySpec: HTTPProxySpec{
|
||||
DomainSpec: DomainSpec{
|
||||
DomainConf: DomainConf{
|
||||
CustomDomains: []string{"web02.yourdomain.com"},
|
||||
SubDomain: "web01",
|
||||
},
|
||||
@ -211,7 +225,7 @@ func Test_Proxy_UnmarshalFromIni(t *testing.T) {
|
||||
ProxyProtocolVersion: "v2",
|
||||
},
|
||||
HTTPSProxySpec: HTTPSProxySpec{
|
||||
DomainSpec: DomainSpec{
|
||||
DomainConf: DomainConf{
|
||||
CustomDomains: []string{"web02.yourdomain.com"},
|
||||
SubDomain: "web01",
|
||||
},
|
||||
@ -290,7 +304,7 @@ func Test_Proxy_UnmarshalFromIni(t *testing.T) {
|
||||
},
|
||||
},
|
||||
TCPMuxProxySpec: TCPMuxProxySpec{
|
||||
DomainSpec: DomainSpec{
|
||||
DomainConf: DomainConf{
|
||||
CustomDomains: []string{"tunnel1"},
|
||||
SubDomain: "",
|
||||
},
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright 2016 fatedier, fatedier@gmail.com
|
||||
// Copyright 2020 The frp Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@ -27,7 +27,7 @@ import (
|
||||
|
||||
// GetDefaultServerConf returns a server configuration with reasonable
|
||||
// defaults.
|
||||
func DefaultServerConf() ServerCommonConf {
|
||||
func GetDefaultServerConf() ServerCommonConf {
|
||||
return ServerCommonConf{
|
||||
ServerConfig: auth.GetDefaultServerConf(),
|
||||
BindAddr: "0.0.0.0",
|
||||
@ -72,7 +72,7 @@ func (cfg *ServerCommonConf) Check() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func LoadServerCommonConf(source interface{}) (ServerCommonConf, error) {
|
||||
func UnmarshalServerConfFromIni(source interface{}) (ServerCommonConf, error) {
|
||||
|
||||
f, err := ini.LoadSources(ini.LoadOptions{
|
||||
Insensitive: false,
|
||||
@ -91,7 +91,7 @@ func LoadServerCommonConf(source interface{}) (ServerCommonConf, error) {
|
||||
return ServerCommonConf{}, err
|
||||
}
|
||||
|
||||
common := DefaultServerConf()
|
||||
common := GetDefaultServerConf()
|
||||
err = s.MapTo(&common)
|
||||
if err != nil {
|
||||
return ServerCommonConf{}, err
|
||||
|
@ -1,3 +1,17 @@
|
||||
// Copyright 2020 The frp Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package config
|
||||
|
||||
import (
|
||||
@ -184,7 +198,7 @@ func Test_LoadServerCommonConf(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, c := range testcases {
|
||||
actual, err := LoadServerCommonConf(c.source)
|
||||
actual, err := UnmarshalServerConfFromIni(c.source)
|
||||
assert.NoError(err)
|
||||
assert.Equal(c.expected, actual)
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright 2019 fatedier, fatedier@gmail.com
|
||||
// Copyright 2020 The frp Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@ -25,7 +25,9 @@ import (
|
||||
"gopkg.in/ini.v1"
|
||||
)
|
||||
|
||||
// Client
|
||||
// ClientCommonConf contains information for a client service. It is
|
||||
// recommended to use GetDefaultClientConf instead of creating this object
|
||||
// directly, so that all unspecified fields have reasonable default values.
|
||||
type ClientCommonConf struct {
|
||||
auth.ClientConfig `ini:",,,,extends",json:"inline"`
|
||||
// ServerAddr specifies the address of the server to connect to. By
|
||||
@ -96,7 +98,7 @@ type ClientCommonConf struct {
|
||||
// Start specifies a set of enabled proxies by name. If this set is empty,
|
||||
// all supplied proxies are enabled. By default, this value is an empty
|
||||
// set.
|
||||
Start []string `ini:"start",json:"start""`
|
||||
Start []string `ini:"start",json:"start"`
|
||||
//Start map[string]struct{} `json:"start"`
|
||||
// Protocol specifies the protocol to use when interacting with the server.
|
||||
// Valid values are "tcp", "kcp" and "websocket". By default, this value
|
||||
@ -132,8 +134,6 @@ type ClientCommonConf struct {
|
||||
UDPPacketSize int64 `ini:"udp_packet_size",json:"udp_packet_size"`
|
||||
}
|
||||
|
||||
// Server
|
||||
|
||||
// ServerCommonConf contains information for a server service. It is
|
||||
// recommended to use GetDefaultServerConf instead of creating this object
|
||||
// directly, so that all unspecified fields have reasonable default values.
|
||||
@ -387,7 +387,7 @@ type BaseProxyConf struct {
|
||||
HealthCheckConf `ini:",,,,extends",json:"inline"`
|
||||
}
|
||||
|
||||
type DomainSpec struct {
|
||||
type DomainConf struct {
|
||||
CustomDomains []string `ini:"custom_domains",json:"custom_domains"`
|
||||
SubDomain string `ini:"subdomain",json:"subdomain"`
|
||||
}
|
||||
@ -399,7 +399,7 @@ type HTTPProxyConf struct {
|
||||
}
|
||||
|
||||
type HTTPProxySpec struct {
|
||||
DomainSpec `ini:",,,,extends",json:"inline"`
|
||||
DomainConf `ini:",,,,extends",json:"inline"`
|
||||
Locations []string `ini:"locations",json:"locations"`
|
||||
HTTPUser string `ini:"http_user",json:"http_user"`
|
||||
HTTPPwd string `ini:"http_pwd",json:"http_pwd"`
|
||||
@ -414,7 +414,7 @@ type HTTPSProxyConf struct {
|
||||
}
|
||||
|
||||
type HTTPSProxySpec struct {
|
||||
DomainSpec `ini:",,,,extends",json:"inline"`
|
||||
DomainConf `ini:",,,,extends",json:"inline"`
|
||||
}
|
||||
|
||||
// TCP
|
||||
@ -434,7 +434,7 @@ type TCPMuxProxyConf struct {
|
||||
}
|
||||
|
||||
type TCPMuxProxySpec struct {
|
||||
DomainSpec `ini:",,,,extends",json:"inline"`
|
||||
DomainConf `ini:",,,,extends",json:"inline"`
|
||||
Multiplexer string `ini:"multiplexer"`
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright 2016 fatedier, fatedier@gmail.com
|
||||
// Copyright 2020 The frp Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@ -15,14 +15,7 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"text/template"
|
||||
)
|
||||
|
||||
func GetMapWithoutPrefix(set map[string]string, prefix string) map[string]string {
|
||||
@ -56,152 +49,3 @@ func GetMapByPrefix(set map[string]string, prefix string) map[string]string {
|
||||
|
||||
return m
|
||||
}
|
||||
|
||||
// Render Env Values
|
||||
var glbEnvs map[string]string
|
||||
|
||||
func init() {
|
||||
glbEnvs = make(map[string]string)
|
||||
envs := os.Environ()
|
||||
for _, env := range envs {
|
||||
kv := strings.Split(env, "=")
|
||||
if len(kv) != 2 {
|
||||
continue
|
||||
}
|
||||
glbEnvs[kv[0]] = kv[1]
|
||||
}
|
||||
}
|
||||
|
||||
type Values struct {
|
||||
Envs map[string]string // environment vars
|
||||
}
|
||||
|
||||
func GetValues() *Values {
|
||||
return &Values{
|
||||
Envs: glbEnvs,
|
||||
}
|
||||
}
|
||||
|
||||
func RenderContent(in []byte) ([]byte, error) {
|
||||
tmpl, err := template.New("frp").Parse(string(in))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
buffer := bytes.NewBufferString("")
|
||||
v := GetValues()
|
||||
err = tmpl.Execute(buffer, v)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return buffer.Bytes(), nil
|
||||
}
|
||||
|
||||
func GetRenderedConfFromFile(path string) ([]byte, error) {
|
||||
data, err := ioutil.ReadFile(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return RenderContent(data)
|
||||
}
|
||||
|
||||
// BandwidthQuantity
|
||||
const (
|
||||
MB = 1024 * 1024
|
||||
KB = 1024
|
||||
)
|
||||
|
||||
type BandwidthQuantity struct {
|
||||
s string // MB or KB
|
||||
|
||||
i int64 // bytes
|
||||
}
|
||||
|
||||
func NewBandwidthQuantity(s string) (BandwidthQuantity, error) {
|
||||
q := BandwidthQuantity{}
|
||||
err := q.UnmarshalString(s)
|
||||
if err != nil {
|
||||
return q, err
|
||||
}
|
||||
return q, nil
|
||||
}
|
||||
|
||||
func MustBandwidthQuantity(s string) BandwidthQuantity {
|
||||
q := BandwidthQuantity{}
|
||||
err := q.UnmarshalString(s)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return q
|
||||
}
|
||||
|
||||
func (q *BandwidthQuantity) Equal(u *BandwidthQuantity) bool {
|
||||
if q == nil && u == nil {
|
||||
return true
|
||||
}
|
||||
if q != nil && u != nil {
|
||||
return q.i == u.i
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (q *BandwidthQuantity) String() string {
|
||||
return q.s
|
||||
}
|
||||
|
||||
func (q *BandwidthQuantity) UnmarshalString(s string) error {
|
||||
s = strings.TrimSpace(s)
|
||||
if s == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
var (
|
||||
base int64
|
||||
f float64
|
||||
err error
|
||||
)
|
||||
if strings.HasSuffix(s, "MB") {
|
||||
base = MB
|
||||
fstr := strings.TrimSuffix(s, "MB")
|
||||
f, err = strconv.ParseFloat(fstr, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else if strings.HasSuffix(s, "KB") {
|
||||
base = KB
|
||||
fstr := strings.TrimSuffix(s, "KB")
|
||||
f, err = strconv.ParseFloat(fstr, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
return errors.New("unit not support")
|
||||
}
|
||||
|
||||
q.s = s
|
||||
q.i = int64(f * float64(base))
|
||||
return nil
|
||||
}
|
||||
|
||||
func (q *BandwidthQuantity) UnmarshalJSON(b []byte) error {
|
||||
if len(b) == 4 && string(b) == "null" {
|
||||
return nil
|
||||
}
|
||||
|
||||
var str string
|
||||
err := json.Unmarshal(b, &str)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return q.UnmarshalString(str)
|
||||
}
|
||||
|
||||
func (q *BandwidthQuantity) MarshalJSON() ([]byte, error) {
|
||||
return []byte("\"" + q.s + "\""), nil
|
||||
}
|
||||
|
||||
func (q *BandwidthQuantity) Bytes() int64 {
|
||||
return q.i
|
||||
}
|
||||
|
78
pkg/config/value.go
Normal file
78
pkg/config/value.go
Normal file
@ -0,0 +1,78 @@
|
||||
// Copyright 2020 The frp Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package config
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strings"
|
||||
"text/template"
|
||||
)
|
||||
|
||||
var (
|
||||
glbEnvs map[string]string
|
||||
)
|
||||
|
||||
func init() {
|
||||
glbEnvs = make(map[string]string)
|
||||
envs := os.Environ()
|
||||
for _, env := range envs {
|
||||
kv := strings.Split(env, "=")
|
||||
if len(kv) != 2 {
|
||||
continue
|
||||
}
|
||||
glbEnvs[kv[0]] = kv[1]
|
||||
}
|
||||
}
|
||||
|
||||
type Values struct {
|
||||
Envs map[string]string // environment vars
|
||||
}
|
||||
|
||||
func GetValues() *Values {
|
||||
return &Values{
|
||||
Envs: glbEnvs,
|
||||
}
|
||||
}
|
||||
|
||||
func RenderContent(in string) (out string, err error) {
|
||||
tmpl, errRet := template.New("frp").Parse(in)
|
||||
if errRet != nil {
|
||||
err = errRet
|
||||
return
|
||||
}
|
||||
|
||||
buffer := bytes.NewBufferString("")
|
||||
v := GetValues()
|
||||
err = tmpl.Execute(buffer, v)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
out = buffer.String()
|
||||
return
|
||||
}
|
||||
|
||||
func GetRenderedConfFromFile(path string) (out string, err error) {
|
||||
var b []byte
|
||||
b, err = ioutil.ReadFile(path)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
content := string(b)
|
||||
|
||||
out, err = RenderContent(content)
|
||||
return
|
||||
}
|
@ -21,7 +21,6 @@ import (
|
||||
"gopkg.in/ini.v1"
|
||||
)
|
||||
|
||||
// Visitor Conf Loader
|
||||
// DefaultVisitorConf creates a empty VisitorConf object by visitorType.
|
||||
// If visitorType doesn't exist, return nil.
|
||||
func DefaultVisitorConf(visitorType string) VisitorConf {
|
||||
@ -59,111 +58,67 @@ func NewVisitorConfFromIni(prefix string, name string, section *ini.Section) (Vi
|
||||
}
|
||||
|
||||
// Base
|
||||
func (c *BaseVisitorConf) GetBaseInfo() *BaseVisitorConf {
|
||||
return c
|
||||
func (cfg *BaseVisitorConf) GetBaseInfo() *BaseVisitorConf {
|
||||
return cfg
|
||||
}
|
||||
|
||||
func (c *BaseVisitorConf) compare(cmp *BaseVisitorConf) bool {
|
||||
if c.ProxyName != cmp.ProxyName ||
|
||||
c.ProxyType != cmp.ProxyType ||
|
||||
c.UseEncryption != cmp.UseEncryption ||
|
||||
c.UseCompression != cmp.UseCompression ||
|
||||
c.Role != cmp.Role ||
|
||||
c.Sk != cmp.Sk ||
|
||||
c.ServerName != cmp.ServerName ||
|
||||
c.BindAddr != cmp.BindAddr ||
|
||||
c.BindPort != cmp.BindPort {
|
||||
func (cfg *BaseVisitorConf) compare(cmp *BaseVisitorConf) bool {
|
||||
if cfg.ProxyName != cmp.ProxyName ||
|
||||
cfg.ProxyType != cmp.ProxyType ||
|
||||
cfg.UseEncryption != cmp.UseEncryption ||
|
||||
cfg.UseCompression != cmp.UseCompression ||
|
||||
cfg.Role != cmp.Role ||
|
||||
cfg.Sk != cmp.Sk ||
|
||||
cfg.ServerName != cmp.ServerName ||
|
||||
cfg.BindAddr != cmp.BindAddr ||
|
||||
cfg.BindPort != cmp.BindPort {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (c *BaseVisitorConf) check() (err error) {
|
||||
if c.Role != "visitor" {
|
||||
func (cfg *BaseVisitorConf) check() (err error) {
|
||||
if cfg.Role != "visitor" {
|
||||
err = fmt.Errorf("invalid role")
|
||||
return
|
||||
}
|
||||
if c.BindAddr == "" {
|
||||
if cfg.BindAddr == "" {
|
||||
err = fmt.Errorf("bind_addr shouldn't be empty")
|
||||
return
|
||||
}
|
||||
if c.BindPort <= 0 {
|
||||
if cfg.BindPort <= 0 {
|
||||
err = fmt.Errorf("bind_port is required")
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (c *BaseVisitorConf) decorate(prefix string, name string, section *ini.Section) error {
|
||||
func (cfg *BaseVisitorConf) decorate(prefix string, name string, section *ini.Section) error {
|
||||
|
||||
// proxy name
|
||||
c.ProxyName = prefix + name
|
||||
cfg.ProxyName = prefix + name
|
||||
|
||||
// server_name
|
||||
c.ServerName = prefix + c.ServerName
|
||||
cfg.ServerName = prefix + cfg.ServerName
|
||||
|
||||
// bind_addr
|
||||
if c.BindAddr == "" {
|
||||
c.BindAddr = "127.0.0.1"
|
||||
if cfg.BindAddr == "" {
|
||||
cfg.BindAddr = "127.0.0.1"
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// STCP
|
||||
var _ VisitorConf = &STCPVisitorConf{}
|
||||
|
||||
func (c *STCPVisitorConf) Compare(conf VisitorConf) bool {
|
||||
cmp, ok := conf.(*STCPVisitorConf)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
|
||||
if !c.BaseVisitorConf.compare(&cmp.BaseVisitorConf) {
|
||||
return false
|
||||
}
|
||||
|
||||
// Add custom login equal, if exists
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func (c *STCPVisitorConf) UnmarshalFromIni(prefix string, name string, section *ini.Section) error {
|
||||
err := section.MapTo(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = c.BaseVisitorConf.decorate(prefix, name, section)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Add custom logic unmarshal, if exists
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cfg *STCPVisitorConf) Check() error {
|
||||
if err := cfg.BaseVisitorConf.check(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Add custom logic validate, if exists
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// SUDP
|
||||
var _ VisitorConf = &SUDPVisitorConf{}
|
||||
|
||||
func (c *SUDPVisitorConf) Compare(conf VisitorConf) bool {
|
||||
cmp, ok := conf.(*SUDPVisitorConf)
|
||||
func (cfg *SUDPVisitorConf) Compare(cmp VisitorConf) bool {
|
||||
cmpConf, ok := cmp.(*SUDPVisitorConf)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
|
||||
if !c.BaseVisitorConf.compare(&cmp.BaseVisitorConf) {
|
||||
if !cfg.BaseVisitorConf.compare(&cmpConf.BaseVisitorConf) {
|
||||
return false
|
||||
}
|
||||
|
||||
@ -172,13 +127,13 @@ func (c *SUDPVisitorConf) Compare(conf VisitorConf) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (c *SUDPVisitorConf) UnmarshalFromIni(prefix string, name string, section *ini.Section) error {
|
||||
err := section.MapTo(c)
|
||||
func (cfg *SUDPVisitorConf) UnmarshalFromIni(prefix string, name string, section *ini.Section) error {
|
||||
err := section.MapTo(cfg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = c.BaseVisitorConf.decorate(prefix, name, section)
|
||||
err = cfg.BaseVisitorConf.decorate(prefix, name, section)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -188,26 +143,70 @@ func (c *SUDPVisitorConf) UnmarshalFromIni(prefix string, name string, section *
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cfg *SUDPVisitorConf) Check() error {
|
||||
if err := cfg.BaseVisitorConf.check(); err != nil {
|
||||
return err
|
||||
func (cfg *SUDPVisitorConf) Check() (err error) {
|
||||
if err = cfg.BaseVisitorConf.check(); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Add custom logic validate, if exists
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// STCP
|
||||
var _ VisitorConf = &STCPVisitorConf{}
|
||||
|
||||
func (cfg *STCPVisitorConf) Compare(cmp VisitorConf) bool {
|
||||
cmpConf, ok := cmp.(*STCPVisitorConf)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
|
||||
if !cfg.BaseVisitorConf.compare(&cmpConf.BaseVisitorConf) {
|
||||
return false
|
||||
}
|
||||
|
||||
// Add custom login equal, if exists
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func (cfg *STCPVisitorConf) UnmarshalFromIni(prefix string, name string, section *ini.Section) error {
|
||||
err := section.MapTo(cfg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = cfg.BaseVisitorConf.decorate(prefix, name, section)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Add custom logic unmarshal, if exists
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cfg *STCPVisitorConf) Check() (err error) {
|
||||
if err = cfg.BaseVisitorConf.check(); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Add custom logic validate, if exists
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// XTCP
|
||||
var _ VisitorConf = &XTCPVisitorConf{}
|
||||
|
||||
func (c *XTCPVisitorConf) Compare(conf VisitorConf) bool {
|
||||
cmp, ok := conf.(*XTCPVisitorConf)
|
||||
func (cfg *XTCPVisitorConf) Compare(cmp VisitorConf) bool {
|
||||
cmpConf, ok := cmp.(*XTCPVisitorConf)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
|
||||
if !c.BaseVisitorConf.compare(&cmp.BaseVisitorConf) {
|
||||
if !cfg.BaseVisitorConf.compare(&cmpConf.BaseVisitorConf) {
|
||||
return false
|
||||
}
|
||||
|
||||
@ -216,13 +215,13 @@ func (c *XTCPVisitorConf) Compare(conf VisitorConf) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (c *XTCPVisitorConf) UnmarshalFromIni(prefix string, name string, section *ini.Section) error {
|
||||
err := section.MapTo(c)
|
||||
func (cfg *XTCPVisitorConf) UnmarshalFromIni(prefix string, name string, section *ini.Section) error {
|
||||
err := section.MapTo(cfg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = c.BaseVisitorConf.decorate(prefix, name, section)
|
||||
err = cfg.BaseVisitorConf.decorate(prefix, name, section)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -232,12 +231,12 @@ func (c *XTCPVisitorConf) UnmarshalFromIni(prefix string, name string, section *
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cfg *XTCPVisitorConf) Check() error {
|
||||
if err := cfg.BaseVisitorConf.check(); err != nil {
|
||||
return err
|
||||
func (cfg *XTCPVisitorConf) Check() (err error) {
|
||||
if err = cfg.BaseVisitorConf.check(); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Add custom logic validate, if exists
|
||||
|
||||
return nil
|
||||
return
|
||||
}
|
||||
|
@ -1,3 +1,17 @@
|
||||
// Copyright 2020 The frp Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package config
|
||||
|
||||
import (
|
||||
|
@ -98,7 +98,7 @@ type TCPOutConf struct {
|
||||
|
||||
type TCPMuxOutConf struct {
|
||||
BaseOutConf
|
||||
config.DomainSpec
|
||||
config.DomainConf
|
||||
Multiplexer string `json:"multiplexer"`
|
||||
}
|
||||
|
||||
@ -109,14 +109,14 @@ type UDPOutConf struct {
|
||||
|
||||
type HTTPOutConf struct {
|
||||
BaseOutConf
|
||||
config.DomainSpec
|
||||
config.DomainConf
|
||||
Locations []string `json:"locations"`
|
||||
HostHeaderRewrite string `json:"host_header_rewrite"`
|
||||
}
|
||||
|
||||
type HTTPSOutConf struct {
|
||||
BaseOutConf
|
||||
config.DomainSpec
|
||||
config.DomainConf
|
||||
}
|
||||
|
||||
type STCPOutConf struct {
|
||||
|
Loading…
Reference in New Issue
Block a user