diff options
Diffstat (limited to '')
25 files changed, 2796 insertions, 0 deletions
diff --git a/reg-tests/http-rules/1k.txt b/reg-tests/http-rules/1k.txt new file mode 100644 index 0000000..bbdd7e7 --- /dev/null +++ b/reg-tests/http-rules/1k.txt @@ -0,0 +1,16 @@ +s313l7hzIJ5FIXCmpr+zAyFK80lNfjOIRNZSXJJn/GQVNQsBqDl3AFcb7JQt1ler +KgBNE1LAiU02vTj4+hlW2qi4Xg1T3lshEOSSxJQN/ITQG/1KVmDiTtsjjSv8iWUj +T403xvLKQd0FB2h00N9pwd9ApbGPYF8uG1kjnNQmzJOqQ2Pz7jUkNpF+sAAQHaRD +ocjEucTsb676w8l9EqWNE+DK5IqoO2AK47bHbr4u38ZOwXjQWGw9MiUJZmVQEqdC +QZlmpFuSKQiig1SZFZlmKVidf1genz6q+4BT80IFU2UE+pWiay/HcZttwM++eG7w +n/Va7yd3D+ryK2j4rw0sOYM7Cu7AwleZeGEaCZINZmnVAWtg2OVFOTxx6jz8wNuY +VJPb3VFD72WnnBhtbik5mEqjzVJy530sQBlGlcxi3Tivq69ZnAk55RBN0LO+jWf4 +DI4189LTIfY5WroA8AQeCCQYnzyXo5O/vDmic+uwKALlQ6TXzSuCNpHO8fL1UwHH +7KBqxHi+/yYJ0431V/LAvRBpVFPYJ8iED7Md67GRVQWy8o+tgC1PmycJtS5ADQGO +Jys46KjhL9cnaS3aP1YcuuGuSUOVMA7BjqPcz7r+hqYTCZ3akaY4w7AGRCZyRf8e +finlAkgFpzKSFwaa2M6H3vUE14WzHC0hJ/bO2epjlcOeoMcgBVn5uUMYMVroAK0+ +vI9jg1RDV17oHberVmWj8VAXolDNS0pW2rt+JbqHsAVDDk/Ex3NJWFSYByHFyglQ +cjYMwrzIsWC09ykW6WhUN6IsopLlDk7O2jcKaHxZ6WaFiVxIGFkepfNhf4wYZ6O9 +tjwMuOqTQtSjdP3MbbVEM6VpAkJW/Si1jmSW02ObMcdEpxJHTB9fC30waMM7e+T4 +FT/AlwB49un/3yYU2iUndW+wenoED9UkdbZ7uvjyu+UgQ3bMaQhX9Z9eHxhfi6Gy +aRM2IJVeEpk5w0ifAQxrL4Wp+dFbzfGN1yPkI2UAo6WbWi63D
\ No newline at end of file diff --git a/reg-tests/http-rules/acl_cli_spaces.vtc b/reg-tests/http-rules/acl_cli_spaces.vtc new file mode 100644 index 0000000..a554977 --- /dev/null +++ b/reg-tests/http-rules/acl_cli_spaces.vtc @@ -0,0 +1,77 @@ +varnishtest "haproxy ACL, CLI and mCLI spaces" +feature ignore_unknown_macro + +server s1 { + rxreq + expect req.method == "GET" + txresp +} -repeat 2 -start + +haproxy h1 -W -S -conf { + defaults + mode http + log global + option httplog + timeout connect "${HAPROXY_TEST_TIMEOUT-5s}" + timeout client "${HAPROXY_TEST_TIMEOUT-5s}" + timeout server "${HAPROXY_TEST_TIMEOUT-5s}" + + frontend fe1 + bind "fd@${fe1}" + + http-request deny if { req.hdr(user-agent) -i -m str -f ${testdir}/agents.acl } + + default_backend be1 + + backend be1 + server s1 ${s1_addr}:${s1_port} + +} -start + +client c1 -connect ${h1_fe1_sock} { + txreq -hdr "User-Agent: Mon User Agent" + rxresp + expect resp.status == 200 +} -run + +haproxy h1 -cli { + send "add acl ${testdir}/agents.acl Mon\\ User\\ Agent\\;" + expect ~ .* + + send "show acl ${testdir}/agents.acl" + expect ~ ".*Mon User Agent.*" +} + +client c1 -connect ${h1_fe1_sock} { + txreq -hdr "User-Agent: Mon User Agent;" + rxresp + expect resp.status == 403 +} -run + + +haproxy h1 -cli { + send "del acl ${testdir}/agents.acl Mon\\ User\\ Agent\\;" + expect ~ .* + + send "show acl ${testdir}/agents.acl" + expect ~ .* +} + +client c1 -connect ${h1_fe1_sock} { + txreq -hdr "User-Agent: Mon User Agent;" + rxresp + expect resp.status == 200 +} -run + + +# Try it with the master CLI +haproxy h1 -mcli { + send "@1 add acl ${testdir}/agents.acl Mon\\ User\\ Agent\\;;@1 show acl ${testdir}/agents.acl" + expect ~ ".*Mon User Agent;.*" +} + +client c1 -connect ${h1_fe1_sock} { + txreq -hdr "User-Agent: Mon User Agent;" + rxresp + expect resp.status == 403 +} -run diff --git a/reg-tests/http-rules/agents.acl b/reg-tests/http-rules/agents.acl new file mode 100644 index 0000000..345e6ae --- /dev/null +++ b/reg-tests/http-rules/agents.acl @@ -0,0 +1 @@ +Test diff --git a/reg-tests/http-rules/converters_ipmask_concat_strcmp_field_word.map b/reg-tests/http-rules/converters_ipmask_concat_strcmp_field_word.map new file mode 100644 index 0000000..9a3e8e6 --- /dev/null +++ b/reg-tests/http-rules/converters_ipmask_concat_strcmp_field_word.map @@ -0,0 +1 @@ +^(.+)_(.+)$ \2_\1 diff --git a/reg-tests/http-rules/converters_ipmask_concat_strcmp_field_word.vtc b/reg-tests/http-rules/converters_ipmask_concat_strcmp_field_word.vtc new file mode 100644 index 0000000..55bcb5f --- /dev/null +++ b/reg-tests/http-rules/converters_ipmask_concat_strcmp_field_word.vtc @@ -0,0 +1,231 @@ +varnishtest "Minimal tests for 1.9 converters: ipmask,concat,strcmp,field,word" +feature ignore_unknown_macro + +# ipmask,hdr_ip tests server +server s1 { + rxreq + expect req.method == "GET" + expect req.http.srciphdr == "192.168.1.101" + expect req.http.srcmask1 == "192.168.1.0" + expect req.http.srcmask2 == "192.168.0.0" + expect req.http.srcmask3 == "192.0.0.0" + + expect req.http.test1mask128 ~ "2001:db8:[0:]*:1" + expect req.http.test2mask64 ~ "2001:db8:[0:]+" + expect req.http.test2mask128 ~ "2001:db8:[0:]*:bad:c0f:ffff" + expect req.http.test2mask120 ~ "2001:db8:[0:]*:bad:c0f:ff00" + expect req.http.test2maskff00 ~ "2001:db8:[0:]*:bad:c0f:ff00" + expect req.http.test2maskfee0 ~ "2001:db8:[0:]*:bad:c0f:fee0" + + expect req.http.test3mask64 ~ "2001:db8:c001:c01a:[0:]+" + expect req.http.test3mask64v2 ~ "2001:db8:c001:c01a:[0:]+" + expect req.http.test3mask64v3 ~ "2001:db8:c001:c01a:[0:]+" + expect req.http.test3maskff ~ "2001:db8:c001:c01a:[0:]*:ffff:10:[0:]+" + expect req.http.test3maskv2 ~ "2001:db8:c001:c01a:c001:c001:[0:]+" + + expect req.http.test4mask32 == "192.168.1.101" + + expect req.http.test5mask24 == "192.168.1.0" + expect req.http.test6mask24 == "192.168.1.0" + expect req.http.test6mask25 == "192.168.1.128" + + expect req.http.ipv4plain == "192.168.2.1" + expect req.http.ipv4port == "192.168.2.1" + expect req.http.ipv6plain == "2001:db8:c001:c01a:ffff:ffff:20:ffff" + expect req.http.ipv6brackets == "2001:db8:c001:c01a:ffff:ffff:20:ffff" + + txresp +} -start + +# concat,strcmp,field,word tests server +server s2 { + rxreq + expect req.method == "GET" + expect req.http.fieldconcat == "f1_f2_f3__f5" + expect req.http.fieldconcat2 == "f1_f2_f3__f5" + expect req.http.fieldconcat3 == "f1_f2_f3__f5" + expect req.http.fieldstrcmp == "0" + + # field tests + expect req.http.fieldtest1 == "f5" + expect req.http.fieldtest2 == "f2_f3__f5" + expect req.http.fieldtest3 == "f2_f3" + expect req.http.fieldtest4 == "f2_f3_" + expect req.http.fieldtest5 == "f1_f2_f3" + expect req.http.okfieldtest == "ok" + expect req.http.qsfieldtest == "IT_IS" + expect req.http.qsfieldconcat == "IT_IS_ok" + expect req.http.fieldtest1strcmp == "0" + + # word tests + expect req.http.wordtest1 == "f5" + expect req.http.wordtest2 == "f2_f3__f5" + expect req.http.wordtest3 == "f3__f5" + expect req.http.wordtest4 == "f1_f2_f3" + expect req.http.wordtest5 == "f1_f2" + expect req.http.okwordtest == "OK" + expect req.http.qswordtest == "Yes_It" + expect req.http.qswordregmtest == "It_Yes" + expect req.http.wordtest1strcmp == "0" + txresp +} -start + + +# ipmask,hdr_ip tests with accept-proxy bind +haproxy h1 -conf { + defaults + mode http + log global + option httplog + timeout connect "${HAPROXY_TEST_TIMEOUT-5s}" + timeout client "${HAPROXY_TEST_TIMEOUT-5s}" + timeout server "${HAPROXY_TEST_TIMEOUT-5s}" + + frontend fe1 + # accept-proxy so test client can send src ip + bind "fd@${fe1}" accept-proxy + + # ipmask tests w/src + http-request set-header Srciphdr %[src] + http-request set-header Srcmask1 %[src,ipmask(24)] # 192.168.1.0 + http-request set-header Srcmask2 %[src,ipmask(16)] # 192.168.0.0 + http-request set-header Srcmask3 %[src,ipmask(8)] # 192.0.0.0 + + # ipmask tests from headers + http-request set-header Test1mask128 %[req.hdr_ip(Addr1),ipmask(24,128)] + + http-request set-header Test2mask64 %[req.hdr_ip(Addr2),ipmask(24,64)] + http-request set-header Test2mask128 %[req.hdr_ip(Addr2),ipmask(24,128)] + http-request set-header Test2mask120 %[req.hdr_ip(Addr2),ipmask(24,120)] + http-request set-header Test2maskff00 %[req.hdr_ip(Addr2),ipmask(24,ffff:ffff:ffff:ffff:ffff:ffff:ffff:ff00)] + http-request set-header Test2maskfee0 %[req.hdr_ip(Addr2),ipmask(24,ffff:ffff:ffff:ffff:ffff:ffff:ffff:fee0)] + + http-request set-header Test3mask64 %[req.hdr_ip(Addr3),ipmask(24,64)] + http-request set-header Test3mask64v2 %[req.hdr_ip(Addr3),ipmask(24,ffff:ffff:ffff:ffff:0:0:0:0)] + http-request set-header Test3mask64v3 %[req.hdr_ip(Addr3),ipmask(24,ffff:ffff:ffff:ffff::)] + http-request set-header Test3maskff %[req.hdr_ip(Addr3),ipmask(24,ffff:ffff:ffff:ffff:0:ffff:ffff:0)] + http-request set-header Test3maskv2 %[req.hdr_ip(Addr3),ipmask(24,ffff:ffff:ffff:ffff:c001:c001:0000:0000)] + + # ipv4 mask applied to ipv4 mapped address + http-request set-header Test4mask32 %[req.hdr_ip(Addr4),ipmask(32,64)] + + http-request set-header Test5mask24 %[req.hdr_ip(Addr5),ipmask(24)] + + http-request set-header Test6mask24 %[req.hdr_ip(Addr6),ipmask(24)] + http-request set-header Test6mask25 %[req.hdr_ip(Addr6),ipmask(25)] + + # track addr/mask in stick table + http-request track-sc0 src,ipmask(24) table be1 + http-request track-sc1 hdr_ip(Addr4),ipmask(32) table be1 + http-request track-sc2 hdr_ip(Addr3),ipmask(24,64) table be1 + + # hdr_ip tests + http-request set-header IPv4plain %[req.hdr_ip(AddrIPv4plain)] + http-request set-header IPv4port %[req.hdr_ip(AddrIPv4port)] + http-request set-header IPv6plain %[req.hdr_ip(AddrIPv6plain)] + http-request set-header IPv6brackets %[req.hdr_ip(AddrIPv6brackets)] + + default_backend be1 + + backend be1 + stick-table type ipv6 size 20 expire 360s store gpc0,conn_cnt + server s1 ${s1_addr}:${s1_port} +} -start + +# concat,strcmp,word,field haproxy +haproxy h2 -conf { + defaults + mode http + log global + option httplog + timeout connect "${HAPROXY_TEST_TIMEOUT-5s}" + timeout client "${HAPROXY_TEST_TIMEOUT-5s}" + timeout server "${HAPROXY_TEST_TIMEOUT-5s}" + + frontend fe2 + bind "fd@${fe2}" + + # concat f1_f2 + _ + f3__f5 tests + http-request set-var(sess.field1) hdr(Field1) + http-request set-var(sess.field2) hdr(Field2) + http-request set-var(sess.fieldhdr) hdr(Fieldhdr) + http-request set-var(sess.fieldconcat) hdr(Field1),concat(_,sess.field2,) + http-request set-header Fieldconcat2 %[var(sess.field1),concat(_,sess.field2,)] + http-request set-header Fieldconcat3 %[hdr(Field1),concat(_,sess.field2,)] + http-request set-header Fieldconcat %[var(sess.fieldconcat)] + http-request set-header Fieldstrcmp %[hdr(Fieldhdr),strcmp(sess.fieldconcat)] + http-request deny unless { hdr(Fieldhdr),strcmp(sess.fieldconcat) eq 0 } + + # field tests + http-request set-header Fieldtest1 %[hdr(Fieldhdr),field(5,_)] #f5 + http-request set-var(sess.fieldtest1var) hdr(Fieldtest1) + http-request set-var(sess.okfield) path,lower,field(4,/,1) #ok + http-request set-header Okfieldtest %[var(sess.okfield)] #ok + http-request set-var(sess.qsfield) url_param(qs),upper,field(2,_,2) #IT_IS + http-request set-header Qsfieldtest %[var(sess.qsfield)] #IT_IS + http-request set-header Qsfieldconcat %[var(sess.qsfield),concat(_,sess.okfield,)] #IT_IS_ok + http-request set-header Fieldtest2 %[var(sess.fieldhdr),field(2,_,0)] #f2_f3__f5 + http-request set-header Fieldtest3 %[var(sess.fieldconcat),field(2,_,2)] #f2_f3 + http-request set-header Fieldtest4 %[hdr(Fieldconcat2),field(-2,_,3)] #f2_f3_ + http-request set-header Fieldtest5 %[hdr(Fieldconcat3),field(-3,_,0)] #f1_f2_f3 + http-request set-header Fieldtest1strcmp %[str(f5),strcmp(sess.fieldtest1var)] + http-request deny unless { str(f5),strcmp(sess.fieldtest1var) eq 0 } + http-request deny unless { str(ok),strcmp(sess.okfield) eq 0 } + http-request deny unless { str(IT_IS),strcmp(sess.qsfield) eq 0 } + + # word tests + http-request set-header Wordtest1 %[hdr(Fieldhdr),word(4,_)] #f5 + http-request set-var(sess.wordtest1var) hdr(Wordtest1) + http-request set-var(sess.okword) path,upper,word(3,/,1) #OK + http-request set-header Okwordtest %[var(sess.okword)] #OK + http-request set-var(sess.qsword) url_param(qs),word(1,_,2) #Yes_It + http-request set-header Qswordtest %[var(sess.qsword)] #Yes_It + http-request set-header Qswordregmtest %[var(sess.qsword),map_regm(${testdir}/converters_ipmask_concat_strcmp_field_word.map)] #It_Yes + http-request set-header Wordtest2 %[var(sess.fieldhdr),word(2,_,0)] #f2_f3__f5 + http-request set-header Wordtest3 %[var(sess.fieldconcat),word(3,_,2)] #f3__f5 + http-request set-header Wordtest4 %[hdr(Fieldconcat2),word(-2,_,3)] #f1_f2_f3 + http-request set-header Wordtest5 %[hdr(Fieldconcat3),word(-3,_,0)] #f1_f2 + http-request set-header Wordtest1strcmp %[str(f5),strcmp(sess.wordtest1var)] + http-request deny unless { str(f5),strcmp(sess.wordtest1var) eq 0 } + http-request deny unless { str(OK),strcmp(sess.okword) eq 0 } + http-request deny unless { str(Yes_It),strcmp(sess.qsword) eq 0 } + + default_backend be2 + + backend be2 + server s2 ${s2_addr}:${s2_port} +} -start + +# ipmask,hdr_ip tests +client c1 -connect ${h1_fe1_sock} -proxy2 "192.168.1.101:1234 127.0.0.1:2345" { + txreq -hdr "Addr1: 2001:db8::1" \ + -hdr "Addr2: 2001:db8::bad:c0f:ffff" \ + -hdr "Addr3: 2001:db8:c001:c01a:ffff:ffff:10:ffff" \ + -hdr "Addr4: ::FFFF:192.168.1.101" \ + -hdr "Addr5: 192.168.1.2" \ + -hdr "Addr6: 192.168.1.255" \ + -hdr "AddrIPv4plain: 192.168.2.1" \ + -hdr "AddrIPv4port: 192.168.2.1:6789" \ + -hdr "AddrIPv6plain: 2001:db8:c001:c01a:ffff:ffff:20:ffff" \ + -hdr "AddrIPv6brackets: [2001:db8:c001:c01a:ffff:ffff:20:ffff]" + rxresp + expect resp.status == 200 +} -run + +# cli show be1 stick table +haproxy h1 -cli { + send "show table be1" + expect ~ "^# table: be1, type: ipv6, size:20, used:3\\n0x[a-f0-9]+: key=::ffff:192\\.168\\.1\\.0 use=0 exp=[[:digit:]]+ shard=0 gpc0=0 conn_cnt=1\\n0x[a-f0-9]+: key=::ffff:192\\.168\\.1\\.101 use=0 exp=[[:digit:]]+ shard=0 gpc0=0 conn_cnt=1\\n0x[a-f0-9]+: key=2001:db8:c001:c01a:[0:]+ use=0 exp=[[:digit:]]+ shard=0 gpc0=0 conn_cnt=1\\n" +} + +# concat,strcmp,word,field tests +client c2 -connect ${h2_fe2_sock} { + txreq -req GET \ + -url /is/this/Ok/or/not?qs=Yes_It_Is \ + -hdr "Fieldhdr: f1_f2_f3__f5" \ + -hdr "Field1: f1_f2" \ + -hdr "Field2: f3__f5" + rxresp + expect resp.status == 200 +} -run + diff --git a/reg-tests/http-rules/default_rules.vtc b/reg-tests/http-rules/default_rules.vtc new file mode 100644 index 0000000..cc726ab --- /dev/null +++ b/reg-tests/http-rules/default_rules.vtc @@ -0,0 +1,159 @@ +varnishtest "Test declaration of HTTP rules in default sections" + +feature cmd "$HAPROXY_PROGRAM -cc 'version_atleast(2.5-dev0)'" +feature ignore_unknown_macro + +server s1 { + rxreq + expect req.http.x-frontend == "fe" + expect req.http.x-backend == "be" + expect req.http.x-test1-frt == "def_front" + expect req.http.x-test1-bck == "def_back" + txresp +} -start + +server s2 { + rxreq + txresp +} -start + +haproxy h1 -conf { + defaults common + mode http + timeout connect "${HAPROXY_TEST_TIMEOUT-5s}" + timeout client "${HAPROXY_TEST_TIMEOUT-5s}" + timeout server "${HAPROXY_TEST_TIMEOUT-5s}" + + defaults def_front from common + http-request set-header x-frontend "%[fe_name]" + http-request set-var(txn.test1) "str(def_front)" + http-response set-header x-frontend "%[fe_name]" + http-response set-var(txn.test2) "str(def_front)" + http-after-response set-var(txn.test3) "str(def_front)" + + defaults def_back from common + http-request set-header x-backend "%[be_name]" + http-request set-var(txn.test1) "str(def_back)" + http-response set-header x-backend "%[be_name]" + http-response set-var(txn.test2) "str(def_back)" + http-after-response set-var(txn.test3) "str(def_back)" + + frontend fe from def_front + bind "fd@${feh1}" + + http-request set-header x-test1-frt "%[var(txn.test1)]" + http-response set-header x-test2-frt "%[var(txn.test2)]" + http-after-response set-header x-test3-frt "%[var(txn.test3)]" + + default_backend be + + backend be from def_back + http-request set-header x-test1-bck "%[var(txn.test1)]" + http-response set-header x-test2-bck "%[var(txn.test2)]" + http-after-response set-header x-test3-bck "%[var(txn.test3)]" + + server s1 ${s1_addr}:${s1_port} + +} -start + + +haproxy h2 -conf { + defaults common + mode http + timeout connect "${HAPROXY_TEST_TIMEOUT-5s}" + timeout client "${HAPROXY_TEST_TIMEOUT-5s}" + timeout server "${HAPROXY_TEST_TIMEOUT-5s}" + + defaults def_front from common + http-request allow + http-response allow + http-after-response allow + + defaults def_back from common + http-request allow + http-response allow + http-after-response allow + + frontend fe from def_front + bind "fd@${feh2}" + + http-request deny status 403 + http-response deny status 502 + http-after-response set-status 502 + + default_backend be + + backend be from def_back + http-request deny status 403 + http-response deny status 502 + http-after-response set-status 502 + + server s2 ${s2_addr}:${s2_port} + +} -start + +haproxy h3 -conf { + defaults base-http + mode http + timeout connect "${HAPROXY_TEST_TIMEOUT-5s}" + timeout client "${HAPROXY_TEST_TIMEOUT-5s}" + timeout server "${HAPROXY_TEST_TIMEOUT-5s}" + + http-request capture hdr(Host) len 64 # idx 0 + http-request capture hdr(X-req-1) len 32 # idx 1 + + frontend fe1 from base-http + bind "fd@${fe1h3}" + declare capture request len 32 # idx 2 + + http-request capture hdr(X-req-2) id 2 + http-request return status 200 hdr "X-Capture-1" "%[capture.req.hdr(0)]" hdr "X-Capture-2" "%[capture.req.hdr(1)]" hdr "X-Capture-3" "%[capture.req.hdr(2)]" + + frontend fe2 from base-http + bind "fd@${fe2h3}" + http-request capture hdr(X-req-2) id 1 + http-request return status 200 hdr "X-Capture-1" "%[capture.req.hdr(0)]" hdr "X-Capture-2" "%[capture.req.hdr(1)]" + +} -start + +client c1 -connect ${h1_feh1_sock} { + txreq -req GET -url / + rxresp + expect resp.status == 200 + expect resp.http.x-frontend == "fe" + expect resp.http.x-backend == "be" + expect resp.http.x-test2-bck == "def_back" + expect resp.http.x-test2-frt == "def_front" + expect resp.http.x-test3-bck == "def_back" + expect resp.http.x-test3-frt == "def_front" +} -run + +client c2 -connect ${h2_feh2_sock} { + txreq -req GET -url / + rxresp + expect resp.status == 200 +} -run + +client c3 -connect ${h3_fe1h3_sock} { + txreq -req GET -url / \ + -hdr "host: v-test" \ + -hdr "x-req-1: val1" \ + -hdr "x-req-2: val2" + rxresp + expect resp.status == 200 + expect resp.http.x-capture-1 == "v-test" + expect resp.http.x-capture-2 == "val1" + expect resp.http.x-capture-3 == "val2" +} -run + +client c4 -connect ${h3_fe2h3_sock} { + txreq -req GET -url / \ + -hdr "host: v-test" \ + -hdr "x-req-1: val1" \ + -hdr "x-req-2: val2" + rxresp + expect resp.status == 200 + expect resp.http.x-capture-1 == "v-test" + expect resp.http.x-capture-2 == "val2" + expect resp.http.x-capture-3 == "<undef>" +} -run diff --git a/reg-tests/http-rules/del_header.vtc b/reg-tests/http-rules/del_header.vtc new file mode 100644 index 0000000..0f74a60 --- /dev/null +++ b/reg-tests/http-rules/del_header.vtc @@ -0,0 +1,93 @@ +varnishtest "del-header tests" + +# This config tests various http-request/response del-header operations +# with or without specified header name matching method. + +feature ignore_unknown_macro + +server s1 { + rxreq + expect req.url == / + expect req.http.x-always == always + expect req.http.x-str1 == <undef> + expect req.http.x-str2 == <undef> + expect req.http.x-beg1 == <undef> + expect req.http.x-beg2 == <undef> + expect req.http.x-end1 == <undef> + expect req.http.x-end2 == end2 + expect req.http.x-sub1 == <undef> + expect req.http.x-sub2 == <undef> + expect req.http.x-reg1 == <undef> + expect req.http.x-reg2 == <undef> + txresp -hdr "x-always: always" \ + -hdr "x-str1: str1" \ + -hdr "x-str2: str2" \ + -hdr "x-beg1: beg1" \ + -hdr "x-beg2: beg2" \ + -hdr "x-end1: end1" \ + -hdr "x-end2: end2" \ + -hdr "x-sub1: sub1" \ + -hdr "x-sub2: sub2" \ + -hdr "x-reg1: reg1" \ + -hdr "x-reg2: reg2" + +} -start + +haproxy h1 -conf { + defaults + mode http + timeout connect "${HAPROXY_TEST_TIMEOUT-5s}" + timeout client "${HAPROXY_TEST_TIMEOUT-5s}" + timeout server "${HAPROXY_TEST_TIMEOUT-5s}" + + frontend fe + bind "fd@${fe}" + + http-request del-header x-str1 + http-request del-header x-str2 -m str + http-request del-header x-beg -m beg + http-request del-header end1 -m end + http-request del-header sub -m sub + http-request del-header ^x.reg.$ -m reg + + http-response del-header x-str1 + http-response del-header x-str2 -m str + http-response del-header x-beg -m beg + http-response del-header end1 -m end + http-response del-header sub -m sub + http-response del-header ^x.reg.$ -m reg + + default_backend be + + backend be + server s1 ${s1_addr}:${s1_port} + +} -start + +client c1 -connect ${h1_fe_sock} { + txreq -req GET -url / \ + -hdr "x-always: always" \ + -hdr "x-str1: str1" \ + -hdr "x-str2: str2" \ + -hdr "x-beg1: beg1" \ + -hdr "x-beg2: beg2" \ + -hdr "x-end1: end1" \ + -hdr "x-end2: end2" \ + -hdr "x-sub1: sub1" \ + -hdr "x-sub2: sub2" \ + -hdr "x-reg1: reg1" \ + -hdr "x-reg2: reg2" + rxresp + expect resp.status == 200 + expect resp.http.x-always == always + expect resp.http.x-str1 == <undef> + expect resp.http.x-str2 == <undef> + expect resp.http.x-beg1 == <undef> + expect resp.http.x-beg2 == <undef> + expect resp.http.x-end1 == <undef> + expect resp.http.x-end2 == end2 + expect resp.http.x-sub1 == <undef> + expect resp.http.x-sub2 == <undef> + expect resp.http.x-reg1 == <undef> + expect resp.http.x-reg2 == <undef> +} -run diff --git a/reg-tests/http-rules/except-forwardfor-originalto.vtc b/reg-tests/http-rules/except-forwardfor-originalto.vtc new file mode 100644 index 0000000..a859160 --- /dev/null +++ b/reg-tests/http-rules/except-forwardfor-originalto.vtc @@ -0,0 +1,143 @@ +varnishtest "Test IPv4/IPv6 except param for the forwardfor and originalto options" +#REQUIRE_VERSION=2.4 + +# This config tests the except parameter for the HTTP forwardfor and originalto +# options. + +feature ignore_unknown_macro + +haproxy h1 -conf { + global + # WT: limit false-positives causing "HTTP header incomplete" due to + # idle server connections being randomly used and randomly expiring + # under us. + tune.idle-pool.shared off + + defaults + mode http + timeout connect "${HAPROXY_TEST_TIMEOUT-5s}" + timeout client "${HAPROXY_TEST_TIMEOUT-5s}" + timeout server "${HAPROXY_TEST_TIMEOUT-5s}" + + frontend fe1 + bind "fd@${fe1}" + http-request set-src hdr(x-src) + http-request set-dst hdr(x-dst) + use_backend be1 if { path /req1 } + use_backend be2 if { path /req2 } + use_backend be3 if { path /req3 } + use_backend be4 if { path /req4 } + use_backend be5 if { path /req5 } + + frontend fe2 + bind "fd@${fe2}" + http-request return status 200 hdr x-ff "%[req.hdr(x-forwarded-for)]" hdr x-ot "%[req.hdr(x-original-to)]" + + backend be1 + option forwardfor except 127.0.0.1 + option originalto except 127.0.0.1 + server s1 ${h1_fe2_addr}:${h1_fe2_port} + + backend be2 + option forwardfor except 10.0.0.1/25 + option originalto except 10.0.0.1/25 + server s1 ${h1_fe2_addr}:${h1_fe2_port} + + backend be3 + option forwardfor except ::1 + option originalto except ::1 + server s1 ${h1_fe2_addr}:${h1_fe2_port} + + backend be4 + option forwardfor except 2001:db8::1:0:0:1 + option originalto except 2001:db8::1:0:0:1 + server s1 ${h1_fe2_addr}:${h1_fe2_port} + + backend be5 + option forwardfor except 2001:db8:1f89::/48 + option originalto except 2001:db8:1f89::/48 + server s1 ${h1_fe2_addr}:${h1_fe2_port} +} -start + +client c1 -connect ${h1_fe1_sock} { + txreq -req GET -url /req1 \ + -hdr "x-src: 127.0.0.1" \ + -hdr "x-dst: 127.0.0.1" + rxresp + expect resp.status == 200 + expect resp.http.x-ff == <undef> + expect resp.http.x-ot == <undef> + + txreq -req GET -url /req1 \ + -hdr "x-src: 127.0.0.2" \ + -hdr "x-dst: 127.0.0.2" + rxresp + expect resp.status == 200 + expect resp.http.x-ff == "127.0.0.2" + expect resp.http.x-ot == "127.0.0.2" + + + txreq -req GET -url /req2 \ + -hdr "x-src: 10.0.0.1" \ + -hdr "x-dst: 10.0.0.1" + rxresp + expect resp.status == 200 + expect resp.http.x-ff == <undef> + expect resp.http.x-ot == <undef> + + txreq -req GET -url /req2 \ + -hdr "x-src: 10.0.0.128" \ + -hdr "x-dst: 10.0.0.128" + rxresp + expect resp.status == 200 + expect resp.http.x-ff == "10.0.0.128" + expect resp.http.x-ot == "10.0.0.128" + + txreq -req GET -url /req3 \ + -hdr "x-src: ::1" \ + -hdr "x-dst: ::1" + rxresp + expect resp.status == 200 + expect resp.http.x-ff == <undef> + expect resp.http.x-ot == <undef> + + txreq -req GET -url /req3 \ + -hdr "x-src: ::2" \ + -hdr "x-dst: ::2" + rxresp + expect resp.status == 200 + expect resp.http.x-ff == "::2" + expect resp.http.x-ot == "::2" + + txreq -req GET -url /req4 \ + -hdr "x-src: 2001:db8::1:0:0:1" \ + -hdr "x-dst: 2001:db8::1:0:0:1" + rxresp + expect resp.status == 200 + expect resp.http.x-ff == <undef> + expect resp.http.x-ot == <undef> + + txreq -req GET -url /req4 \ + -hdr "x-src: 2001:db8::1:0:0:2" \ + -hdr "x-dst: 2001:db8::1:0:0:2" + rxresp + expect resp.status == 200 + expect resp.http.x-ff == "2001:db8::1:0:0:2" + expect resp.http.x-ot == "2001:db8::1:0:0:2" + + txreq -req GET -url /req5 \ + -hdr "x-src: 2001:db8:1f89::1" \ + -hdr "x-dst: 2001:db8:1f89::1" + rxresp + expect resp.status == 200 + expect resp.http.x-ff == <undef> + expect resp.http.x-ot == <undef> + + txreq -req GET -url /req5 \ + -hdr "x-src: 2001:db8:1f90::1" \ + -hdr "x-dst: 2001:db8:1f90::1" + rxresp + expect resp.status == 200 + expect resp.http.x-ff == "2001:db8:1f90::1" + expect resp.http.x-ot == "2001:db8:1f90::1" +} -run diff --git a/reg-tests/http-rules/forwarded-header-7239.vtc b/reg-tests/http-rules/forwarded-header-7239.vtc new file mode 100644 index 0000000..a894113 --- /dev/null +++ b/reg-tests/http-rules/forwarded-header-7239.vtc @@ -0,0 +1,171 @@ +varnishtest "Test RFC 7239 forwarded header support (forwarded option and related converters)" +feature cmd "$HAPROXY_PROGRAM -cc 'version_atleast(2.8-dev0)'" + +# This config tests the HTTP forwarded option and RFC7239 related converters. + +feature ignore_unknown_macro + +#test: converters, parsing and header injection logic +haproxy h1 -conf { + global + # WT: limit false-positives causing "HTTP header incomplete" due to + # idle server connections being randomly used and randomly expiring + # under us. + tune.idle-pool.shared off + + defaults + mode http + timeout connect "${HAPROXY_TEST_TIMEOUT-5s}" + timeout client "${HAPROXY_TEST_TIMEOUT-5s}" + timeout server "${HAPROXY_TEST_TIMEOUT-5s}" + + frontend fe1 + bind "fd@${fe1}" + http-request set-src hdr(x-src) + http-request set-dst hdr(x-dst) + http-request set-header host %[str(vtest)] + use_backend be1 if { path /req1 } + use_backend be2 if { path /req2 } + use_backend be3 if { path /req3 } + use_backend be4 if { path /req4 } + + frontend fe2 + bind "fd@${fe2}" + http-request return status 200 hdr forwarded "%[req.hdr(forwarded)]" + + backend be1 + option forwarded + server s1 ${h1_fe2_addr}:${h1_fe2_port} + + backend be2 + option forwarded for-expr src for_port-expr str(id) by by_port-expr int(10) + server s1 ${h1_fe2_addr}:${h1_fe2_port} + + backend be3 + acl valid req.hdr(forwarded),rfc7239_is_valid + http-request return status 200 if valid + http-request return status 400 + + backend be4 + http-request set-var(req.fnode) req.hdr(forwarded),rfc7239_field(for) + http-request return status 200 hdr nodename "%[var(req.fnode),rfc7239_n2nn]" hdr nodeport "%[var(req.fnode),rfc7239_n2np]" + +} -start + +#test: "default" and "no option forwarded" +haproxy h2 -conf { + global + # WT: limit false-positives causing "HTTP header incomplete" due to + # idle server connections being randomly used and randomly expiring + # under us. + tune.idle-pool.shared off + + defaults + mode http + timeout connect "${HAPROXY_TEST_TIMEOUT-5s}" + timeout client "${HAPROXY_TEST_TIMEOUT-5s}" + timeout server "${HAPROXY_TEST_TIMEOUT-5s}" + option forwarded + + frontend fe1 + bind "fd@${fe1h2}" + use_backend default if { path /default } + use_backend override if { path /override } + use_backend disabled if { path /disabled } + + backend default + server s1 ${h1_fe2_addr}:${h1_fe2_port} + + backend override + option forwarded host-expr str(override) + server s1 ${h1_fe2_addr}:${h1_fe2_port} + + backend disabled + no option forwarded + server s1 ${h1_fe2_addr}:${h1_fe2_port} + +} -start + +client c1 -connect ${h1_fe1_sock} { + txreq -req GET -url /req1 \ + -hdr "x-src: 127.0.0.1" + rxresp + expect resp.status == 200 + expect resp.http.forwarded == "proto=http;for=127.0.0.1" + + txreq -req GET -url /req2 \ + -hdr "x-src: 127.0.0.2" \ + -hdr "x-dst: 127.0.0.3" + rxresp + expect resp.status == 200 + expect resp.http.forwarded == "by=\"127.0.0.3:10\";for=\"127.0.0.2:_id\"" + + txreq -req GET -url /req3 \ + -hdr "forwarded: for=\"unknown:132\";host=\"[::1]:65535\";by=\"_obfs:_port\";proto=https" + rxresp + expect resp.status == 200 + + txreq -req GET -url /req3 \ + -hdr "forwarded: for=\"127.0.0.1\";host=v.test" + rxresp + expect resp.status == 200 + + txreq -req GET -url /req3 \ + -hdr "forwarded: fore=\"unknown:132\"" + rxresp + expect resp.status == 400 + + txreq -req GET -url /req3 \ + -hdr "forwarded: proto=http;proto=http" + rxresp + expect resp.status == 400 + + txreq -req GET -url /req3 \ + -hdr "forwarded: \"" + rxresp + expect resp.status == 400 + + txreq -req GET -url /req3 \ + -hdr "forwarded: by=[::1]" + rxresp + expect resp.status == 400 + + txreq -req GET -url /req3 \ + -hdr "forwarded: by=\"[::1]\"" + rxresp + expect resp.status == 200 + + txreq -req GET -url /req3 \ + -hdr "forwarded: by=\"[::1]:\"" + rxresp + expect resp.status == 400 + + txreq -req GET -url /req3 \ + -hdr "forwarded: by=\"[::1]:3\"" + rxresp + expect resp.status == 200 + + txreq -req GET -url /req4 \ + -hdr "forwarded: proto=http;for=\"[::1]:_id\"" + rxresp + expect resp.status == 200 + expect resp.http.nodename == "::1" + expect resp.http.nodeport == "_id" +} -run + +client c2 -connect ${h2_fe1h2_sock} { + txreq -req GET -url /default + rxresp + expect resp.status == 200 + expect resp.http.forwarded != <undef> + + txreq -req GET -url /override + rxresp + expect resp.status == 200 + expect resp.http.forwarded == "host=\"override\"" + + txreq -req GET -url /disabled + rxresp + expect resp.status == 200 + expect resp.http.forwarded == <undef> +} -run diff --git a/reg-tests/http-rules/h1or2_to_h1c.vtc b/reg-tests/http-rules/h1or2_to_h1c.vtc new file mode 100644 index 0000000..3dd907e --- /dev/null +++ b/reg-tests/http-rules/h1or2_to_h1c.vtc @@ -0,0 +1,233 @@ +varnishtest "Composite HTTP manipulation test (H1 and H2 clear to H1 clear)" + +# This config tests several http-request features and their interactions. +# It extracts some samples, places them into variables, modifies some header +# fields, appends multiple identical header fields, overwrites the start line +# using several methods, then dumps the initial list of variables and the final +# one, then applies CRC32 to these values as signatures that are easy to test. +# Then it does it again in the backend after saving the current headers into +# the same names prefixed by "fe-". Then it does the same on the response path. +# If some modifications are performed, the crc values need to be adjusted based +# on the failed logs. +# +# Run it with HAPROXY_PROGRAM=$PWD/haproxy varnishtest -l -k -t 1 "$1" + +feature ignore_unknown_macro + +server s1 { + rxreq + txresp \ + -status 234 \ + -hdr "hdr1: val1" \ + -hdr "hdr2: val2a" \ + -hdr "hdr2: val2b" \ + -hdr "hdr3: val3a, val3b" \ + -hdr "hdr4:" \ + -body "This is a body" + + expect req.method == "GET" + expect req.http.fe-sl1-crc == 1874847043 + expect req.http.fe-sl2-crc == 1142278307 + expect req.http.fe-hdr-crc == 1719311923 + expect req.http.be-sl1-crc == 3455320059 + expect req.http.be-sl2-crc == 2509326257 + expect req.http.be-hdr-crc == 3634102538 +} -repeat 2 -start + +haproxy h1 -conf { + defaults + mode http + timeout connect "${HAPROXY_TEST_TIMEOUT-5s}" + timeout client "${HAPROXY_TEST_TIMEOUT-5s}" + timeout server "${HAPROXY_TEST_TIMEOUT-5s}" + + frontend fe + bind "fd@${feh1}" + bind "fd@${feh2}" proto h2 + + #### requests + http-request set-var(req.method) method + http-request set-var(req.uri) url + http-request set-var(req.path) path + http-request set-var(req.query) query + http-request set-var(req.param) url_param(qs_arg) + http-request set-var(req.cl) req.fhdr(content-length) + + http-request set-header sl1 "sl1: " + + http-request set-method "%[str(GET)]" + http-request set-uri %[str(),concat(/bu/,req.uri,/eu)] + http-request set-path "/bp/%[var(req.path)]/ep" + http-request set-query "bq&%[var(req.query)]&eq" + + http-request set-header sl2 "sl2: " + + http-request set-header sl1 "%[req.fhdr(sl1)] method=<%[var(req.method)]>; uri=<%[var(req.uri)]>; path=<%[var(req.path)]>;" + http-request set-header sl1 "%[req.fhdr(sl1)] query=<%[var(req.query)]>; param=<%[var(req.param)]>" + http-request set-header sl1 "%[req.fhdr(sl1)] cl=<%[var(req.cl)]>" + http-request set-header sl2 "%[req.fhdr(sl2)] method=<%[method]>; uri=<%[url]>; path=<%[path]>; " + http-request set-header sl2 "%[req.fhdr(sl2)] query=<%[query]>; param=<%[url_param(qs_arg)]>" + http-request set-header sl2 "%[req.fhdr(sl2)] cl=<%[req.fhdr(content-length)]>" + http-request set-header hdr "%[req.fhdr(hdr)] hdr1=<%[req.hdr(hdr1)]>; fhdr1=<%[req.fhdr(hdr1)]>;" + http-request set-header hdr "%[req.fhdr(hdr)] hdr2=<%[req.hdr(hdr2)]>; fhdr2=<%[req.fhdr(hdr2)]>;" + http-request set-header hdr "%[req.fhdr(hdr)] hdr3=<%[req.hdr(hdr3)]>; fhdr3=<%[req.fhdr(hdr3)]>;" + http-request set-header hdr "%[req.fhdr(hdr)] hdr4=<%[req.hdr(hdr4)]>; fhdr4=<%[req.fhdr(hdr4)]>;" + + http-request set-header sl1-crc "%[req.fhdr(sl1),crc32]" + http-request set-header sl2-crc "%[req.fhdr(sl2),crc32]" + http-request set-header hdr-crc "%[req.fhdr(hdr),crc32]" + + #### responses + http-response set-header be-sl1 "%[res.fhdr(sl1)]" + http-response set-header be-sl2 "%[res.fhdr(sl2)]" + http-response set-header be-hdr "%[res.fhdr(hdr)]" + + http-response set-header be-sl1-crc "%[res.fhdr(sl1-crc)]" + http-response set-header be-sl2-crc "%[res.fhdr(sl2-crc)]" + http-response set-header be-hdr-crc "%[res.fhdr(hdr-crc)]" + + http-response set-var(res.status) status + http-response set-header sl1 "sl1: " + + http-response set-status 200 + + http-response set-header sl2 "sl2: " + + http-response set-header sl1 "%[res.fhdr(sl1)] status=<%[var(res.status)]>;" + http-response set-header sl2 "%[res.fhdr(sl2)] status=<%[status]>;" + http-response set-header hdr "%[res.fhdr(hdr)] hdr1=<%[res.hdr(hdr1)]>; fhdr1=<%[res.fhdr(hdr1)]>;" + http-response set-header hdr "%[res.fhdr(hdr)] hdr2=<%[res.hdr(hdr2)]>; fhdr2=<%[res.fhdr(hdr2)]>;" + http-response set-header hdr "%[res.fhdr(hdr)] hdr3=<%[res.hdr(hdr3)]>; fhdr3=<%[res.fhdr(hdr3)]>;" + http-response set-header hdr "%[res.fhdr(hdr)] hdr4=<%[res.hdr(hdr4)]>; fhdr4=<%[res.fhdr(hdr4)]>;" + + http-response set-header fe-sl1-crc "%[res.fhdr(sl1),crc32]" + http-response set-header fe-sl2-crc "%[res.fhdr(sl2),crc32]" + http-response set-header fe-hdr-crc "%[res.fhdr(hdr),crc32]" + + default_backend be + + backend be + #### requests + http-request set-header fe-sl1 "%[req.fhdr(sl1)]" + http-request set-header fe-sl2 "%[req.fhdr(sl2)]" + http-request set-header fe-hdr "%[req.fhdr(hdr)]" + + http-request set-header fe-sl1-crc "%[req.fhdr(sl1-crc)]" + http-request set-header fe-sl2-crc "%[req.fhdr(sl2-crc)]" + http-request set-header fe-hdr-crc "%[req.fhdr(hdr-crc)]" + + http-request set-var(req.method) method + http-request set-var(req.uri) url + http-request set-var(req.path) path + http-request set-var(req.query) query + http-request set-var(req.param) url_param(qs_arg) + http-request set-var(req.cl) req.fhdr(content-length) + + http-request set-header sl1 "sl1: " + + http-request set-method "%[str(GET)]" + http-request set-uri %[str(),concat(/bu/,req.uri,/eu)] + http-request set-path "/bp/%[var(req.path)]/ep" + http-request set-query "bq&%[var(req.query)]&eq" + + http-request set-header sl2 "sl2: " + + http-request set-header sl1 "%[req.fhdr(sl1)] method=<%[var(req.method)]>; uri=<%[var(req.uri)]>; path=<%[var(req.path)]>;" + http-request set-header sl1 "%[req.fhdr(sl1)] query=<%[var(req.query)]>; param=<%[var(req.param)]>" + http-request set-header sl1 "%[req.fhdr(sl1)] cl=<%[var(req.cl)]>" + http-request set-header sl2 "%[req.fhdr(sl2)] method=<%[method]>; uri=<%[url]>; path=<%[path]>; " + http-request set-header sl2 "%[req.fhdr(sl2)] query=<%[query]>; param=<%[url_param(QS_arg,,i)]>" + http-request set-header sl2 "%[req.fhdr(sl2)] cl=<%[req.fhdr(content-length)]>" + http-request set-header hdr "%[req.fhdr(hdr)] hdr1=<%[req.hdr(hdr1)]>; fhdr1=<%[req.fhdr(hdr1)]>;" + http-request set-header hdr "%[req.fhdr(hdr)] hdr2=<%[req.hdr(hdr2)]>; fhdr2=<%[req.fhdr(hdr2)]>;" + http-request set-header hdr "%[req.fhdr(hdr)] hdr3=<%[req.hdr(hdr3)]>; fhdr3=<%[req.fhdr(hdr3)]>;" + http-request set-header hdr "%[req.fhdr(hdr)] hdr4=<%[req.hdr(hdr4)]>; fhdr4=<%[req.fhdr(hdr4)]>;" + + http-request set-header be-sl1-crc "%[req.fhdr(sl1),crc32]" + http-request set-header be-sl2-crc "%[req.fhdr(sl2),crc32]" + http-request set-header be-hdr-crc "%[req.fhdr(hdr),crc32]" + + #### responses + http-response set-var(res.status) status + http-response set-header sl1 "sl1: " + + http-response set-status 200 + + http-response set-header sl2 "sl2: " + + http-response set-header sl1 "%[res.fhdr(sl1)] status=<%[var(res.status)]>;" + http-response set-header sl2 "%[res.fhdr(sl2)] status=<%[status]>;" + http-response set-header hdr "%[res.fhdr(hdr)] hdr1=<%[res.hdr(hdr1)]>; fhdr1=<%[res.fhdr(hdr1)]>;" + http-response set-header hdr "%[res.fhdr(hdr)] hdr2=<%[res.hdr(hdr2)]>; fhdr2=<%[res.fhdr(hdr2)]>;" + http-response set-header hdr "%[res.fhdr(hdr)] hdr3=<%[res.hdr(hdr3)]>; fhdr3=<%[res.fhdr(hdr3)]>;" + http-response set-header hdr "%[res.fhdr(hdr)] hdr4=<%[res.hdr(hdr4)]>; fhdr4=<%[res.fhdr(hdr4)]>;" + + http-response set-header sl1-crc "%[res.fhdr(sl1),crc32]" + http-response set-header sl2-crc "%[res.fhdr(sl2),crc32]" + http-response set-header hdr-crc "%[res.fhdr(hdr),crc32]" + http-response allow + http-response deny # must not be evaluated + + server s1 ${s1_addr}:${s1_port} +} -start + +client c1h1 -connect ${h1_feh1_sock} { + txreq \ + -req GET \ + -url /path/to/file.extension?qs_arg=qs_value \ + -hdr "content-length: 000, 00" \ + -hdr "hdr1: val1" \ + -hdr "hdr2: val2a" \ + -hdr "hdr2: val2b" \ + -hdr "hdr3: val3a, val3b" \ + -hdr "hdr4:" + rxresp + + expect resp.status == 200 + expect resp.http.be-sl1-crc == 487202719 + expect resp.http.be-sl2-crc == 561949791 + expect resp.http.be-hdr-crc == 1719311923 + expect resp.http.fe-sl1-crc == 146151597 + expect resp.http.fe-sl2-crc == 561949791 + expect resp.http.fe-hdr-crc == 3634102538 + expect resp.bodylen == 14 + expect resp.body == "This is a body" +} -run + +client c1h2 -connect ${h1_feh2_sock} { + txpri + stream 0 { + txsettings + rxsettings + txsettings -ack + rxsettings + expect settings.ack == true + } -run + stream 1 { + # warning: -req, -scheme, -url MUST be placed first otherwise + # the H2 protocol is invalid since they are pseudo-headers + txreq \ + -req GET \ + -scheme "https" \ + -url /path/to/file.extension?qs_arg=qs_value \ + -hdr "content-length" "000, 00" \ + -hdr "hdr1" "val1" \ + -hdr "hdr2" " val2a" \ + -hdr "hdr2" " val2b" \ + -hdr "hdr3" " val3a, val3b" \ + -hdr "hdr4" "" + + rxhdrs + expect resp.status == 200 + expect resp.http.be-sl1-crc == 487202719 + expect resp.http.be-sl2-crc == 561949791 + expect resp.http.be-hdr-crc == 1719311923 + expect resp.http.fe-sl1-crc == 146151597 + expect resp.http.fe-sl2-crc == 561949791 + expect resp.http.fe-hdr-crc == 3634102538 + expect resp.http.content-length == 14 + + rxdata -all + expect resp.body == "This is a body" + } -run +} -run diff --git a/reg-tests/http-rules/http_after_response.vtc b/reg-tests/http-rules/http_after_response.vtc new file mode 100644 index 0000000..7e8cc1d --- /dev/null +++ b/reg-tests/http-rules/http_after_response.vtc @@ -0,0 +1,192 @@ +varnishtest "Test HTTP response manipulation under the http-after-response rulesets" +#REQUIRE_VERSION=2.2 + +# This config tests various http-after-response rules for HTTP responses from a +# server and the stats applet, but also for internal responses +# (deny/redirect/auth/return). + +feature ignore_unknown_macro + +server s1 { + rxreq + txresp \ + -status 234 \ + -hdr "hdr1: val1" \ + -hdr "hdr2: val2a" \ + -hdr "hdr2: val2b" \ + -hdr "hdr3: val3a, val3b" \ + -hdr "hdr4:" \ + -body "This is a body" +} -repeat 2 -start + +haproxy h1 -conf { + defaults + mode http + timeout connect "${HAPROXY_TEST_TIMEOUT-5s}" + timeout client "${HAPROXY_TEST_TIMEOUT-5s}" + timeout server "${HAPROXY_TEST_TIMEOUT-5s}" + + frontend fe + bind "fd@${feh1}" + + http-request deny if { path /deny } + http-request redirect location / if { path /redir } + http-request auth if { path /auth } + + http-after-response allow if { status eq 403 } + http-after-response allow if { status eq 302 } + http-after-response allow if { status eq 401 } + + http-after-response set-header be-sl1 "%[res.fhdr(sl1)]" + http-after-response set-header be-sl2 "%[res.fhdr(sl2)]" + http-after-response set-header be-hdr "%[res.fhdr(hdr)]" + + http-after-response set-header be-sl1-crc "%[res.fhdr(sl1-crc)]" + http-after-response set-header be-sl2-crc "%[res.fhdr(sl2-crc)]" + http-after-response set-header be-hdr-crc "%[res.fhdr(hdr-crc)]" + + http-after-response set-var(res.status) status + http-after-response set-header sl1 "sl1: " + + http-after-response set-status 200 + + http-after-response set-header sl2 "sl2: " + + http-after-response set-header sl1 "%[res.fhdr(sl1)] status=<%[var(res.status)]>;" + http-after-response set-header sl2 "%[res.fhdr(sl2)] status=<%[status]>;" + http-after-response set-header hdr "%[res.fhdr(hdr)] hdr1=<%[res.hdr(hdr1)]>; fhdr1=<%[res.fhdr(hdr1)]>;" + http-after-response set-header hdr "%[res.fhdr(hdr)] hdr2=<%[res.hdr(hdr2)]>; fhdr2=<%[res.fhdr(hdr2)]>;" + http-after-response set-header hdr "%[res.fhdr(hdr)] hdr3=<%[res.hdr(hdr3)]>; fhdr3=<%[res.fhdr(hdr3)]>;" + http-after-response set-header hdr "%[res.fhdr(hdr)] hdr4=<%[res.hdr(hdr4)]>; fhdr4=<%[res.fhdr(hdr4)]>;" + + http-after-response set-header fe-sl1-crc "%[res.fhdr(sl1),crc32]" + http-after-response set-header fe-sl2-crc "%[res.fhdr(sl2),crc32]" + http-after-response set-header fe-hdr-crc "%[res.fhdr(hdr),crc32]" + + default_backend be + + backend be + stats enable + stats uri /stats + + http-request return status 234 content-type "text/plain" string "This is a body" if { path /return } + + http-response deny if { capture.req.uri /deny-srv } + + http-after-response allow if { status eq 502 } + + http-after-response set-status 234 if { capture.req.uri /stats } + http-after-response add-header hdr1 val1 unless { capture.req.uri / } + http-after-response add-header hdr2 val2a unless { capture.req.uri / } + http-after-response add-header hdr2 val2b unless { capture.req.uri / } + http-after-response add-header hdr3 "val3a, val3b" unless { capture.req.uri / } + http-after-response add-header hdr4 "%[str()]" unless { capture.req.uri / } + http-after-response del-header content-type + + http-after-response set-var(res.status) status + http-after-response set-header sl1 "sl1: " + + http-after-response set-status 200 + + http-after-response set-header sl2 "sl2: " + + http-after-response set-header sl1 "%[res.fhdr(sl1)] status=<%[var(res.status)]>;" + http-after-response set-header sl2 "%[res.fhdr(sl2)] status=<%[status]>;" + http-after-response set-header hdr "%[res.fhdr(hdr)] hdr1=<%[res.hdr(hdr1)]>; fhdr1=<%[res.fhdr(hdr1)]>;" + http-after-response set-header hdr "%[res.fhdr(hdr)] hdr2=<%[res.hdr(hdr2)]>; fhdr2=<%[res.fhdr(hdr2)]>;" + http-after-response set-header hdr "%[res.fhdr(hdr)] hdr3=<%[res.hdr(hdr3)]>; fhdr3=<%[res.fhdr(hdr3)]>;" + http-after-response set-header hdr "%[res.fhdr(hdr)] hdr4=<%[res.hdr(hdr4)]>; fhdr4=<%[res.fhdr(hdr4)]>;" + + http-after-response set-header sl1-crc "%[res.fhdr(sl1),crc32]" + http-after-response set-header sl2-crc "%[res.fhdr(sl2),crc32]" + http-after-response set-header hdr-crc "%[res.fhdr(hdr),crc32]" + + server s1 ${s1_addr}:${s1_port} +} -start + +client c1 -connect ${h1_feh1_sock} { + txreq -req GET -url / + rxresp + expect resp.status == 200 + expect resp.http.be-sl1-crc == 487202719 + expect resp.http.be-sl2-crc == 561949791 + expect resp.http.be-hdr-crc == 1719311923 + expect resp.http.fe-sl1-crc == 146151597 + expect resp.http.fe-sl2-crc == 561949791 + expect resp.http.fe-hdr-crc == 3634102538 + expect resp.http.content-type == <undef> + expect resp.bodylen == 14 + expect resp.body == "This is a body" + + txreq -req GET -url /return + rxresp + expect resp.status == 200 + expect resp.http.be-sl1-crc == 487202719 + expect resp.http.be-sl2-crc == 561949791 + expect resp.http.be-hdr-crc == 1719311923 + expect resp.http.fe-sl1-crc == 146151597 + expect resp.http.fe-sl2-crc == 561949791 + expect resp.http.fe-hdr-crc == 3634102538 + expect resp.http.content-type == <undef> + expect resp.bodylen == 14 + expect resp.body == "This is a body" + + txreq -req GET -url /stats + rxresp + expect resp.status == 200 + expect resp.http.be-sl1-crc == 487202719 + expect resp.http.be-sl2-crc == 561949791 + expect resp.http.be-hdr-crc == 1719311923 + expect resp.http.fe-sl1-crc == 146151597 + expect resp.http.fe-sl2-crc == 561949791 + expect resp.http.fe-hdr-crc == 3634102538 + expect resp.http.content-type == <undef> +} -run + +client c2 -connect ${h1_feh1_sock} { + txreq -req GET -url /deny + rxresp + expect resp.status == 403 + expect resp.http.be-sl1 == <undef> + expect resp.http.be-sl2 == <undef> + expect resp.http.be-hdr == <undef> + expect resp.http.sl1 == <undef> + expect resp.http.sl2 == <undef> + expect resp.http.hdr == <undef> +} -run + +client c3 -connect ${h1_feh1_sock} { + txreq -req GET -url /redir + rxresp + expect resp.status == 302 + expect resp.http.be-sl1 == <undef> + expect resp.http.be-sl2 == <undef> + expect resp.http.be-hdr == <undef> + expect resp.http.sl1 == <undef> + expect resp.http.sl2 == <undef> + expect resp.http.hdr == <undef> +} -run + +client c4 -connect ${h1_feh1_sock} { + txreq -req GET -url /auth + rxresp + expect resp.status == 401 + expect resp.http.be-sl1 == <undef> + expect resp.http.be-sl2 == <undef> + expect resp.http.be-hdr == <undef> + expect resp.http.sl1 == <undef> + expect resp.http.sl2 == <undef> + expect resp.http.hdr == <undef> +} -run + +client c5 -connect ${h1_feh1_sock} { + txreq -req GET -url /deny-srv + rxresp + expect resp.status == 200 + expect resp.http.be-sl1 == "" + expect resp.http.be-sl2 == "" + expect resp.http.be-hdr == "" + expect resp.http.fe-sl1-crc == 3104968915 + expect resp.http.fe-sl2-crc == 561949791 + expect resp.http.fe-hdr-crc == 623352154 +} -run diff --git a/reg-tests/http-rules/http_return.vtc b/reg-tests/http-rules/http_return.vtc new file mode 100644 index 0000000..ae96775 --- /dev/null +++ b/reg-tests/http-rules/http_return.vtc @@ -0,0 +1,99 @@ +varnishtest "Test the HTTP return action" +#REQUIRE_VERSION=2.2 + +# This config tests the HTTP return action. + +feature ignore_unknown_macro + +haproxy h1 -conf { + global + # WT: limit false-positives causing "HTTP header incomplete" due to + # idle server connections being randomly used and randomly expiring + # under us. + tune.idle-pool.shared off + + defaults + mode http + timeout connect "${HAPROXY_TEST_TIMEOUT-5s}" + timeout client "${HAPROXY_TEST_TIMEOUT-5s}" + timeout server "${HAPROXY_TEST_TIMEOUT-5s}" + + frontend fe1 + bind "fd@${fe1}" + http-request return if { path /def-1 } + http-request return hdr "x-custom-hdr" "%[url]" if { path /def-2 } + http-request return status 403 if { path /def-3 } + http-request return content-type "text/plain" if { path /def-4 } + + http-request return content-type "text/plain" string "hello" hdr "x-custom-hdr" "%[url]" if { path /string } + http-request return content-type "text/plain" lf-string "path is %[url]" hdr "x-custom-hdr" "%[url]" if { path /lf-string } + http-request return content-type "text/plain" file /dev/null hdr "x-custom-hdr" "%[url]" if { path /empty-file } + http-request return content-type "text/plain" file ${testdir}/1k.txt hdr "x-custom-hdr" "%[url]" if { path /file } + http-request return content-type "text/plain" lf-file ${testdir}/lf-file.txt hdr "x-custom-hdr" "%[url]" if { path /lf-file } +} -start + +client c1 -connect ${h1_fe1_sock} { + txreq -req GET -url /def-1 + rxresp + expect resp.status == 200 + expect resp.http.content-length == 0 + expect resp.http.content-type == <undef> + expect resp.http.x-custom-hdr == <undef> + + txreq -req GET -url /def-2 + rxresp + expect resp.status == 200 + expect resp.http.content-length == 0 + expect resp.http.content-type == <undef> + expect resp.http.x-custom-hdr == "/def-2" + + txreq -req GET -url /def-3 + rxresp + expect resp.status == 403 + expect resp.http.content-length == 0 + expect resp.http.content-type == <undef> + + txreq -req GET -url /def-4 + rxresp + expect resp.status == 200 + expect resp.http.content-length == 0 + expect resp.http.content-type == <undef> + + txreq -req GET -url /string + rxresp + expect resp.status == 200 + expect resp.http.content-length == 5 + expect resp.http.content-type == "text/plain" + expect resp.http.x-custom-hdr == "/string" + expect resp.body == "hello" + + txreq -req GET -url /lf-string + rxresp + expect resp.status == 200 + expect resp.http.content-length == 18 + expect resp.http.content-type == "text/plain" + expect resp.http.x-custom-hdr == "/lf-string" + expect resp.body == "path is /lf-string" + + txreq -req GET -url /empty-file + rxresp + expect resp.status == 200 + expect resp.http.content-length == 0 + expect resp.http.content-type == <undef> + expect resp.http.x-custom-hdr == "/empty-file" + + txreq -req GET -url /file + rxresp + expect resp.status == 200 + expect resp.http.content-length == 1024 + expect resp.http.content-type == "text/plain" + expect resp.http.x-custom-hdr == "/file" + + txreq -req GET -url /lf-file + rxresp + expect resp.status == 200 + expect resp.http.content-length == 17 + expect resp.http.content-type == "text/plain" + expect resp.http.x-custom-hdr == "/lf-file" + expect resp.body == "path is /lf-file\n" +} -run diff --git a/reg-tests/http-rules/ifnone-forwardfor.vtc b/reg-tests/http-rules/ifnone-forwardfor.vtc new file mode 100644 index 0000000..a743b10 --- /dev/null +++ b/reg-tests/http-rules/ifnone-forwardfor.vtc @@ -0,0 +1,98 @@ +varnishtest "Test if-none param for the forwardfor option" +feature cmd "$HAPROXY_PROGRAM -cc 'version_atleast(2.6-dev0)'" + +# This config tests the if-none parameter for the HTTP forwardfor option. + +feature ignore_unknown_macro + +haproxy h1 -conf { + global + # WT: limit false-positives causing "HTTP header incomplete" due to + # idle server connections being randomly used and randomly expiring + # under us. + tune.idle-pool.shared off + + defaults + mode http + timeout connect "${HAPROXY_TEST_TIMEOUT-5s}" + timeout client "${HAPROXY_TEST_TIMEOUT-5s}" + timeout server "${HAPROXY_TEST_TIMEOUT-5s}" + + frontend none + bind "fd@${none}" + http-request set-src hdr(x-src) + option forwardfor if-none + use_backend be1 if { path /req1 } + use_backend be2 if { path /req2 } + use_backend be3 if { path /req3 } + + frontend normal + bind "fd@${normal}" + http-request set-src hdr(x-src) + option forwardfor + use_backend be1 if { path /req1 } + use_backend be2 if { path /req2 } + + + frontend fe2 + bind "fd@${fe2}" + http-request return status 200 hdr x-ff "%[req.fhdr_cnt(x-forwarded-for)]" + + backend be1 + option forwardfor + server s1 ${h1_fe2_addr}:${h1_fe2_port} + + backend be2 + option forwardfor if-none + server s1 ${h1_fe2_addr}:${h1_fe2_port} + + backend be3 + server s1 ${h1_fe2_addr}:${h1_fe2_port} +} -start + +client c1 -connect ${h1_none_sock} { + txreq -req GET -url /req1 \ + -hdr "x-src: 10.0.0.128" \ + -hdr "x-forwarded-for: 127.0.0.1" + rxresp + expect resp.status == 200 + expect resp.http.x-ff == 2 + + txreq -req GET -url /req2 \ + -hdr "x-src: 10.0.0.128" \ + -hdr "x-forwarded-for: 127.0.0.1" + rxresp + expect resp.status == 200 + expect resp.http.x-ff == 1 + + txreq -req GET -url /req2 \ + -hdr "x-src: 10.0.0.128" + rxresp + expect resp.status == 200 + expect resp.http.x-ff == 1 + + txreq -req GET -url /req3 \ + -hdr "x-src: 10.0.0.128" \ + -hdr "x-forwarded-for: 127.0.0.1" + rxresp + expect resp.status == 200 + expect resp.http.x-ff == 1 + +} -run + +client c1 -connect ${h1_normal_sock} { + txreq -req GET -url /req1 \ + -hdr "x-src: 10.0.0.128" \ + -hdr "x-forwarded-for: 127.0.0.1" + rxresp + expect resp.status == 200 + expect resp.http.x-ff == 2 + + txreq -req GET -url /req2 \ + -hdr "x-src: 10.0.0.128" \ + -hdr "x-forwarded-for: 127.0.0.1" + rxresp + expect resp.status == 200 + expect resp.http.x-ff == 2 + +} -run diff --git a/reg-tests/http-rules/lf-file.txt b/reg-tests/http-rules/lf-file.txt new file mode 100644 index 0000000..7fda1d4 --- /dev/null +++ b/reg-tests/http-rules/lf-file.txt @@ -0,0 +1 @@ +path is %[url] diff --git a/reg-tests/http-rules/map_ordering.map b/reg-tests/http-rules/map_ordering.map new file mode 100644 index 0000000..dcd9529 --- /dev/null +++ b/reg-tests/http-rules/map_ordering.map @@ -0,0 +1,4 @@ +# These entries are used for list-based match ordering tests +first.domain.tld first +domain.tld domain +second.domain.tld second diff --git a/reg-tests/http-rules/map_ordering.vtc b/reg-tests/http-rules/map_ordering.vtc new file mode 100644 index 0000000..40da465 --- /dev/null +++ b/reg-tests/http-rules/map_ordering.vtc @@ -0,0 +1,32 @@ +varnishtest "Test list-based matching types ordering" +feature cmd "$HAPROXY_PROGRAM -cc 'version_atleast(2.5-dev0)'" +feature ignore_unknown_macro + +haproxy h1 -conf { + defaults + mode http + timeout connect "${HAPROXY_TEST_TIMEOUT-5s}" + timeout client "${HAPROXY_TEST_TIMEOUT-5s}" + timeout server "${HAPROXY_TEST_TIMEOUT-5s}" + + frontend fe1 + bind "fd@${fe1}" + + # check list ordering using map_dom (list-based match) + http-request return hdr dom %[req.hdr(Host),lower,map_dom(${testdir}/map_ordering.map)] if { url_beg /dom } +} -start + +# Check map ordering +client c1 -connect ${h1_fe1_sock} { + # first.domain.tld is above domain.tld so it should match first + txreq -url "/dom" -hdr "Host: first.domain.tld" + rxresp + expect resp.status == 200 + expect resp.http.dom == "first" + + # second.domain.tld is below domain.tld so domain.tld should match first + txreq -url "/dom" -hdr "Host: second.domain.tld" + rxresp + expect resp.status == 200 + expect resp.http.dom == "domain" +} -run diff --git a/reg-tests/http-rules/map_redirect-be.map b/reg-tests/http-rules/map_redirect-be.map new file mode 100644 index 0000000..c8822fc --- /dev/null +++ b/reg-tests/http-rules/map_redirect-be.map @@ -0,0 +1,4 @@ +# These entries are used for use_backend rules +test1.example.com test1_be +test1.example.invalid test1_be +test2.example.com test2_be diff --git a/reg-tests/http-rules/map_redirect.map b/reg-tests/http-rules/map_redirect.map new file mode 100644 index 0000000..c4743f6 --- /dev/null +++ b/reg-tests/http-rules/map_redirect.map @@ -0,0 +1,5 @@ +# These entries are used for http-request redirect rules +example.org https://www.example.org +subdomain.example.org https://www.subdomain.example.org + +/path/to/old/file /path/to/new/file diff --git a/reg-tests/http-rules/map_redirect.vtc b/reg-tests/http-rules/map_redirect.vtc new file mode 100644 index 0000000..f55e0d8 --- /dev/null +++ b/reg-tests/http-rules/map_redirect.vtc @@ -0,0 +1,200 @@ +varnishtest "haproxy host header: map / redirect tests" +feature cmd "$HAPROXY_PROGRAM -cc 'version_atleast(2.5-dev5) && (feature(PCRE) || feature(PCRE2))'" +feature ignore_unknown_macro + + +server s1 { + rxreq + expect req.method == "GET" + expect req.http.host == "test1.example.com" + txresp -body "test1 ok" +} -start + +server s2 { + rxreq + expect req.method == "GET" + expect req.http.host == "test2.example.com" + txresp -body "test2 ok" +} -start + +server s3 { + rxreq + expect req.method == "GET" + expect req.http.host == "test3.example.com" + txresp -body "test3 ok" +} -start + +server s4 { + rxreq + expect req.method == "GET" + expect req.http.host == "test1.example.invalid" + txresp -body "test1 after del map ok" +} -start + +haproxy h1 -conf { + defaults + mode http + log global + option httplog + timeout connect "${HAPROXY_TEST_TIMEOUT-5s}" + timeout client "${HAPROXY_TEST_TIMEOUT-5s}" + timeout server "${HAPROXY_TEST_TIMEOUT-5s}" + + frontend fe1 + bind "fd@${fe1}" + + # automatically redirect matching paths from maps but skip rule on no-match + http-request redirect code 301 location %[path,map_str(${testdir}/map_redirect.map)] ignore-empty + + # redirect Host: example.org / subdomain.example.org + http-request redirect prefix %[req.hdr(Host),lower,regsub(:\d+$,,),map_str(${testdir}/map_redirect.map)] code 301 if { hdr(Host),lower,regsub(:\d+$,,),map_str(${testdir}/map_redirect.map) -m found } + + # set var and redirect in be1 + http-request set-var(txn.testvar) req.hdr(Testvar),lower,regsub(:\d+$,,),map_str(${testdir}/map_redirect.map) if { hdr(Testvar),lower,regsub(:\d+$,,),map_str(${testdir}/map_redirect.map) -m found } + + # use map to select backend (no default map value) + use_backend %[req.hdr(Host),lower,map_dom(${testdir}/map_redirect-be.map)] if { hdr_dom(Host) -i test1.example.com || hdr_dom(Host) -i test2.example.com } + + # use map to select backend with default value(test3_be) + use_backend %[req.hdr(Host),lower,map_dom(${testdir}/map_redirect-be.map,test3_be)] if { hdr_dom(Host) -m end -i example.com } + + # use map(after del map test1.example.com) default value(test4_be) + use_backend %[req.hdr(Host),lower,map_dom(${testdir}/map_redirect-be.map,test4_be)] if { hdr_dom(Host) -m end -i example.invalid } + + default_backend be1 + + backend be1 + http-request redirect prefix %[var(txn.testvar)] code 301 if { var(txn.testvar) -m found } + http-request deny + + backend test1_be + server s1 ${s1_addr}:${s1_port} + + backend test2_be + server s2 ${s2_addr}:${s2_port} + + backend test3_be + server s3 ${s3_addr}:${s3_port} + + backend test4_be + server s4 ${s4_addr}:${s4_port} +} -start + +# Check map redirects +client c1 -connect ${h1_fe1_sock} { + txreq -hdr "Host: example.org:8443" + rxresp + expect resp.status == 301 + expect resp.http.location ~ "https://www.example.org" + + txreq -url /path/to/old/file + rxresp + expect resp.status == 301 + expect resp.http.location ~ "/path/to/new/file" + + # Closes connection +} -run + +client c2 -connect ${h1_fe1_sock} { + txreq -hdr "Host: subdomain.example.org" + rxresp + expect resp.status == 301 + expect resp.http.location ~ "https://www.subdomain.example.org" + # Closes connection +} -run + +client c3 -connect ${h1_fe1_sock} { + # redirect on Testvar header + txreq -hdr "Testvar: subdomain.example.org" + rxresp + expect resp.status == 301 + expect resp.http.location ~ "https://www.subdomain.example.org" + # Closes connection +} -run + +client c4 -connect ${h1_fe1_sock} { + txreq -hdr "Host: www.subdomain.example.org" + rxresp + expect resp.status == 403 + # Closes connection +} -run + +client c5 -connect ${h1_fe1_sock} { + txreq -hdr "Testvar: www.subdomain.example.org" + rxresp + expect resp.status == 403 + # Closes connection +} -run + +client c6 -connect ${h1_fe1_sock} { + txreq -hdr "Host: :8443example.org" + rxresp + expect resp.status == 403 + # Closes connection +} -run + +# Check map backend selection +client c7 -connect ${h1_fe1_sock} { + txreq -hdr "Host: test1.example.com" + rxresp + expect resp.status == 200 + expect resp.body == "test1 ok" + + txreq -hdr "Host: test2.example.com" + rxresp + expect resp.status == 200 + expect resp.body == "test2 ok" + + txreq -hdr "Host: test3.example.com" + rxresp + expect resp.status == 200 + expect resp.body == "test3 ok" +} -run + +# cli show maps +haproxy h1 -cli { + send "show map ${testdir}/map_redirect.map" + expect ~ "^0x[a-f0-9]+ example\\.org https://www\\.example\\.org\\n0x[a-f0-9]+ subdomain\\.example\\.org https://www\\.subdomain\\.example\\.org\\n0x[a-f0-9]+ /path/to/old/file /path/to/new/file\n$" + + send "show map ${testdir}/map_redirect-be.map" + expect ~ "^0x[a-f0-9]+ test1\\.example\\.com test1_be\\n0x[a-f0-9]+ test1\\.example\\.invalid test1_be\\n0x[a-f0-9]+ test2\\.example\\.com test2_be\\n$" +} + +haproxy h1 -cli { + # clear map ${testdir}/map_redirect.map + send "clear map ${testdir}/map_redirect.map" + expect ~ "^\\n" + + send "show map ${testdir}/map_redirect.map" + expect ~ "^\\n" + + # add map ${testdir}/map_redirect.map + send "add map ${testdir}/map_redirect.map site1_key site1_value" + expect ~ "^\\n" + + # add 2 more entries as payload + send "add map ${testdir}/map_redirect.map <<\nsite2_key site2_value\nsite3_key site3_value\n" + expect ~ "^\\n" + + send "show map ${testdir}/map_redirect.map" + expect ~ "^0x[a-f0-9]+ site1_key site1_value\\n0x[a-f0-9]+ site2_key site2_value\\n0x[a-f0-9]+ site3_key site3_value\\n$" + + # del map ${testdir}/map_redirect-be.map test1.example.{com,invalid} + send "del map ${testdir}/map_redirect-be.map test1.example.com" + expect ~ "^\\n" + + send "del map ${testdir}/map_redirect-be.map test1.example.invalid" + expect ~ "^\\n" + + send "show map ${testdir}/map_redirect-be.map" + expect ~ "^0x[a-f0-9]+ test2\\.example\\.com test2_be\\n$" +} + +# Check map backend after del map +client c6 -connect ${h1_fe1_sock} { + # test1.example.invalid should go to test4_be after del map + txreq -hdr "Host: test1.example.invalid" + rxresp + expect resp.status == 200 + expect resp.body == "test1 after del map ok" +} -run diff --git a/reg-tests/http-rules/map_regm_with_backref.map b/reg-tests/http-rules/map_regm_with_backref.map new file mode 100644 index 0000000..08ffcfb --- /dev/null +++ b/reg-tests/http-rules/map_regm_with_backref.map @@ -0,0 +1 @@ +^(.*)\.(.*)$ \1_AND_\2 diff --git a/reg-tests/http-rules/map_regm_with_backref.vtc b/reg-tests/http-rules/map_regm_with_backref.vtc new file mode 100644 index 0000000..c3b21fb --- /dev/null +++ b/reg-tests/http-rules/map_regm_with_backref.vtc @@ -0,0 +1,73 @@ +#commit 271022150d7961b9aa39dbfd88e0c6a4bc48c3ee +# BUG/MINOR: map: fix map_regm with backref +# +# Due to a cascade of get_trash_chunk calls the sample is +# corrupted when we want to read it. +# +# The fix consist to use a temporary chunk to copy the sample +# value and use it. + +varnishtest "map_regm get_trash_chunk test" +feature ignore_unknown_macro + +#REGTEST_TYPE=bug + +syslog S1 -level notice { + recv info + # not expecting ${h1_pid} with master-worker + expect ~ "[^:\\[ ]\\[[[:digit:]]+\\]: .* fe1 be1/s1 [[:digit:]]+/[[:digit:]]+/[[:digit:]]+/[[:digit:]]+/[[:digit:]]+ 200 [[:digit:]]+ - - ---- .* \"GET / HTTP/(1|2)(\\.1)?\"" +} -start + +server s1 { + rxreq + expect req.method == "GET" + expect req.http.x-mapped-from-header == example_AND_org + expect req.http.x-mapped-from-var == example_AND_org + txresp + + rxreq + expect req.method == "GET" + expect req.http.x-mapped-from-header == www.example_AND_org + expect req.http.x-mapped-from-var == www.example_AND_org + txresp +} -start + +haproxy h1 -conf { + global + log ${S1_addr}:${S1_port} local0 debug err + + defaults + mode http + log global + option httplog + timeout connect "${HAPROXY_TEST_TIMEOUT-5s}" + timeout client "${HAPROXY_TEST_TIMEOUT-5s}" + timeout server "${HAPROXY_TEST_TIMEOUT-5s}" + + frontend fe1 + bind "fd@${fe1}" + # Remove port from Host header + http-request replace-value Host '(.*):.*' '\1' + # Store host header in variable + http-request set-var(txn.host) req.hdr(Host) + # This works correctly + http-request set-header X-Mapped-From-Header %[req.hdr(Host),map_regm(${testdir}/map_regm_with_backref.map,"unknown")] + # This breaks before commit 271022150d7961b9aa39dbfd88e0c6a4bc48c3ee + http-request set-header X-Mapped-From-Var %[var(txn.host),map_regm(${testdir}/map_regm_with_backref.map,"unknown")] + + default_backend be1 + + backend be1 + server s1 ${s1_addr}:${s1_port} +} -start + +client c1 -connect ${h1_fe1_sock} { + txreq -hdr "Host: example.org:8443" + rxresp + expect resp.status == 200 + + txreq -hdr "Host: www.example.org" + rxresp + expect resp.status == 200 +} -run + diff --git a/reg-tests/http-rules/normalize_uri.vtc b/reg-tests/http-rules/normalize_uri.vtc new file mode 100644 index 0000000..ad7b44a --- /dev/null +++ b/reg-tests/http-rules/normalize_uri.vtc @@ -0,0 +1,549 @@ +varnishtest "normalize-uri tests" +#REQUIRE_VERSION=2.4 + +# This reg-test tests the http-request normalize-uri action. + +feature ignore_unknown_macro + +server s1 { + rxreq + txresp -hdr "connection: close" +} -repeat 70 -start + +haproxy h1 -conf { + global + # WT: limit false-positives causing "HTTP header incomplete" due to + # idle server connections being randomly used and randomly expiring + # under us. + tune.idle-pool.shared off + expose-experimental-directives + + defaults + mode http + timeout connect "${HAPROXY_TEST_TIMEOUT-5s}" + timeout client "${HAPROXY_TEST_TIMEOUT-5s}" + timeout server "${HAPROXY_TEST_TIMEOUT-5s}" + + frontend fe_path_merge_slashes + bind "fd@${fe_path_merge_slashes}" + + http-request set-var(txn.before) url + http-request normalize-uri path-merge-slashes + http-request set-var(txn.after) url + + http-response add-header before %[var(txn.before)] + http-response add-header after %[var(txn.after)] + + default_backend be + + frontend fe_path_strip_dotdot + bind "fd@${fe_path_strip_dotdot}" + + http-request set-var(txn.before) url + http-request normalize-uri path-strip-dotdot + http-request set-var(txn.after) url + + http-request set-uri %[var(txn.before)] + http-request normalize-uri path-strip-dotdot full + http-request set-var(txn.after_full) url + + http-response add-header before %[var(txn.before)] + http-response add-header after %[var(txn.after)] + http-response add-header after-full %[var(txn.after_full)] + + default_backend be + + frontend fe_sort_query_by_name + bind "fd@${fe_sort_query_by_name}" + + http-request set-var(txn.before) url + http-request normalize-uri query-sort-by-name + http-request set-var(txn.after) url + + http-response add-header before %[var(txn.before)] + http-response add-header after %[var(txn.after)] + + default_backend be + + frontend fe_percent_to_uppercase + bind "fd@${fe_percent_to_uppercase}" + + http-request set-var(txn.before) url + http-request normalize-uri percent-to-uppercase + http-request set-var(txn.after) url + + http-response add-header before %[var(txn.before)] + http-response add-header after %[var(txn.after)] + + default_backend be + + frontend fe_percent_to_uppercase_strict + bind "fd@${fe_percent_to_uppercase_strict}" + + http-request set-var(txn.before) url + http-request normalize-uri percent-to-uppercase strict + http-request set-var(txn.after) url + + http-response add-header before %[var(txn.before)] + http-response add-header after %[var(txn.after)] + + default_backend be + + frontend fe_dot + bind "fd@${fe_dot}" + + http-request set-var(txn.before) url + http-request normalize-uri path-strip-dot + http-request set-var(txn.after) url + + http-response add-header before %[var(txn.before)] + http-response add-header after %[var(txn.after)] + + default_backend be + + frontend fe_percent_decode_unreserved + bind "fd@${fe_percent_decode_unreserved}" + + http-request set-var(txn.before) url + http-request normalize-uri percent-decode-unreserved + http-request set-var(txn.after) url + + http-response add-header before %[var(txn.before)] + http-response add-header after %[var(txn.after)] + + default_backend be + + frontend fe_percent_decode_unreserved_strict + bind "fd@${fe_percent_decode_unreserved_strict}" + + http-request set-var(txn.before) url + http-request normalize-uri percent-decode-unreserved strict + http-request set-var(txn.after) url + + http-response add-header before %[var(txn.before)] + http-response add-header after %[var(txn.after)] + + default_backend be + + frontend fe_fragment_strip + bind "fd@${fe_fragment_strip}" + option accept-invalid-http-request + + http-request set-var(txn.before) url + http-request normalize-uri fragment-strip + http-request set-var(txn.after) url + + http-response add-header before %[var(txn.before)] + http-response add-header after %[var(txn.after)] + + default_backend be + + frontend fe_fragment_encode + bind "fd@${fe_fragment_encode}" + option accept-invalid-http-request + + http-request set-var(txn.before) url + http-request normalize-uri fragment-encode + http-request set-var(txn.after) url + + http-response add-header before %[var(txn.before)] + http-response add-header after %[var(txn.after)] + + default_backend be + + frontend fe_fragment_block + bind "fd@${fe_fragment_block}" + http-request normalize-uri fragment-strip + default_backend be + + backend be + server s1 ${s1_addr}:${s1_port} + +} -start + +client c1 -connect ${h1_fe_path_merge_slashes_sock} { + txreq -url "/foo/bar" + rxresp + expect resp.http.before == "/foo/bar" + expect resp.http.after == "/foo/bar" + + txreq -url "/foo//bar" + rxresp + expect resp.http.before == "/foo//bar" + expect resp.http.after == "/foo/bar" + + txreq -url "/foo///bar" + rxresp + expect resp.http.before == "/foo///bar" + expect resp.http.after == "/foo/bar" + + txreq -url "///foo///bar" + rxresp + expect resp.http.before == "///foo///bar" + expect resp.http.after == "/foo/bar" + + txreq -url "///foo/bar" + rxresp + expect resp.http.before == "///foo/bar" + expect resp.http.after == "/foo/bar" + + txreq -url "///foo///bar///" + rxresp + expect resp.http.before == "///foo///bar///" + expect resp.http.after == "/foo/bar/" + + txreq -url "///" + rxresp + expect resp.http.before == "///" + expect resp.http.after == "/" + + txreq -url "/foo?bar=///" + rxresp + expect resp.http.before == "/foo?bar=///" + expect resp.http.after == "/foo?bar=///" + + txreq -url "//foo?bar=///" + rxresp + expect resp.http.before == "//foo?bar=///" + expect resp.http.after == "/foo?bar=///" + + txreq -req OPTIONS -url "*" + rxresp + expect resp.http.before == "*" + expect resp.http.after == "*" +} -run + +client c2 -connect ${h1_fe_path_strip_dotdot_sock} { + txreq -url "/foo/bar" + rxresp + expect resp.http.before == "/foo/bar" + expect resp.http.after == "/foo/bar" + expect resp.http.after-full == "/foo/bar" + + txreq -url "/foo/.." + rxresp + expect resp.http.before == "/foo/.." + expect resp.http.after == "/" + expect resp.http.after-full == "/" + + txreq -url "/foo/../" + rxresp + expect resp.http.before == "/foo/../" + expect resp.http.after == "/" + expect resp.http.after-full == "/" + + txreq -url "/foo/bar/../" + rxresp + expect resp.http.before == "/foo/bar/../" + expect resp.http.after == "/foo/" + expect resp.http.after-full == "/foo/" + + txreq -url "/foo/../bar" + rxresp + expect resp.http.before == "/foo/../bar" + expect resp.http.after == "/bar" + expect resp.http.after-full == "/bar" + + txreq -url "/foo/../bar/" + rxresp + expect resp.http.before == "/foo/../bar/" + expect resp.http.after == "/bar/" + expect resp.http.after-full == "/bar/" + + txreq -url "/foo/../../bar/" + rxresp + expect resp.http.before == "/foo/../../bar/" + expect resp.http.after == "/../bar/" + expect resp.http.after-full == "/bar/" + + txreq -url "/foo//../../bar/" + rxresp + expect resp.http.before == "/foo//../../bar/" + expect resp.http.after == "/bar/" + expect resp.http.after-full == "/bar/" + + txreq -url "/foo/?bar=/foo/../" + rxresp + expect resp.http.before == "/foo/?bar=/foo/../" + expect resp.http.after == "/foo/?bar=/foo/../" + expect resp.http.after-full == "/foo/?bar=/foo/../" + + txreq -url "/foo/../?bar=/foo/../" + rxresp + expect resp.http.before == "/foo/../?bar=/foo/../" + expect resp.http.after == "/?bar=/foo/../" + expect resp.http.after-full == "/?bar=/foo/../" + + txreq -req OPTIONS -url "*" + rxresp + expect resp.http.before == "*" + expect resp.http.after == "*" + expect resp.http.after-full == "*" +} -run + +client c3 -connect ${h1_fe_sort_query_by_name_sock} { + txreq -url "/?a=a" + rxresp + expect resp.http.before == "/?a=a" + expect resp.http.after == "/?a=a" + + txreq -url "/?a=a&z=z" + rxresp + expect resp.http.before == "/?a=a&z=z" + expect resp.http.after == "/?a=a&z=z" + + txreq -url "/?z=z&a=a" + rxresp + expect resp.http.before == "/?z=z&a=a" + expect resp.http.after == "/?a=a&z=z" + + txreq -url "/?a=z&z=a" + rxresp + expect resp.http.before == "/?a=z&z=a" + expect resp.http.after == "/?a=z&z=a" + + txreq -url "/?z=a&a=z" + rxresp + expect resp.http.before == "/?z=a&a=z" + expect resp.http.after == "/?a=z&z=a" + + txreq -url "/?c&b&a&z&x&y" + rxresp + expect resp.http.before == "/?c&b&a&z&x&y" + expect resp.http.after == "/?a&b&c&x&y&z" + + txreq -url "/?a=&aa=&aaa=&aaaa=" + rxresp + expect resp.http.before == "/?a=&aa=&aaa=&aaaa=" + expect resp.http.after == "/?a=&aa=&aaa=&aaaa=" + + txreq -url "/?aaaa=&a=&aa=&aaa=" + rxresp + expect resp.http.before == "/?aaaa=&a=&aa=&aaa=" + expect resp.http.after == "/?a=&aa=&aaa=&aaaa=" + + txreq -url "/?a=5&a=3&a=1&a=2&a=4" + rxresp + expect resp.http.before == "/?a=5&a=3&a=1&a=2&a=4" + expect resp.http.after == "/?a=5&a=3&a=1&a=2&a=4" + + txreq -url "/?a=5&b=3&a=1&a=2&b=4" + rxresp + expect resp.http.before == "/?a=5&b=3&a=1&a=2&b=4" + expect resp.http.after == "/?a=5&a=1&a=2&b=3&b=4" + + txreq -url "/" + rxresp + expect resp.http.before == "/" + expect resp.http.after == "/" + + txreq -url "/?" + rxresp + expect resp.http.before == "/?" + expect resp.http.after == "/?" + + txreq -req OPTIONS -url "*" + rxresp + expect resp.http.before == "*" + expect resp.http.after == "*" +} -run + +client c4 -connect ${h1_fe_percent_to_uppercase_sock} { + txreq -url "/a?a=a" + rxresp + expect resp.http.before == "/a?a=a" + expect resp.http.after == "/a?a=a" + + txreq -url "/%aa?a=%aa" + rxresp + expect resp.http.before == "/%aa?a=%aa" + expect resp.http.after == "/%AA?a=%AA" + + txreq -url "/%zz?a=%zz" + rxresp + expect resp.status == 200 + expect resp.http.before == "/%zz?a=%zz" + expect resp.http.after == "/%zz?a=%zz" + + txreq -req OPTIONS -url "*" + rxresp + expect resp.http.before == "*" + expect resp.http.after == "*" +} -run + +client c5 -connect ${h1_fe_percent_to_uppercase_strict_sock} { + txreq -url "/a?a=a" + rxresp + expect resp.http.before == "/a?a=a" + expect resp.http.after == "/a?a=a" + + txreq -url "/%aa?a=%aa" + rxresp + expect resp.http.before == "/%aa?a=%aa" + expect resp.http.after == "/%AA?a=%AA" + + txreq -url "/%zz?a=%zz" + rxresp + expect resp.status == 400 +} -run + +client c6 -connect ${h1_fe_dot_sock} { + txreq -url "/" + rxresp + expect resp.http.before == "/" + expect resp.http.after == "/" + + txreq -url "/a/b" + rxresp + expect resp.http.before == "/a/b" + expect resp.http.after == "/a/b" + + txreq -url "/." + rxresp + expect resp.http.before == "/." + expect resp.http.after == "/" + + txreq -url "/./" + rxresp + expect resp.http.before == "/./" + expect resp.http.after == "/" + + txreq -url "/a/." + rxresp + expect resp.http.before == "/a/." + expect resp.http.after == "/a/" + + txreq -url "/a." + rxresp + expect resp.http.before == "/a." + expect resp.http.after == "/a." + + txreq -url "/.a" + rxresp + expect resp.http.before == "/.a" + expect resp.http.after == "/.a" + + txreq -url "/a/." + rxresp + expect resp.http.before == "/a/." + expect resp.http.after == "/a/" + + txreq -url "/a/./" + rxresp + expect resp.http.before == "/a/./" + expect resp.http.after == "/a/" + + txreq -url "/a/./a" + rxresp + expect resp.http.before == "/a/./a" + expect resp.http.after == "/a/a" + + txreq -url "/a/../" + rxresp + expect resp.http.before == "/a/../" + expect resp.http.after == "/a/../" + + txreq -url "/a/../a" + rxresp + expect resp.http.before == "/a/../a" + expect resp.http.after == "/a/../a" + + txreq -url "/?a=/./" + rxresp + expect resp.http.before == "/?a=/./" + expect resp.http.after == "/?a=/./" +} -run + +client c7 -connect ${h1_fe_percent_decode_unreserved_sock} { + txreq -url "/a?a=a" + rxresp + expect resp.http.before == "/a?a=a" + expect resp.http.after == "/a?a=a" + + txreq -url "/%61?%61=%61" + rxresp + expect resp.http.before == "/%61?%61=%61" + expect resp.http.after == "/a?a=a" + + txreq -url "/%3F?foo=bar" + rxresp + expect resp.http.before == "/%3F?foo=bar" + expect resp.http.after == "/%3F?foo=bar" + + txreq -url "/%%36%36" + rxresp + expect resp.status == 200 + expect resp.http.before == "/%%36%36" + expect resp.http.after == "/%66" + + txreq -req OPTIONS -url "*" + rxresp + expect resp.http.before == "*" + expect resp.http.after == "*" +} -run + +client c8 -connect ${h1_fe_percent_decode_unreserved_strict_sock} { + txreq -url "/a?a=a" + rxresp + expect resp.http.before == "/a?a=a" + expect resp.http.after == "/a?a=a" + + txreq -url "/%61?%61=%61" + rxresp + expect resp.http.before == "/%61?%61=%61" + expect resp.http.after == "/a?a=a" + + txreq -url "/%3F?foo=bar" + rxresp + expect resp.http.before == "/%3F?foo=bar" + expect resp.http.after == "/%3F?foo=bar" + + txreq -url "/%%36%36" + rxresp + expect resp.status == 400 +} -run + +client c9 -connect ${h1_fe_fragment_strip_sock} { + txreq -url "/#foo" + rxresp + expect resp.http.before == "/#foo" + expect resp.http.after == "/" + + txreq -url "/%23foo" + rxresp + expect resp.http.before == "/%23foo" + expect resp.http.after == "/%23foo" + + txreq -req OPTIONS -url "*" + rxresp + expect resp.http.before == "*" + expect resp.http.after == "*" +} -run + +client c10 -connect ${h1_fe_fragment_encode_sock} { + txreq -url "/#foo" + rxresp + expect resp.http.before == "/#foo" + expect resp.http.after == "/%23foo" + + txreq -url "/#foo/#foo" + rxresp + expect resp.http.before == "/#foo/#foo" + expect resp.http.after == "/%23foo/%23foo" + + txreq -url "/%23foo" + rxresp + expect resp.http.before == "/%23foo" + expect resp.http.after == "/%23foo" + + txreq -req OPTIONS -url "*" + rxresp + expect resp.http.before == "*" + expect resp.http.after == "*" +} -run + +client c11 -connect ${h1_fe_fragment_block_sock} { + txreq -url "/#foo" + rxresp + expect resp.status == 400 +} -run diff --git a/reg-tests/http-rules/path_and_pathq.vtc b/reg-tests/http-rules/path_and_pathq.vtc new file mode 100644 index 0000000..31e85be --- /dev/null +++ b/reg-tests/http-rules/path_and_pathq.vtc @@ -0,0 +1,64 @@ +varnishtest "path vs pathq tests" +#REQUIRE_VERSION=2.2 + +# This config tests various http request rules (set/replace) manipulating the +# path, with or without the query-string. It also test path and pathq sample +# fetches. + +feature ignore_unknown_macro + +server s1 { + rxreq + expect req.url == /regtest/foo/fe/req1/bar?param1=val1¶m2=val2 + expect req.http.x-path == /req1 + expect req.http.x-pathq == /req1?param1=val1¶m2=val2 + expect req.http.x-query == param1=val1¶m2=val2 + expect req.http.x-url == /req1?param1=val1¶m2=val2 + txresp + + rxreq + expect req.url == http://127.0.0.1/regtest/foo/fe/req2/bar?param1=val1¶m2=val2 + expect req.http.x-path == /req2 + expect req.http.x-pathq == /req2?param1=val1¶m2=val2 + expect req.http.x-query == param1=val1¶m2=val2 + expect req.http.x-url == http://127.0.0.1/req2?param1=val1¶m2=val2 + txresp +} -start + +haproxy h1 -conf { + defaults + mode http + timeout connect "${HAPROXY_TEST_TIMEOUT-5s}" + timeout client "${HAPROXY_TEST_TIMEOUT-5s}" + timeout server "${HAPROXY_TEST_TIMEOUT-5s}" + + frontend fe + bind "fd@${fe}" + + http-request add-header x-path %[path] + http-request add-header x-pathq %[pathq] + http-request add-header x-query %[query] + http-request add-header x-url %[url] + + http-request set-path /fe%[path] + http-request replace-path (.*) /foo\1 + http-request replace-path (.*) \1/bar + http-request set-pathq %[path]?app=regtest&%[query] + http-request replace-pathq /([^?]*)\?app=([^&]*)&?(.*) /\2/\1?\3 + + default_backend be + + backend be + server s1 ${s1_addr}:${s1_port} + +} -start + +client c1 -connect ${h1_fe_sock} { + txreq -req GET -url /req1?param1=val1¶m2=val2 + rxresp + expect resp.status == 200 + + txreq -req GET -url http://127.0.0.1/req2?param1=val1¶m2=val2 + rxresp + expect resp.status == 200 +} -run diff --git a/reg-tests/http-rules/restrict_req_hdr_names.vtc b/reg-tests/http-rules/restrict_req_hdr_names.vtc new file mode 100644 index 0000000..4b26e33 --- /dev/null +++ b/reg-tests/http-rules/restrict_req_hdr_names.vtc @@ -0,0 +1,185 @@ +varnishtest "http-restrict-req-hdr-names option tests" +feature cmd "$HAPROXY_PROGRAM -cc 'version_atleast(2.0-dev0)'" + +# This config tests "http-restrict-req-hdr-names" option + +feature ignore_unknown_macro + +server s1 { + rxreq + expect req.http.x-my_hdr == on + txresp +} -start + +server s2 { + rxreq + expect req.http.x-my_hdr == <undef> + txresp +} -start + +server s3 { + rxreq + expect req.http.x-my_hdr == on + txresp +} -start + +server s4 { + rxreq + expect req.http.x-my_hdr == <undef> + txresp +} -start + +server s5 { + rxreq + expect req.http.x-my_hdr == on + txresp +} -start + +server s6 { + rxreq + expect req.http.x_my_hdr_with_lots_of_underscores == <undef> + txresp +} -start + +server s7 { + rxreq + expect req.http.x_my_hdr-1 == <undef> + expect req.http.x-my-hdr-2 == on + txresp +} -start + +server s8 { + rxreq + expect req.http.x-my_hdr-1 == <undef> + expect req.http.x-my_hdr-2 == <undef> + txresp +} -start + +server s9 { + rxreq + expect req.http.x-my-hdr-with-trailing-underscore_ == <undef> + txresp +} -start + +haproxy h1 -conf { + defaults + mode http + timeout connect "${HAPROXY_TEST_TIMEOUT-5s}" + timeout client "${HAPROXY_TEST_TIMEOUT-5s}" + timeout server "${HAPROXY_TEST_TIMEOUT-5s}" + + frontend fe1 + bind "fd@${fe1}" + use_backend be-http1 if { path /req1 } + use_backend be-http2 if { path /req2 } + use_backend be-http3 if { path /req3 } + use_backend be-fcgi1 if { path /req4 } + use_backend be-fcgi2 if { path /req5 } + use_backend be-fcgi3 if { path /req6 } + use_backend be-http4 if { path /req7 } + use_backend be-http5 if { path /req8 } + use_backend be-http6 if { path /req9 } + use_backend be-http7 if { path /req10 } + + backend be-http1 + server s1 ${s1_addr}:${s1_port} + + backend be-http2 + option http-restrict-req-hdr-names delete + server s2 ${s2_addr}:${s2_port} + + backend be-http3 + option http-restrict-req-hdr-names reject + + backend be-fcgi1 + option http-restrict-req-hdr-names preserve + server s3 ${s3_addr}:${s3_port} + + backend be-fcgi2 + option http-restrict-req-hdr-names delete + server s4 ${s4_addr}:${s4_port} + + backend be-fcgi3 + option http-restrict-req-hdr-names reject + + backend be-http4 + option http-restrict-req-hdr-names delete + server s6 ${s6_addr}:${s6_port} + + backend be-http5 + option http-restrict-req-hdr-names delete + server s7 ${s7_addr}:${s7_port} + + backend be-http6 + option http-restrict-req-hdr-names delete + server s8 ${s8_addr}:${s8_port} + + backend be-http7 + option http-restrict-req-hdr-names delete + server s9 ${s9_addr}:${s9_port} + + defaults + mode http + timeout connect "${HAPROXY_TEST_TIMEOUT-5s}" + timeout client "${HAPROXY_TEST_TIMEOUT-5s}" + timeout server "${HAPROXY_TEST_TIMEOUT-5s}" + option http-restrict-req-hdr-names preserve + + frontend fe2 + bind "fd@${fe2}" + default_backend be-fcgi4 + + backend be-fcgi4 + server s5 ${s5_addr}:${s5_port} + + fcgi-app my-fcgi-app + docroot ${testdir} +} -start + +client c1 -connect ${h1_fe1_sock} { + txreq -req GET -url /req1 -hdr "X-my_hdr: on" + rxresp + expect resp.status == 200 + + txreq -req GET -url /req2 -hdr "X-my_hdr: on" + rxresp + expect resp.status == 200 + + txreq -req GET -url /req3 -hdr "X-my_hdr: on" + rxresp + expect resp.status == 403 + + txreq -req GET -url /req4 -hdr "X-my_hdr: on" + rxresp + expect resp.status == 200 + + txreq -req GET -url /req5 -hdr "X-my_hdr: on" + rxresp + expect resp.status == 200 + + txreq -req GET -url /req6 -hdr "X-my_hdr: on" + rxresp + expect resp.status == 403 + + txreq -req GET -url /req7 -hdr "X_my_hdr_with_lots_of_underscores: on" + rxresp + expect resp.status == 200 + + txreq -req GET -url /req8 -hdr "X_my_hdr-1: on" -hdr "X-my-hdr-2: on" + rxresp + expect resp.status == 200 + + txreq -req GET -url /req9 -hdr "X-my_hdr-1: on" -hdr "X-my_hdr-2: on" + rxresp + expect resp.status == 200 + + txreq -req GET -url /req10 -hdr "X-my-hdr-with-trailing-underscore_: on" + rxresp + expect resp.status == 200 +} -run + +client c2 -connect ${h1_fe2_sock} { + txreq -req GET -url /req1 -hdr "X-my_hdr: on" + rxresp + expect resp.status == 200 +} -run diff --git a/reg-tests/http-rules/strict_rw_mode.vtc b/reg-tests/http-rules/strict_rw_mode.vtc new file mode 100644 index 0000000..14e6901 --- /dev/null +++ b/reg-tests/http-rules/strict_rw_mode.vtc @@ -0,0 +1,164 @@ +varnishtest "Test the strict rewriting mode" +#REQUIRE_VERSION=2.2 + +# This config tests the strict-mode of HTTP rules. + +feature ignore_unknown_macro + +server s1 { + rxreq + txresp \ + -status 200 + expect req.method == "GET" + expect req.url == "/req1" + expect req.http.x-hdr1 == "123456789012345678901234567890123456789012345678901234567890" + + accept + rxreq + txresp \ + -status 200 + expect req.method == "GET" + expect req.url == "/req3" + expect req.http.x-hdr1 == "123456789012345678901234567890123456789012345678901234567890" + expect req.http.x-hdr3 == <undef> +} -start + +server s2 { + rxreq + txresp \ + -status 200 \ + -hdr "x-req: /req1" \ + -bodylen 2000 + expect req.method == "GET" + expect req.url == "/req1" + + accept + rxreq + txresp \ + -status 200 \ + -hdr "x-req: /req2" \ + -bodylen 2000 + expect req.method == "GET" + expect req.url == "/req2" + + accept + rxreq + txresp \ + -status 200 \ + -hdr "x-req: /req3" \ + -bodylen 2000 + expect req.method == "GET" + expect req.url == "/req3" + + accept + rxreq + txresp \ + -status 200 \ + -hdr "x-req: /req4" \ + -bodylen 2000 + expect req.method == "GET" + expect req.url == "/req4" + +} -start + +haproxy h1 -conf { + global + tune.bufsize 2048 + tune.maxrewrite 128 + + defaults + mode http + timeout connect "${HAPROXY_TEST_TIMEOUT-5s}" + timeout client "${HAPROXY_TEST_TIMEOUT-5s}" + timeout server "${HAPROXY_TEST_TIMEOUT-5s}" + option http-buffer-request + + frontend fe1 + bind "fd@${fe1}" + http-request set-header x-hdr1 123456789012345678901234567890123456789012345678901234567890 + http-request set-header x-hdr2 123456789012345678901234567890123456789012345678901234567890 if { path /req2 } + http-request strict-mode off if { path /req3 } + http-request set-header x-hdr3 123456789012345678901234567890123456789012345678901234567890 if { path /req3 } + default_backend be1 + + backend be1 + http-request set-header x-hdr3 123456789012345678901234567890123456789012345678901234567890 if { path /req4 } + server s1 ${s1_addr}:${s1_port} + + frontend fe2 + bind "fd@${fe2}" + http-response set-header x-hdr4 123456789012345678901234567890123456789012345678901234567890 if { res.hdr(x-req) /req4 } + default_backend be2 + backend be2 + http-response set-header x-hdr1 123456789012345678901234567890123456789012345678901234567890 + http-response set-header x-hdr2 123456789012345678901234567890123456789012345678901234567890 if { res.hdr(x-req) /req2 } + http-response strict-mode off if { res.hdr(x-req) /req3 } + http-response set-header x-hdr3 123456789012345678901234567890123456789012345678901234567890 if { res.hdr(-req) /req3 } + server s2 ${s2_addr}:${s2_port} + +} -start + +client c1r1 -connect ${h1_fe1_sock} { + txreq \ + -req GET \ + -url /req1 \ + -bodylen 2000 + rxresp + expect resp.status == 200 +} -run +client c1r2 -connect ${h1_fe1_sock} { + txreq \ + -req GET \ + -url /req2 \ + -bodylen 2000 + rxresp + expect resp.status == 500 +} -run +client c1r3 -connect ${h1_fe1_sock} { + txreq \ + -req GET \ + -url /req3 \ + -bodylen 2000 + rxresp + expect resp.status == 200 +} -run +client c1r4 -connect ${h1_fe1_sock} { + txreq \ + -req GET \ + -url /req4 \ + -bodylen 2000 + rxresp + expect resp.status == 500 +} -run + +client c2r1 -connect ${h1_fe2_sock} { + txreq \ + -req GET \ + -url /req1 + rxresp + expect resp.status == 200 + expect resp.http.x-hdr1 == "123456789012345678901234567890123456789012345678901234567890" +} -run +client c2r2 -connect ${h1_fe2_sock} { + txreq \ + -req GET \ + -url /req2 + rxresp + expect resp.status == 500 +} -run +client c2r3 -connect ${h1_fe2_sock} { + txreq \ + -req GET \ + -url /req3 + rxresp + expect resp.status == 200 + expect resp.http.x-hdr1 == "123456789012345678901234567890123456789012345678901234567890" + expect resp.http.x-hdr3 == <undef> +} -run +client c2r4 -connect ${h1_fe2_sock} { + txreq \ + -req GET \ + -url /req4 + rxresp + expect resp.status == 500 +} -run |