Mercurial > hg > nginx-quic
comparison src/http/modules/ngx_http_gzip_filter.c @ 320:d621239c30f7
nginx-0.0.3-2004-04-18-23:06:02 import
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Sun, 18 Apr 2004 19:06:02 +0000 |
parents | 7a8ebba985a9 |
children | 32847588a82a |
comparison
equal
deleted
inserted
replaced
319:7a8ebba985a9 | 320:d621239c30f7 |
---|---|
16 ngx_uint_t proxied; | 16 ngx_uint_t proxied; |
17 | 17 |
18 int level; | 18 int level; |
19 size_t wbits; | 19 size_t wbits; |
20 size_t memlevel; | 20 size_t memlevel; |
21 size_t min_length; | |
21 } ngx_http_gzip_conf_t; | 22 } ngx_http_gzip_conf_t; |
22 | 23 |
23 | 24 |
24 enum { | 25 #define NGX_HTTP_GZIP_PROXIED_OFF 0x0002 |
25 NGX_HTTP_GZIP_PROXIED_OFF = 0, | 26 #define NGX_HTTP_GZIP_PROXIED_EXPIRED 0x0004 |
26 NGX_HTTP_GZIP_PROXIED_NOCACHABLE, | 27 #define NGX_HTTP_GZIP_PROXIED_NO_CACHE 0x0008 |
27 NGX_HTTP_GZIP_PROXIED_POOR_CACHABLE, | 28 #define NGX_HTTP_GZIP_PROXIED_NO_STORE 0x0010 |
28 NGX_HTTP_GZIP_PROXIED_ON | 29 #define NGX_HTTP_GZIP_PROXIED_PRIVATE 0x0020 |
29 }; | 30 #define NGX_HTTP_GZIP_PROXIED_NO_LM 0x0040 |
31 #define NGX_HTTP_GZIP_PROXIED_NO_ETAG 0x0080 | |
32 #define NGX_HTTP_GZIP_PROXIED_AUTH 0x0100 | |
33 #define NGX_HTTP_GZIP_PROXIED_ANY 0x0200 | |
30 | 34 |
31 | 35 |
32 typedef struct { | 36 typedef struct { |
33 ngx_chain_t *in; | 37 ngx_chain_t *in; |
34 ngx_chain_t *free; | 38 ngx_chain_t *free; |
35 ngx_chain_t *busy; | 39 ngx_chain_t *busy; |
36 ngx_chain_t *out; | 40 ngx_chain_t *out; |
37 ngx_chain_t **last_out; | 41 ngx_chain_t **last_out; |
38 ngx_hunk_t *in_hunk; | 42 ngx_hunk_t *in_hunk; |
39 ngx_hunk_t *out_hunk; | 43 ngx_hunk_t *out_hunk; |
40 int hunks; | 44 ngx_int_t hunks; |
41 | 45 |
42 off_t length; | 46 off_t length; |
43 | 47 |
44 void *preallocated; | 48 void *preallocated; |
45 char *free_mem; | 49 char *free_mem; |
56 z_stream zstream; | 60 z_stream zstream; |
57 ngx_http_request_t *request; | 61 ngx_http_request_t *request; |
58 } ngx_http_gzip_ctx_t; | 62 } ngx_http_gzip_ctx_t; |
59 | 63 |
60 | 64 |
65 static int ngx_http_gzip_proxied(ngx_http_request_t *r, | |
66 ngx_http_gzip_conf_t *conf); | |
61 static void *ngx_http_gzip_filter_alloc(void *opaque, u_int items, | 67 static void *ngx_http_gzip_filter_alloc(void *opaque, u_int items, |
62 u_int size); | 68 u_int size); |
63 static void ngx_http_gzip_filter_free(void *opaque, void *address); | 69 static void ngx_http_gzip_filter_free(void *opaque, void *address); |
64 | |
65 ngx_inline static int ngx_http_gzip_error(ngx_http_gzip_ctx_t *ctx); | 70 ngx_inline static int ngx_http_gzip_error(ngx_http_gzip_ctx_t *ctx); |
66 | 71 |
67 static u_char *ngx_http_gzip_log_ratio(ngx_http_request_t *r, u_char *buf, | 72 static u_char *ngx_http_gzip_log_ratio(ngx_http_request_t *r, u_char *buf, |
68 uintptr_t data); | 73 uintptr_t data); |
69 | 74 |
92 { ngx_string("1.1"), NGX_HTTP_VERSION_11 }, | 97 { ngx_string("1.1"), NGX_HTTP_VERSION_11 }, |
93 { ngx_null_string, 0 } | 98 { ngx_null_string, 0 } |
94 }; | 99 }; |
95 | 100 |
96 | 101 |
97 static ngx_conf_enum_t ngx_http_gzip_proxied[] = { | 102 static ngx_conf_bitmask_t ngx_http_gzip_proxied_mask[] = { |
98 { ngx_string("off"), NGX_HTTP_GZIP_PROXIED_OFF }, | 103 { ngx_string("off"), NGX_HTTP_GZIP_PROXIED_OFF }, |
99 { ngx_string("nocachable"), NGX_HTTP_GZIP_PROXIED_NOCACHABLE }, | 104 { ngx_string("expired"), NGX_HTTP_GZIP_PROXIED_EXPIRED }, |
100 { ngx_string("poor_cachable"), NGX_HTTP_GZIP_PROXIED_POOR_CACHABLE }, | 105 { ngx_string("no-cache"), NGX_HTTP_GZIP_PROXIED_NO_CACHE }, |
101 { ngx_string("on"), NGX_HTTP_GZIP_PROXIED_ON }, | 106 { ngx_string("no-store"), NGX_HTTP_GZIP_PROXIED_NO_STORE }, |
107 { ngx_string("private"), NGX_HTTP_GZIP_PROXIED_PRIVATE }, | |
108 { ngx_string("no_last_modified"), NGX_HTTP_GZIP_PROXIED_NO_LM }, | |
109 { ngx_string("no_etag"), NGX_HTTP_GZIP_PROXIED_NO_ETAG }, | |
110 { ngx_string("auth"), NGX_HTTP_GZIP_PROXIED_AUTH }, | |
111 { ngx_string("any"), NGX_HTTP_GZIP_PROXIED_ANY }, | |
102 { ngx_null_string, 0 } | 112 { ngx_null_string, 0 } |
103 }; | 113 }; |
104 | 114 |
105 | 115 |
106 static ngx_command_t ngx_http_gzip_filter_commands[] = { | 116 static ngx_command_t ngx_http_gzip_filter_commands[] = { |
154 offsetof(ngx_http_gzip_conf_t, http_version), | 164 offsetof(ngx_http_gzip_conf_t, http_version), |
155 &ngx_http_gzip_http_version }, | 165 &ngx_http_gzip_http_version }, |
156 | 166 |
157 { ngx_string("gzip_proxied"), | 167 { ngx_string("gzip_proxied"), |
158 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_ANY, | 168 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_ANY, |
159 ngx_conf_set_enum_slot, | 169 ngx_conf_set_bitmask_slot, |
160 NGX_HTTP_LOC_CONF_OFFSET, | 170 NGX_HTTP_LOC_CONF_OFFSET, |
161 offsetof(ngx_http_gzip_conf_t, proxied), | 171 offsetof(ngx_http_gzip_conf_t, proxied), |
162 &ngx_http_gzip_proxied }, | 172 &ngx_http_gzip_proxied_mask }, |
173 | |
174 { ngx_string("gzip_min_length"), | |
175 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, | |
176 ngx_conf_set_size_slot, | |
177 NGX_HTTP_LOC_CONF_OFFSET, | |
178 offsetof(ngx_http_gzip_conf_t, min_length), | |
179 NULL}, | |
163 | 180 |
164 ngx_null_command | 181 ngx_null_command |
165 }; | 182 }; |
166 | 183 |
167 | 184 |
219 static ngx_http_output_body_filter_pt ngx_http_next_body_filter; | 236 static ngx_http_output_body_filter_pt ngx_http_next_body_filter; |
220 | 237 |
221 | 238 |
222 static int ngx_http_gzip_header_filter(ngx_http_request_t *r) | 239 static int ngx_http_gzip_header_filter(ngx_http_request_t *r) |
223 { | 240 { |
224 time_t date, expires; | |
225 ngx_http_gzip_ctx_t *ctx; | 241 ngx_http_gzip_ctx_t *ctx; |
226 ngx_http_gzip_conf_t *conf; | 242 ngx_http_gzip_conf_t *conf; |
227 | 243 |
228 conf = ngx_http_get_module_loc_conf(r, ngx_http_gzip_filter_module); | 244 conf = ngx_http_get_module_loc_conf(r, ngx_http_gzip_filter_module); |
229 | 245 |
232 || r->header_only | 248 || r->header_only |
233 || r->http_version < conf->http_version | 249 || r->http_version < conf->http_version |
234 || (r->headers_out.content_encoding | 250 || (r->headers_out.content_encoding |
235 && r->headers_out.content_encoding->value.len) | 251 && r->headers_out.content_encoding->value.len) |
236 || r->headers_in.accept_encoding == NULL | 252 || r->headers_in.accept_encoding == NULL |
253 || (r->headers_out.content_length_n != -1 | |
254 && r->headers_out.content_length_n < conf->min_length) | |
237 || ngx_strstr(r->headers_in.accept_encoding->value.data, "gzip") == NULL | 255 || ngx_strstr(r->headers_in.accept_encoding->value.data, "gzip") == NULL |
238 ) | 256 ) |
239 { | 257 { |
240 return ngx_http_next_header_filter(r); | 258 return ngx_http_next_header_filter(r); |
241 } | 259 } |
247 { | 265 { |
248 return ngx_http_next_header_filter(r); | 266 return ngx_http_next_header_filter(r); |
249 } | 267 } |
250 | 268 |
251 | 269 |
252 if (r->headers_in.via && conf->proxied != NGX_HTTP_GZIP_PROXIED_ON) { | 270 if (r->headers_in.via) { |
253 | 271 if (conf->proxied & NGX_HTTP_GZIP_PROXIED_OFF) { |
254 if (conf->proxied == NGX_HTTP_GZIP_PROXIED_OFF) { | |
255 return ngx_http_next_header_filter(r); | 272 return ngx_http_next_header_filter(r); |
256 } | 273 } |
257 | 274 |
258 if (r->headers_out.expires) { | 275 if (!(conf->proxied & NGX_HTTP_GZIP_PROXIED_ANY) |
259 expires = ngx_http_parse_time(r->headers_out.expires->value.data, | 276 && ngx_http_gzip_proxied(r, conf) == NGX_DECLINED) |
260 r->headers_out.expires->value.len); | 277 { |
261 if (expires == NGX_ERROR) { | |
262 return ngx_http_next_header_filter(r); | |
263 } | |
264 | |
265 if (r->headers_out.date) { | |
266 date = ngx_http_parse_time(r->headers_out.date->value.data, | |
267 r->headers_out.date->value.len); | |
268 if (date == NGX_ERROR) { | |
269 return ngx_http_next_header_filter(r); | |
270 } | |
271 | |
272 } else { | |
273 date = ngx_cached_time; | |
274 } | |
275 | |
276 if (expires >= date) { | |
277 return ngx_http_next_header_filter(r); | |
278 } | |
279 | |
280 } else if (r->headers_out.cache_control) { | |
281 | |
282 if (conf->proxied == NGX_HTTP_GZIP_PROXIED_NOCACHABLE) { | |
283 if (ngx_strstr(r->headers_out.cache_control->value.data, | |
284 "no-cache") == NULL) | |
285 { | |
286 return ngx_http_next_header_filter(r); | |
287 } | |
288 | |
289 } else { /* NGX_HTTP_GZIP_PROXIED_POOR_CACHABLE */ | |
290 | |
291 /* STUB: should be one cycle for all values */ | |
292 | |
293 if (ngx_strstr(r->headers_out.cache_control->value.data, | |
294 "no-cache") == NULL | |
295 && ngx_strstr(r->headers_out.cache_control->value.data, | |
296 "private") == NULL | |
297 && ngx_strstr(r->headers_out.cache_control->value.data, | |
298 "no-store") == NULL) | |
299 { | |
300 return ngx_http_next_header_filter(r); | |
301 } | |
302 } | |
303 | |
304 } else if (conf->proxied == NGX_HTTP_GZIP_PROXIED_NOCACHABLE) { | |
305 return ngx_http_next_header_filter(r); | 278 return ngx_http_next_header_filter(r); |
306 | |
307 } else { /* NGX_HTTP_GZIP_PROXIED_POOR_CACHABLE */ | |
308 | |
309 if (r->headers_out.last_modified || r->headers_out.etag) { | |
310 return ngx_http_next_header_filter(r); | |
311 } | |
312 } | 279 } |
313 } | 280 } |
314 | 281 |
315 | 282 |
316 /* | 283 /* |
349 r->headers_out.content_length = NULL; | 316 r->headers_out.content_length = NULL; |
350 } | 317 } |
351 r->filter |= NGX_HTTP_FILTER_NEED_IN_MEMORY; | 318 r->filter |= NGX_HTTP_FILTER_NEED_IN_MEMORY; |
352 | 319 |
353 return ngx_http_next_header_filter(r); | 320 return ngx_http_next_header_filter(r); |
321 } | |
322 | |
323 | |
324 static int ngx_http_gzip_proxied(ngx_http_request_t *r, | |
325 ngx_http_gzip_conf_t *conf) | |
326 { | |
327 time_t date, expires; | |
328 | |
329 if (r->headers_in.authorization | |
330 && (conf->proxied & NGX_HTTP_GZIP_PROXIED_AUTH)) | |
331 { | |
332 return NGX_OK; | |
333 } | |
334 | |
335 if (r->headers_out.expires) { | |
336 | |
337 if (!(conf->proxied & NGX_HTTP_GZIP_PROXIED_EXPIRED)) { | |
338 return NGX_DECLINED; | |
339 } | |
340 | |
341 expires = ngx_http_parse_time(r->headers_out.expires->value.data, | |
342 r->headers_out.expires->value.len); | |
343 if (expires == NGX_ERROR) { | |
344 return NGX_DECLINED; | |
345 } | |
346 | |
347 if (r->headers_out.date) { | |
348 date = ngx_http_parse_time(r->headers_out.date->value.data, | |
349 r->headers_out.date->value.len); | |
350 if (date == NGX_ERROR) { | |
351 return NGX_DECLINED; | |
352 } | |
353 | |
354 } else { | |
355 date = ngx_cached_time; | |
356 } | |
357 | |
358 if (expires < date) { | |
359 return NGX_OK; | |
360 } | |
361 | |
362 return NGX_DECLINED; | |
363 } | |
364 | |
365 if (r->headers_out.cache_control) { | |
366 | |
367 if ((conf->proxied & NGX_HTTP_GZIP_PROXIED_NO_CACHE) | |
368 && ngx_strstr(r->headers_out.cache_control->value.data, "no-cache") | |
369 == NULL) | |
370 { | |
371 return NGX_OK; | |
372 } | |
373 | |
374 if ((conf->proxied & NGX_HTTP_GZIP_PROXIED_NO_STORE) | |
375 && ngx_strstr(r->headers_out.cache_control->value.data, "no-store") | |
376 == NULL) | |
377 { | |
378 return NGX_OK; | |
379 } | |
380 | |
381 if ((conf->proxied & NGX_HTTP_GZIP_PROXIED_PRIVATE) | |
382 && ngx_strstr(r->headers_out.cache_control->value.data, "private") | |
383 == NULL) | |
384 { | |
385 return NGX_OK; | |
386 } | |
387 | |
388 return NGX_DECLINED; | |
389 } | |
390 | |
391 if ((conf->proxied & NGX_HTTP_GZIP_PROXIED_NO_LM) | |
392 && r->headers_out.last_modified) | |
393 { | |
394 return NGX_DECLINED; | |
395 } | |
396 | |
397 if ((conf->proxied & NGX_HTTP_GZIP_PROXIED_NO_ETAG) | |
398 && r->headers_out.etag) | |
399 { | |
400 return NGX_DECLINED; | |
401 } | |
402 | |
403 return NGX_OK; | |
354 } | 404 } |
355 | 405 |
356 | 406 |
357 static int ngx_http_gzip_body_filter(ngx_http_request_t *r, ngx_chain_t *in) | 407 static int ngx_http_gzip_body_filter(ngx_http_request_t *r, ngx_chain_t *in) |
358 { | 408 { |
768 | 818 |
769 ngx_test_null(conf, | 819 ngx_test_null(conf, |
770 ngx_pcalloc(cf->pool, sizeof(ngx_http_gzip_conf_t)), | 820 ngx_pcalloc(cf->pool, sizeof(ngx_http_gzip_conf_t)), |
771 NGX_CONF_ERROR); | 821 NGX_CONF_ERROR); |
772 | 822 |
823 /* set by ngx_pcalloc(): | |
824 | |
825 conf->bufs.num = 0; | |
826 conf->proxied = 0; | |
827 | |
828 */ | |
829 | |
830 | |
773 conf->enable = NGX_CONF_UNSET; | 831 conf->enable = NGX_CONF_UNSET; |
774 conf->no_buffer = NGX_CONF_UNSET; | 832 conf->no_buffer = NGX_CONF_UNSET; |
775 | 833 |
776 /* conf->bufs.num = 0; */ | |
777 | 834 |
778 conf->http_version = NGX_CONF_UNSET_UINT; | 835 conf->http_version = NGX_CONF_UNSET_UINT; |
779 conf->proxied = NGX_CONF_UNSET_UINT; | |
780 | 836 |
781 conf->level = NGX_CONF_UNSET; | 837 conf->level = NGX_CONF_UNSET; |
782 conf->wbits = NGX_CONF_UNSET; | 838 conf->wbits = NGX_CONF_UNSET_UINT; |
783 conf->memlevel = NGX_CONF_UNSET; | 839 conf->memlevel = NGX_CONF_UNSET_UINT; |
840 conf->min_length = NGX_CONF_UNSET_UINT; | |
784 | 841 |
785 return conf; | 842 return conf; |
786 } | 843 } |
787 | 844 |
788 | 845 |
797 ngx_conf_merge_bufs_value(conf->bufs, prev->bufs, 4, | 854 ngx_conf_merge_bufs_value(conf->bufs, prev->bufs, 4, |
798 /* STUB: PAGE_SIZE */ 4096); | 855 /* STUB: PAGE_SIZE */ 4096); |
799 | 856 |
800 ngx_conf_merge_unsigned_value(conf->http_version, prev->http_version, | 857 ngx_conf_merge_unsigned_value(conf->http_version, prev->http_version, |
801 NGX_HTTP_VERSION_11); | 858 NGX_HTTP_VERSION_11); |
802 ngx_conf_merge_unsigned_value(conf->proxied, prev->proxied, | 859 ngx_conf_merge_bitmask_value(conf->proxied, prev->proxied, |
803 NGX_HTTP_GZIP_PROXIED_OFF); | 860 (NGX_CONF_BITMASK_SET |
861 |NGX_HTTP_GZIP_PROXIED_OFF)); | |
804 | 862 |
805 ngx_conf_merge_value(conf->level, prev->level, 1); | 863 ngx_conf_merge_value(conf->level, prev->level, 1); |
806 ngx_conf_merge_size_value(conf->wbits, prev->wbits, MAX_WBITS); | 864 ngx_conf_merge_size_value(conf->wbits, prev->wbits, MAX_WBITS); |
807 ngx_conf_merge_size_value(conf->memlevel, prev->memlevel, | 865 ngx_conf_merge_size_value(conf->memlevel, prev->memlevel, |
808 MAX_MEM_LEVEL - 1); | 866 MAX_MEM_LEVEL - 1); |
867 ngx_conf_merge_size_value(conf->min_length, prev->min_length, 0); | |
809 ngx_conf_merge_value(conf->no_buffer, prev->no_buffer, 0); | 868 ngx_conf_merge_value(conf->no_buffer, prev->no_buffer, 0); |
810 | 869 |
811 return NGX_CONF_OK; | 870 return NGX_CONF_OK; |
812 } | 871 } |
813 | 872 |