b71741cce1020cd23d924188efb20ea4329603a5
[openwrt-packages.git] /
1 commit eaf650083924a697cde3379703984c5e7a5ebd41
2 Author: Tim Duesterhus <tim@bastelstu.be>
3 Date:   Mon Jun 17 16:10:07 2019 +0200
4
5     BUG/MEDIUM: compression: Set Vary: Accept-Encoding for compressed responses
6     
7     Make HAProxy set the `Vary: Accept-Encoding` response header if it compressed
8     the server response.
9     
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.
14     
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
19     roundtrip to HAProxy.
20     
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
23     
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
27     in the wild in 2019.
28     
29     Add a reg-test to ensure the behaviour as described in this commit message.
30     
31     see issue #121
32     Should be backported to all branches with compression (i.e. 1.6+).
33     
34     (cherry picked from commit 721d686bd10dc6993859f9026ad907753d1d2064)
35     Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
36
37 diff --git a/reg-tests/compression/vary.vtc b/reg-tests/compression/vary.vtc
38 new file mode 100644
39 index 00000000..0a060e4b
40 --- /dev/null
41 +++ b/reg-tests/compression/vary.vtc
42 @@ -0,0 +1,187 @@
43 +varnishtest "Compression sets Vary header"
44 +
45 +#REQUIRE_VERSION=1.9
46 +#REQUIRE_OPTION=ZLIB|SLZ
47 +
48 +feature ignore_unknown_macro
49 +
50 +server s1 {
51 +        rxreq
52 +        expect req.url == "/plain/accept-encoding-gzip"
53 +        expect req.http.accept-encoding == "gzip"
54 +        txresp \
55 +          -hdr "Content-Type: text/plain" \
56 +          -bodylen 100
57 +
58 +        rxreq
59 +        expect req.url == "/plain/accept-encoding-invalid"
60 +        expect req.http.accept-encoding == "invalid"
61 +        txresp \
62 +          -hdr "Content-Type: text/plain" \
63 +          -bodylen 100
64 +
65 +        rxreq
66 +        expect req.url == "/plain/accept-encoding-null"
67 +        expect req.http.accept-encoding == "<undef>"
68 +        txresp \
69 +          -hdr "Content-Type: text/plain" \
70 +          -bodylen 100
71 +
72 +        rxreq
73 +        expect req.url == "/html/accept-encoding-gzip"
74 +        expect req.http.accept-encoding == "gzip"
75 +        txresp \
76 +          -hdr "Content-Type: text/html" \
77 +          -bodylen 100
78 +
79 +        rxreq
80 +        expect req.url == "/html/accept-encoding-invalid"
81 +        expect req.http.accept-encoding == "invalid"
82 +        txresp \
83 +          -hdr "Content-Type: text/html" \
84 +          -bodylen 100
85 +
86 +
87 +        rxreq
88 +        expect req.url == "/html/accept-encoding-null"
89 +        expect req.http.accept-encoding == "<undef>"
90 +        txresp \
91 +          -hdr "Content-Type: text/html" \
92 +          -bodylen 100
93 +
94 +        rxreq
95 +        expect req.url == "/dup-etag/accept-encoding-gzip"
96 +        expect req.http.accept-encoding == "gzip"
97 +        txresp \
98 +          -hdr "Content-Type: text/plain" \
99 +          -hdr "ETag: \"123\"" \
100 +          -hdr "ETag: \"123\"" \
101 +          -bodylen 100
102 +} -repeat 2 -start
103 +
104 +
105 +haproxy h1 -conf {
106 +    defaults
107 +        mode http
108 +        ${no-htx} option http-use-htx
109 +        timeout connect 1s
110 +        timeout client  1s
111 +        timeout server  1s
112 +
113 +    frontend fe-gzip
114 +        bind "fd@${fe_gzip}"
115 +        default_backend be-gzip
116 +
117 +    backend be-gzip
118 +        compression algo gzip
119 +        compression type text/plain
120 +        server www ${s1_addr}:${s1_port}
121 +
122 +    frontend fe-nothing
123 +        bind "fd@${fe_nothing}"
124 +        default_backend be-nothing
125 +
126 +    backend be-nothing
127 +        server www ${s1_addr}:${s1_port}
128 +} -start
129 +
130 +client c1 -connect ${h1_fe_gzip_sock} {
131 +        txreq -url "/plain/accept-encoding-gzip" \
132 +          -hdr "Accept-Encoding: gzip"
133 +        rxresp
134 +        expect resp.status == 200
135 +        expect resp.http.content-encoding == "gzip"
136 +        expect resp.http.vary == "Accept-Encoding"
137 +        gunzip
138 +        expect resp.bodylen == 100
139 +
140 +        txreq -url "/plain/accept-encoding-invalid" \
141 +          -hdr "Accept-Encoding: invalid"
142 +        rxresp
143 +        expect resp.status == 200
144 +        expect resp.http.vary == "<undef>"
145 +        expect resp.bodylen == 100
146 +
147 +        txreq -url "/plain/accept-encoding-null"
148 +        rxresp
149 +        expect resp.status == 200
150 +        expect resp.http.vary == "<undef>"
151 +        expect resp.bodylen == 100
152 +
153 +        txreq -url "/html/accept-encoding-gzip" \
154 +          -hdr "Accept-Encoding: gzip"
155 +        rxresp
156 +        expect resp.status == 200
157 +        expect resp.http.vary == "<undef>"
158 +        expect resp.bodylen == 100
159 +
160 +        txreq -url "/html/accept-encoding-invalid" \
161 +          -hdr "Accept-Encoding: invalid"
162 +        rxresp
163 +        expect resp.status == 200
164 +        expect resp.http.vary == "<undef>"
165 +        expect resp.bodylen == 100
166 +
167 +        txreq -url "/html/accept-encoding-null"
168 +        rxresp
169 +        expect resp.status == 200
170 +        expect resp.http.vary == "<undef>"
171 +        expect resp.bodylen == 100
172 +
173 +        txreq -url "/dup-etag/accept-encoding-gzip" \
174 +          -hdr "Accept-Encoding: gzip"
175 +        rxresp
176 +        expect resp.status == 200
177 +        expect resp.http.vary == "<undef>"
178 +        expect resp.bodylen == 100
179 +} -run
180 +
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"
185 +        rxresp
186 +        expect resp.status == 200
187 +        expect resp.http.vary == "<undef>"
188 +        expect resp.bodylen == 100
189 +
190 +        txreq -url "/plain/accept-encoding-invalid" \
191 +          -hdr "Accept-Encoding: invalid"
192 +        rxresp
193 +        expect resp.status == 200
194 +        expect resp.http.vary == "<undef>"
195 +        expect resp.bodylen == 100
196 +
197 +        txreq -url "/plain/accept-encoding-null"
198 +        rxresp
199 +        expect resp.status == 200
200 +        expect resp.http.vary == "<undef>"
201 +        expect resp.bodylen == 100
202 +
203 +        txreq -url "/html/accept-encoding-gzip" \
204 +          -hdr "Accept-Encoding: gzip"
205 +        rxresp
206 +        expect resp.status == 200
207 +        expect resp.http.vary == "<undef>"
208 +        expect resp.bodylen == 100
209 +
210 +        txreq -url "/html/accept-encoding-invalid" \
211 +          -hdr "Accept-Encoding: invalid"
212 +        rxresp
213 +        expect resp.status == 200
214 +        expect resp.http.vary == "<undef>"
215 +        expect resp.bodylen == 100
216 +
217 +        txreq -url "/html/accept-encoding-null"
218 +        rxresp
219 +        expect resp.status == 200
220 +        expect resp.http.vary == "<undef>"
221 +        expect resp.bodylen == 100
222 +
223 +        txreq -url "/dup-etag/accept-encoding-gzip" \
224 +          -hdr "Accept-Encoding: gzip"
225 +        rxresp
226 +        expect resp.status == 200
227 +        expect resp.http.vary == "<undef>"
228 +        expect resp.bodylen == 100
229 +} -run
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
235                 }
236         }
237  
238 +       if (http_header_add_tail2(msg, &txn->hdr_idx, "Vary: Accept-Encoding", 21) < 0)
239 +               goto error;
240 +
241         return 1;
242  
243    error:
244 @@ -577,6 +580,9 @@ htx_set_comp_reshdr(struct comp_state *st, struct stream *s, struct http_msg *ms
245                 }
246         }
247  
248 +       if (!http_add_header(htx, ist("Vary"), ist("Accept-Encoding")))
249 +               goto error;
250 +
251         return 1;
252  
253    error:
git clone https://git.99rst.org/PROJECT