New entry point parser.

This commit is contained in:
Ludovic Fernandez 2017-10-13 15:04:02 +02:00 committed by Traefiker
parent 8af39bdaf7
commit 9598f646f5
2 changed files with 82 additions and 58 deletions

View file

@ -5,7 +5,6 @@ import (
"fmt"
"io/ioutil"
"os"
"regexp"
"strings"
"time"
@ -193,55 +192,52 @@ func (ep *EntryPoints) String() string {
// Set's argument is a string to be parsed to set the flag.
// It's a comma-separated list, so we split it.
func (ep *EntryPoints) Set(value string) error {
result, err := parseEntryPointsConfiguration(value)
if err != nil {
return err
}
result := parseEntryPointsConfiguration(value)
var configTLS *TLS
if len(result["TLS"]) > 0 {
if len(result["tls"]) > 0 {
certs := Certificates{}
if err := certs.Set(result["TLS"]); err != nil {
if err := certs.Set(result["tls"]); err != nil {
return err
}
configTLS = &TLS{
Certificates: certs,
}
} else if len(result["TLSACME"]) > 0 {
} else if len(result["tls_acme"]) > 0 {
configTLS = &TLS{
Certificates: Certificates{},
}
}
if len(result["CA"]) > 0 {
files := strings.Split(result["CA"], ",")
if len(result["ca"]) > 0 {
files := strings.Split(result["ca"], ",")
configTLS.ClientCAFiles = files
}
var redirect *Redirect
if len(result["RedirectEntryPoint"]) > 0 || len(result["RedirectRegex"]) > 0 || len(result["RedirectReplacement"]) > 0 {
if len(result["redirect_entrypoint"]) > 0 || len(result["redirect_regex"]) > 0 || len(result["redirect_replacement"]) > 0 {
redirect = &Redirect{
EntryPoint: result["RedirectEntryPoint"],
Regex: result["RedirectRegex"],
Replacement: result["RedirectReplacement"],
EntryPoint: result["redirect_entrypoint"],
Regex: result["redirect_regex"],
Replacement: result["redirect_replacement"],
}
}
whiteListSourceRange := []string{}
if len(result["WhiteListSourceRange"]) > 0 {
whiteListSourceRange = strings.Split(result["WhiteListSourceRange"], ",")
if len(result["whitelistsourcerange"]) > 0 {
whiteListSourceRange = strings.Split(result["whitelistsourcerange"], ",")
}
compress := toBool(result, "Compress")
compress := toBool(result, "compress")
var proxyProtocol *ProxyProtocol
if len(result["ProxyProtocol"]) > 0 {
trustedIPs := strings.Split(result["ProxyProtocol"], ",")
if len(result["proxyprotocol_trustedips"]) > 0 {
trustedIPs := strings.Split(result["proxyprotocol_trustedips"], ",")
proxyProtocol = &ProxyProtocol{
TrustedIPs: trustedIPs,
}
}
(*ep)[result["Name"]] = &EntryPoint{
Address: result["Address"],
(*ep)[result["name"]] = &EntryPoint{
Address: result["address"],
TLS: configTLS,
Redirect: redirect,
Compress: compress,
@ -252,20 +248,24 @@ func (ep *EntryPoints) Set(value string) error {
return nil
}
func parseEntryPointsConfiguration(value string) (map[string]string, error) {
regex := regexp.MustCompile(`(?:Name:(?P<Name>\S*))\s*(?:Address:(?P<Address>\S*))?\s*(?:TLS:(?P<TLS>\S*))?\s*(?P<TLSACME>TLS)?\s*(?:CA:(?P<CA>\S*))?\s*(?:Redirect\.EntryPoint:(?P<RedirectEntryPoint>\S*))?\s*(?:Redirect\.Regex:(?P<RedirectRegex>\S*))?\s*(?:Redirect\.Replacement:(?P<RedirectReplacement>\S*))?\s*(?:Compress:(?P<Compress>\S*))?\s*(?:WhiteListSourceRange:(?P<WhiteListSourceRange>\S*))?\s*(?:ProxyProtocol\.TrustedIPs:(?P<ProxyProtocol>\S*))?`)
match := regex.FindAllStringSubmatch(value, -1)
if match == nil {
return nil, fmt.Errorf("bad EntryPoints format: %s", value)
}
matchResult := match[0]
result := make(map[string]string)
for i, name := range regex.SubexpNames() {
if i != 0 && len(matchResult[i]) != 0 {
result[name] = matchResult[i]
func parseEntryPointsConfiguration(raw string) map[string]string {
sections := strings.Fields(raw)
config := make(map[string]string)
for _, part := range sections {
field := strings.SplitN(part, ":", 2)
name := strings.ToLower(strings.Replace(field[0], ".", "_", -1))
if len(field) > 1 {
config[name] = field[1]
} else {
if strings.EqualFold(name, "TLS") {
config["tls_acme"] = "TLS"
} else {
config[name] = ""
}
}
}
return result, nil
return config
}
func toBool(conf map[string]string, key string) bool {

View file

@ -16,36 +16,36 @@ func Test_parseEntryPointsConfiguration(t *testing.T) {
}{
{
name: "all parameters",
value: "Name:foo Address:bar TLS:goo TLS CA:car Redirect.EntryPoint:RedirectEntryPoint Redirect.Regex:RedirectRegex Redirect.Replacement:RedirectReplacement Compress:true WhiteListSourceRange:WhiteListSourceRange ProxyProtocol.TrustedIPs:192.168.0.1",
value: "Name:foo TLS:goo TLS CA:car Redirect.EntryPoint:RedirectEntryPoint Redirect.Regex:RedirectRegex Redirect.Replacement:RedirectReplacement Compress:true WhiteListSourceRange:WhiteListSourceRange ProxyProtocol.TrustedIPs:192.168.0.1 Address::8000",
expectedResult: map[string]string{
"Name": "foo",
"Address": "bar",
"CA": "car",
"TLS": "goo",
"TLSACME": "TLS",
"RedirectEntryPoint": "RedirectEntryPoint",
"RedirectRegex": "RedirectRegex",
"RedirectReplacement": "RedirectReplacement",
"WhiteListSourceRange": "WhiteListSourceRange",
"ProxyProtocol": "192.168.0.1",
"Compress": "true",
"name": "foo",
"address": ":8000",
"ca": "car",
"tls": "goo",
"tls_acme": "TLS",
"redirect_entrypoint": "RedirectEntryPoint",
"redirect_regex": "RedirectRegex",
"redirect_replacement": "RedirectReplacement",
"whitelistsourcerange": "WhiteListSourceRange",
"proxyprotocol_trustedips": "192.168.0.1",
"compress": "true",
},
},
{
name: "compress on",
value: "Name:foo Compress:on",
value: "name:foo Compress:on",
expectedResult: map[string]string{
"Name": "foo",
"Compress": "on",
"name": "foo",
"compress": "on",
},
},
{
name: "TLS",
value: "Name:foo TLS:goo TLS",
expectedResult: map[string]string{
"Name": "foo",
"TLS": "goo",
"TLSACME": "TLS",
"name": "foo",
"tls": "goo",
"tls_acme": "TLS",
},
},
}
@ -55,10 +55,7 @@ func Test_parseEntryPointsConfiguration(t *testing.T) {
t.Run(test.name, func(t *testing.T) {
t.Parallel()
conf, err := parseEntryPointsConfiguration(test.value)
if err != nil {
t.Error(err)
}
conf := parseEntryPointsConfiguration(test.value)
for key, value := range conf {
fmt.Println(key, value)
@ -133,11 +130,38 @@ func TestEntryPoints_Set(t *testing.T) {
expectedEntryPoint *EntryPoint
}{
{
name: "all parameters",
expression: "Name:foo Address:bar TLS:goo,gii TLS CA:car Redirect.EntryPoint:RedirectEntryPoint Redirect.Regex:RedirectRegex Redirect.Replacement:RedirectReplacement Compress:true WhiteListSourceRange:Range ProxyProtocol.TrustedIPs:192.168.0.1",
name: "all parameters camelcase",
expression: "Name:foo Address::8000 TLS:goo,gii TLS CA:car Redirect.EntryPoint:RedirectEntryPoint Redirect.Regex:RedirectRegex Redirect.Replacement:RedirectReplacement Compress:true WhiteListSourceRange:Range ProxyProtocol.TrustedIPs:192.168.0.1",
expectedEntryPointName: "foo",
expectedEntryPoint: &EntryPoint{
Address: "bar",
Address: ":8000",
Redirect: &Redirect{
EntryPoint: "RedirectEntryPoint",
Regex: "RedirectRegex",
Replacement: "RedirectReplacement",
},
Compress: true,
ProxyProtocol: &ProxyProtocol{
TrustedIPs: []string{"192.168.0.1"},
},
WhitelistSourceRange: []string{"Range"},
TLS: &TLS{
ClientCAFiles: []string{"car"},
Certificates: Certificates{
{
CertFile: FileOrContent("goo"),
KeyFile: FileOrContent("gii"),
},
},
},
},
},
{
name: "all parameters lowercase",
expression: "name:foo address::8000 tls:goo,gii tls ca:car redirect.entryPoint:RedirectEntryPoint redirect.regex:RedirectRegex redirect.replacement:RedirectReplacement compress:true whiteListSourceRange:Range proxyProtocol.TrustedIPs:192.168.0.1",
expectedEntryPointName: "foo",
expectedEntryPoint: &EntryPoint{
Address: ":8000",
Redirect: &Redirect{
EntryPoint: "RedirectEntryPoint",
Regex: "RedirectRegex",