From 3b19aa2b5a77440f8cb4d11e80937935d187f1cd Mon Sep 17 00:00:00 2001
From: Francis Lavoie <lavofr@gmail.com>
Date: Thu, 15 Jun 2023 19:18:55 -0400
Subject: [PATCH] headers: Allow `>` to defer shortcut for replacements (#5574)

---
 caddytest/integration/caddyfile_adapt/header.txt | 15 +++++++++++++++
 modules/caddyhttp/headers/caddyfile.go           |  6 +++++-
 2 files changed, 20 insertions(+), 1 deletion(-)

diff --git a/caddytest/integration/caddyfile_adapt/header.txt b/caddytest/integration/caddyfile_adapt/header.txt
index 95c1474bf..ec2a842a3 100644
--- a/caddytest/integration/caddyfile_adapt/header.txt
+++ b/caddytest/integration/caddyfile_adapt/header.txt
@@ -18,6 +18,7 @@
 		+Link "Bar"
 	}
 	header >Set Defer
+	header >Replace Deferred Replacement
 }
 ----------
 {
@@ -148,6 +149,20 @@
 											]
 										}
 									}
+								},
+								{
+									"handler": "headers",
+									"response": {
+										"deferred": true,
+										"replace": {
+											"Replace": [
+												{
+													"replace": "Replacement",
+													"search_regexp": "Deferred"
+												}
+											]
+										}
+									}
 								}
 							]
 						}
diff --git a/modules/caddyhttp/headers/caddyfile.go b/modules/caddyhttp/headers/caddyfile.go
index d7e644c3b..2b069100b 100644
--- a/modules/caddyhttp/headers/caddyfile.go
+++ b/modules/caddyhttp/headers/caddyfile.go
@@ -247,10 +247,14 @@ func applyHeaderOp(ops *HeaderOps, respHeaderOps *RespHeaderOps, field, value, r
 		respHeaderOps.Set.Set(field, value)
 
 	case replacement != "": // replace
+		// allow defer shortcut for replace syntax
+		if strings.HasPrefix(field, ">") && respHeaderOps != nil {
+			respHeaderOps.Deferred = true
+		}
 		if ops.Replace == nil {
 			ops.Replace = make(map[string][]Replacement)
 		}
-		field = strings.TrimLeft(field, "+-?")
+		field = strings.TrimLeft(field, "+-?>")
 		ops.Replace[field] = append(
 			ops.Replace[field],
 			Replacement{