|  | @ -91,12 +91,13 @@ func parseCaddyfile(h httpcaddyfile.Helper) (caddyhttp.MiddlewareHandler, error) | 
			
		
	
		
		
			
				
					|  |  | //             ...
 |  |  | //             ...
 | 
			
		
	
		
		
			
				
					|  |  | //         }
 |  |  | //         }
 | 
			
		
	
		
		
			
				
					|  |  | //
 |  |  | //
 | 
			
		
	
		
		
			
				
					
					|  |  | //         # handle responses
 |  |  | //         # intercepting responses
 | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					|  |  | //         @name {
 |  |  | //         @name {
 | 
			
		
	
		
		
			
				
					|  |  | //             status <code...>
 |  |  | //             status <code...>
 | 
			
		
	
		
		
			
				
					|  |  | //             header <field> [<value>]
 |  |  | //             header <field> [<value>]
 | 
			
		
	
		
		
			
				
					|  |  | //         }
 |  |  | //         }
 | 
			
		
	
		
		
			
				
					
					|  |  | //         handle_response [<matcher>] [status_code] {
 |  |  | //         replace_status <matcher> <status_code>
 | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					|  |  |  |  |  | //         handle_response [<matcher>] {
 | 
			
		
	
		
		
			
				
					|  |  | //             <directives...>
 |  |  | //             <directives...>
 | 
			
		
	
		
		
			
				
					|  |  | //         }
 |  |  | //         }
 | 
			
		
	
		
		
			
				
					|  |  | //     }
 |  |  | //     }
 | 
			
		
	
	
		
		
			
				
					|  | @ -651,6 +652,39 @@ func (h *Handler) UnmarshalCaddyfile(d *caddyfile.Dispenser) error { | 
			
		
	
		
		
			
				
					|  |  | 				// See h.FinalizeUnmarshalCaddyfile
 |  |  | 				// See h.FinalizeUnmarshalCaddyfile
 | 
			
		
	
		
		
			
				
					|  |  | 				h.handleResponseSegments = append(h.handleResponseSegments, d.NewFromNextSegment()) |  |  | 				h.handleResponseSegments = append(h.handleResponseSegments, d.NewFromNextSegment()) | 
			
		
	
		
		
			
				
					|  |  | 
 |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  |  |  |  | 			case "replace_status": | 
			
		
	
		
		
			
				
					|  |  |  |  |  | 				args := d.RemainingArgs() | 
			
		
	
		
		
			
				
					|  |  |  |  |  | 				if len(args) != 2 { | 
			
		
	
		
		
			
				
					|  |  |  |  |  | 					return d.Errf("must have two arguments: a response matcher and a status code") | 
			
		
	
		
		
			
				
					|  |  |  |  |  | 				} | 
			
		
	
		
		
			
				
					|  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  |  |  |  | 				if !strings.HasPrefix(args[0], matcherPrefix) { | 
			
		
	
		
		
			
				
					|  |  |  |  |  | 					return d.Errf("must use a named response matcher, starting with '@'") | 
			
		
	
		
		
			
				
					|  |  |  |  |  | 				} | 
			
		
	
		
		
			
				
					|  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  |  |  |  | 				foundMatcher, ok := h.responseMatchers[args[0]] | 
			
		
	
		
		
			
				
					|  |  |  |  |  | 				if !ok { | 
			
		
	
		
		
			
				
					|  |  |  |  |  | 					return d.Errf("no named response matcher defined with name '%s'", args[0][1:]) | 
			
		
	
		
		
			
				
					|  |  |  |  |  | 				} | 
			
		
	
		
		
			
				
					|  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  |  |  |  | 				_, err := strconv.Atoi(args[1]) | 
			
		
	
		
		
			
				
					|  |  |  |  |  | 				if err != nil { | 
			
		
	
		
		
			
				
					|  |  |  |  |  | 					return d.Errf("bad integer value '%s': %v", args[1], err) | 
			
		
	
		
		
			
				
					|  |  |  |  |  | 				} | 
			
		
	
		
		
			
				
					|  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  |  |  |  | 				// make sure there's no block, cause it doesn't make sense
 | 
			
		
	
		
		
			
				
					|  |  |  |  |  | 				if d.NextBlock(1) { | 
			
		
	
		
		
			
				
					|  |  |  |  |  | 					return d.Errf("cannot define routes for 'replace_status', use 'handle_response' instead.") | 
			
		
	
		
		
			
				
					|  |  |  |  |  | 				} | 
			
		
	
		
		
			
				
					|  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  |  |  |  | 				h.HandleResponse = append( | 
			
		
	
		
		
			
				
					|  |  |  |  |  | 					h.HandleResponse, | 
			
		
	
		
		
			
				
					|  |  |  |  |  | 					caddyhttp.ResponseHandler{ | 
			
		
	
		
		
			
				
					|  |  |  |  |  | 						Match:      &foundMatcher, | 
			
		
	
		
		
			
				
					|  |  |  |  |  | 						StatusCode: caddyhttp.WeakString(args[1]), | 
			
		
	
		
		
			
				
					|  |  |  |  |  | 					}, | 
			
		
	
		
		
			
				
					|  |  |  |  |  | 				) | 
			
		
	
		
		
			
				
					|  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  | 			default: |  |  | 			default: | 
			
		
	
		
		
			
				
					|  |  | 				return d.Errf("unrecognized subdirective %s", d.Val()) |  |  | 				return d.Errf("unrecognized subdirective %s", d.Val()) | 
			
		
	
		
		
			
				
					|  |  | 			} |  |  | 			} | 
			
		
	
	
		
		
			
				
					|  | @ -699,20 +733,20 @@ func (h *Handler) FinalizeUnmarshalCaddyfile(helper httpcaddyfile.Helper) error | 
			
		
	
		
		
			
				
					|  |  | 	for _, d := range h.handleResponseSegments { |  |  | 	for _, d := range h.handleResponseSegments { | 
			
		
	
		
		
			
				
					|  |  | 		// consume the "handle_response" token
 |  |  | 		// consume the "handle_response" token
 | 
			
		
	
		
		
			
				
					|  |  | 		d.Next() |  |  | 		d.Next() | 
			
		
	
		
		
			
				
					|  |  | 
 |  |  |  | 
			
		
	
		
		
			
				
					|  |  | 		var matcher *caddyhttp.ResponseMatcher |  |  |  | 
			
		
	
		
		
			
				
					|  |  | 		args := d.RemainingArgs() |  |  | 		args := d.RemainingArgs() | 
			
		
	
		
		
			
				
					|  |  | 
 |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  | 		// the first arg should be a matcher (optional)
 |  |  | 		// TODO: Remove this check at some point in the future
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  | 		// the second arg should be a status code (optional)
 |  |  | 		if len(args) == 2 { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  | 		// any more than that isn't currently supported
 |  |  | 			return d.Errf("configuring 'handle_response' for status code replacement is no longer supported. Use 'replace_status' instead.") | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  | 		if len(args) > 2 { |  |  | 		} | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					|  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  |  |  |  | 		if len(args) > 1 { | 
			
		
	
		
		
			
				
					|  |  | 			return d.Errf("too many arguments for 'handle_response': %s", args) |  |  | 			return d.Errf("too many arguments for 'handle_response': %s", args) | 
			
		
	
		
		
			
				
					|  |  | 		} |  |  | 		} | 
			
		
	
		
		
			
				
					|  |  | 
 |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  | 		// the first arg should always be a matcher.
 |  |  | 		var matcher *caddyhttp.ResponseMatcher | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  | 		// it doesn't really make sense to support status code without a matcher.
 |  |  | 		if len(args) == 1 { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  | 		if len(args) > 0 { |  |  | 			// the first arg should always be a matcher.
 | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					|  |  | 			if !strings.HasPrefix(args[0], matcherPrefix) { |  |  | 			if !strings.HasPrefix(args[0], matcherPrefix) { | 
			
		
	
		
		
			
				
					|  |  | 				return d.Errf("must use a named response matcher, starting with '@'") |  |  | 				return d.Errf("must use a named response matcher, starting with '@'") | 
			
		
	
		
		
			
				
					|  |  | 			} |  |  | 			} | 
			
		
	
	
		
		
			
				
					|  | @ -724,29 +758,6 @@ func (h *Handler) FinalizeUnmarshalCaddyfile(helper httpcaddyfile.Helper) error | 
			
		
	
		
		
			
				
					|  |  | 			matcher = &foundMatcher |  |  | 			matcher = &foundMatcher | 
			
		
	
		
		
			
				
					|  |  | 		} |  |  | 		} | 
			
		
	
		
		
			
				
					|  |  | 
 |  |  | 
 | 
			
		
	
		
		
			
				
					|  |  | 		// a second arg should be a status code, in which case
 |  |  |  | 
			
		
	
		
		
			
				
					|  |  | 		// we skip parsing the block for routes
 |  |  |  | 
			
		
	
		
		
			
				
					|  |  | 		if len(args) == 2 { |  |  |  | 
			
		
	
		
		
			
				
					|  |  | 			_, err := strconv.Atoi(args[1]) |  |  |  | 
			
		
	
		
		
			
				
					|  |  | 			if err != nil { |  |  |  | 
			
		
	
		
		
			
				
					|  |  | 				return d.Errf("bad integer value '%s': %v", args[1], err) |  |  |  | 
			
		
	
		
		
			
				
					|  |  | 			} |  |  |  | 
			
		
	
		
		
			
				
					|  |  | 
 |  |  |  | 
			
		
	
		
		
			
				
					|  |  | 			// make sure there's no block, cause it doesn't make sense
 |  |  |  | 
			
		
	
		
		
			
				
					|  |  | 			if d.NextBlock(1) { |  |  |  | 
			
		
	
		
		
			
				
					|  |  | 				return d.Errf("cannot define routes for 'handle_response' when changing the status code") |  |  |  | 
			
		
	
		
		
			
				
					|  |  | 			} |  |  |  | 
			
		
	
		
		
			
				
					|  |  | 
 |  |  |  | 
			
		
	
		
		
			
				
					|  |  | 			h.HandleResponse = append( |  |  |  | 
			
		
	
		
		
			
				
					|  |  | 				h.HandleResponse, |  |  |  | 
			
		
	
		
		
			
				
					|  |  | 				caddyhttp.ResponseHandler{ |  |  |  | 
			
		
	
		
		
			
				
					|  |  | 					Match:      matcher, |  |  |  | 
			
		
	
		
		
			
				
					|  |  | 					StatusCode: caddyhttp.WeakString(args[1]), |  |  |  | 
			
		
	
		
		
			
				
					|  |  | 				}, |  |  |  | 
			
		
	
		
		
			
				
					|  |  | 			) |  |  |  | 
			
		
	
		
		
			
				
					|  |  | 			continue |  |  |  | 
			
		
	
		
		
			
				
					|  |  | 		} |  |  |  | 
			
		
	
		
		
			
				
					|  |  | 
 |  |  |  | 
			
		
	
		
		
			
				
					|  |  | 		// parse the block as routes
 |  |  | 		// parse the block as routes
 | 
			
		
	
		
		
			
				
					|  |  | 		handler, err := httpcaddyfile.ParseSegmentAsSubroute(helper.WithDispenser(d.NewFromNextSegment())) |  |  | 		handler, err := httpcaddyfile.ParseSegmentAsSubroute(helper.WithDispenser(d.NewFromNextSegment())) | 
			
		
	
		
		
			
				
					|  |  | 		if err != nil { |  |  | 		if err != nil { | 
			
		
	
	
		
		
			
				
					|  | 
 |