caddyhttp: Support placeholders in MatchHost (#2810)

* Replace global placeholders in host matcher

* caddyhttp: Fix panic on MatchHost tests
This commit is contained in:
Pascal 2019-10-14 19:29:36 +02:00 committed by Matt Holt
parent fcd8869f51
commit bc738991b6
3 changed files with 58 additions and 0 deletions

View File

@ -273,6 +273,8 @@ func (app *App) automaticHTTPS() error {
// addresses to the routes that do HTTP->HTTPS redirects
lnAddrRedirRoutes := make(map[string]Route)
repl := caddy.NewReplacer()
for srvName, srv := range app.Servers {
srv.tlsApp = tlsApp
@ -294,6 +296,7 @@ func (app *App) automaticHTTPS() error {
for _, m := range matcherSet {
if hm, ok := m.(*MatchHost); ok {
for _, d := range *hm {
d = repl.ReplaceAll(d, "")
if certmagic.HostQualifies(d) &&
!srv.AutoHTTPS.Skipped(d, srv.AutoHTTPS.Skip) {
domainSet[d] = struct{}{}

View File

@ -118,8 +118,11 @@ func (m MatchHost) Match(r *http.Request) bool {
reqHost = strings.TrimSuffix(reqHost, "]")
}
repl := r.Context().Value(caddy.ReplacerCtxKey).(caddy.Replacer)
outer:
for _, host := range m {
host = repl.ReplaceAll(host, "")
if strings.Contains(host, "*") {
patternParts := strings.Split(host, ".")
incomingParts := strings.Split(reqHost, ".")

View File

@ -20,12 +20,18 @@ import (
"net/http"
"net/http/httptest"
"net/url"
"os"
"testing"
"github.com/caddyserver/caddy/v2"
)
func TestHostMatcher(t *testing.T) {
err := os.Setenv("GO_BENCHMARK_DOMAIN", "localhost")
if err != nil {
t.Errorf("error while setting up environment: %v", err)
}
for i, tc := range []struct {
match MatchHost
input string
@ -106,8 +112,22 @@ func TestHostMatcher(t *testing.T) {
input: "example.com:5555",
expect: true,
},
{
match: MatchHost{"{env.GO_BENCHMARK_DOMAIN}"},
input: "localhost",
expect: true,
},
{
match: MatchHost{"{env.GO_NONEXISTENT}"},
input: "localhost",
expect: false,
},
} {
req := &http.Request{Host: tc.input}
repl := caddy.NewReplacer()
ctx := context.WithValue(req.Context(), caddy.ReplacerCtxKey, repl)
req = req.WithContext(ctx)
actual := tc.match.Match(req)
if actual != tc.expect {
t.Errorf("Test %d %v: Expected %t, got %t for '%s'", i, tc.match, tc.expect, actual, tc.input)
@ -518,3 +538,35 @@ func TestResponseMatcher(t *testing.T) {
}
}
}
func BenchmarkHostMatcherWithoutPlaceholder(b *testing.B) {
req := &http.Request{Host: "localhost"}
repl := caddy.NewReplacer()
ctx := context.WithValue(req.Context(), caddy.ReplacerCtxKey, repl)
req = req.WithContext(ctx)
match := MatchHost{"localhost"}
b.ResetTimer()
for i := 0; i < b.N; i++ {
match.Match(req)
}
}
func BenchmarkHostMatcherWithPlaceholder(b *testing.B) {
err := os.Setenv("GO_BENCHMARK_DOMAIN", "localhost")
if err != nil {
b.Errorf("error while setting up environment: %v", err)
}
req := &http.Request{Host: "localhost"}
repl := caddy.NewReplacer()
ctx := context.WithValue(req.Context(), caddy.ReplacerCtxKey, repl)
req = req.WithContext(ctx)
match := MatchHost{"{env.GO_BENCHMARK_DOMAIN}"}
b.ResetTimer()
for i := 0; i < b.N; i++ {
match.Match(req)
}
}