blob: eefee9aa648ee70d2a4bf2193d5fdb52825c5aea [file] [log] [blame]
Remi Tricot-Le Breton2d2ceb52021-12-16 17:14:41 +01001#REGTEST_TYPE=devel
2
3# This regtest checks the multiple conditions that can be specified to a
4# set-var call (be it a converter or HTTP or TCP action). It mainly uses the
5# actions but since the "var_set" function is used for the converter and for
6# the actions, it should be enough to focus on one type of set-var.
7# Among the variables that can be defined and the multiple scopes they can
8# have, the proc scope is the only one having a specific behaviour. Proc scoped
9# variables are created during init when a variable of any other scope is
10# created during the first successful set-var.
11# Since this test uses variables of different scopes, the validation cannot be
12# based on the "show var" command of the CLI because it only displays process
13# variables. It then always follows the same logic, for every sub test case :
14# an HTTP header is added to the response in which we add a concatenation of
15# all the tested variables (which exist in the request/response scope). These
16# HTTP headers are then tested upon an expected result (which changes for every
17# test case).
18#
19
20varnishtest "Test the conditional set-var converter and action"
21feature cmd "$HAPROXY_PROGRAM -cc 'version_atleast(2.5-dev0)'"
22feature cmd "command -v socat"
23feature ignore_unknown_macro
24
25server s1 -repeat 10 {
26 rxreq
27 txresp
28} -start
29
30haproxy h1 -conf {
31 global
32 tune.ssl.default-dh-param 2048
33 tune.ssl.capture-buffer-size 1
34 set-var proc.int12 int(12)
35 set-var proc.int5 var(proc.str60,60),div(proc.int12)
36
37 defaults
38 mode http
39 timeout connect 100ms
40 timeout client 1s
41 timeout server 1s
42
43 listen main-fe
44 bind "fd@${mainfe}"
45
46 use_backend ifexists_be if { path_beg /ifexists }
47 use_backend ifnotexists_be if { path_beg /ifnotexists }
48 use_backend ifempty_be if { path_beg /ifempty }
49 use_backend ifnotempty_be if { path_beg /ifnotempty }
50 use_backend ifset_be if { path_beg /ifset }
51 use_backend ifnotset_be if { path_beg /ifnotset }
52 use_backend ifgt_be if { path_beg /ifgt }
53 use_backend iflt_be if { path_beg /iflt }
54 use_backend combined_be if { path_beg /combined }
55 use_backend converter_be if { path_beg /converter }
56
57
58 backend ifexists_be
59 server s1 ${s1_addr}:${s1_port}
60
61 # proc scope variables are created during configuration parsing so the
62 # ifexists condition will always be true for those variables
63 http-response set-var(proc.ifexists_proc,ifexists) var(proc.int12)
64 http-response set-var(sess.ifexists_sess,ifexists) var(proc.int5)
65 http-response set-var(res.ifexists_res,ifexists) str(toto)
66
67 http-response set-header x-var "proc.ifexists=%[var(proc.ifexists_proc)] sess.ifexists=%[var(sess.ifexists_sess)] res.ifexists=%[var(res.ifexists_res)]"
68
69
70 backend ifnotexists_be
71 server s1 ${s1_addr}:${s1_port}
72
73 http-response set-header x-var-init "proc.ifnotexists=%[var(proc.ifnotexists_proc)] sess.ifnotexists=%[var(sess.ifnotexists_sess)] res.ifnotexists=%[var(res.ifnotexists_res)]"
74
75 http-response set-var(proc.ifnotexists_proc,ifnotexists) var(proc.int12)
76 http-response set-var(sess.ifnotexists_sess,ifnotexists) var(proc.int5)
77 http-response set-var(res.ifnotexists_res,ifnotexists) str(toto)
78
79 http-response set-header x-var "proc.ifnotexists=%[var(proc.ifnotexists_proc)] sess.ifnotexists=%[var(sess.ifnotexists_sess)] res.ifnotexists=%[var(res.ifnotexists_res)]"
80
81
82 backend ifempty_be
83 server s1 ${s1_addr}:${s1_port}
84 # init
85 http-response set-var(proc.ifempty_proc) str(ifempty_proc)
86 http-response set-var(sess.ifempty_sess) bin(6966656d7074795f73657373) #ifempty_sess
87 http-response set-var(res.ifempty_res) str(ifempty_res)
88 http-response set-var(res.ifempty_res_int) int(5)
89
90 http-response set-header x-var-init "proc.ifempty=%[var(proc.ifempty_proc)] sess.ifempty=%[var(sess.ifempty_sess)] res.ifempty=%[var(res.ifempty_res)] res.ifempty_res_int=%[var(res.ifempty_res_int)]"
91
92 # None of those set-var calls should actually change their respective variables
93 # since none of the samples is empty
94 http-response set-var(proc.ifempty_proc,ifempty) int(12)
95 http-response set-var(sess.ifempty_sess,ifempty) bool(false)
96 http-response set-var(res.ifempty_res,ifempty) bin(746F746F) # "toto"
97 http-response set-var(res.ifempty_res_int,ifempty) str(toto)
98
99 http-response set-header x-var1 "proc.ifempty=%[var(proc.ifempty_proc)] sess.ifempty=%[var(sess.ifempty_sess)] res.ifempty=%[var(res.ifempty_res)] res.ifempty_res_int=%[var(res.ifempty_res_int)]"
100
101 http-response set-var(proc.ifempty_proc,ifempty) str()
102 http-response set-var(sess.ifempty_sess,ifempty) str()
103 http-response set-var(res.ifempty_res,ifempty) str()
104 http-response set-var(res.ifempty_res_int,ifempty) int(7) # should not work, scalar types are never empty
105
106 http-response set-header x-var2 "proc.ifempty=%[var(proc.ifempty_proc)] sess.ifempty=%[var(sess.ifempty_sess)] res.ifempty=%[var(res.ifempty_res)] res.ifempty_res_int=%[var(res.ifempty_res_int)]"
107
108
109 backend ifnotempty_be
110 server s1 ${s1_addr}:${s1_port}
111 # init
112 http-response set-var(proc.ifnotempty_proc) str(ifnotempty_proc)
113 http-response set-var(sess.ifnotempty_sess) bin(69666e6f74656d7074795f73657373) # "ifnotempty_sess"
114 http-response set-var(res.ifnotempty_res) str(ifnotempty_res)
115 http-response set-var(res.ifnotempty_res_int) int(5)
116
117 http-response set-header x-var-init "proc.ifnotempty=%[var(proc.ifnotempty_proc)] sess.ifnotempty=%[var(sess.ifnotempty_sess)] res.ifnotempty=%[var(res.ifnotempty_res)] res.ifnotempty_res_int=%[var(res.ifnotempty_res_int)]"
118
119 # None of those set-var calls should actually change their respective variables
120 # since none of the samples is not empty
121 http-response set-var(proc.ifnotempty_proc,ifnotempty) str(toto)
122 http-response set-var(sess.ifnotempty_sess,ifnotempty) bin(746F746F) # "toto"
123 http-response set-var(res.ifnotempty_res,ifnotempty) str(tata)
124 http-response set-var(res.ifnotempty_res_int,ifnotempty) int(6)
125
126 http-response set-header x-var1 "proc.ifnotempty=%[var(proc.ifnotempty_proc)] sess.ifnotempty=%[var(sess.ifnotempty_sess)] res.ifnotempty=%[var(res.ifnotempty_res)] res.ifnotempty_res_int=%[var(res.ifnotempty_res_int)]"
127
128 # The first three variables should remain unchanged.
129 http-response set-var(proc.ifnotempty_proc,ifnotempty) str()
130 http-response set-var(sess.ifnotempty_sess,ifnotempty) str()
131 http-response set-var(res.ifnotempty_res,ifnotempty) str()
132 http-response set-var(res.ifnotempty_res_int,ifnotempty) int(7) # should not work
133
134 http-response set-header x-var2 "proc.ifnotempty=%[var(proc.ifnotempty_proc)] sess.ifnotempty=%[var(sess.ifnotempty_sess)] res.ifnotempty=%[var(res.ifnotempty_res)] res.ifnotempty_res_int=%[var(res.ifnotempty_res_int)]"
135
136
137 backend ifset_be
138 server s1 ${s1_addr}:${s1_port}
139 # init
140 http-response set-var(proc.ifset_proc) str(ifset_proc)
141 http-response set-var(sess.ifset_sess) bin(69667365745f73657373) # "ifset_sess"
142 http-response set-var(res.ifset_res) str(ifset_res)
143 http-response set-var(res.ifset_res_int) int(5)
144
145 http-response set-header x-var-init "proc.ifset=%[var(proc.ifset_proc)] sess.ifset=%[var(sess.ifset_sess)] res.ifset=%[var(res.ifset_res)] res.ifset_res_int=%[var(res.ifset_res_int)]"
146
147 # All those set-var calls should succeed
148 http-response set-var(proc.ifset_proc,ifset) str(toto)
149 http-response set-var(sess.ifset_sess,ifset) bin(746F746F) # "toto"
150 http-response set-var(res.ifset_res,ifset) int(123)
151 http-response set-var(res.ifset_res_int,ifset) str(azerty)
152
153 http-response set-header x-var1 "proc.ifset=%[var(proc.ifset_proc)] sess.ifset=%[var(sess.ifset_sess)] res.ifset=%[var(res.ifset_res)] res.ifset_res_int=%[var(res.ifset_res_int)]"
154
155 http-response unset-var(proc.ifset_proc)
156 http-response unset-var(sess.ifset_sess)
157 http-response unset-var(res.ifset_res)
158 http-response unset-var(res.ifset_res_int)
159
160 http-response set-header x-var2 "proc.ifset=%[var(proc.ifset_proc)] sess.ifset=%[var(sess.ifset_sess)] res.ifset=%[var(res.ifset_res)] res.ifset_res_int=%[var(res.ifset_res_int)]"
161
162 # None of those set-var calls should succeed
163 http-response set-var(proc.ifset_proc,ifset) str(toto)
164 http-response set-var(sess.ifset_sess,ifset) bin(746F746F) # "toto"
165 http-response set-var(res.ifset_res,ifset) int(123)
166 http-response set-var(res.ifset_res_int,ifset) str(azerty)
167
168 http-response set-header x-var3 "proc.ifset=%[var(proc.ifset_proc)] sess.ifset=%[var(sess.ifset_sess)] res.ifset=%[var(res.ifset_res)] res.ifset_res_int=%[var(res.ifset_res_int)]"
169
170
171 backend ifnotset_be
172 server s1 ${s1_addr}:${s1_port}
173 # init
174 http-response set-var(proc.ifnotset_proc) str(ifnotset_proc)
175 http-response set-var(sess.ifnotset_sess) bin(69666e6f747365745f73657373) # "ifnotset_sess"
176 http-response set-var(res.ifnotset_res) str(ifnotset_res)
177 http-response set-var(res.ifnotset_res_int) int(5)
178
179 http-response set-header x-var-init "proc.ifnotset=%[var(proc.ifnotset_proc)] sess.ifnotset=%[var(sess.ifnotset_sess)] res.ifnotset=%[var(res.ifnotset_res)] res.ifnotset_res_int=%[var(res.ifnotset_res_int)]"
180
181 # None of those set-var calls should succeed
182 http-response set-var(proc.ifnotset_proc,ifnotset) str(toto)
183 http-response set-var(sess.ifnotset_sess,ifnotset) bin(746F746F) # "toto"
184 http-response set-var(res.ifnotset_res,ifnotset) int(123)
185 http-response set-var(res.ifnotset_res_int,ifnotset) str(azerty)
186
187 http-response set-header x-var1 "proc.ifnotset=%[var(proc.ifnotset_proc)] sess.ifnotset=%[var(sess.ifnotset_sess)] res.ifnotset=%[var(res.ifnotset_res)] res.ifnotset_res_int=%[var(res.ifnotset_res_int)]"
188
189 http-response unset-var(proc.ifnotset_proc)
190 http-response unset-var(sess.ifnotset_sess)
191 http-response unset-var(res.ifnotset_res)
192 http-response unset-var(res.ifnotset_res_int)
193
194 http-response set-header x-var2 "proc.ifnotset=%[var(proc.ifnotset_proc)] sess.ifnotset=%[var(sess.ifnotset_sess)] res.ifnotset=%[var(res.ifnotset_res)] res.ifnotset_res_int=%[var(res.ifnotset_res_int)]"
195
196 # All of those set-var calls should succeed
197 http-response set-var(proc.ifnotset_proc,ifnotset) str(toto)
198 http-response set-var(sess.ifnotset_sess,ifnotset) bin(746F746F) # "toto"
199 http-response set-var(res.ifnotset_res,ifnotset) int(123)
200 http-response set-var(res.ifnotset_res_int,ifnotset) str(azerty)
201
202 http-response set-header x-var3 "proc.ifnotset=%[var(proc.ifnotset_proc)] sess.ifnotset=%[var(sess.ifnotset_sess)] res.ifnotset=%[var(res.ifnotset_res)] res.ifnotset_res_int=%[var(res.ifnotset_res_int)]"
203
204 backend ifgt_be
205 server s1 ${s1_addr}:${s1_port}
206 # init
207 http-response set-var(proc.ifgt_proc) str(ifgt_proc)
208 http-response set-var(sess.ifgt_sess) bin(696667745f73657373) # "ifgt_sess"
209 http-response set-var(res.ifgt_res1) str(ifgt_res)
210 http-response set-var(res.ifgt_res2) int(5)
211 http-response set-var(res.ifgt_res_int1) int(5)
212 http-response set-var(res.ifgt_res_int2) int(5)
213
214 http-response set-header x-var-init "proc.ifgt=%[var(proc.ifgt_proc)] sess.ifgt=%[var(sess.ifgt_sess)] res.ifgt1=%[var(res.ifgt_res1)] res.ifgt2=%[var(res.ifgt_res2)] res.ifgt_res_int1=%[var(res.ifgt_res_int1)] res.ifgt_res_int2=%[var(res.ifgt_res_int2)]"
215
216 # ifgt does not apply on non scalar type so the two following set-var will ignore the condition
217 http-response set-var(proc.ifgt_proc,ifgt) str(toto)
218 http-response set-var(sess.ifgt_sess,ifgt) bin(746F746F) # "toto"
219 # ifgt can only apply when the variable and the sample are both scalar. In this case, the variable was a string so the condition is ignored
220 http-response set-var(res.ifgt_res1,ifgt) int(55)
221 # ifgt can only apply when the variable and the sample are both scalar. In this case, the sample is a string so the condition is ignored
222 http-response set-var(res.ifgt_res2,ifgt) str(text)
223 http-response set-var(res.ifgt_res_int1,ifgt) int(55) # should not work
224 http-response set-var(res.ifgt_res_int2,ifgt) int(2) # should work
225
226 http-response set-header x-var1 "proc.ifgt=%[var(proc.ifgt_proc)] sess.ifgt=%[var(sess.ifgt_sess)] res.ifgt1=%[var(res.ifgt_res1)] res.ifgt2=%[var(res.ifgt_res2)] res.ifgt_res_int1=%[var(res.ifgt_res_int1)] res.ifgt_res_int2=%[var(res.ifgt_res_int2)]"
227
228
229 backend iflt_be
230 server s1 ${s1_addr}:${s1_port}
231 # init
232 http-response set-var(proc.iflt_proc) str(iflt_proc)
233 http-response set-var(sess.iflt_sess) bin(69666c745f73657373) # "iflt_sess"
234 http-response set-var(res.iflt_res1) str(iflt_res)
235 http-response set-var(res.iflt_res2) int(5)
236 http-response set-var(res.iflt_res_int1) int(5)
237 http-response set-var(res.iflt_res_int2) int(5)
238
239 http-response set-header x-var-init "proc.iflt=%[var(proc.iflt_proc)] sess.iflt=%[var(sess.iflt_sess)] res.iflt1=%[var(res.iflt_res1)] res.iflt2=%[var(res.iflt_res2)] res.iflt_res_int1=%[var(res.iflt_res_int1)] res.iflt_res_int2=%[var(res.iflt_res_int2)]"
240
241 # iflt does not apply on non scalar type so the two following set-var will ignore the condition
242 http-response set-var(proc.iflt_proc,iflt) str(toto)
243 http-response set-var(sess.iflt_sess,iflt) bin(746F746F) # "toto"
244 # iflt can only apply when the variable and the sample are both scalar. In this case, the variable was a string so the condition is ignored
245 http-response set-var(res.iflt_res1,iflt) int(55)
246 # iflt can only apply when the variable and the sample are both scalar. In this case, the sample is a string so the condition is ignored
247 http-response set-var(res.iflt_res2,iflt) str(text)
248 http-response set-var(res.iflt_res_int1,iflt) int(55) # should work
249 http-response set-var(res.iflt_res_int2,iflt) int(2) # should not work
250
251 http-response set-header x-var1 "proc.iflt=%[var(proc.iflt_proc)] sess.iflt=%[var(sess.iflt_sess)] res.iflt1=%[var(res.iflt_res1)] res.iflt2=%[var(res.iflt_res2)] res.iflt_res_int1=%[var(res.iflt_res_int1)] res.iflt_res_int2=%[var(res.iflt_res_int2)]"
252
253
254 # Test multiple conditions at once
255 backend combined_be
256 server s1 ${s1_addr}:${s1_port}
257 # init
258 http-response set-var(proc.combined_proc) str(combined_proc)
259 http-response set-var(res.combined_res) int(5)
260 http-response unset-var(proc.combined_proc)
261
262 http-response set-header x-var-init "proc.combined=%[var(proc.combined_proc)] res.combined=%[var(res.combined_res)]"
263
264 http-response set-var(proc.combined_proc,ifnotset,ifnotempty) str(toto)
265 http-response set-var(res.combined_res,ifset,iflt) int(55)
266
267 http-response set-header x-var1 "proc.combined=%[var(proc.combined_proc)] res.combined=%[var(res.combined_res)]"
268
269
270 # Test the set-var converter
271 backend converter_be
272 server s1 ${s1_addr}:${s1_port}
273
274 http-request deny if { req.len,set-var(proc.req_len,ifexists) -m int 0 }
275 http-request deny if { req.hdr("X-Cust"),set-var(sess.x_cust,ifnotempty,ifnotset),length -m int 0 }
276
277 http-response set-header x-var "proc.req_len=%[var(proc.req_len)] sess.x_cust=%[var(sess.x_cust)]"
278
279} -start
280
281
282client c1 -connect ${h1_mainfe_sock} {
283 txreq -url "/ifexists"
284 rxresp
285 expect resp.status == 200
286 expect resp.http.x-var == "proc.ifexists=12 sess.ifexists= res.ifexists="
287} -run
288
289client c2 -connect ${h1_mainfe_sock} {
290 txreq -url "/ifnotexists"
291 rxresp
292 expect resp.status == 200
293 expect resp.http.x-var-init == "proc.ifnotexists= sess.ifnotexists= res.ifnotexists="
294 expect resp.http.x-var == "proc.ifnotexists= sess.ifnotexists=5 res.ifnotexists=toto"
295} -run
296
297client c3 -connect ${h1_mainfe_sock} {
298 txreq -url "/ifempty"
299 rxresp
300 expect resp.status == 200
301 expect resp.http.x-var-init == "proc.ifempty=ifempty_proc sess.ifempty=ifempty_sess res.ifempty=ifempty_res res.ifempty_res_int=5"
302 expect resp.http.x-var1 == "proc.ifempty=ifempty_proc sess.ifempty=ifempty_sess res.ifempty=ifempty_res res.ifempty_res_int=5"
303 expect resp.http.x-var2 == "proc.ifempty= sess.ifempty= res.ifempty= res.ifempty_res_int=5"
304} -run
305
306client c4 -connect ${h1_mainfe_sock} {
307 txreq -url "/ifnotempty"
308 rxresp
309 expect resp.status == 200
310 expect resp.http.x-var-init == "proc.ifnotempty=ifnotempty_proc sess.ifnotempty=ifnotempty_sess res.ifnotempty=ifnotempty_res res.ifnotempty_res_int=5"
311 expect resp.http.x-var1 == "proc.ifnotempty=toto sess.ifnotempty=toto res.ifnotempty=tata res.ifnotempty_res_int=6"
312 expect resp.http.x-var2 == "proc.ifnotempty=toto sess.ifnotempty=toto res.ifnotempty=tata res.ifnotempty_res_int=7"
313} -run
314
315client c5 -connect ${h1_mainfe_sock} {
316 txreq -url "/ifset"
317 rxresp
318 expect resp.status == 200
319 expect resp.http.x-var-init == "proc.ifset=ifset_proc sess.ifset=ifset_sess res.ifset=ifset_res res.ifset_res_int=5"
320 expect resp.http.x-var1 == "proc.ifset=toto sess.ifset=toto res.ifset=123 res.ifset_res_int=azerty"
321 expect resp.http.x-var2 == "proc.ifset= sess.ifset= res.ifset= res.ifset_res_int="
322 expect resp.http.x-var3 == "proc.ifset= sess.ifset= res.ifset= res.ifset_res_int="
323} -run
324
325client c6 -connect ${h1_mainfe_sock} {
326 txreq -url "/ifnotset"
327 rxresp
328 expect resp.status == 200
329 expect resp.http.x-var-init == "proc.ifnotset=ifnotset_proc sess.ifnotset=ifnotset_sess res.ifnotset=ifnotset_res res.ifnotset_res_int=5"
330 expect resp.http.x-var1 == "proc.ifnotset=ifnotset_proc sess.ifnotset=ifnotset_sess res.ifnotset=ifnotset_res res.ifnotset_res_int=5"
331 expect resp.http.x-var2 == "proc.ifnotset= sess.ifnotset= res.ifnotset= res.ifnotset_res_int="
332 expect resp.http.x-var3 == "proc.ifnotset=toto sess.ifnotset=toto res.ifnotset=123 res.ifnotset_res_int=azerty"
333} -run
334
335client c7 -connect ${h1_mainfe_sock} {
336 txreq -url "/ifgt"
337 rxresp
338 expect resp.status == 200
339 expect resp.http.x-var-init == "proc.ifgt=ifgt_proc sess.ifgt=ifgt_sess res.ifgt1=ifgt_res res.ifgt2=5 res.ifgt_res_int1=5 res.ifgt_res_int2=5"
340 expect resp.http.x-var1 == "proc.ifgt=toto sess.ifgt=toto res.ifgt1=55 res.ifgt2=text res.ifgt_res_int1=5 res.ifgt_res_int2=2"
341} -run
342
343client c8 -connect ${h1_mainfe_sock} {
344 txreq -url "/iflt"
345 rxresp
346 expect resp.status == 200
347 expect resp.http.x-var-init == "proc.iflt=iflt_proc sess.iflt=iflt_sess res.iflt1=iflt_res res.iflt2=5 res.iflt_res_int1=5 res.iflt_res_int2=5"
348 expect resp.http.x-var1 == "proc.iflt=toto sess.iflt=toto res.iflt1=55 res.iflt2=text res.iflt_res_int1=55 res.iflt_res_int2=5"
349} -run
350
351client c9 -connect ${h1_mainfe_sock} {
352 txreq -url "/combined"
353 rxresp
354 expect resp.status == 200
355 expect resp.http.x-var-init == "proc.combined= res.combined=5"
356 expect resp.http.x-var1 == "proc.combined=toto res.combined=55"
357} -run
358
359client c10 -connect ${h1_mainfe_sock} {
360 txreq -url "/converter" -hdr "X-Cust: foobar"
361 rxresp
362 expect resp.status == 200
363 expect resp.http.x-var == "proc.req_len=67 sess.x_cust=foobar"
364} -run