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