nginxtra 1.2.8.8 → 1.4.0.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (89) hide show
  1. data/bin/nginxtra +1 -1
  2. data/bin/nginxtra_rails +1 -1
  3. data/lib/nginxtra/version.rb +1 -1
  4. data/vendor/nginx/CHANGES +202 -63
  5. data/vendor/nginx/CHANGES.ru +208 -66
  6. data/vendor/nginx/auto/lib/md5/conf +3 -3
  7. data/vendor/nginx/auto/lib/perl/conf +3 -1
  8. data/vendor/nginx/auto/lib/perl/make +21 -16
  9. data/vendor/nginx/auto/lib/sha1/conf +1 -1
  10. data/vendor/nginx/auto/modules +25 -4
  11. data/vendor/nginx/auto/options +7 -1
  12. data/vendor/nginx/auto/sources +15 -1
  13. data/vendor/nginx/auto/unix +14 -0
  14. data/vendor/nginx/src/core/nginx.h +2 -2
  15. data/vendor/nginx/src/core/ngx_array.c +1 -7
  16. data/vendor/nginx/src/core/ngx_array.h +2 -2
  17. data/vendor/nginx/src/core/ngx_connection.c +13 -7
  18. data/vendor/nginx/src/core/ngx_connection.h +1 -2
  19. data/vendor/nginx/src/core/ngx_core.h +1 -2
  20. data/vendor/nginx/src/core/ngx_crypt.c +37 -0
  21. data/vendor/nginx/src/core/ngx_cycle.h +1 -1
  22. data/vendor/nginx/src/core/ngx_inet.c +219 -48
  23. data/vendor/nginx/src/core/ngx_inet.h +1 -1
  24. data/vendor/nginx/src/event/modules/ngx_devpoll_module.c +7 -1
  25. data/vendor/nginx/src/event/modules/ngx_eventport_module.c +1 -1
  26. data/vendor/nginx/src/event/ngx_event.c +5 -1
  27. data/vendor/nginx/src/event/ngx_event.h +1 -0
  28. data/vendor/nginx/src/event/ngx_event_connect.c +1 -1
  29. data/vendor/nginx/src/event/ngx_event_openssl.c +135 -9
  30. data/vendor/nginx/src/event/ngx_event_openssl.h +9 -0
  31. data/vendor/nginx/src/event/ngx_event_openssl_stapling.c +1749 -0
  32. data/vendor/nginx/src/http/modules/ngx_http_addition_filter_module.c +1 -0
  33. data/vendor/nginx/src/http/modules/ngx_http_chunked_filter_module.c +1 -0
  34. data/vendor/nginx/src/http/modules/ngx_http_fastcgi_module.c +5 -0
  35. data/vendor/nginx/src/http/modules/ngx_http_flv_module.c +4 -0
  36. data/vendor/nginx/src/http/modules/ngx_http_geo_module.c +7 -8
  37. data/vendor/nginx/src/http/modules/ngx_http_geoip_module.c +10 -12
  38. data/vendor/nginx/src/http/modules/ngx_http_gunzip_filter_module.c +677 -0
  39. data/vendor/nginx/src/http/modules/ngx_http_gzip_filter_module.c +3 -0
  40. data/vendor/nginx/src/http/modules/ngx_http_gzip_static_module.c +36 -10
  41. data/vendor/nginx/src/http/modules/ngx_http_headers_filter_module.c +31 -13
  42. data/vendor/nginx/src/http/modules/ngx_http_image_filter_module.c +13 -0
  43. data/vendor/nginx/src/http/modules/ngx_http_limit_conn_module.c +18 -2
  44. data/vendor/nginx/src/http/modules/ngx_http_limit_req_module.c +19 -2
  45. data/vendor/nginx/src/http/modules/ngx_http_map_module.c +1 -1
  46. data/vendor/nginx/src/http/modules/ngx_http_memcached_module.c +60 -8
  47. data/vendor/nginx/src/http/modules/ngx_http_mp4_module.c +4 -8
  48. data/vendor/nginx/src/http/modules/ngx_http_not_modified_filter_module.c +126 -29
  49. data/vendor/nginx/src/http/modules/ngx_http_proxy_module.c +59 -301
  50. data/vendor/nginx/src/http/modules/ngx_http_range_filter_module.c +34 -6
  51. data/vendor/nginx/src/http/modules/ngx_http_realip_module.c +13 -12
  52. data/vendor/nginx/src/http/modules/ngx_http_scgi_module.c +30 -11
  53. data/vendor/nginx/src/http/modules/ngx_http_ssi_filter_module.c +1 -0
  54. data/vendor/nginx/src/http/modules/ngx_http_ssl_module.c +155 -4
  55. data/vendor/nginx/src/http/modules/ngx_http_ssl_module.h +6 -0
  56. data/vendor/nginx/src/http/modules/ngx_http_static_module.c +4 -0
  57. data/vendor/nginx/src/http/modules/ngx_http_stub_status_module.c +90 -3
  58. data/vendor/nginx/src/http/modules/ngx_http_sub_filter_module.c +1 -0
  59. data/vendor/nginx/src/http/modules/ngx_http_upstream_ip_hash_module.c +5 -0
  60. data/vendor/nginx/src/http/modules/ngx_http_upstream_least_conn_module.c +5 -0
  61. data/vendor/nginx/src/http/modules/ngx_http_uwsgi_module.c +14 -1
  62. data/vendor/nginx/src/http/modules/ngx_http_xslt_filter_module.c +1 -0
  63. data/vendor/nginx/src/http/modules/perl/Makefile.PL +4 -2
  64. data/vendor/nginx/src/http/modules/perl/nginx.pm +1 -1
  65. data/vendor/nginx/src/http/modules/perl/nginx.xs +36 -3
  66. data/vendor/nginx/src/http/ngx_http.c +24 -1
  67. data/vendor/nginx/src/http/ngx_http.h +26 -2
  68. data/vendor/nginx/src/http/ngx_http_core_module.c +136 -10
  69. data/vendor/nginx/src/http/ngx_http_core_module.h +37 -13
  70. data/vendor/nginx/src/http/ngx_http_header_filter_module.c +9 -2
  71. data/vendor/nginx/src/http/ngx_http_parse.c +404 -0
  72. data/vendor/nginx/src/http/ngx_http_request.c +840 -517
  73. data/vendor/nginx/src/http/ngx_http_request.h +37 -25
  74. data/vendor/nginx/src/http/ngx_http_request_body.c +585 -156
  75. data/vendor/nginx/src/http/ngx_http_spdy.c +2882 -0
  76. data/vendor/nginx/src/http/ngx_http_spdy.h +235 -0
  77. data/vendor/nginx/src/http/ngx_http_spdy_filter_module.c +999 -0
  78. data/vendor/nginx/src/http/ngx_http_spdy_module.c +351 -0
  79. data/vendor/nginx/src/http/ngx_http_spdy_module.h +36 -0
  80. data/vendor/nginx/src/http/ngx_http_special_response.c +3 -1
  81. data/vendor/nginx/src/http/ngx_http_upstream.c +415 -26
  82. data/vendor/nginx/src/http/ngx_http_upstream.h +11 -1
  83. data/vendor/nginx/src/http/ngx_http_upstream_round_robin.c +2 -45
  84. data/vendor/nginx/src/http/ngx_http_upstream_round_robin.h +0 -2
  85. data/vendor/nginx/src/http/ngx_http_variables.c +72 -12
  86. data/vendor/nginx/src/mail/ngx_mail.h +2 -2
  87. data/vendor/nginx/src/mail/ngx_mail_auth_http_module.c +35 -25
  88. data/vendor/nginx/src/mail/ngx_mail_core_module.c +5 -1
  89. metadata +9 -2
