diff --git a/bin/varnishd/cache/cache_http.c b/bin/varnishd/cache/cache_http.c index 8de17ec3e3e..2cdb28c7581 100644 --- a/bin/varnishd/cache/cache_http.c +++ b/bin/varnishd/cache/cache_http.c @@ -992,6 +992,7 @@ HTTP_Merge(struct worker *wrk, struct objcore *oc, struct http *to) const char *ptr; unsigned u; const char *p; + unsigned nhd_before_merge; CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC); CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC); @@ -1009,10 +1010,12 @@ HTTP_Merge(struct worker *wrk, struct objcore *oc, struct http *to) http_SetH(to, u, ptr); ptr = strchr(ptr, '\0') + 1; } + nhd_before_merge = to->nhd; while (*ptr != '\0') { p = strchr(ptr, ':'); AN(p); - if (!http_findhdr(to, p - ptr, ptr)) + u = http_findhdr(to, p - ptr, ptr); + if (u == 0 || u >= nhd_before_merge) http_SetHeader(to, ptr); ptr = strchr(ptr, '\0') + 1; } diff --git a/bin/varnishtest/tests/r01879.vtc b/bin/varnishtest/tests/r01879.vtc new file mode 100644 index 00000000000..8c3d7e29689 --- /dev/null +++ b/bin/varnishtest/tests/r01879.vtc @@ -0,0 +1,48 @@ +varnishtest "r01879: Check duplicate headers handling on IMS header merge" + +server s1 { + rxreq + txresp -hdr {etag: "foo"} -hdr "foo: a" -hdr "foo: b" -body "bdy" + rxreq + expect req.http.if-none-match == {"foo"} + txresp -status 304 -hdr {etag: "foo"} -hdr "foo: c" -hdr "foo: d" + rxreq + txresp -hdr {etag: "bar"} -hdr "foo: a" -hdr "foo: b" -body "bdy" + rxreq + expect req.http.if-none-match == {"bar"} + txresp -status 304 -hdr {etag: "bar"} +} -start + +varnish v1 -vcl+backend { + import std; + + sub vcl_backend_response { + set beresp.ttl = 0.00001s; + set beresp.grace = 0.1s; + set beresp.keep = 9999s; + } + sub vcl_deliver { + std.collect(resp.http.foo); + } +} -start + +client c1 { + txreq + rxresp + expect resp.http.foo == "a, b" + delay .5 + txreq + rxresp + expect resp.http.foo == "c, d" + delay .5 +} -run + +client c2 { + txreq + rxresp + expect resp.http.foo == "a, b" + delay .5 + txreq + rxresp + expect resp.http.foo == "a, b" +} -run