From a762bec06deea849a62bce3383c1ca0b84ab314d Mon Sep 17 00:00:00 2001 From: William Bezuidenhout Date: Sat, 16 Apr 2016 19:03:56 +0200 Subject: [PATCH] Add hostname placeholder. Header uses replacer On matched header rules, replacer is used to replace any placeholders defined in header rules iex. X-Backend {hostname} where {hostname} will be replaced by the hostname key present in the replacer hostname key added to replacer. The value is determined by the output of `os.Hostname()` --- middleware/headers/headers.go | 3 ++- middleware/headers/headers_test.go | 7 +++++++ middleware/replacer.go | 8 ++++++++ middleware/replacer_test.go | 9 +++++++++ 4 files changed, 26 insertions(+), 1 deletion(-) diff --git a/middleware/headers/headers.go b/middleware/headers/headers.go index e71e9fe3..831a1afb 100644 --- a/middleware/headers/headers.go +++ b/middleware/headers/headers.go @@ -20,13 +20,14 @@ type Headers struct { // ServeHTTP implements the middleware.Handler interface and serves requests, // setting headers on the response according to the configured rules. func (h Headers) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error) { + replacer := middleware.NewReplacer(r, nil, "") for _, rule := range h.Rules { if middleware.Path(r.URL.Path).Matches(rule.Path) { for _, header := range rule.Headers { if strings.HasPrefix(header.Name, "-") { w.Header().Del(strings.TrimLeft(header.Name, "-")) } else { - w.Header().Set(header.Name, header.Value) + w.Header().Set(header.Name, replacer.Replace(header.Value)) } } } diff --git a/middleware/headers/headers_test.go b/middleware/headers/headers_test.go index e6285897..0627902d 100644 --- a/middleware/headers/headers_test.go +++ b/middleware/headers/headers_test.go @@ -3,12 +3,17 @@ package headers import ( "net/http" "net/http/httptest" + "os" "testing" "github.com/mholt/caddy/middleware" ) func TestHeaders(t *testing.T) { + hostname, err := os.Hostname() + if err != nil { + t.Fatalf("Could not determine hostname: %v", err) + } for i, test := range []struct { from string name string @@ -17,6 +22,7 @@ func TestHeaders(t *testing.T) { {"/a", "Foo", "Bar"}, {"/a", "Bar", ""}, {"/a", "Baz", ""}, + {"/a", "ServerName", hostname}, {"/b", "Foo", ""}, {"/b", "Bar", "Removed in /a"}, } { @@ -27,6 +33,7 @@ func TestHeaders(t *testing.T) { Rules: []Rule{ {Path: "/a", Headers: []Header{ {Name: "Foo", Value: "Bar"}, + {Name: "ServerName", Value: "{hostname}"}, {Name: "-Bar"}, }}, }, diff --git a/middleware/replacer.go b/middleware/replacer.go index 85659ca0..6748f606 100644 --- a/middleware/replacer.go +++ b/middleware/replacer.go @@ -4,6 +4,7 @@ import ( "net" "net/http" "net/url" + "os" "path" "strconv" "strings" @@ -52,6 +53,13 @@ func NewReplacer(r *http.Request, rr *ResponseRecorder, emptyValue string) Repla } return "http" }(), + "{hostname}": func() string { + name, err := os.Hostname() + if err != nil { + return "" + } + return name + }(), "{host}": r.Host, "{path}": r.URL.Path, "{path_escaped}": url.QueryEscape(r.URL.Path), diff --git a/middleware/replacer_test.go b/middleware/replacer_test.go index 4ffdfba1..f5d50b04 100644 --- a/middleware/replacer_test.go +++ b/middleware/replacer_test.go @@ -3,6 +3,7 @@ package middleware import ( "net/http" "net/http/httptest" + "os" "strings" "testing" ) @@ -53,6 +54,14 @@ func TestReplace(t *testing.T) { request.Header.Set("ShorterVal", "1") repl := NewReplacer(request, recordRequest, "-") + hostname, err := os.Hostname() + if err != nil { + t.Fatal("Failed to determine hostname\n") + } + if expected, actual := "This hostname is "+hostname, repl.Replace("This hostname is {hostname}"); expected != actual { + t.Errorf("{hostname} replacement: expected '%s', got '%s'", expected, actual) + } + if expected, actual := "This host is localhost.", repl.Replace("This host is {host}."); expected != actual { t.Errorf("{host} replacement: expected '%s', got '%s'", expected, actual) }