mirror of
https://github.com/caddyserver/caddy.git
synced 2024-11-26 10:13:39 +08:00
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()`
This commit is contained in:
parent
b75016e646
commit
a762bec06d
|
@ -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
|
||||||
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) {
|
||||||
{"/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) {
|
||||||
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 (
|
||||||
"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
|
||||||
}
|
}
|
||||||
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
|
||||||
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) {
|
||||||
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)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user