@@ -121,6 +121,7 @@ ngx_http_addition_header_filter(ngx_http_request_t *r)
121
121
 
122
122
  ngx_http_clear_content_length(r);
123
123
  ngx_http_clear_accept_ranges(r);
124
+ ngx_http_clear_etag(r);
124
125
 
125
126
  return ngx_http_next_header_filter(r);
126
127
  }
@@ -62,6 +62,7 @@ ngx_http_chunked_header_filter(ngx_http_request_t *r)
62
62
 
63
63
  if (r->headers_out.status == NGX_HTTP_NOT_MODIFIED
64
64
  || r->headers_out.status == NGX_HTTP_NO_CONTENT
65
+ || r->headers_out.status < NGX_HTTP_OK
65
66
  || r != r->main
66
67
  || (r->method & NGX_HTTP_HEAD))
67
68
  {
@@ -2091,6 +2091,8 @@ ngx_http_fastcgi_create_loc_conf(ngx_conf_t *cf)
2091
2091
  conf->upstream.buffering = NGX_CONF_UNSET;
2092
2092
  conf->upstream.ignore_client_abort = NGX_CONF_UNSET;
2093
2093
 
2094
+ conf->upstream.local = NGX_CONF_UNSET_PTR;
2095
+
2094
2096
  conf->upstream.connect_timeout = NGX_CONF_UNSET_MSEC;
2095
2097
  conf->upstream.send_timeout = NGX_CONF_UNSET_MSEC;
2096
2098
  conf->upstream.read_timeout = NGX_CONF_UNSET_MSEC;
@@ -2162,6 +2164,9 @@ ngx_http_fastcgi_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
2162
2164
  ngx_conf_merge_value(conf->upstream.ignore_client_abort,
2163
2165
  prev->upstream.ignore_client_abort, 0);
2164
2166
 
2167
+ ngx_conf_merge_ptr_value(conf->upstream.local,
2168
+ prev->upstream.local, NULL);
2169
+
2165
2170
  ngx_conf_merge_msec_value(conf->upstream.connect_timeout,
2166
2171
  prev->upstream.connect_timeout, 60000);
2167
2172
 
@@ -194,6 +194,10 @@ ngx_http_flv_handler(ngx_http_request_t *r)
194
194
  r->headers_out.content_length_n = len;
195
195
  r->headers_out.last_modified_time = of.mtime;
196
196
 
197
+ if (ngx_http_set_etag(r) != NGX_OK) {
198
+ return NGX_HTTP_INTERNAL_SERVER_ERROR;
199
+ }
200
+
197
201
  if (ngx_http_set_content_type(r) != NGX_OK) {
198
202
  return NGX_HTTP_INTERNAL_SERVER_ERROR;
199
203
  }
@@ -314,18 +314,17 @@ static ngx_int_t
314
314
  ngx_http_geo_addr(ngx_http_request_t *r, ngx_http_geo_ctx_t *ctx,
315
315
  ngx_addr_t *addr)
316
316
  {
317
- ngx_table_elt_t *xfwd;
317
+ ngx_array_t *xfwd;
318
318
 
319
319
  if (ngx_http_geo_real_addr(r, ctx, addr) != NGX_OK) {
320
320
  return NGX_ERROR;
321
321
  }
322
322
 
323
- xfwd = r->headers_in.x_forwarded_for;
323
+ xfwd = &r->headers_in.x_forwarded_for;
324
324
 
325
- if (xfwd != NULL && ctx->proxies != NULL) {
326
- (void) ngx_http_get_forwarded_addr(r, addr, xfwd->value.data,
327
- xfwd->value.len, ctx->proxies,
328
- ctx->proxy_recursive);
325
+ if (xfwd->nelts > 0 && ctx->proxies != NULL) {
326
+ (void) ngx_http_get_forwarded_addr(r, addr, xfwd, NULL,
327
+ ctx->proxies, ctx->proxy_recursive);
329
328
  }
330
329
 
331
330
  return NGX_OK;
@@ -431,14 +430,14 @@ ngx_http_geo_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
431
430
  return NGX_CONF_ERROR;
432
431
  }
433
432
 
434
- pool = ngx_create_pool(16384, cf->log);
433
+ pool = ngx_create_pool(NGX_DEFAULT_POOL_SIZE, cf->log);
435
434
  if (pool == NULL) {
436
435
  return NGX_CONF_ERROR;
437
436
  }
438
437
 
439
438
  ngx_memzero(&ctx, sizeof(ngx_http_geo_conf_ctx_t));
440
439
 
441
- ctx.temp_pool = ngx_create_pool(16384, cf->log);
440
+ ctx.temp_pool = ngx_create_pool(NGX_DEFAULT_POOL_SIZE, cf->log);
442
441
  if (ctx.temp_pool == NULL) {
443
442
  return NGX_CONF_ERROR;
444
443
  }
@@ -240,19 +240,18 @@ static u_long
240
240
  ngx_http_geoip_addr(ngx_http_request_t *r, ngx_http_geoip_conf_t *gcf)
241
241
  {
242
242
  ngx_addr_t addr;
243
- ngx_table_elt_t *xfwd;
243
+ ngx_array_t *xfwd;
244
244
  struct sockaddr_in *sin;
245
245
 
246
246
  addr.sockaddr = r->connection->sockaddr;
247
247
  addr.socklen = r->connection->socklen;
248
248
  /* addr.name = r->connection->addr_text; */
249
249
 
250
- xfwd = r->headers_in.x_forwarded_for;
250
+ xfwd = &r->headers_in.x_forwarded_for;
251
251
 
252
- if (xfwd != NULL && gcf->proxies != NULL) {
253
- (void) ngx_http_get_forwarded_addr(r, &addr, xfwd->value.data,
254
- xfwd->value.len, gcf->proxies,
255
- gcf->proxy_recursive);
252
+ if (xfwd->nelts > 0 && gcf->proxies != NULL) {
253
+ (void) ngx_http_get_forwarded_addr(r, &addr, xfwd, NULL,
254
+ gcf->proxies, gcf->proxy_recursive);
256
255
  }
257
256
 
258
257
  #if (NGX_HAVE_INET6)
@@ -293,7 +292,7 @@ static geoipv6_t
293
292
  ngx_http_geoip_addr_v6(ngx_http_request_t *r, ngx_http_geoip_conf_t *gcf)
294
293
  {
295
294
  ngx_addr_t addr;
296
- ngx_table_elt_t *xfwd;
295
+ ngx_array_t *xfwd;
297
296
  in_addr_t addr4;
298
297
  struct in6_addr addr6;
299
298
  struct sockaddr_in *sin;
@@ -303,12 +302,11 @@ ngx_http_geoip_addr_v6(ngx_http_request_t *r, ngx_http_geoip_conf_t *gcf)
303
302
  addr.socklen = r->connection->socklen;
304
303
  /* addr.name = r->connection->addr_text; */
305
304
 
306
- xfwd = r->headers_in.x_forwarded_for;
305
+ xfwd = &r->headers_in.x_forwarded_for;
307
306
 
308
- if (xfwd != NULL && gcf->proxies != NULL) {
309
- (void) ngx_http_get_forwarded_addr(r, &addr, xfwd->value.data,
310
- xfwd->value.len, gcf->proxies,
311
- gcf->proxy_recursive);
307
+ if (xfwd->nelts > 0 && gcf->proxies != NULL) {
308
+ (void) ngx_http_get_forwarded_addr(r, &addr, xfwd, NULL,
309
+ gcf->proxies, gcf->proxy_recursive);
312
310
  }
313
311
 
314
312
  switch (addr.sockaddr->sa_family) {
@@ -0,0 +1,677 @@
1
+
2
+ /*
3
+ * Copyright (C) Igor Sysoev
4
+ * Copyright (C) Maxim Dounin
5
+ * Copyright (C) Nginx, Inc.
6
+ */
7
+
8
+
9
+ #include <ngx_config.h>
10
+ #include <ngx_core.h>
11
+ #include <ngx_http.h>
12
+
13
+ #include <zlib.h>
14
+
15
+
16
+ typedef struct {
17
+ ngx_flag_t enable;
18
+ ngx_bufs_t bufs;
19
+ } ngx_http_gunzip_conf_t;
20
+
21
+
22
+ typedef struct {
23
+ ngx_chain_t *in;
24
+ ngx_chain_t *free;
25
+ ngx_chain_t *busy;
26
+ ngx_chain_t *out;
27
+ ngx_chain_t **last_out;
28
+
29
+ ngx_buf_t *in_buf;
30
+ ngx_buf_t *out_buf;
31
+ ngx_int_t bufs;
32
+
33
+ unsigned started:1;
34
+ unsigned flush:4;
35
+ unsigned redo:1;
36
+ unsigned done:1;
37
+ unsigned nomem:1;
38
+
39
+ z_stream zstream;
40
+ ngx_http_request_t *request;
41
+ } ngx_http_gunzip_ctx_t;
42
+
43
+
44
+ static ngx_int_t ngx_http_gunzip_filter_inflate_start(ngx_http_request_t *r,
45
+ ngx_http_gunzip_ctx_t *ctx);
46
+ static ngx_int_t ngx_http_gunzip_filter_add_data(ngx_http_request_t *r,
47
+ ngx_http_gunzip_ctx_t *ctx);
48
+ static ngx_int_t ngx_http_gunzip_filter_get_buf(ngx_http_request_t *r,
49
+ ngx_http_gunzip_ctx_t *ctx);
50
+ static ngx_int_t ngx_http_gunzip_filter_inflate(ngx_http_request_t *r,
51
+ ngx_http_gunzip_ctx_t *ctx);
52
+ static ngx_int_t ngx_http_gunzip_filter_inflate_end(ngx_http_request_t *r,
53
+ ngx_http_gunzip_ctx_t *ctx);
54
+
55
+ static void *ngx_http_gunzip_filter_alloc(void *opaque, u_int items,
56
+ u_int size);
57
+ static void ngx_http_gunzip_filter_free(void *opaque, void *address);
58
+
59
+ static ngx_int_t ngx_http_gunzip_filter_init(ngx_conf_t *cf);
60
+ static void *ngx_http_gunzip_create_conf(ngx_conf_t *cf);
61
+ static char *ngx_http_gunzip_merge_conf(ngx_conf_t *cf,
62
+ void *parent, void *child);
63
+
64
+
65
+ static ngx_command_t ngx_http_gunzip_filter_commands[] = {
66
+
67
+ { ngx_string("gunzip"),
68
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
69
+ ngx_conf_set_flag_slot,
70
+ NGX_HTTP_LOC_CONF_OFFSET,
71
+ offsetof(ngx_http_gunzip_conf_t, enable),
72
+ NULL },
73
+
74
+ { ngx_string("gunzip_buffers"),
75
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE2,
76
+ ngx_conf_set_bufs_slot,
77
+ NGX_HTTP_LOC_CONF_OFFSET,
78
+ offsetof(ngx_http_gunzip_conf_t, bufs),
79
+ NULL },
80
+
81
+ ngx_null_command
82
+ };
83
+
84
+
85
+ static ngx_http_module_t ngx_http_gunzip_filter_module_ctx = {
86
+ NULL, /* preconfiguration */
87
+ ngx_http_gunzip_filter_init, /* postconfiguration */
88
+
89
+ NULL, /* create main configuration */
90
+ NULL, /* init main configuration */
91
+
92
+ NULL, /* create server configuration */
93
+ NULL, /* merge server configuration */
94
+
95
+ ngx_http_gunzip_create_conf, /* create location configuration */
96
+ ngx_http_gunzip_merge_conf /* merge location configuration */
97
+ };
98
+
99
+
100
+ ngx_module_t ngx_http_gunzip_filter_module = {
101
+ NGX_MODULE_V1,
102
+ &ngx_http_gunzip_filter_module_ctx, /* module context */
103
+ ngx_http_gunzip_filter_commands, /* module directives */
104
+ NGX_HTTP_MODULE, /* module type */
105
+ NULL, /* init master */
106
+ NULL, /* init module */
107
+ NULL, /* init process */
108
+ NULL, /* init thread */
109
+ NULL, /* exit thread */
110
+ NULL, /* exit process */
111
+ NULL, /* exit master */
112
+ NGX_MODULE_V1_PADDING
113
+ };
114
+
115
+
116
+ static ngx_http_output_header_filter_pt ngx_http_next_header_filter;
117
+ static ngx_http_output_body_filter_pt ngx_http_next_body_filter;
118
+
119
+
120
+ static ngx_int_t
121
+ ngx_http_gunzip_header_filter(ngx_http_request_t *r)
122
+ {
123
+ ngx_http_gunzip_ctx_t *ctx;
124
+ ngx_http_gunzip_conf_t *conf;
125
+
126
+ conf = ngx_http_get_module_loc_conf(r, ngx_http_gunzip_filter_module);
127
+
128
+ /* TODO support multiple content-codings */
129
+ /* TODO always gunzip - due to configuration or module request */
130
+ /* TODO ignore content encoding? */
131
+
132
+ if (!conf->enable
133
+ || r->headers_out.content_encoding == NULL
134
+ || r->headers_out.content_encoding->value.len != 4
135
+ || ngx_strncasecmp(r->headers_out.content_encoding->value.data,
136
+ (u_char *) "gzip", 4) != 0)
137
+ {
138
+ return ngx_http_next_header_filter(r);
139
+ }
140
+
141
+ r->gzip_vary = 1;
142
+
143
+ if (!r->gzip_tested) {
144
+ if (ngx_http_gzip_ok(r) == NGX_OK) {
145
+ return ngx_http_next_header_filter(r);
146
+ }
147
+
148
+ } else if (r->gzip_ok) {
149
+ return ngx_http_next_header_filter(r);
150
+ }
151
+
152
+ ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_gunzip_ctx_t));
153
+ if (ctx == NULL) {
154
+ return NGX_ERROR;
155
+ }
156
+
157
+ ngx_http_set_ctx(r, ctx, ngx_http_gunzip_filter_module);
158
+
159
+ ctx->request = r;
160
+
161
+ r->filter_need_in_memory = 1;
162
+
163
+ r->headers_out.content_encoding->hash = 0;
164
+ r->headers_out.content_encoding = NULL;
165
+
166
+ ngx_http_clear_content_length(r);
167
+ ngx_http_clear_accept_ranges(r);
168
+ ngx_http_clear_etag(r);
169
+
170
+ return ngx_http_next_header_filter(r);
171
+ }
172
+
173
+
174
+ static ngx_int_t
175
+ ngx_http_gunzip_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
176
+ {
177
+ int rc;
178
+ ngx_chain_t *cl;
179
+ ngx_http_gunzip_ctx_t *ctx;
180
+
181
+ ctx = ngx_http_get_module_ctx(r, ngx_http_gunzip_filter_module);
182
+
183
+ if (ctx == NULL || ctx->done) {
184
+ return ngx_http_next_body_filter(r, in);
185
+ }
186
+
187
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
188
+ "http gunzip filter");
189
+
190
+ if (!ctx->started) {
191
+ if (ngx_http_gunzip_filter_inflate_start(r, ctx) != NGX_OK) {
192
+ goto failed;
193
+ }
194
+ }
195
+
196
+ if (in) {
197
+ if (ngx_chain_add_copy(r->pool, &ctx->in, in) != NGX_OK) {
198
+ goto failed;
199
+ }
200
+ }
201
+
202
+ if (ctx->nomem) {
203
+
204
+ /* flush busy buffers */
205
+
206
+ if (ngx_http_next_body_filter(r, NULL) == NGX_ERROR) {
207
+ goto failed;
208
+ }
209
+
210
+ cl = NULL;
211
+
212
+ ngx_chain_update_chains(r->pool, &ctx->free, &ctx->busy, &cl,
213
+ (ngx_buf_tag_t) &ngx_http_gunzip_filter_module);
214
+ ctx->nomem = 0;
215
+ }
216
+
217
+ for ( ;; ) {
218
+
219
+ /* cycle while we can write to a client */
220
+
221
+ for ( ;; ) {
222
+
223
+ /* cycle while there is data to feed zlib and ... */
224
+
225
+ rc = ngx_http_gunzip_filter_add_data(r, ctx);
226
+
227
+ if (rc == NGX_DECLINED) {
228
+ break;
229
+ }
230
+
231
+ if (rc == NGX_AGAIN) {
232
+ continue;
233
+ }
234
+
235
+
236
+ /* ... there are buffers to write zlib output */
237
+
238
+ rc = ngx_http_gunzip_filter_get_buf(r, ctx);
239
+
240
+ if (rc == NGX_DECLINED) {
241
+ break;
242
+ }
243
+
244
+ if (rc == NGX_ERROR) {
245
+ goto failed;
246
+ }
247
+
248
+ rc = ngx_http_gunzip_filter_inflate(r, ctx);
249
+
250
+ if (rc == NGX_OK) {
251
+ break;
252
+ }
253
+
254
+ if (rc == NGX_ERROR) {
255
+ goto failed;
256
+ }
257
+
258
+ /* rc == NGX_AGAIN */
259
+ }
260
+
261
+ if (ctx->out == NULL) {
262
+ return ctx->busy ? NGX_AGAIN : NGX_OK;
263
+ }
264
+
265
+ rc = ngx_http_next_body_filter(r, ctx->out);
266
+
267
+ if (rc == NGX_ERROR) {
268
+ goto failed;
269
+ }
270
+
271
+ ngx_chain_update_chains(r->pool, &ctx->free, &ctx->busy, &ctx->out,
272
+ (ngx_buf_tag_t) &ngx_http_gunzip_filter_module);
273
+ ctx->last_out = &ctx->out;
274
+
275
+ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
276
+ "gunzip out: %p", ctx->out);
277
+
278
+ ctx->nomem = 0;
279
+
280
+ if (ctx->done) {
281
+ return rc;
282
+ }
283
+ }
284
+
285
+ /* unreachable */
286
+
287
+ failed:
288
+
289
+ ctx->done = 1;
290
+
291
+ return NGX_ERROR;
292
+ }
293
+
294
+
295
+ static ngx_int_t
296
+ ngx_http_gunzip_filter_inflate_start(ngx_http_request_t *r,
297
+ ngx_http_gunzip_ctx_t *ctx)
298
+ {
299
+ int rc;
300
+
301
+ ctx->zstream.next_in = Z_NULL;
302
+ ctx->zstream.avail_in = 0;
303
+
304
+ ctx->zstream.zalloc = ngx_http_gunzip_filter_alloc;
305
+ ctx->zstream.zfree = ngx_http_gunzip_filter_free;
306
+ ctx->zstream.opaque = ctx;
307
+
308
+ /* windowBits +16 to decode gzip, zlib 1.2.0.4+ */
309
+ rc = inflateInit2(&ctx->zstream, MAX_WBITS + 16);
310
+
311
+ if (rc != Z_OK) {
312
+ ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
313
+ "inflateInit2() failed: %d", rc);
314
+ return NGX_ERROR;
315
+ }
316
+
317
+ ctx->started = 1;
318
+
319
+ ctx->last_out = &ctx->out;
320
+ ctx->flush = Z_NO_FLUSH;
321
+
322
+ return NGX_OK;
323
+ }
324
+
325
+
326
+ static ngx_int_t
327
+ ngx_http_gunzip_filter_add_data(ngx_http_request_t *r,
328
+ ngx_http_gunzip_ctx_t *ctx)
329
+ {
330
+ if (ctx->zstream.avail_in || ctx->flush != Z_NO_FLUSH || ctx->redo) {
331
+ return NGX_OK;
332
+ }
333
+
334
+ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
335
+ "gunzip in: %p", ctx->in);
336
+
337
+ if (ctx->in == NULL) {
338
+ return NGX_DECLINED;
339
+ }
340
+
341
+ ctx->in_buf = ctx->in->buf;
342
+ ctx->in = ctx->in->next;
343
+
344
+ ctx->zstream.next_in = ctx->in_buf->pos;
345
+ ctx->zstream.avail_in = ctx->in_buf->last - ctx->in_buf->pos;
346
+
347
+ ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
348
+ "gunzip in_buf:%p ni:%p ai:%ud",
349
+ ctx->in_buf,
350
+ ctx->zstream.next_in, ctx->zstream.avail_in);
351
+
352
+ if (ctx->in_buf->last_buf || ctx->in_buf->last_in_chain) {
353
+ ctx->flush = Z_FINISH;
354
+
355
+ } else if (ctx->in_buf->flush) {
356
+ ctx->flush = Z_SYNC_FLUSH;
357
+
358
+ } else if (ctx->zstream.avail_in == 0) {
359
+ /* ctx->flush == Z_NO_FLUSH */
360
+ return NGX_AGAIN;
361
+ }
362
+
363
+ return NGX_OK;
364
+ }
365
+
366
+
367
+ static ngx_int_t
368
+ ngx_http_gunzip_filter_get_buf(ngx_http_request_t *r,
369
+ ngx_http_gunzip_ctx_t *ctx)
370
+ {
371
+ ngx_http_gunzip_conf_t *conf;
372
+
373
+ if (ctx->zstream.avail_out) {
374
+ return NGX_OK;
375
+ }
376
+
377
+ conf = ngx_http_get_module_loc_conf(r, ngx_http_gunzip_filter_module);
378
+
379
+ if (ctx->free) {
380
+ ctx->out_buf = ctx->free->buf;
381
+ ctx->free = ctx->free->next;
382
+
383
+ ctx->out_buf->flush = 0;
384
+
385
+ } else if (ctx->bufs < conf->bufs.num) {
386
+
387
+ ctx->out_buf = ngx_create_temp_buf(r->pool, conf->bufs.size);
388
+ if (ctx->out_buf == NULL) {
389
+ return NGX_ERROR;
390
+ }
391
+
392
+ ctx->out_buf->tag = (ngx_buf_tag_t) &ngx_http_gunzip_filter_module;
393
+ ctx->out_buf->recycled = 1;
394
+ ctx->bufs++;
395
+
396
+ } else {
397
+ ctx->nomem = 1;
398
+ return NGX_DECLINED;
399
+ }
400
+
401
+ ctx->zstream.next_out = ctx->out_buf->pos;
402
+ ctx->zstream.avail_out = conf->bufs.size;
403
+
404
+ return NGX_OK;
405
+ }
406
+
407
+
408
+ static ngx_int_t
409
+ ngx_http_gunzip_filter_inflate(ngx_http_request_t *r,
410
+ ngx_http_gunzip_ctx_t *ctx)
411
+ {
412
+ int rc;
413
+ ngx_buf_t *b;
414
+ ngx_chain_t *cl;
415
+
416
+ ngx_log_debug6(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
417
+ "inflate in: ni:%p no:%p ai:%ud ao:%ud fl:%d redo:%d",
418
+ ctx->zstream.next_in, ctx->zstream.next_out,
419
+ ctx->zstream.avail_in, ctx->zstream.avail_out,
420
+ ctx->flush, ctx->redo);
421
+
422
+ rc = inflate(&ctx->zstream, ctx->flush);
423
+
424
+ if (rc != Z_OK && rc != Z_STREAM_END && rc != Z_BUF_ERROR) {
425
+ ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
426
+ "inflate() failed: %d, %d", ctx->flush, rc);
427
+ return NGX_ERROR;
428
+ }
429
+
430
+ ngx_log_debug5(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
431
+ "inflate out: ni:%p no:%p ai:%ud ao:%ud rc:%d",
432
+ ctx->zstream.next_in, ctx->zstream.next_out,
433
+ ctx->zstream.avail_in, ctx->zstream.avail_out,
434
+ rc);
435
+
436
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
437
+ "gunzip in_buf:%p pos:%p",
438
+ ctx->in_buf, ctx->in_buf->pos);
439
+
440
+ if (ctx->zstream.next_in) {
441
+ ctx->in_buf->pos = ctx->zstream.next_in;
442
+
443
+ if (ctx->zstream.avail_in == 0) {
444
+ ctx->zstream.next_in = NULL;
445
+ }
446
+ }
447
+
448
+ ctx->out_buf->last = ctx->zstream.next_out;
449
+
450
+ if (ctx->zstream.avail_out == 0) {
451
+
452
+ /* zlib wants to output some more data */
453
+
454
+ cl = ngx_alloc_chain_link(r->pool);
455
+ if (cl == NULL) {
456
+ return NGX_ERROR;
457
+ }
458
+
459
+ cl->buf = ctx->out_buf;
460
+ cl->next = NULL;
461
+ *ctx->last_out = cl;
462
+ ctx->last_out = &cl->next;
463
+
464
+ ctx->redo = 1;
465
+
466
+ return NGX_AGAIN;
467
+ }
468
+
469
+ ctx->redo = 0;
470
+
471
+ if (ctx->flush == Z_SYNC_FLUSH) {
472
+
473
+ ctx->flush = Z_NO_FLUSH;
474
+
475
+ cl = ngx_alloc_chain_link(r->pool);
476
+ if (cl == NULL) {
477
+ return NGX_ERROR;
478
+ }
479
+
480
+ b = ctx->out_buf;
481
+
482
+ if (ngx_buf_size(b) == 0) {
483
+
484
+ b = ngx_calloc_buf(ctx->request->pool);
485
+ if (b == NULL) {
486
+ return NGX_ERROR;
487
+ }
488
+
489
+ } else {
490
+ ctx->zstream.avail_out = 0;
491
+ }
492
+
493
+ b->flush = 1;
494
+
495
+ cl->buf = b;
496
+ cl->next = NULL;
497
+ *ctx->last_out = cl;
498
+ ctx->last_out = &cl->next;
499
+
500
+ return NGX_OK;
501
+ }
502
+
503
+ if (rc == Z_STREAM_END && ctx->flush == Z_FINISH
504
+ && ctx->zstream.avail_in == 0)
505
+ {
506
+
507
+ if (ngx_http_gunzip_filter_inflate_end(r, ctx) != NGX_OK) {
508
+ return NGX_ERROR;
509
+ }
510
+
511
+ return NGX_OK;
512
+ }
513
+
514
+ if (rc == Z_STREAM_END && ctx->zstream.avail_in > 0) {
515
+
516
+ rc = inflateReset(&ctx->zstream);
517
+
518
+ if (rc != Z_OK) {
519
+ ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
520
+ "inflateReset() failed: %d", rc);
521
+ return NGX_ERROR;
522
+ }
523
+
524
+ ctx->redo = 1;
525
+
526
+ return NGX_AGAIN;
527
+ }
528
+
529
+ if (ctx->in == NULL) {
530
+
531
+ b = ctx->out_buf;
532
+
533
+ if (ngx_buf_size(b) == 0) {
534
+ return NGX_OK;
535
+ }
536
+
537
+ cl = ngx_alloc_chain_link(r->pool);
538
+ if (cl == NULL) {
539
+ return NGX_ERROR;
540
+ }
541
+
542
+ ctx->zstream.avail_out = 0;
543
+
544
+ cl->buf = b;
545
+ cl->next = NULL;
546
+ *ctx->last_out = cl;
547
+ ctx->last_out = &cl->next;
548
+
549
+ return NGX_OK;
550
+ }
551
+
552
+ return NGX_AGAIN;
553
+ }
554
+
555
+
556
+ static ngx_int_t
557
+ ngx_http_gunzip_filter_inflate_end(ngx_http_request_t *r,
558
+ ngx_http_gunzip_ctx_t *ctx)
559
+ {
560
+ int rc;
561
+ ngx_buf_t *b;
562
+ ngx_chain_t *cl;
563
+
564
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
565
+ "gunzip inflate end");
566
+
567
+ rc = inflateEnd(&ctx->zstream);
568
+
569
+ if (rc != Z_OK) {
570
+ ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
571
+ "inflateEnd() failed: %d", rc);
572
+ return NGX_ERROR;
573
+ }
574
+
575
+ b = ctx->out_buf;
576
+
577
+ if (ngx_buf_size(b) == 0) {
578
+
579
+ b = ngx_calloc_buf(ctx->request->pool);
580
+ if (b == NULL) {
581
+ return NGX_ERROR;
582
+ }
583
+ }
584
+
585
+ cl = ngx_alloc_chain_link(r->pool);
586
+ if (cl == NULL) {
587
+ return NGX_ERROR;
588
+ }
589
+
590
+ cl->buf = b;
591
+ cl->next = NULL;
592
+ *ctx->last_out = cl;
593
+ ctx->last_out = &cl->next;
594
+
595
+ b->last_buf = (r == r->main) ? 1 : 0;
596
+ b->last_in_chain = 1;
597
+ b->sync = 1;
598
+
599
+ ctx->done = 1;
600
+
601
+ return NGX_OK;
602
+ }
603
+
604
+
605
+ static void *
606
+ ngx_http_gunzip_filter_alloc(void *opaque, u_int items, u_int size)
607
+ {
608
+ ngx_http_gunzip_ctx_t *ctx = opaque;
609
+
610
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, ctx->request->connection->log, 0,
611
+ "gunzip alloc: n:%ud s:%ud",
612
+ items, size);
613
+
614
+ return ngx_palloc(ctx->request->pool, items * size);
615
+ }
616
+
617
+
618
+ static void
619
+ ngx_http_gunzip_filter_free(void *opaque, void *address)
620
+ {
621
+ #if 0
622
+ ngx_http_gunzip_ctx_t *ctx = opaque;
623
+
624
+ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ctx->request->connection->log, 0,
625
+ "gunzip free: %p", address);
626
+ #endif
627
+ }
628
+
629
+
630
+ static void *
631
+ ngx_http_gunzip_create_conf(ngx_conf_t *cf)
632
+ {
633
+ ngx_http_gunzip_conf_t *conf;
634
+
635
+ conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_gunzip_conf_t));
636
+ if (conf == NULL) {
637
+ return NULL;
638
+ }
639
+
640
+ /*
641
+ * set by ngx_pcalloc():
642
+ *
643
+ * conf->bufs.num = 0;
644
+ */
645
+
646
+ conf->enable = NGX_CONF_UNSET;
647
+
648
+ return conf;
649
+ }
650
+
651
+
652
+ static char *
653
+ ngx_http_gunzip_merge_conf(ngx_conf_t *cf, void *parent, void *child)
654
+ {
655
+ ngx_http_gunzip_conf_t *prev = parent;
656
+ ngx_http_gunzip_conf_t *conf = child;
657
+
658
+ ngx_conf_merge_value(conf->enable, prev->enable, 0);
659
+
660
+ ngx_conf_merge_bufs_value(conf->bufs, prev->bufs,
661
+ (128 * 1024) / ngx_pagesize, ngx_pagesize);
662
+
663
+ return NGX_CONF_OK;
664
+ }
665
+
666
+
667
+ static ngx_int_t
668
+ ngx_http_gunzip_filter_init(ngx_conf_t *cf)
669
+ {
670
+ ngx_http_next_header_filter = ngx_http_top_header_filter;
671
+ ngx_http_top_header_filter = ngx_http_gunzip_header_filter;
672
+
673
+ ngx_http_next_body_filter = ngx_http_top_body_filter;
674
+ ngx_http_top_body_filter = ngx_http_gunzip_body_filter;
675
+
676
+ return NGX_OK;
677
+ }