From fec7fa8bfda713e8042b9bbf9a480c7792b78c41 Mon Sep 17 00:00:00 2001 From: Matthew Holt Date: Mon, 20 May 2019 10:59:20 -0600 Subject: Implement most of static file server; refactor and improve Replacer --- replacer.go | 104 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 replacer.go (limited to 'replacer.go') diff --git a/replacer.go b/replacer.go new file mode 100644 index 0000000..6d7865a --- /dev/null +++ b/replacer.go @@ -0,0 +1,104 @@ +package caddy2 + +import ( + "os" + "path/filepath" + "runtime" + "strings" +) + +// Replacer can replace values in strings. +type Replacer interface { + Set(variable, value string) + Delete(variable string) + Map(func() map[string]string) + ReplaceAll(input, empty string) string +} + +// NewReplacer returns a new Replacer. +func NewReplacer() Replacer { + rep := &replacer{ + static: make(map[string]string), + } + rep.providers = []ReplacementsFunc{ + defaultReplacements, + func() map[string]string { return rep.static }, + } + return rep +} + +type replacer struct { + providers []ReplacementsFunc + static map[string]string +} + +// Map augments the map of replacements with those returned +// by the given replacements function. The function is only +// executed at replace-time. +func (r *replacer) Map(replacements func() map[string]string) { + r.providers = append(r.providers, replacements) +} + +// Set sets a custom variable to a static value. +func (r *replacer) Set(variable, value string) { + r.static[variable] = value +} + +// Delete removes a variable with a static value +// that was created using Set. +func (r *replacer) Delete(variable string) { + delete(r.static, variable) +} + +// ReplaceAll replaces placeholders in input with their values. +// Values that are empty string will be substituted with the +// empty parameter. +func (r *replacer) ReplaceAll(input, empty string) string { + if !strings.Contains(input, phOpen) { + return input + } + for _, replacements := range r.providers { + for key, val := range replacements() { + if val == "" { + val = empty + } + input = strings.ReplaceAll(input, phOpen+key+phClose, val) + } + } + return input +} + +// ReplacementsFunc is a function that returns replacements, +// which is variable names mapped to their values. The +// function will be evaluated only at replace-time to ensure +// the most current values are mapped. +type ReplacementsFunc func() map[string]string + +var defaultReplacements = func() map[string]string { + m := map[string]string{ + "system.hostname": func() string { + // OK if there is an error; just return empty string + name, _ := os.Hostname() + return name + }(), + "system.slash": string(filepath.Separator), + "system.os": runtime.GOOS, + "system.arch": runtime.GOARCH, + } + + // add environment variables + for _, keyval := range os.Environ() { + parts := strings.SplitN(keyval, "=", 2) + if len(parts) != 2 { + continue + } + m["env."+strings.ToUpper(parts[0])] = parts[1] + } + + return m +} + +// ReplacerCtxKey is the context key for a replacer. +const ReplacerCtxKey CtxKey = "replacer" + +const phOpen, phClose = "{", "}" -- cgit v1.2.3