From e74149eed2333b8a4d425a96fb44aa5fdec0cb4f Mon Sep 17 00:00:00 2001 From: Ingo Oppermann Date: Wed, 24 Aug 2022 12:29:54 +0300 Subject: [PATCH] Allow glob pattern in placerholder matching --- glob/glob.go | 3 +++ restream/app/process.go | 5 +++++ restream/replace/replace.go | 14 +++++++++----- restream/replace/replace_test.go | 31 +++++++++++++++++++++++++++---- 4 files changed, 44 insertions(+), 9 deletions(-) diff --git a/glob/glob.go b/glob/glob.go index 690daf61..89b57f00 100644 --- a/glob/glob.go +++ b/glob/glob.go @@ -4,6 +4,9 @@ import ( "github.com/gobwas/glob" ) +// Match returns whether the name matches the glob pattern, also considering +// one or several optionnal separator. An error is only returned if the pattern +// is invalid. func Match(pattern, name string, separators ...rune) (bool, error) { g, err := glob.Compile(pattern, separators...) if err != nil { diff --git a/restream/app/process.go b/restream/app/process.go index b8fb75d8..cbab2c40 100644 --- a/restream/app/process.go +++ b/restream/app/process.go @@ -84,6 +84,7 @@ func (config *Config) ResolvePlaceholders(r replace.Replacer) { for i, option := range config.Options { // Replace any known placeholders option = r.Replace(option, "diskfs", "") + option = r.Replace(option, "fs:disk", "") config.Options[i] = option } @@ -98,6 +99,7 @@ func (config *Config) ResolvePlaceholders(r replace.Replacer) { input.Address = r.Replace(input.Address, "reference", config.Reference) input.Address = r.Replace(input.Address, "diskfs", "") input.Address = r.Replace(input.Address, "memfs", "") + input.Address = r.Replace(input.Address, "fs:*", "") input.Address = r.Replace(input.Address, "rtmp", "") input.Address = r.Replace(input.Address, "srt", "") @@ -108,6 +110,7 @@ func (config *Config) ResolvePlaceholders(r replace.Replacer) { option = r.Replace(option, "reference", config.Reference) option = r.Replace(option, "diskfs", "") option = r.Replace(option, "memfs", "") + option = r.Replace(option, "fs:*", "") input.Options[j] = option } @@ -124,6 +127,7 @@ func (config *Config) ResolvePlaceholders(r replace.Replacer) { output.Address = r.Replace(output.Address, "reference", config.Reference) output.Address = r.Replace(output.Address, "diskfs", "") output.Address = r.Replace(output.Address, "memfs", "") + output.Address = r.Replace(output.Address, "fs:*", "") output.Address = r.Replace(output.Address, "rtmp", "") output.Address = r.Replace(output.Address, "srt", "") @@ -134,6 +138,7 @@ func (config *Config) ResolvePlaceholders(r replace.Replacer) { option = r.Replace(option, "reference", config.Reference) option = r.Replace(option, "diskfs", "") option = r.Replace(option, "memfs", "") + option = r.Replace(option, "fs:*", "") output.Options[j] = option } diff --git a/restream/replace/replace.go b/restream/replace/replace.go index 47885a38..4c1760f6 100644 --- a/restream/replace/replace.go +++ b/restream/replace/replace.go @@ -4,6 +4,8 @@ import ( "net/url" "regexp" "strings" + + "github.com/datarhei/core/v16/glob" ) type Replacer interface { @@ -24,7 +26,8 @@ type Replacer interface { // the value of the corresponding key in the parameters. // If the value is an empty string, the registered templates will be searched for that // placeholder. If no template is found, the placeholder will be replaced by the empty string. - // A placeholder name may consist on of the letters a-z. + // A placeholder name may consist on of the letters a-z and ':'. The placeholder may contain + // a glob pattern to find the appropriate template. Replace(str, placeholder, value string) string } @@ -39,8 +42,8 @@ type replacer struct { func New() Replacer { r := &replacer{ templates: make(map[string]func() string), - re: regexp.MustCompile(`{([a-z]+)(?:\^(.))?(?:,(.*?))?}`), - templateRe: regexp.MustCompile(`{([a-z]+)}`), + re: regexp.MustCompile(`{([a-z:]+)(?:\^(.))?(?:,(.*?))?}`), + templateRe: regexp.MustCompile(`{([a-z:]+)}`), } return r @@ -57,7 +60,8 @@ func (r *replacer) RegisterTemplateFunc(placeholder string, template func() stri func (r *replacer) Replace(str, placeholder, value string) string { str = r.re.ReplaceAllStringFunc(str, func(match string) string { matches := r.re.FindStringSubmatch(match) - if matches[1] != placeholder { + + if ok, _ := glob.Match(placeholder, matches[1], ':'); !ok { return match } @@ -66,7 +70,7 @@ func (r *replacer) Replace(str, placeholder, value string) string { // Check for a registered template if len(v) == 0 { - tmplFunc, ok := r.templates[placeholder] + tmplFunc, ok := r.templates[matches[1]] if ok { v = tmplFunc() } diff --git a/restream/replace/replace_test.go b/restream/replace/replace_test.go index 7474775d..a1ea491e 100644 --- a/restream/replace/replace_test.go +++ b/restream/replace/replace_test.go @@ -34,15 +34,29 @@ func TestReplace(t *testing.T) { func TestReplaceTemplate(t *testing.T) { r := New() - r.RegisterTemplate("foobar", "Hello {who}! {what}?") + r.RegisterTemplate("foo:bar", "Hello {who}! {what}?") - replaced := r.Replace("{foobar,who=World}", "foobar", "") + replaced := r.Replace("{foo:bar,who=World}", "foo:bar", "") require.Equal(t, "Hello World! {what}?", replaced) - replaced = r.Replace("{foobar,who=World,what=E%3dmc^2}", "foobar", "") + replaced = r.Replace("{foo:bar,who=World,what=E%3dmc^2}", "foo:bar", "") require.Equal(t, "Hello World! E=mc^2?", replaced) - replaced = r.Replace("{foobar^:,who=World,what=E%3dmc:2}", "foobar", "") + replaced = r.Replace("{foo:bar^:,who=World,what=E%3dmc:2}", "foo:bar", "") + require.Equal(t, "Hello World! E=mc\\\\:2?", replaced) +} + +func TestReplaceTemplateFunc(t *testing.T) { + r := New() + r.RegisterTemplateFunc("foo:bar", func() string { return "Hello {who}! {what}?" }) + + replaced := r.Replace("{foo:bar,who=World}", "foo:bar", "") + require.Equal(t, "Hello World! {what}?", replaced) + + replaced = r.Replace("{foo:bar,who=World,what=E%3dmc^2}", "foo:bar", "") + require.Equal(t, "Hello World! E=mc^2?", replaced) + + replaced = r.Replace("{foo:bar^:,who=World,what=E%3dmc:2}", "foo:bar", "") require.Equal(t, "Hello World! E=mc\\\\:2?", replaced) } @@ -62,3 +76,12 @@ func TestReplaceCompileTemplate(t *testing.T) { require.Equal(t, e[2], replaced, e[0]) } } + +func TestReplaceGlob(t *testing.T) { + r := New() + r.RegisterTemplate("foo:bar", "Hello foobar") + r.RegisterTemplate("foo:baz", "Hello foobaz") + + replaced := r.Replace("{foo:baz}, {foo:bar}", "foo:*", "") + require.Equal(t, "Hello foobaz, Hello foobar", replaced) +}