|  |  | @ -43,7 +43,7 @@ type Handler struct { | 
			
		
	
		
			
				
					|  |  |  | 	Destinations []string `json:"destinations,omitempty"` | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | 	// Mappings from source values (inputs) to destination values (outputs).
 | 
			
		
	
		
			
				
					|  |  |  | 	// The first matching mapping will be applied.
 | 
			
		
	
		
			
				
					|  |  |  | 	// The first matching, non-nil mapping will be applied.
 | 
			
		
	
		
			
				
					|  |  |  | 	Mappings []Mapping `json:"mappings,omitempty"` | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | 	// If no mappings match or if the mapped output is null/nil, the associated
 | 
			
		
	
	
		
			
				
					|  |  | @ -69,9 +69,6 @@ func (h *Handler) Provision(_ caddy.Context) error { | 
			
		
	
		
			
				
					|  |  |  | 		if m.InputRegexp == "" { | 
			
		
	
		
			
				
					|  |  |  | 			continue | 
			
		
	
		
			
				
					|  |  |  | 		} | 
			
		
	
		
			
				
					|  |  |  | 		if m.Input != "" { | 
			
		
	
		
			
				
					|  |  |  | 			return fmt.Errorf("mapping %d has both input and input_regexp fields specified, which is confusing", i) | 
			
		
	
		
			
				
					|  |  |  | 		} | 
			
		
	
		
			
				
					|  |  |  | 		var err error | 
			
		
	
		
			
				
					|  |  |  | 		h.Mappings[i].re, err = regexp.Compile(m.InputRegexp) | 
			
		
	
		
			
				
					|  |  |  | 		if err != nil { | 
			
		
	
	
		
			
				
					|  |  | @ -94,11 +91,20 @@ func (h *Handler) Validate() error { | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | 	seen := make(map[string]int) | 
			
		
	
		
			
				
					|  |  |  | 	for i, m := range h.Mappings { | 
			
		
	
		
			
				
					|  |  |  | 		// prevent confusing/ambiguous mappings
 | 
			
		
	
		
			
				
					|  |  |  | 		if m.Input != "" && m.InputRegexp != "" { | 
			
		
	
		
			
				
					|  |  |  | 			return fmt.Errorf("mapping %d has both input and input_regexp fields specified, which is confusing", i) | 
			
		
	
		
			
				
					|  |  |  | 		} | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | 		// prevent duplicate mappings
 | 
			
		
	
		
			
				
					|  |  |  | 		if prev, ok := seen[m.Input]; ok { | 
			
		
	
		
			
				
					|  |  |  | 			return fmt.Errorf("mapping %d has a duplicate input '%s' previously used with mapping %d", i, m.Input, prev) | 
			
		
	
		
			
				
					|  |  |  | 		input := m.Input | 
			
		
	
		
			
				
					|  |  |  | 		if m.InputRegexp != "" { | 
			
		
	
		
			
				
					|  |  |  | 			input = m.InputRegexp | 
			
		
	
		
			
				
					|  |  |  | 		} | 
			
		
	
		
			
				
					|  |  |  | 		if prev, ok := seen[input]; ok { | 
			
		
	
		
			
				
					|  |  |  | 			return fmt.Errorf("mapping %d has a duplicate input '%s' previously used with mapping %d", i, input, prev) | 
			
		
	
		
			
				
					|  |  |  | 		} | 
			
		
	
		
			
				
					|  |  |  | 		seen[m.Input] = i | 
			
		
	
		
			
				
					|  |  |  | 		seen[input] = i | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | 		// ensure mappings have 1:1 output-to-destination correspondence
 | 
			
		
	
		
			
				
					|  |  |  | 		nOut := len(m.Outputs) | 
			
		
	
	
		
			
				
					|  |  | @ -128,7 +134,7 @@ func (h Handler) ServeHTTP(w http.ResponseWriter, r *http.Request, next caddyhtt | 
			
		
	
		
			
				
					|  |  |  | 			if m.re != nil { | 
			
		
	
		
			
				
					|  |  |  | 				if m.re.MatchString(input) { | 
			
		
	
		
			
				
					|  |  |  | 					if output := m.Outputs[destIdx]; output == nil { | 
			
		
	
		
			
				
					|  |  |  | 						break | 
			
		
	
		
			
				
					|  |  |  | 						continue | 
			
		
	
		
			
				
					|  |  |  | 					} else { | 
			
		
	
		
			
				
					|  |  |  | 						return output, true | 
			
		
	
		
			
				
					|  |  |  | 					} | 
			
		
	
	
		
			
				
					|  |  | @ -137,7 +143,7 @@ func (h Handler) ServeHTTP(w http.ResponseWriter, r *http.Request, next caddyhtt | 
			
		
	
		
			
				
					|  |  |  | 			} | 
			
		
	
		
			
				
					|  |  |  | 			if input == m.Input { | 
			
		
	
		
			
				
					|  |  |  | 				if output := m.Outputs[destIdx]; output == nil { | 
			
		
	
		
			
				
					|  |  |  | 					break | 
			
		
	
		
			
				
					|  |  |  | 					continue | 
			
		
	
		
			
				
					|  |  |  | 				} else { | 
			
		
	
		
			
				
					|  |  |  | 					return output, true | 
			
		
	
		
			
				
					|  |  |  | 				} | 
			
		
	
	
		
			
				
					|  |  | @ -176,7 +182,8 @@ type Mapping struct { | 
			
		
	
		
			
				
					|  |  |  | 	InputRegexp string `json:"input_regexp,omitempty"` | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | 	// Upon a match with the input, each output is positionally correlated
 | 
			
		
	
		
			
				
					|  |  |  | 	// with each destination of the parent handler.
 | 
			
		
	
		
			
				
					|  |  |  | 	// with each destination of the parent handler. An output that is null
 | 
			
		
	
		
			
				
					|  |  |  | 	// (nil) will be treated as if it was not mapped at all.
 | 
			
		
	
		
			
				
					|  |  |  | 	Outputs []interface{} `json:"outputs,omitempty"` | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | 	re *regexp.Regexp | 
			
		
	
	
		
			
				
					|  |  | 
 |