diff --git a/reg-tests/http-rules/map_ordering.map b/reg-tests/http-rules/map_ordering.map index dcd952955..dc9ac71bd 100644 --- a/reg-tests/http-rules/map_ordering.map +++ b/reg-tests/http-rules/map_ordering.map @@ -2,3 +2,5 @@ first.domain.tld first domain.tld domain second.domain.tld second +# This entry is used to test duplicate behavior (ie: tree-based match) +first.domain.tld first_dup diff --git a/reg-tests/http-rules/map_ordering.vtc b/reg-tests/http-rules/map_ordering.vtc index 40da465ca..923d19fa5 100644 --- a/reg-tests/http-rules/map_ordering.vtc +++ b/reg-tests/http-rules/map_ordering.vtc @@ -1,4 +1,4 @@ -varnishtest "Test list-based matching types ordering" +varnishtest "Ensure mapfile ordering is preserved when loading the file" feature cmd "$HAPROXY_PROGRAM -cc 'version_atleast(2.5-dev0)'" feature ignore_unknown_macro @@ -14,9 +14,13 @@ haproxy h1 -conf { # 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 } + + # check tree ordering using map_str (tree-based match) and duplicated keys + http-request return hdr str %[req.hdr(Host),lower,map_str(${testdir}/map_ordering.map)] if { url_beg /str } + } -start -# Check map ordering +# Check map ordering for list-based matching types 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" @@ -30,3 +34,13 @@ client c1 -connect ${h1_fe1_sock} { expect resp.status == 200 expect resp.http.dom == "domain" } -run + +# Check map ordering for tree-based matching types (check that the matching +# key is the first one seen in the file) +client c2 -connect ${h1_fe1_sock} { + # first.domain.tld is first mapped to "first" in the mapfile + txreq -url "/str" -hdr "Host: first.domain.tld" + rxresp + expect resp.status == 200 + expect resp.http.str == "first" +} -run diff --git a/src/pattern.c b/src/pattern.c index 57ef92320..f07223f7c 100644 --- a/src/pattern.c +++ b/src/pattern.c @@ -2512,7 +2512,10 @@ int pattern_read_from_file(struct pattern_head *head, unsigned int refflags, /* Load reference content in the pattern expression. * We need to load elements in the same order they were seen in the - * file as list-based matching types may rely on it. + * file. Indeed, some list-based matching types may rely on it as the + * list is positional, and for tree-based matching, even if the tree is + * content-based in case of duplicated keys we only want the first key + * in the file to be considered. */ list_for_each_entry(elt, &ref->head, list) { if (!pat_ref_push(elt, expr, patflags, err)) {