Mercurial > hg > nginx-quic
comparison src/http/modules/ngx_http_gzip_filter.c @ 452:23fb87bddda1 release-0.1.1
nginx-0.1.1-RELEASE import
*) Feature: the gzip_types directive.
*) Feature: the tcp_nodelay directive.
*) Feature: the send_lowat directive is working not only on OSes that
support kqueue NOTE_LOWAT, but also on OSes that support SO_SNDLOWAT.
*) Feature: the setproctitle() emulation for Linux and Solaris.
*) Bugfix: the "Location" header rewrite bug fixed while the proxying.
*) Bugfix: the ngx_http_chunked_module module may get caught in an
endless loop.
*) Bugfix: the /dev/poll module bugs fixed.
*) Bugfix: the responses were corrupted when the temporary files were
used while the proxying.
*) Bugfix: the unescaped requests were passed to the backend.
*) Bugfix: while the build configuration on Linux 2.4 the
--with-poll_module parameter was required.
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Mon, 11 Oct 2004 15:07:03 +0000 |
parents | 42d11f017717 |
children | 295d97d70c69 |
comparison
equal
deleted
inserted
replaced
451:f40362e47689 | 452:23fb87bddda1 |
---|---|
12 | 12 |
13 | 13 |
14 typedef struct { | 14 typedef struct { |
15 ngx_flag_t enable; | 15 ngx_flag_t enable; |
16 ngx_flag_t no_buffer; | 16 ngx_flag_t no_buffer; |
17 | |
18 ngx_array_t *types; /* array of ngx_http_gzip_type_t */ | |
17 | 19 |
18 ngx_bufs_t bufs; | 20 ngx_bufs_t bufs; |
19 | 21 |
20 ngx_uint_t http_version; | 22 ngx_uint_t http_version; |
21 ngx_uint_t proxied; | 23 ngx_uint_t proxied; |
23 int level; | 25 int level; |
24 size_t wbits; | 26 size_t wbits; |
25 size_t memlevel; | 27 size_t memlevel; |
26 ssize_t min_length; | 28 ssize_t min_length; |
27 } ngx_http_gzip_conf_t; | 29 } ngx_http_gzip_conf_t; |
30 | |
31 | |
32 typedef struct { | |
33 ngx_str_t name; | |
34 ngx_uint_t enable; | |
35 } ngx_http_gzip_type_t; | |
28 | 36 |
29 | 37 |
30 #define NGX_HTTP_GZIP_PROXIED_OFF 0x0002 | 38 #define NGX_HTTP_GZIP_PROXIED_OFF 0x0002 |
31 #define NGX_HTTP_GZIP_PROXIED_EXPIRED 0x0004 | 39 #define NGX_HTTP_GZIP_PROXIED_EXPIRED 0x0004 |
32 #define NGX_HTTP_GZIP_PROXIED_NO_CACHE 0x0008 | 40 #define NGX_HTTP_GZIP_PROXIED_NO_CACHE 0x0008 |
55 ngx_uint_t allocated; | 63 ngx_uint_t allocated; |
56 | 64 |
57 unsigned flush:4; | 65 unsigned flush:4; |
58 unsigned redo:1; | 66 unsigned redo:1; |
59 unsigned done:1; | 67 unsigned done:1; |
60 #if 0 | |
61 unsigned pass:1; | |
62 unsigned blocked:1; | |
63 #endif | |
64 | 68 |
65 size_t zin; | 69 size_t zin; |
66 size_t zout; | 70 size_t zout; |
67 | 71 |
68 uint32_t crc32; | 72 uint32_t crc32; |
84 static ngx_int_t ngx_http_gzip_pre_conf(ngx_conf_t *cf); | 88 static ngx_int_t ngx_http_gzip_pre_conf(ngx_conf_t *cf); |
85 static ngx_int_t ngx_http_gzip_filter_init(ngx_cycle_t *cycle); | 89 static ngx_int_t ngx_http_gzip_filter_init(ngx_cycle_t *cycle); |
86 static void *ngx_http_gzip_create_conf(ngx_conf_t *cf); | 90 static void *ngx_http_gzip_create_conf(ngx_conf_t *cf); |
87 static char *ngx_http_gzip_merge_conf(ngx_conf_t *cf, | 91 static char *ngx_http_gzip_merge_conf(ngx_conf_t *cf, |
88 void *parent, void *child); | 92 void *parent, void *child); |
93 static char *ngx_http_gzip_set_types(ngx_conf_t *cf, ngx_command_t *cmd, | |
94 void *conf); | |
89 static char *ngx_http_gzip_set_window(ngx_conf_t *cf, void *post, void *data); | 95 static char *ngx_http_gzip_set_window(ngx_conf_t *cf, void *post, void *data); |
90 static char *ngx_http_gzip_set_hash(ngx_conf_t *cf, void *post, void *data); | 96 static char *ngx_http_gzip_set_hash(ngx_conf_t *cf, void *post, void *data); |
91 | 97 |
92 | 98 |
93 static ngx_conf_num_bounds_t ngx_http_gzip_comp_level_bounds = { | 99 static ngx_conf_num_bounds_t ngx_http_gzip_comp_level_bounds = { |
136 ngx_conf_set_bufs_slot, | 142 ngx_conf_set_bufs_slot, |
137 NGX_HTTP_LOC_CONF_OFFSET, | 143 NGX_HTTP_LOC_CONF_OFFSET, |
138 offsetof(ngx_http_gzip_conf_t, bufs), | 144 offsetof(ngx_http_gzip_conf_t, bufs), |
139 NULL }, | 145 NULL }, |
140 | 146 |
147 { ngx_string("gzip_types"), | |
148 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE, | |
149 ngx_http_gzip_set_types, | |
150 NGX_HTTP_LOC_CONF_OFFSET, | |
151 0, | |
152 NULL }, | |
153 | |
141 { ngx_string("gzip_comp_level"), | 154 { ngx_string("gzip_comp_level"), |
142 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, | 155 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, |
143 ngx_conf_set_num_slot, | 156 ngx_conf_set_num_slot, |
144 NGX_HTTP_LOC_CONF_OFFSET, | 157 NGX_HTTP_LOC_CONF_OFFSET, |
145 offsetof(ngx_http_gzip_conf_t, level), | 158 offsetof(ngx_http_gzip_conf_t, level), |
209 NGX_MODULE, | 222 NGX_MODULE, |
210 &ngx_http_gzip_filter_module_ctx, /* module context */ | 223 &ngx_http_gzip_filter_module_ctx, /* module context */ |
211 ngx_http_gzip_filter_commands, /* module directives */ | 224 ngx_http_gzip_filter_commands, /* module directives */ |
212 NGX_HTTP_MODULE, /* module type */ | 225 NGX_HTTP_MODULE, /* module type */ |
213 ngx_http_gzip_filter_init, /* init module */ | 226 ngx_http_gzip_filter_init, /* init module */ |
214 NULL /* init child */ | 227 NULL /* init process */ |
215 }; | 228 }; |
216 | 229 |
217 | 230 |
218 static ngx_http_log_op_name_t ngx_http_gzip_log_fmt_ops[] = { | 231 static ngx_http_log_op_name_t ngx_http_gzip_log_fmt_ops[] = { |
219 { ngx_string("gzip_ratio"), NGX_INT32_LEN + 3, ngx_http_gzip_log_ratio }, | 232 { ngx_string("gzip_ratio"), NGX_INT32_LEN + 3, ngx_http_gzip_log_ratio }, |
245 static ngx_http_output_body_filter_pt ngx_http_next_body_filter; | 258 static ngx_http_output_body_filter_pt ngx_http_next_body_filter; |
246 | 259 |
247 | 260 |
248 static ngx_int_t ngx_http_gzip_header_filter(ngx_http_request_t *r) | 261 static ngx_int_t ngx_http_gzip_header_filter(ngx_http_request_t *r) |
249 { | 262 { |
263 ngx_uint_t i, found; | |
250 ngx_http_gzip_ctx_t *ctx; | 264 ngx_http_gzip_ctx_t *ctx; |
251 ngx_http_gzip_conf_t *conf; | 265 ngx_http_gzip_conf_t *conf; |
266 ngx_http_gzip_type_t *type; | |
252 | 267 |
253 conf = ngx_http_get_module_loc_conf(r, ngx_http_gzip_filter_module); | 268 conf = ngx_http_get_module_loc_conf(r, ngx_http_gzip_filter_module); |
254 | 269 |
255 if (!conf->enable | 270 if (!conf->enable |
256 || r->headers_out.status != NGX_HTTP_OK | 271 || (r->headers_out.status != NGX_HTTP_OK |
272 && r->headers_out.status != NGX_HTTP_FORBIDDEN | |
273 && r->headers_out.status != NGX_HTTP_NOT_FOUND) | |
257 || r->header_only | 274 || r->header_only |
258 || r->http_version < conf->http_version | 275 || r->http_version < conf->http_version |
276 || r->headers_out.content_type == NULL | |
259 || (r->headers_out.content_encoding | 277 || (r->headers_out.content_encoding |
260 && r->headers_out.content_encoding->value.len) | 278 && r->headers_out.content_encoding->value.len) |
261 || r->headers_in.accept_encoding == NULL | 279 || r->headers_in.accept_encoding == NULL |
262 || (r->headers_out.content_length_n != -1 | 280 || (r->headers_out.content_length_n != -1 |
263 && r->headers_out.content_length_n < conf->min_length) | 281 && r->headers_out.content_length_n < conf->min_length) |
265 ) | 283 ) |
266 { | 284 { |
267 return ngx_http_next_header_filter(r); | 285 return ngx_http_next_header_filter(r); |
268 } | 286 } |
269 | 287 |
270 /* TODO: "text/html" -> custom types */ | 288 |
271 if (r->headers_out.content_type | 289 found = 0; |
272 && ngx_strncasecmp(r->headers_out.content_type->value.data, | 290 type = conf->types->elts; |
273 "text/html", 9) != 0) | 291 |
274 { | 292 for (i = 0; i < conf->types->nelts; i++) { |
293 if (r->headers_out.content_type->value.len >= type[i].name.len | |
294 && ngx_strncasecmp(r->headers_out.content_type->value.data, | |
295 type[i].name.data, type[i].name.len) == 0) | |
296 { | |
297 found = 1; | |
298 break; | |
299 } | |
300 } | |
301 | |
302 if (!found) { | |
275 return ngx_http_next_header_filter(r); | 303 return ngx_http_next_header_filter(r); |
276 } | 304 } |
277 | 305 |
278 | 306 |
279 if (r->headers_in.via) { | 307 if (r->headers_in.via) { |
570 &ngx_http_gzip_filter_module; | 598 &ngx_http_gzip_filter_module; |
571 ctx->out_buf->recycled = 1; | 599 ctx->out_buf->recycled = 1; |
572 ctx->bufs++; | 600 ctx->bufs++; |
573 | 601 |
574 } else { | 602 } else { |
575 #if 0 | |
576 ctx->blocked = 1; | |
577 #endif | |
578 break; | 603 break; |
579 } | 604 } |
580 | 605 |
581 #if 0 | |
582 ctx->blocked = 0; | |
583 #endif | |
584 ctx->zstream.next_out = ctx->out_buf->pos; | 606 ctx->zstream.next_out = ctx->out_buf->pos; |
585 ctx->zstream.avail_out = conf->bufs.size; | 607 ctx->zstream.avail_out = conf->bufs.size; |
586 } | 608 } |
587 | 609 |
588 ngx_log_debug6(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | 610 ngx_log_debug6(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, |
643 | 665 |
644 ngx_alloc_link_and_set_buf(cl, ctx->out_buf, r->pool, | 666 ngx_alloc_link_and_set_buf(cl, ctx->out_buf, r->pool, |
645 ngx_http_gzip_error(ctx)); | 667 ngx_http_gzip_error(ctx)); |
646 *ctx->last_out = cl; | 668 *ctx->last_out = cl; |
647 ctx->last_out = &cl->next; | 669 ctx->last_out = &cl->next; |
648 | |
649 #if 0 | |
650 ctx->pass = 1; | |
651 #endif | |
652 | 670 |
653 break; | 671 break; |
654 } | 672 } |
655 | 673 |
656 if (rc == Z_STREAM_END) { | 674 if (rc == Z_STREAM_END) { |
710 | 728 |
711 ctx->zstream.avail_in = 0; | 729 ctx->zstream.avail_in = 0; |
712 ctx->zstream.avail_out = 0; | 730 ctx->zstream.avail_out = 0; |
713 | 731 |
714 ctx->done = 1; | 732 ctx->done = 1; |
715 #if 0 | |
716 ctx->pass = 1; | |
717 #endif | |
718 | 733 |
719 break; | 734 break; |
720 } | 735 } |
721 | 736 |
722 if (conf->no_buffer && ctx->in == NULL) { | 737 if (conf->no_buffer && ctx->in == NULL) { |
723 ngx_alloc_link_and_set_buf(cl, ctx->out_buf, r->pool, | 738 ngx_alloc_link_and_set_buf(cl, ctx->out_buf, r->pool, |
724 ngx_http_gzip_error(ctx)); | 739 ngx_http_gzip_error(ctx)); |
725 *ctx->last_out = cl; | 740 *ctx->last_out = cl; |
726 ctx->last_out = &cl->next; | 741 ctx->last_out = &cl->next; |
727 | 742 |
728 #if 0 | |
729 ctx->pass = 1; | |
730 #endif | |
731 | |
732 break; | 743 break; |
733 } | 744 } |
734 } | 745 } |
735 | |
736 #if 0 | |
737 | |
738 /* OLD CODE */ | |
739 | |
740 if (ctx->out) { | |
741 if (ctx->pass) { | |
742 ctx->pass = 0; | |
743 | |
744 } else if (last == NGX_AGAIN) { | |
745 return last; | |
746 } | |
747 | |
748 } else if (ctx->busy->buf && ngx_buf_size(ctx->busy->buf)) { | |
749 if (last != NGX_NONE) { | |
750 return last; | |
751 } | |
752 | |
753 } else if (ctx->blocked) { | |
754 if (last != NGX_NONE) { | |
755 return last; | |
756 } | |
757 | |
758 } else { | |
759 if (last == NGX_NONE) { | |
760 return NGX_OK; | |
761 } | |
762 | |
763 return last; | |
764 } | |
765 #endif | |
766 | |
767 /* NEW CODE */ | |
768 | 746 |
769 if (last == NGX_AGAIN) { | 747 if (last == NGX_AGAIN) { |
770 return NGX_AGAIN; | 748 return NGX_AGAIN; |
771 } | 749 } |
772 | 750 |
773 if (ctx->out == NULL && ctx->busy == NULL) { | 751 if (ctx->out == NULL && ctx->busy == NULL) { |
774 return NGX_OK; | 752 return NGX_OK; |
775 } | 753 } |
776 | |
777 /**/ | |
778 | 754 |
779 last = ngx_http_next_body_filter(r, ctx->out); | 755 last = ngx_http_next_body_filter(r, ctx->out); |
780 | 756 |
781 /* | 757 /* |
782 * we do not check NGX_AGAIN here because the downstream filters | 758 * we do not check NGX_AGAIN here because the downstream filters |
864 #if 0 | 840 #if 0 |
865 return buf + ngx_snprintf((char *) buf, NGX_INT32_LEN + 4, "%.2f", | 841 return buf + ngx_snprintf((char *) buf, NGX_INT32_LEN + 4, "%.2f", |
866 (float) ctx->zin / ctx->zout); | 842 (float) ctx->zin / ctx->zout); |
867 #endif | 843 #endif |
868 | 844 |
869 /* we prefer do not use FPU */ | 845 /* we prefer do not use the FPU */ |
870 | 846 |
871 zint = (ngx_uint_t) (ctx->zin / ctx->zout); | 847 zint = (ngx_uint_t) (ctx->zin / ctx->zout); |
872 zfrac = (ngx_uint_t) ((ctx->zin * 100 / ctx->zout) % 100); | 848 zfrac = (ngx_uint_t) ((ctx->zin * 100 / ctx->zout) % 100); |
873 | 849 |
874 if ((ctx->zin * 1000 / ctx->zout) %10 > 4) { | 850 if ((ctx->zin * 1000 / ctx->zout) %10 > 4) { |
945 set by ngx_pcalloc(): | 921 set by ngx_pcalloc(): |
946 | 922 |
947 conf->bufs.num = 0; | 923 conf->bufs.num = 0; |
948 conf->proxied = 0; | 924 conf->proxied = 0; |
949 | 925 |
926 conf->types = NULL; | |
927 | |
950 */ | 928 */ |
951 | 929 |
952 conf->enable = NGX_CONF_UNSET; | 930 conf->enable = NGX_CONF_UNSET; |
953 conf->no_buffer = NGX_CONF_UNSET; | 931 conf->no_buffer = NGX_CONF_UNSET; |
954 | 932 |
966 static char *ngx_http_gzip_merge_conf(ngx_conf_t *cf, | 944 static char *ngx_http_gzip_merge_conf(ngx_conf_t *cf, |
967 void *parent, void *child) | 945 void *parent, void *child) |
968 { | 946 { |
969 ngx_http_gzip_conf_t *prev = parent; | 947 ngx_http_gzip_conf_t *prev = parent; |
970 ngx_http_gzip_conf_t *conf = child; | 948 ngx_http_gzip_conf_t *conf = child; |
949 | |
950 ngx_http_gzip_type_t *type; | |
971 | 951 |
972 ngx_conf_merge_value(conf->enable, prev->enable, 0); | 952 ngx_conf_merge_value(conf->enable, prev->enable, 0); |
973 | 953 |
974 ngx_conf_merge_bufs_value(conf->bufs, prev->bufs, 4, ngx_pagesize); | 954 ngx_conf_merge_bufs_value(conf->bufs, prev->bufs, 4, ngx_pagesize); |
975 | 955 |
984 ngx_conf_merge_size_value(conf->memlevel, prev->memlevel, | 964 ngx_conf_merge_size_value(conf->memlevel, prev->memlevel, |
985 MAX_MEM_LEVEL - 1); | 965 MAX_MEM_LEVEL - 1); |
986 ngx_conf_merge_value(conf->min_length, prev->min_length, 0); | 966 ngx_conf_merge_value(conf->min_length, prev->min_length, 0); |
987 ngx_conf_merge_value(conf->no_buffer, prev->no_buffer, 0); | 967 ngx_conf_merge_value(conf->no_buffer, prev->no_buffer, 0); |
988 | 968 |
969 if (conf->types == NULL) { | |
970 if (prev->types == NULL) { | |
971 conf->types = ngx_array_create(cf->pool, 1, | |
972 sizeof(ngx_http_gzip_type_t)); | |
973 if (conf->types == NULL) { | |
974 return NGX_CONF_ERROR; | |
975 } | |
976 | |
977 if (!(type = ngx_array_push(conf->types))) { | |
978 return NGX_CONF_ERROR; | |
979 } | |
980 | |
981 type->name.len = sizeof("text/html") - 1; | |
982 type->name.data = (u_char *) "text/html"; | |
983 type->enable = 1; | |
984 | |
985 } else { | |
986 conf->types = prev->types; | |
987 } | |
988 } | |
989 | |
990 return NGX_CONF_OK; | |
991 } | |
992 | |
993 | |
994 static char *ngx_http_gzip_set_types(ngx_conf_t *cf, ngx_command_t *cmd, | |
995 void *conf) | |
996 { | |
997 ngx_http_gzip_conf_t *gcf = conf; | |
998 | |
999 ngx_str_t *value; | |
1000 ngx_uint_t i; | |
1001 ngx_http_gzip_type_t *type; | |
1002 | |
1003 if (gcf->types == NULL) { | |
1004 gcf->types = ngx_array_create(cf->pool, 5, | |
1005 sizeof(ngx_http_gzip_type_t)); | |
1006 if (gcf->types == NULL) { | |
1007 return NGX_CONF_ERROR; | |
1008 } | |
1009 | |
1010 if (!(type = ngx_array_push(gcf->types))) { | |
1011 return NGX_CONF_ERROR; | |
1012 } | |
1013 | |
1014 type->name.len = sizeof("text/html") - 1; | |
1015 type->name.data = (u_char *) "text/html"; | |
1016 type->enable = 1; | |
1017 } | |
1018 | |
1019 value = cf->args->elts; | |
1020 | |
1021 for (i = 1; i < cf->args->nelts; i++) { | |
1022 | |
1023 if (ngx_strcmp(value[i].data, "text/html") == 0) { | |
1024 continue; | |
1025 } | |
1026 | |
1027 if (!(type = ngx_array_push(gcf->types))) { | |
1028 return NGX_CONF_ERROR; | |
1029 } | |
1030 | |
1031 type->name.len = value[i].len; | |
1032 | |
1033 if (!(type->name.data = ngx_palloc(cf->pool, type->name.len + 1))) { | |
1034 return NGX_CONF_ERROR; | |
1035 } | |
1036 | |
1037 ngx_cpystrn(type->name.data, value[i].data, type->name.len + 1); | |
1038 } | |
1039 | |
989 return NGX_CONF_OK; | 1040 return NGX_CONF_OK; |
990 } | 1041 } |
991 | 1042 |
992 | 1043 |
993 static char *ngx_http_gzip_set_window(ngx_conf_t *cf, void *post, void *data) | 1044 static char *ngx_http_gzip_set_window(ngx_conf_t *cf, void *post, void *data) |