61
},
62
}
63
}
64
- handler, handlerWithRequire := makeHandler(), makeHandler()
64
+ handler := makeHandler()
65
+
66
+ // one handler per '?' default, each requiring only its own field to be absent
67
+ var defaultHandlers []Handler
68
+ applyOp := func(field, value string, replacement *string) error {
69
+ if !strings.HasPrefix(field, "?") {
70
+ return applyHeaderOp(handler.Response.HeaderOps, handler.Response, field, value, replacement)
71
+ }
72
+ defaultHandler := makeHandler()
73
+ defaultHandlers = append(defaultHandlers, defaultHandler)
74
+ return applyHeaderOp(defaultHandler.Response.HeaderOps, defaultHandler.Response, field, value, replacement)
75
+ }
76
+ var responseMatcher *caddyhttp.ResponseMatcher
77
78
// first see if headers are in the initial line
79
var hasArgs bool
89
arg := h.Val()
90
replacement = &arg
91
}
80
- err := applyHeaderOp(
81
- handler.Response.HeaderOps,
82
- handler.Response,
83
- field,
84
- value,
85
- replacement,
86
- )
92
+ err := applyOp(field, value, replacement)
93
if err != nil {
94
return nil, h.Err(err.Error())
95
}
112
return nil, err
113
}
114
matcher := responseMatchers["match"]
109
- handler.Response.Require = &matcher
115
+ responseMatcher = &matcher
116
continue
117
}
118
if hasArgs {
134
replacement = &arg
135
}
136
131
- handlerToUse := handler
132
- if strings.HasPrefix(field, "?") {
133
- handlerToUse = handlerWithRequire
134
- }
135
-
136
- err := applyHeaderOp(
137
- handlerToUse.Response.HeaderOps,
138
- handlerToUse.Response,
139
- field,
140
- value,
141
- replacement,
142
- )
137
+ err := applyOp(field, value, replacement)
138
if err != nil {
139
return nil, h.Err(err.Error())
140
}
141
}
142
143
+ // the response matcher also applies to the defaults; a default already
144
+ // requires its own field to be absent, so the matcher can only ask the same
145
+ if responseMatcher != nil {
146
+ handler.Response.Require = responseMatcher
147
+ for _, defaultHandler := range defaultHandlers {
148
+ require := defaultHandler.Response.Require
149
+ require.StatusCode = responseMatcher.StatusCode
150
+ for field, vals := range responseMatcher.Headers {
151
+ if _, ok := defaultHandler.Response.Set[http.CanonicalHeaderKey(field)]; ok {
152
+ if vals == nil {
153
+ continue
154
+ }
155
+ return nil, h.Errf("cannot match on response header %s and also set a default for it", http.CanonicalHeaderKey(field))
156
+ }
157
+ require.Headers[field] = vals
158
+ }
159
+ }
160
+ }
161
+
162
var configValues []httpcaddyfile.ConfigValue
163
if !reflect.DeepEqual(handler, makeHandler()) {
164
configValues = append(configValues, h.NewRoute(matcherSet, handler)...)
165
}
152
- if !reflect.DeepEqual(handlerWithRequire, makeHandler()) {
153
- configValues = append(configValues, h.NewRoute(matcherSet, handlerWithRequire)...)
166
+ for _, defaultHandler := range defaultHandlers {
167
+ configValues = append(configValues, h.NewRoute(matcherSet, defaultHandler)...)
168
}
169
170
return configValues, nil