From b783caaaeddaee61384b963ce48bfe385a65b9a5 Mon Sep 17 00:00:00 2001
From: Gyula Voros <gyulavoros87@gmail.com>
Date: Thu, 17 Nov 2016 05:41:53 +0100
Subject: [PATCH] Filter empty headers (#1239)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* Filter empty headers

Some web servers (e.g. Jetty 9.3) don’t like HTTP headers with empty values. This commit filters header replacements with zero length.

* Extend tests to verify removal of empty headers

* Handle add-header case

* Change - Use short variable assignment
---
 caddyhttp/proxy/proxy.go      | 10 ++++++++--
 caddyhttp/proxy/proxy_test.go | 12 ++++++++++++
 2 files changed, 20 insertions(+), 2 deletions(-)

diff --git a/caddyhttp/proxy/proxy.go b/caddyhttp/proxy/proxy.go
index 11f2d5d01..fe959791b 100644
--- a/caddyhttp/proxy/proxy.go
+++ b/caddyhttp/proxy/proxy.go
@@ -287,12 +287,18 @@ func mutateHeadersByRules(headers, rules http.Header, repl httpserver.Replacer)
 	for ruleField, ruleValues := range rules {
 		if strings.HasPrefix(ruleField, "+") {
 			for _, ruleValue := range ruleValues {
-				headers.Add(strings.TrimPrefix(ruleField, "+"), repl.Replace(ruleValue))
+				replacement := repl.Replace(ruleValue)
+				if len(replacement) > 0 {
+					headers.Add(strings.TrimPrefix(ruleField, "+"), replacement)
+				}
 			}
 		} else if strings.HasPrefix(ruleField, "-") {
 			headers.Del(strings.TrimPrefix(ruleField, "-"))
 		} else if len(ruleValues) > 0 {
-			headers.Set(ruleField, repl.Replace(ruleValues[len(ruleValues)-1]))
+			replacement := repl.Replace(ruleValues[len(ruleValues)-1])
+			if len(replacement) > 0 {
+				headers.Set(ruleField, replacement)
+			}
 		}
 	}
 }
diff --git a/caddyhttp/proxy/proxy_test.go b/caddyhttp/proxy/proxy_test.go
index 290cae938..fe3772786 100644
--- a/caddyhttp/proxy/proxy_test.go
+++ b/caddyhttp/proxy/proxy_test.go
@@ -407,8 +407,10 @@ func TestUpstreamHeadersUpdate(t *testing.T) {
 		"Upgrade":    {"{>Upgrade}"},
 		"+Merge-Me":  {"Merge-Value"},
 		"+Add-Me":    {"Add-Value"},
+		"+Add-Empty": {"{}"},
 		"-Remove-Me": {""},
 		"Replace-Me": {"{hostname}"},
+		"Clear-Me":   {""},
 		"Host":       {"{>Host}"},
 	}
 	// set up proxy
@@ -448,6 +450,11 @@ func TestUpstreamHeadersUpdate(t *testing.T) {
 			headerKey, expect, got)
 	}
 
+	headerKey = "Add-Empty"
+	if _, ok := actualHeaders[headerKey]; ok {
+		t.Errorf("Request sent to upstream backend should not contain empty %v header", headerKey)
+	}
+
 	headerKey = "Remove-Me"
 	if _, ok := actualHeaders[headerKey]; ok {
 		t.Errorf("Request sent to upstream backend should not contain %v header", headerKey)
@@ -461,6 +468,11 @@ func TestUpstreamHeadersUpdate(t *testing.T) {
 			headerKey, expect, got)
 	}
 
+	headerKey = "Clear-Me"
+	if _, ok := actualHeaders[headerKey]; ok {
+		t.Errorf("Request sent to upstream backend should not contain empty %v header", headerKey)
+	}
+
 	if actualHost != expectHost {
 		t.Errorf("Request sent to upstream backend should have value of Host with %s, but got %s", expectHost, actualHost)
 	}