summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthew Holt <mholt@users.noreply.github.com>2019-09-11 18:48:37 -0600
committerMatthew Holt <mholt@users.noreply.github.com>2019-09-11 18:48:37 -0600
commit005a11cf4b0af5bfbbb72f8572681b327675541c (patch)
treeba075312bab40d49e66cb9fe24f722896b99028c
parent194df652eb9d92bcc61d83055aebe176adc8fa2d (diff)
headers: New 'request_header' directive; handle Host header specially
Before this change, only response headers could be manipulated with the Caddyfile's 'header' directive. Also handle the request Host header specially, since the Go standard library treats it separately from the other header fields...
-rw-r--r--caddyconfig/httpcaddyfile/directives.go1
-rw-r--r--modules/caddyhttp/headers/caddyfile.go73
-rw-r--r--modules/caddyhttp/headers/headers.go11
3 files changed, 69 insertions, 16 deletions
diff --git a/caddyconfig/httpcaddyfile/directives.go b/caddyconfig/httpcaddyfile/directives.go
index 573db8d..14c5f44 100644
--- a/caddyconfig/httpcaddyfile/directives.go
+++ b/caddyconfig/httpcaddyfile/directives.go
@@ -30,6 +30,7 @@ var defaultDirectiveOrder = []string{
"rewrite",
"try_files",
"headers",
+ "request_header",
"encode",
"templates",
"redir",
diff --git a/modules/caddyhttp/headers/caddyfile.go b/modules/caddyhttp/headers/caddyfile.go
index 12ec8a0..d806005 100644
--- a/modules/caddyhttp/headers/caddyfile.go
+++ b/modules/caddyhttp/headers/caddyfile.go
@@ -24,9 +24,11 @@ import (
func init() {
httpcaddyfile.RegisterHandlerDirective("headers", parseCaddyfile)
+ httpcaddyfile.RegisterHandlerDirective("request_header", parseReqHdrCaddyfile)
}
-// parseCaddyfile sets up the handler from Caddyfile tokens. Syntax:
+// parseCaddyfile sets up the handler for response headers from
+// Caddyfile tokens. Syntax:
//
// headers [<matcher>] [[+|-]<field> <value>] {
// [+][<field>] [<value>]
@@ -43,9 +45,11 @@ func parseCaddyfile(h httpcaddyfile.Helper) (caddyhttp.MiddlewareHandler, error)
if h.NextArg() {
hasArgs = true
field := h.Val()
- h.NextArg()
- value := h.Val()
- processCaddyfileLine(hdr, field, value)
+ var value string
+ if h.NextArg() {
+ value = h.Val()
+ }
+ processCaddyfileLineRespHdr(hdr, field, value)
}
// if not, they should be in a block
@@ -58,31 +62,68 @@ func parseCaddyfile(h httpcaddyfile.Helper) (caddyhttp.MiddlewareHandler, error)
if h.NextArg() {
value = h.Val()
}
- processCaddyfileLine(hdr, field, value)
+ processCaddyfileLineRespHdr(hdr, field, value)
}
}
return hdr, nil
}
-func processCaddyfileLine(hdr *Headers, field, value string) {
- if strings.HasPrefix(field, "+") {
- if hdr.Response == nil {
- hdr.Response = &RespHeaderOps{HeaderOps: new(HeaderOps)}
+// parseReqHdrCaddyfile sets up the handler for request headers
+// from Caddyfile tokens. Syntax:
+//
+// request_header [<matcher>] [[+|-]<field> <value>]
+//
+func parseReqHdrCaddyfile(h httpcaddyfile.Helper) (caddyhttp.MiddlewareHandler, error) {
+ hdr := new(Headers)
+ for h.Next() {
+ if !h.NextArg() {
+ return nil, h.ArgErr()
+ }
+ field := h.Val()
+ var value string
+ if h.NextArg() {
+ value = h.Val()
+ }
+
+ if hdr.Request == nil {
+ hdr.Request = new(HeaderOps)
+ }
+ if strings.HasPrefix(field, "+") {
+ if hdr.Request.Add == nil {
+ hdr.Request.Add = make(http.Header)
+ }
+ hdr.Request.Add.Set(field[1:], value)
+ } else if strings.HasPrefix(field, "-") {
+ hdr.Request.Delete = append(hdr.Request.Delete, field[1:])
+ } else {
+ if hdr.Request.Set == nil {
+ hdr.Request.Set = make(http.Header)
+ }
+ hdr.Request.Set.Set(field, value)
+ }
+
+ if h.NextArg() {
+ return nil, h.ArgErr()
+ }
+ }
+ return hdr, nil
+}
+
+func processCaddyfileLineRespHdr(hdr *Headers, field, value string) {
+ if hdr.Response == nil {
+ hdr.Response = &RespHeaderOps{
+ HeaderOps: new(HeaderOps),
+ Deferred: true,
}
+ }
+ if strings.HasPrefix(field, "+") {
if hdr.Response.Add == nil {
hdr.Response.Add = make(http.Header)
}
hdr.Response.Add.Set(field[1:], value)
} else if strings.HasPrefix(field, "-") {
- if hdr.Response == nil {
- hdr.Response = &RespHeaderOps{HeaderOps: new(HeaderOps)}
- }
hdr.Response.Delete = append(hdr.Response.Delete, field[1:])
- hdr.Response.Deferred = true
} else {
- if hdr.Response == nil {
- hdr.Response = &RespHeaderOps{HeaderOps: new(HeaderOps)}
- }
if hdr.Response.Set == nil {
hdr.Response.Set = make(http.Header)
}
diff --git a/modules/caddyhttp/headers/headers.go b/modules/caddyhttp/headers/headers.go
index e740004..ba9d89d 100644
--- a/modules/caddyhttp/headers/headers.go
+++ b/modules/caddyhttp/headers/headers.go
@@ -58,7 +58,18 @@ type RespHeaderOps struct {
func (h Headers) ServeHTTP(w http.ResponseWriter, r *http.Request, next caddyhttp.Handler) error {
repl := r.Context().Value(caddy.ReplacerCtxKey).(caddy.Replacer)
+
apply(h.Request, r.Header, repl)
+
+ // request header's Host is handled specially by the
+ // Go standard library, so if that header was changed,
+ // change it in the Host field since the Header won't
+ // be used
+ if intendedHost := r.Header.Get("Host"); intendedHost != "" {
+ r.Host = intendedHost
+ r.Header.Del("Host")
+ }
+
if h.Response != nil {
if h.Response.Deferred || h.Response.Require != nil {
w = &responseWriterWrapper{