1 commit eaf650083924a697cde3379703984c5e7a5ebd41
2 Author: Tim Duesterhus <tim@bastelstu.be>
3 Date: Mon Jun 17 16:10:07 2019 +0200
5 BUG/MEDIUM: compression: Set Vary: Accept-Encoding for compressed responses
7 Make HAProxy set the `Vary: Accept-Encoding` response header if it compressed
10 Technically the `Vary` header SHOULD also be set for responses that would
11 normally be compressed based off the current configuration, but are not due
12 to a missing or invalid `Accept-Encoding` request header or due to the
13 maximum compression rate being exceeded.
15 Not setting the header in these cases does no real harm, though: An
16 uncompressed response might be returned by a Cache, even if a compressed
17 one could be retrieved from HAProxy. This increases the traffic to the end
18 user if the cache is unable to compress itself, but it saves another
21 see the discussion on the mailing list: https://www.mail-archive.com/haproxy@formilux.org/msg34221.html
22 Message-ID: 20190617121708.GA2964@1wt.eu
24 A small issue remains: The User-Agent is not added to the `Vary` header,
25 despite being relevant to the response. Adding the User-Agent header would
26 make responses effectively uncacheable and it's unlikely to see a Mozilla/4
29 Add a reg-test to ensure the behaviour as described in this commit message.
32 Should be backported to all branches with compression (i.e. 1.6+).
34 (cherry picked from commit 721d686bd10dc6993859f9026ad907753d1d2064)
35 Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
37 diff --git a/reg-tests/compression/vary.vtc b/reg-tests/compression/vary.vtc
39 index 00000000..0a060e4b
41 +++ b/reg-tests/compression/vary.vtc
43 +varnishtest "Compression sets Vary header"
46 +#REQUIRE_OPTION=ZLIB|SLZ
48 +feature ignore_unknown_macro
52 + expect req.url == "/plain/accept-encoding-gzip"
53 + expect req.http.accept-encoding == "gzip"
55 + -hdr "Content-Type: text/plain" \
59 + expect req.url == "/plain/accept-encoding-invalid"
60 + expect req.http.accept-encoding == "invalid"
62 + -hdr "Content-Type: text/plain" \
66 + expect req.url == "/plain/accept-encoding-null"
67 + expect req.http.accept-encoding == "<undef>"
69 + -hdr "Content-Type: text/plain" \
73 + expect req.url == "/html/accept-encoding-gzip"
74 + expect req.http.accept-encoding == "gzip"
76 + -hdr "Content-Type: text/html" \
80 + expect req.url == "/html/accept-encoding-invalid"
81 + expect req.http.accept-encoding == "invalid"
83 + -hdr "Content-Type: text/html" \
88 + expect req.url == "/html/accept-encoding-null"
89 + expect req.http.accept-encoding == "<undef>"
91 + -hdr "Content-Type: text/html" \
95 + expect req.url == "/dup-etag/accept-encoding-gzip"
96 + expect req.http.accept-encoding == "gzip"
98 + -hdr "Content-Type: text/plain" \
99 + -hdr "ETag: \"123\"" \
100 + -hdr "ETag: \"123\"" \
108 + ${no-htx} option http-use-htx
114 + bind "fd@${fe_gzip}"
115 + default_backend be-gzip
118 + compression algo gzip
119 + compression type text/plain
120 + server www ${s1_addr}:${s1_port}
122 + frontend fe-nothing
123 + bind "fd@${fe_nothing}"
124 + default_backend be-nothing
127 + server www ${s1_addr}:${s1_port}
130 +client c1 -connect ${h1_fe_gzip_sock} {
131 + txreq -url "/plain/accept-encoding-gzip" \
132 + -hdr "Accept-Encoding: gzip"
134 + expect resp.status == 200
135 + expect resp.http.content-encoding == "gzip"
136 + expect resp.http.vary == "Accept-Encoding"
138 + expect resp.bodylen == 100
140 + txreq -url "/plain/accept-encoding-invalid" \
141 + -hdr "Accept-Encoding: invalid"
143 + expect resp.status == 200
144 + expect resp.http.vary == "<undef>"
145 + expect resp.bodylen == 100
147 + txreq -url "/plain/accept-encoding-null"
149 + expect resp.status == 200
150 + expect resp.http.vary == "<undef>"
151 + expect resp.bodylen == 100
153 + txreq -url "/html/accept-encoding-gzip" \
154 + -hdr "Accept-Encoding: gzip"
156 + expect resp.status == 200
157 + expect resp.http.vary == "<undef>"
158 + expect resp.bodylen == 100
160 + txreq -url "/html/accept-encoding-invalid" \
161 + -hdr "Accept-Encoding: invalid"
163 + expect resp.status == 200
164 + expect resp.http.vary == "<undef>"
165 + expect resp.bodylen == 100
167 + txreq -url "/html/accept-encoding-null"
169 + expect resp.status == 200
170 + expect resp.http.vary == "<undef>"
171 + expect resp.bodylen == 100
173 + txreq -url "/dup-etag/accept-encoding-gzip" \
174 + -hdr "Accept-Encoding: gzip"
176 + expect resp.status == 200
177 + expect resp.http.vary == "<undef>"
178 + expect resp.bodylen == 100
181 +# This Client duplicates c1, against the "nothing" frontend, ensuring no Vary header is ever set.
182 +client c2 -connect ${h1_fe_nothing_sock} {
183 + txreq -url "/plain/accept-encoding-gzip" \
184 + -hdr "Accept-Encoding: gzip"
186 + expect resp.status == 200
187 + expect resp.http.vary == "<undef>"
188 + expect resp.bodylen == 100
190 + txreq -url "/plain/accept-encoding-invalid" \
191 + -hdr "Accept-Encoding: invalid"
193 + expect resp.status == 200
194 + expect resp.http.vary == "<undef>"
195 + expect resp.bodylen == 100
197 + txreq -url "/plain/accept-encoding-null"
199 + expect resp.status == 200
200 + expect resp.http.vary == "<undef>"
201 + expect resp.bodylen == 100
203 + txreq -url "/html/accept-encoding-gzip" \
204 + -hdr "Accept-Encoding: gzip"
206 + expect resp.status == 200
207 + expect resp.http.vary == "<undef>"
208 + expect resp.bodylen == 100
210 + txreq -url "/html/accept-encoding-invalid" \
211 + -hdr "Accept-Encoding: invalid"
213 + expect resp.status == 200
214 + expect resp.http.vary == "<undef>"
215 + expect resp.bodylen == 100
217 + txreq -url "/html/accept-encoding-null"
219 + expect resp.status == 200
220 + expect resp.http.vary == "<undef>"
221 + expect resp.bodylen == 100
223 + txreq -url "/dup-etag/accept-encoding-gzip" \
224 + -hdr "Accept-Encoding: gzip"
226 + expect resp.status == 200
227 + expect resp.http.vary == "<undef>"
228 + expect resp.bodylen == 100
230 diff --git a/src/flt_http_comp.c b/src/flt_http_comp.c
231 index b04dcd14..37f237fe 100644
232 --- a/src/flt_http_comp.c
233 +++ b/src/flt_http_comp.c
234 @@ -523,6 +523,9 @@ http_set_comp_reshdr(struct comp_state *st, struct stream *s, struct http_msg *m
238 + if (http_header_add_tail2(msg, &txn->hdr_idx, "Vary: Accept-Encoding", 21) < 0)
244 @@ -577,6 +580,9 @@ htx_set_comp_reshdr(struct comp_state *st, struct stream *s, struct http_msg *ms
248 + if (!http_add_header(htx, ist("Vary"), ist("Accept-Encoding")))