summaryrefslogtreecommitdiff
path: root/replacer.go
diff options
context:
space:
mode:
authorMatthew Holt <mholt@users.noreply.github.com>2019-05-20 10:59:20 -0600
committerMatthew Holt <mholt@users.noreply.github.com>2019-05-20 10:59:20 -0600
commitfec7fa8bfda713e8042b9bbf9a480c7792b78c41 (patch)
tree53d86ab50ef7d15e9688c81b6618024c4243c98d /replacer.go
parent1a20fe330ecc39e8b98b5669b836f3b1b185f622 (diff)
Implement most of static file server; refactor and improve Replacer
Diffstat (limited to 'replacer.go')
-rw-r--r--replacer.go104
1 files changed, 104 insertions, 0 deletions
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 = "{", "}"