Commit a762bec0 authored by William Bezuidenhout's avatar William Bezuidenhout

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()`
parent b75016e6
...@@ -20,13 +20,14 @@ type Headers struct { ...@@ -20,13 +20,14 @@ type Headers struct {
// ServeHTTP implements the middleware.Handler interface and serves requests, // ServeHTTP implements the middleware.Handler interface and serves requests,
// setting headers on the response according to the configured rules. // setting headers on the response according to the configured rules.
func (h Headers) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error) { func (h Headers) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error) {
replacer := middleware.NewReplacer(r, nil, "")
for _, rule := range h.Rules { for _, rule := range h.Rules {
if middleware.Path(r.URL.Path).Matches(rule.Path) { if middleware.Path(r.URL.Path).Matches(rule.Path) {
for _, header := range rule.Headers { for _, header := range rule.Headers {
if strings.HasPrefix(header.Name, "-") { if strings.HasPrefix(header.Name, "-") {
w.Header().Del(strings.TrimLeft(header.Name, "-")) w.Header().Del(strings.TrimLeft(header.Name, "-"))
} else { } else {
w.Header().Set(header.Name, header.Value) w.Header().Set(header.Name, replacer.Replace(header.Value))
} }
} }
} }
......
...@@ -3,12 +3,17 @@ package headers ...@@ -3,12 +3,17 @@ package headers
import ( import (
"net/http" "net/http"
"net/http/httptest" "net/http/httptest"
"os"
"testing" "testing"
"github.com/mholt/caddy/middleware" "github.com/mholt/caddy/middleware"
) )
func TestHeaders(t *testing.T) { 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 { for i, test := range []struct {
from string from string
name string name string
...@@ -17,6 +22,7 @@ func TestHeaders(t *testing.T) { ...@@ -17,6 +22,7 @@ func TestHeaders(t *testing.T) {
{"/a", "Foo", "Bar"}, {"/a", "Foo", "Bar"},
{"/a", "Bar", ""}, {"/a", "Bar", ""},
{"/a", "Baz", ""}, {"/a", "Baz", ""},
{"/a", "ServerName", hostname},
{"/b", "Foo", ""}, {"/b", "Foo", ""},
{"/b", "Bar", "Removed in /a"}, {"/b", "Bar", "Removed in /a"},
} { } {
...@@ -27,6 +33,7 @@ func TestHeaders(t *testing.T) { ...@@ -27,6 +33,7 @@ func TestHeaders(t *testing.T) {
Rules: []Rule{ Rules: []Rule{
{Path: "/a", Headers: []Header{ {Path: "/a", Headers: []Header{
{Name: "Foo", Value: "Bar"}, {Name: "Foo", Value: "Bar"},
{Name: "ServerName", Value: "{hostname}"},
{Name: "-Bar"}, {Name: "-Bar"},
}}, }},
}, },
......
...@@ -4,6 +4,7 @@ import ( ...@@ -4,6 +4,7 @@ import (
"net" "net"
"net/http" "net/http"
"net/url" "net/url"
"os"
"path" "path"
"strconv" "strconv"
"strings" "strings"
...@@ -52,6 +53,13 @@ func NewReplacer(r *http.Request, rr *ResponseRecorder, emptyValue string) Repla ...@@ -52,6 +53,13 @@ func NewReplacer(r *http.Request, rr *ResponseRecorder, emptyValue string) Repla
} }
return "http" return "http"
}(), }(),
"{hostname}": func() string {
name, err := os.Hostname()
if err != nil {
return ""
}
return name
}(),
"{host}": r.Host, "{host}": r.Host,
"{path}": r.URL.Path, "{path}": r.URL.Path,
"{path_escaped}": url.QueryEscape(r.URL.Path), "{path_escaped}": url.QueryEscape(r.URL.Path),
......
...@@ -3,6 +3,7 @@ package middleware ...@@ -3,6 +3,7 @@ package middleware
import ( import (
"net/http" "net/http"
"net/http/httptest" "net/http/httptest"
"os"
"strings" "strings"
"testing" "testing"
) )
...@@ -53,6 +54,14 @@ func TestReplace(t *testing.T) { ...@@ -53,6 +54,14 @@ func TestReplace(t *testing.T) {
request.Header.Set("ShorterVal", "1") request.Header.Set("ShorterVal", "1")
repl := NewReplacer(request, recordRequest, "-") 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 { 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) t.Errorf("{host} replacement: expected '%s', got '%s'", expected, actual)
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment