|
|
- commit eaf650083924a697cde3379703984c5e7a5ebd41
- Author: Tim Duesterhus <tim@bastelstu.be>
- Date: Mon Jun 17 16:10:07 2019 +0200
-
- BUG/MEDIUM: compression: Set Vary: Accept-Encoding for compressed responses
-
- Make HAProxy set the `Vary: Accept-Encoding` response header if it compressed
- the server response.
-
- Technically the `Vary` header SHOULD also be set for responses that would
- normally be compressed based off the current configuration, but are not due
- to a missing or invalid `Accept-Encoding` request header or due to the
- maximum compression rate being exceeded.
-
- Not setting the header in these cases does no real harm, though: An
- uncompressed response might be returned by a Cache, even if a compressed
- one could be retrieved from HAProxy. This increases the traffic to the end
- user if the cache is unable to compress itself, but it saves another
- roundtrip to HAProxy.
-
- see the discussion on the mailing list: https://www.mail-archive.com/haproxy@formilux.org/msg34221.html
- Message-ID: 20190617121708.GA2964@1wt.eu
-
- A small issue remains: The User-Agent is not added to the `Vary` header,
- despite being relevant to the response. Adding the User-Agent header would
- make responses effectively uncacheable and it's unlikely to see a Mozilla/4
- in the wild in 2019.
-
- Add a reg-test to ensure the behaviour as described in this commit message.
-
- see issue #121
- Should be backported to all branches with compression (i.e. 1.6+).
-
- (cherry picked from commit 721d686bd10dc6993859f9026ad907753d1d2064)
- Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
-
- diff --git a/reg-tests/compression/vary.vtc b/reg-tests/compression/vary.vtc
- new file mode 100644
- index 00000000..0a060e4b
- --- /dev/null
- +++ b/reg-tests/compression/vary.vtc
- @@ -0,0 +1,187 @@
- +varnishtest "Compression sets Vary header"
- +
- +#REQUIRE_VERSION=1.9
- +#REQUIRE_OPTION=ZLIB|SLZ
- +
- +feature ignore_unknown_macro
- +
- +server s1 {
- + rxreq
- + expect req.url == "/plain/accept-encoding-gzip"
- + expect req.http.accept-encoding == "gzip"
- + txresp \
- + -hdr "Content-Type: text/plain" \
- + -bodylen 100
- +
- + rxreq
- + expect req.url == "/plain/accept-encoding-invalid"
- + expect req.http.accept-encoding == "invalid"
- + txresp \
- + -hdr "Content-Type: text/plain" \
- + -bodylen 100
- +
- + rxreq
- + expect req.url == "/plain/accept-encoding-null"
- + expect req.http.accept-encoding == "<undef>"
- + txresp \
- + -hdr "Content-Type: text/plain" \
- + -bodylen 100
- +
- + rxreq
- + expect req.url == "/html/accept-encoding-gzip"
- + expect req.http.accept-encoding == "gzip"
- + txresp \
- + -hdr "Content-Type: text/html" \
- + -bodylen 100
- +
- + rxreq
- + expect req.url == "/html/accept-encoding-invalid"
- + expect req.http.accept-encoding == "invalid"
- + txresp \
- + -hdr "Content-Type: text/html" \
- + -bodylen 100
- +
- +
- + rxreq
- + expect req.url == "/html/accept-encoding-null"
- + expect req.http.accept-encoding == "<undef>"
- + txresp \
- + -hdr "Content-Type: text/html" \
- + -bodylen 100
- +
- + rxreq
- + expect req.url == "/dup-etag/accept-encoding-gzip"
- + expect req.http.accept-encoding == "gzip"
- + txresp \
- + -hdr "Content-Type: text/plain" \
- + -hdr "ETag: \"123\"" \
- + -hdr "ETag: \"123\"" \
- + -bodylen 100
- +} -repeat 2 -start
- +
- +
- +haproxy h1 -conf {
- + defaults
- + mode http
- + ${no-htx} option http-use-htx
- + timeout connect 1s
- + timeout client 1s
- + timeout server 1s
- +
- + frontend fe-gzip
- + bind "fd@${fe_gzip}"
- + default_backend be-gzip
- +
- + backend be-gzip
- + compression algo gzip
- + compression type text/plain
- + server www ${s1_addr}:${s1_port}
- +
- + frontend fe-nothing
- + bind "fd@${fe_nothing}"
- + default_backend be-nothing
- +
- + backend be-nothing
- + server www ${s1_addr}:${s1_port}
- +} -start
- +
- +client c1 -connect ${h1_fe_gzip_sock} {
- + txreq -url "/plain/accept-encoding-gzip" \
- + -hdr "Accept-Encoding: gzip"
- + rxresp
- + expect resp.status == 200
- + expect resp.http.content-encoding == "gzip"
- + expect resp.http.vary == "Accept-Encoding"
- + gunzip
- + expect resp.bodylen == 100
- +
- + txreq -url "/plain/accept-encoding-invalid" \
- + -hdr "Accept-Encoding: invalid"
- + rxresp
- + expect resp.status == 200
- + expect resp.http.vary == "<undef>"
- + expect resp.bodylen == 100
- +
- + txreq -url "/plain/accept-encoding-null"
- + rxresp
- + expect resp.status == 200
- + expect resp.http.vary == "<undef>"
- + expect resp.bodylen == 100
- +
- + txreq -url "/html/accept-encoding-gzip" \
- + -hdr "Accept-Encoding: gzip"
- + rxresp
- + expect resp.status == 200
- + expect resp.http.vary == "<undef>"
- + expect resp.bodylen == 100
- +
- + txreq -url "/html/accept-encoding-invalid" \
- + -hdr "Accept-Encoding: invalid"
- + rxresp
- + expect resp.status == 200
- + expect resp.http.vary == "<undef>"
- + expect resp.bodylen == 100
- +
- + txreq -url "/html/accept-encoding-null"
- + rxresp
- + expect resp.status == 200
- + expect resp.http.vary == "<undef>"
- + expect resp.bodylen == 100
- +
- + txreq -url "/dup-etag/accept-encoding-gzip" \
- + -hdr "Accept-Encoding: gzip"
- + rxresp
- + expect resp.status == 200
- + expect resp.http.vary == "<undef>"
- + expect resp.bodylen == 100
- +} -run
- +
- +# This Client duplicates c1, against the "nothing" frontend, ensuring no Vary header is ever set.
- +client c2 -connect ${h1_fe_nothing_sock} {
- + txreq -url "/plain/accept-encoding-gzip" \
- + -hdr "Accept-Encoding: gzip"
- + rxresp
- + expect resp.status == 200
- + expect resp.http.vary == "<undef>"
- + expect resp.bodylen == 100
- +
- + txreq -url "/plain/accept-encoding-invalid" \
- + -hdr "Accept-Encoding: invalid"
- + rxresp
- + expect resp.status == 200
- + expect resp.http.vary == "<undef>"
- + expect resp.bodylen == 100
- +
- + txreq -url "/plain/accept-encoding-null"
- + rxresp
- + expect resp.status == 200
- + expect resp.http.vary == "<undef>"
- + expect resp.bodylen == 100
- +
- + txreq -url "/html/accept-encoding-gzip" \
- + -hdr "Accept-Encoding: gzip"
- + rxresp
- + expect resp.status == 200
- + expect resp.http.vary == "<undef>"
- + expect resp.bodylen == 100
- +
- + txreq -url "/html/accept-encoding-invalid" \
- + -hdr "Accept-Encoding: invalid"
- + rxresp
- + expect resp.status == 200
- + expect resp.http.vary == "<undef>"
- + expect resp.bodylen == 100
- +
- + txreq -url "/html/accept-encoding-null"
- + rxresp
- + expect resp.status == 200
- + expect resp.http.vary == "<undef>"
- + expect resp.bodylen == 100
- +
- + txreq -url "/dup-etag/accept-encoding-gzip" \
- + -hdr "Accept-Encoding: gzip"
- + rxresp
- + expect resp.status == 200
- + expect resp.http.vary == "<undef>"
- + expect resp.bodylen == 100
- +} -run
- diff --git a/src/flt_http_comp.c b/src/flt_http_comp.c
- index b04dcd14..37f237fe 100644
- --- a/src/flt_http_comp.c
- +++ b/src/flt_http_comp.c
- @@ -523,6 +523,9 @@ http_set_comp_reshdr(struct comp_state *st, struct stream *s, struct http_msg *m
- }
- }
-
- + if (http_header_add_tail2(msg, &txn->hdr_idx, "Vary: Accept-Encoding", 21) < 0)
- + goto error;
- +
- return 1;
-
- error:
- @@ -577,6 +580,9 @@ htx_set_comp_reshdr(struct comp_state *st, struct stream *s, struct http_msg *ms
- }
- }
-
- + if (!http_add_header(htx, ist("Vary"), ist("Accept-Encoding")))
- + goto error;
- +
- return 1;
-
- error:
|