nginxtra 1.2.6.8 → 1.2.7.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) 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 +72 -0
  5. data/vendor/nginx/CHANGES.ru +76 -0
  6. data/vendor/nginx/LICENSE +2 -2
  7. data/vendor/nginx/auto/cc/msvc +0 -3
  8. data/vendor/nginx/auto/lib/geoip/conf +17 -2
  9. data/vendor/nginx/auto/lib/libgd/conf +1 -1
  10. data/vendor/nginx/auto/lib/pcre/conf +1 -0
  11. data/vendor/nginx/auto/lib/perl/make +1 -3
  12. data/vendor/nginx/auto/lib/zlib/conf +4 -1
  13. data/vendor/nginx/man/nginx.8 +2 -2
  14. data/vendor/nginx/src/core/nginx.h +2 -2
  15. data/vendor/nginx/src/core/ngx_conf_file.c +4 -19
  16. data/vendor/nginx/src/core/ngx_conf_file.h +1 -10
  17. data/vendor/nginx/src/core/ngx_cycle.c +2 -19
  18. data/vendor/nginx/src/core/ngx_file.c +4 -4
  19. data/vendor/nginx/src/core/ngx_inet.c +1 -1
  20. data/vendor/nginx/src/core/ngx_inet.h +1 -1
  21. data/vendor/nginx/src/core/ngx_radix_tree.c +202 -5
  22. data/vendor/nginx/src/core/ngx_radix_tree.h +9 -0
  23. data/vendor/nginx/src/event/modules/ngx_poll_module.c +2 -2
  24. data/vendor/nginx/src/event/ngx_event.c +4 -0
  25. data/vendor/nginx/src/event/ngx_event_openssl.c +27 -13
  26. data/vendor/nginx/src/http/modules/ngx_http_auth_basic_module.c +38 -49
  27. data/vendor/nginx/src/http/modules/ngx_http_fastcgi_module.c +44 -59
  28. data/vendor/nginx/src/http/modules/ngx_http_geo_module.c +310 -103
  29. data/vendor/nginx/src/http/modules/ngx_http_geoip_module.c +145 -15
  30. data/vendor/nginx/src/http/modules/ngx_http_gzip_filter_module.c +5 -1
  31. data/vendor/nginx/src/http/modules/ngx_http_headers_filter_module.c +1 -0
  32. data/vendor/nginx/src/http/modules/ngx_http_image_filter_module.c +27 -13
  33. data/vendor/nginx/src/http/modules/ngx_http_log_module.c +378 -40
  34. data/vendor/nginx/src/http/modules/ngx_http_map_module.c +7 -0
  35. data/vendor/nginx/src/http/modules/ngx_http_proxy_module.c +9 -7
  36. data/vendor/nginx/src/http/modules/ngx_http_scgi_module.c +1 -1
  37. data/vendor/nginx/src/http/modules/ngx_http_secure_link_module.c +15 -2
  38. data/vendor/nginx/src/http/modules/ngx_http_split_clients_module.c +1 -1
  39. data/vendor/nginx/src/http/modules/ngx_http_sub_filter_module.c +2 -2
  40. data/vendor/nginx/src/http/modules/ngx_http_upstream_keepalive_module.c +4 -0
  41. data/vendor/nginx/src/http/modules/ngx_http_upstream_least_conn_module.c +3 -1
  42. data/vendor/nginx/src/http/modules/ngx_http_uwsgi_module.c +1 -1
  43. data/vendor/nginx/src/http/modules/ngx_http_xslt_filter_module.c +2 -2
  44. data/vendor/nginx/src/http/modules/perl/Makefile.PL +3 -14
  45. data/vendor/nginx/src/http/modules/perl/nginx.pm +2 -2
  46. data/vendor/nginx/src/http/ngx_http_core_module.c +2 -1
  47. data/vendor/nginx/src/http/ngx_http_script.c +3 -7
  48. data/vendor/nginx/src/http/ngx_http_upstream.c +9 -0
  49. data/vendor/nginx/src/http/ngx_http_upstream_round_robin.c +3 -1
  50. data/vendor/nginx/src/http/ngx_http_variables.c +114 -0
  51. data/vendor/nginx/src/http/ngx_http_write_filter_module.c +1 -1
  52. data/vendor/nginx/src/os/unix/ngx_files.c +1 -1
  53. data/vendor/nginx/src/os/unix/ngx_user.c +13 -14
  54. metadata +2 -2
@@ -13,12 +13,22 @@
13
13
  #include <GeoIPCity.h>
14
14
 
15
15
 
16
+ #define NGX_GEOIP_COUNTRY_CODE 0
17
+ #define NGX_GEOIP_COUNTRY_CODE3 1
18
+ #define NGX_GEOIP_COUNTRY_NAME 2
19
+
20
+
16
21
  typedef struct {
17
22
  GeoIP *country;
18
23
  GeoIP *org;
19
24
  GeoIP *city;
20
25
  ngx_array_t *proxies; /* array of ngx_cidr_t */
21
26
  ngx_flag_t proxy_recursive;
27
+ #if (NGX_HAVE_GEOIP_V6)
28
+ unsigned country_v6:1;
29
+ unsigned org_v6:1;
30
+ unsigned city_v6:1;
31
+ #endif
22
32
  } ngx_http_geoip_conf_t;
23
33
 
24
34
 
@@ -28,10 +38,32 @@ typedef struct {
28
38
  } ngx_http_geoip_var_t;
29
39
 
30
40
 
31
- typedef char *(*ngx_http_geoip_variable_handler_pt)(GeoIP *, u_long addr);
41
+ typedef const char *(*ngx_http_geoip_variable_handler_pt)(GeoIP *,
42
+ u_long addr);
43
+
44
+
45
+ ngx_http_geoip_variable_handler_pt ngx_http_geoip_country_functions[] = {
46
+ GeoIP_country_code_by_ipnum,
47
+ GeoIP_country_code3_by_ipnum,
48
+ GeoIP_country_name_by_ipnum,
49
+ };
50
+
51
+
52
+ #if (NGX_HAVE_GEOIP_V6)
53
+
54
+ typedef const char *(*ngx_http_geoip_variable_handler_v6_pt)(GeoIP *,
55
+ geoipv6_t addr);
56
+
57
+
58
+ ngx_http_geoip_variable_handler_v6_pt ngx_http_geoip_country_v6_functions[] = {
59
+ GeoIP_country_code_by_ipnum_v6,
60
+ GeoIP_country_code3_by_ipnum_v6,
61
+ GeoIP_country_name_by_ipnum_v6,
62
+ };
63
+
64
+ #endif
65
+
32
66
 
33
- static u_long ngx_http_geoip_addr(ngx_http_request_t *r,
34
- ngx_http_geoip_conf_t *gcf);
35
67
  static ngx_int_t ngx_http_geoip_country_variable(ngx_http_request_t *r,
36
68
  ngx_http_variable_value_t *v, uintptr_t data);
37
69
  static ngx_int_t ngx_http_geoip_org_variable(ngx_http_request_t *r,
@@ -138,19 +170,19 @@ static ngx_http_variable_t ngx_http_geoip_vars[] = {
138
170
 
139
171
  { ngx_string("geoip_country_code"), NULL,
140
172
  ngx_http_geoip_country_variable,
141
- (uintptr_t) GeoIP_country_code_by_ipnum, 0, 0 },
173
+ NGX_GEOIP_COUNTRY_CODE, 0, 0 },
142
174
 
143
175
  { ngx_string("geoip_country_code3"), NULL,
144
176
  ngx_http_geoip_country_variable,
145
- (uintptr_t) GeoIP_country_code3_by_ipnum, 0, 0 },
177
+ NGX_GEOIP_COUNTRY_CODE3, 0, 0 },
146
178
 
147
179
  { ngx_string("geoip_country_name"), NULL,
148
180
  ngx_http_geoip_country_variable,
149
- (uintptr_t) GeoIP_country_name_by_ipnum, 0, 0 },
181
+ NGX_GEOIP_COUNTRY_NAME, 0, 0 },
150
182
 
151
183
  { ngx_string("geoip_org"), NULL,
152
184
  ngx_http_geoip_org_variable,
153
- (uintptr_t) GeoIP_name_by_ipnum, 0, 0 },
185
+ 0, 0, 0 },
154
186
 
155
187
  { ngx_string("geoip_city_continent_code"), NULL,
156
188
  ngx_http_geoip_city_variable,
@@ -255,12 +287,68 @@ ngx_http_geoip_addr(ngx_http_request_t *r, ngx_http_geoip_conf_t *gcf)
255
287
  }
256
288
 
257
289
 
290
+ #if (NGX_HAVE_GEOIP_V6)
291
+
292
+ static geoipv6_t
293
+ ngx_http_geoip_addr_v6(ngx_http_request_t *r, ngx_http_geoip_conf_t *gcf)
294
+ {
295
+ ngx_addr_t addr;
296
+ ngx_table_elt_t *xfwd;
297
+ in_addr_t addr4;
298
+ struct in6_addr addr6;
299
+ struct sockaddr_in *sin;
300
+ struct sockaddr_in6 *sin6;
301
+
302
+ addr.sockaddr = r->connection->sockaddr;
303
+ addr.socklen = r->connection->socklen;
304
+ /* addr.name = r->connection->addr_text; */
305
+
306
+ xfwd = r->headers_in.x_forwarded_for;
307
+
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);
312
+ }
313
+
314
+ switch (addr.sockaddr->sa_family) {
315
+
316
+ case AF_INET:
317
+ /* Produce IPv4-mapped IPv6 address. */
318
+ sin = (struct sockaddr_in *) addr.sockaddr;
319
+ addr4 = ntohl(sin->sin_addr.s_addr);
320
+
321
+ ngx_memzero(&addr6, sizeof(struct in6_addr));
322
+ addr6.s6_addr[10] = 0xff;
323
+ addr6.s6_addr[11] = 0xff;
324
+ addr6.s6_addr[12] = addr4 >> 24;
325
+ addr6.s6_addr[13] = addr4 >> 16;
326
+ addr6.s6_addr[14] = addr4 >> 8;
327
+ addr6.s6_addr[15] = addr4;
328
+ return addr6;
329
+
330
+ case AF_INET6:
331
+ sin6 = (struct sockaddr_in6 *) addr.sockaddr;
332
+ return sin6->sin6_addr;
333
+
334
+ default:
335
+ return in6addr_any;
336
+ }
337
+ }
338
+
339
+ #endif
340
+
341
+
258
342
  static ngx_int_t
259
343
  ngx_http_geoip_country_variable(ngx_http_request_t *r,
260
344
  ngx_http_variable_value_t *v, uintptr_t data)
261
345
  {
262
- ngx_http_geoip_variable_handler_pt handler =
263
- (ngx_http_geoip_variable_handler_pt) data;
346
+ ngx_http_geoip_variable_handler_pt handler =
347
+ ngx_http_geoip_country_functions[data];
348
+ #if (NGX_HAVE_GEOIP_V6)
349
+ ngx_http_geoip_variable_handler_v6_pt handler_v6 =
350
+ ngx_http_geoip_country_v6_functions[data];
351
+ #endif
264
352
 
265
353
  const char *val;
266
354
  ngx_http_geoip_conf_t *gcf;
@@ -271,7 +359,13 @@ ngx_http_geoip_country_variable(ngx_http_request_t *r,
271
359
  goto not_found;
272
360
  }
273
361
 
362
+ #if (NGX_HAVE_GEOIP_V6)
363
+ val = gcf->country_v6
364
+ ? handler_v6(gcf->country, ngx_http_geoip_addr_v6(r, gcf))
365
+ : handler(gcf->country, ngx_http_geoip_addr(r, gcf));
366
+ #else
274
367
  val = handler(gcf->country, ngx_http_geoip_addr(r, gcf));
368
+ #endif
275
369
 
276
370
  if (val == NULL) {
277
371
  goto not_found;
@@ -297,9 +391,6 @@ static ngx_int_t
297
391
  ngx_http_geoip_org_variable(ngx_http_request_t *r,
298
392
  ngx_http_variable_value_t *v, uintptr_t data)
299
393
  {
300
- ngx_http_geoip_variable_handler_pt handler =
301
- (ngx_http_geoip_variable_handler_pt) data;
302
-
303
394
  size_t len;
304
395
  char *val;
305
396
  ngx_http_geoip_conf_t *gcf;
@@ -310,7 +401,15 @@ ngx_http_geoip_org_variable(ngx_http_request_t *r,
310
401
  goto not_found;
311
402
  }
312
403
 
313
- val = handler(gcf->org, ngx_http_geoip_addr(r, gcf));
404
+ #if (NGX_HAVE_GEOIP_V6)
405
+ val = gcf->org_v6
406
+ ? GeoIP_name_by_ipnum_v6(gcf->org,
407
+ ngx_http_geoip_addr_v6(r, gcf))
408
+ : GeoIP_name_by_ipnum(gcf->org,
409
+ ngx_http_geoip_addr(r, gcf));
410
+ #else
411
+ val = GeoIP_name_by_ipnum(gcf->org, ngx_http_geoip_addr(r, gcf));
412
+ #endif
314
413
 
315
414
  if (val == NULL) {
316
415
  goto not_found;
@@ -500,7 +599,15 @@ ngx_http_geoip_get_city_record(ngx_http_request_t *r)
500
599
  gcf = ngx_http_get_module_main_conf(r, ngx_http_geoip_module);
501
600
 
502
601
  if (gcf->city) {
602
+ #if (NGX_HAVE_GEOIP_V6)
603
+ return gcf->city_v6
604
+ ? GeoIP_record_by_ipnum_v6(gcf->city,
605
+ ngx_http_geoip_addr_v6(r, gcf))
606
+ : GeoIP_record_by_ipnum(gcf->city,
607
+ ngx_http_geoip_addr(r, gcf));
608
+ #else
503
609
  return GeoIP_record_by_ipnum(gcf->city, ngx_http_geoip_addr(r, gcf));
610
+ #endif
504
611
  }
505
612
 
506
613
  return NULL;
@@ -598,11 +705,16 @@ ngx_http_geoip_country(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
598
705
  switch (gcf->country->databaseType) {
599
706
 
600
707
  case GEOIP_COUNTRY_EDITION:
601
- case GEOIP_PROXY_EDITION:
602
- case GEOIP_NETSPEED_EDITION:
603
708
 
604
709
  return NGX_CONF_OK;
605
710
 
711
+ #if (NGX_HAVE_GEOIP_V6)
712
+ case GEOIP_COUNTRY_EDITION_V6:
713
+
714
+ gcf->country_v6 = 1;
715
+ return NGX_CONF_OK;
716
+ #endif
717
+
606
718
  default:
607
719
  ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
608
720
  "invalid GeoIP database \"%V\" type:%d",
@@ -654,6 +766,16 @@ ngx_http_geoip_org(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
654
766
 
655
767
  return NGX_CONF_OK;
656
768
 
769
+ #if (NGX_HAVE_GEOIP_V6)
770
+ case GEOIP_ISP_EDITION_V6:
771
+ case GEOIP_ORG_EDITION_V6:
772
+ case GEOIP_DOMAIN_EDITION_V6:
773
+ case GEOIP_ASNUM_EDITION_V6:
774
+
775
+ gcf->org_v6 = 1;
776
+ return NGX_CONF_OK;
777
+ #endif
778
+
657
779
  default:
658
780
  ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
659
781
  "invalid GeoIP database \"%V\" type:%d",
@@ -703,6 +825,14 @@ ngx_http_geoip_city(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
703
825
 
704
826
  return NGX_CONF_OK;
705
827
 
828
+ #if (NGX_HAVE_GEOIP_V6)
829
+ case GEOIP_CITY_EDITION_REV0_V6:
830
+ case GEOIP_CITY_EDITION_REV1_V6:
831
+
832
+ gcf->city_v6 = 1;
833
+ return NGX_CONF_OK;
834
+ #endif
835
+
706
836
  default:
707
837
  ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
708
838
  "invalid GeoIP City database \"%V\" type:%d",
@@ -320,7 +320,7 @@ ngx_http_gzip_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
320
320
 
321
321
  ctx = ngx_http_get_module_ctx(r, ngx_http_gzip_filter_module);
322
322
 
323
- if (ctx == NULL || ctx->done) {
323
+ if (ctx == NULL || ctx->done || r->header_only) {
324
324
  return ngx_http_next_body_filter(r, in);
325
325
  }
326
326
 
@@ -497,6 +497,10 @@ ngx_http_gzip_filter_memory(ngx_http_request_t *r, ngx_http_gzip_ctx_t *ctx)
497
497
  wbits--;
498
498
  memlevel--;
499
499
  }
500
+
501
+ if (memlevel < 1) {
502
+ memlevel = 1;
503
+ }
500
504
  }
501
505
 
502
506
  ctx->wbits = wbits;
@@ -149,6 +149,7 @@ ngx_http_headers_filter(ngx_http_request_t *r)
149
149
  if ((conf->expires == NGX_HTTP_EXPIRES_OFF && conf->headers == NULL)
150
150
  || r != r->main
151
151
  || (r->headers_out.status != NGX_HTTP_OK
152
+ && r->headers_out.status != NGX_HTTP_CREATED
152
153
  && r->headers_out.status != NGX_HTTP_NO_CONTENT
153
154
  && r->headers_out.status != NGX_HTTP_PARTIAL_CONTENT
154
155
  && r->headers_out.status != NGX_HTTP_MOVED_PERMANENTLY
@@ -1169,10 +1169,22 @@ ngx_http_image_filter_create_conf(ngx_conf_t *cf)
1169
1169
  return NULL;
1170
1170
  }
1171
1171
 
1172
+ /*
1173
+ * set by ngx_pcalloc():
1174
+ *
1175
+ * conf->width = 0;
1176
+ * conf->height = 0;
1177
+ * conf->angle = 0;
1178
+ * conf->wcv = NULL;
1179
+ * conf->hcv = NULL;
1180
+ * conf->acv = NULL;
1181
+ * conf->jqcv = NULL;
1182
+ * conf->shcv = NULL;
1183
+ */
1184
+
1172
1185
  conf->filter = NGX_CONF_UNSET_UINT;
1173
1186
  conf->jpeg_quality = NGX_CONF_UNSET_UINT;
1174
1187
  conf->sharpen = NGX_CONF_UNSET_UINT;
1175
- conf->angle = NGX_CONF_UNSET_UINT;
1176
1188
  conf->transparency = NGX_CONF_UNSET;
1177
1189
  conf->buffer_size = NGX_CONF_UNSET_SIZE;
1178
1190
 
@@ -1195,27 +1207,29 @@ ngx_http_image_filter_merge_conf(ngx_conf_t *cf, void *parent, void *child)
1195
1207
  conf->filter = prev->filter;
1196
1208
  conf->width = prev->width;
1197
1209
  conf->height = prev->height;
1210
+ conf->angle = prev->angle;
1198
1211
  conf->wcv = prev->wcv;
1199
1212
  conf->hcv = prev->hcv;
1213
+ conf->acv = prev->acv;
1200
1214
  }
1201
1215
  }
1202
1216
 
1203
- /* 75 is libjpeg default quality */
1204
- ngx_conf_merge_uint_value(conf->jpeg_quality, prev->jpeg_quality, 75);
1205
-
1206
- if (conf->jqcv == NULL) {
1207
- conf->jqcv = prev->jqcv;
1208
- }
1217
+ if (conf->jpeg_quality == NGX_CONF_UNSET_UINT) {
1209
1218
 
1210
- ngx_conf_merge_uint_value(conf->sharpen, prev->sharpen, 0);
1219
+ /* 75 is libjpeg default quality */
1220
+ ngx_conf_merge_uint_value(conf->jpeg_quality, prev->jpeg_quality, 75);
1211
1221
 
1212
- if (conf->shcv == NULL) {
1213
- conf->shcv = prev->shcv;
1222
+ if (conf->jqcv == NULL) {
1223
+ conf->jqcv = prev->jqcv;
1224
+ }
1214
1225
  }
1215
1226
 
1216
- ngx_conf_merge_uint_value(conf->angle, prev->angle, 0);
1217
- if (conf->acv == NULL) {
1218
- conf->acv = prev->acv;
1227
+ if (conf->sharpen == NGX_CONF_UNSET_UINT) {
1228
+ ngx_conf_merge_uint_value(conf->sharpen, prev->sharpen, 0);
1229
+
1230
+ if (conf->shcv == NULL) {
1231
+ conf->shcv = prev->shcv;
1232
+ }
1219
1233
  }
1220
1234
 
1221
1235
  ngx_conf_merge_value(conf->transparency, prev->transparency, 1);
@@ -9,6 +9,10 @@
9
9
  #include <ngx_core.h>
10
10
  #include <ngx_http.h>
11
11
 
12
+ #if (NGX_ZLIB)
13
+ #include <zlib.h>
14
+ #endif
15
+
12
16
 
13
17
  typedef struct ngx_http_log_op_s ngx_http_log_op_t;
14
18
 
@@ -40,6 +44,17 @@ typedef struct {
40
44
  } ngx_http_log_main_conf_t;
41
45
 
42
46
 
47
+ typedef struct {
48
+ u_char *start;
49
+ u_char *pos;
50
+ u_char *last;
51
+
52
+ ngx_event_t *event;
53
+ ngx_msec_t flush;
54
+ ngx_int_t gzip;
55
+ } ngx_http_log_buf_t;
56
+
57
+
43
58
  typedef struct {
44
59
  ngx_array_t *lengths;
45
60
  ngx_array_t *values;
@@ -78,6 +93,17 @@ static void ngx_http_log_write(ngx_http_request_t *r, ngx_http_log_t *log,
78
93
  static ssize_t ngx_http_log_script_write(ngx_http_request_t *r,
79
94
  ngx_http_log_script_t *script, u_char **name, u_char *buf, size_t len);
80
95
 
96
+ #if (NGX_ZLIB)
97
+ static ssize_t ngx_http_log_gzip(ngx_fd_t fd, u_char *buf, size_t len,
98
+ ngx_int_t level, ngx_log_t *log);
99
+
100
+ static void *ngx_http_log_gzip_alloc(void *opaque, u_int items, u_int size);
101
+ static void ngx_http_log_gzip_free(void *opaque, void *address);
102
+ #endif
103
+
104
+ static void ngx_http_log_flush(ngx_open_file_t *file, ngx_log_t *log);
105
+ static void ngx_http_log_flush_handler(ngx_event_t *ev);
106
+
81
107
  static u_char *ngx_http_log_pipe(ngx_http_request_t *r, u_char *buf,
82
108
  ngx_http_log_op_t *op);
83
109
  static u_char *ngx_http_log_time(ngx_http_request_t *r, u_char *buf,
@@ -132,7 +158,7 @@ static ngx_command_t ngx_http_log_commands[] = {
132
158
 
133
159
  { ngx_string("access_log"),
134
160
  NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
135
- |NGX_HTTP_LMT_CONF|NGX_CONF_TAKE123,
161
+ |NGX_HTTP_LMT_CONF|NGX_CONF_1MORE,
136
162
  ngx_http_log_set_log,
137
163
  NGX_HTTP_LOC_CONF_OFFSET,
138
164
  0,
@@ -216,8 +242,8 @@ ngx_http_log_handler(ngx_http_request_t *r)
216
242
  size_t len;
217
243
  ngx_uint_t i, l;
218
244
  ngx_http_log_t *log;
219
- ngx_open_file_t *file;
220
245
  ngx_http_log_op_t *op;
246
+ ngx_http_log_buf_t *buffer;
221
247
  ngx_http_log_loc_conf_t *lcf;
222
248
 
223
249
  ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
@@ -258,21 +284,25 @@ ngx_http_log_handler(ngx_http_request_t *r)
258
284
 
259
285
  len += NGX_LINEFEED_SIZE;
260
286
 
261
- file = log[l].file;
287
+ buffer = log[l].file ? log[l].file->data : NULL;
262
288
 
263
- if (file && file->buffer) {
289
+ if (buffer) {
264
290
 
265
- if (len > (size_t) (file->last - file->pos)) {
291
+ if (len > (size_t) (buffer->last - buffer->pos)) {
266
292
 
267
- ngx_http_log_write(r, &log[l], file->buffer,
268
- file->pos - file->buffer);
293
+ ngx_http_log_write(r, &log[l], buffer->start,
294
+ buffer->pos - buffer->start);
269
295
 
270
- file->pos = file->buffer;
296
+ buffer->pos = buffer->start;
271
297
  }
272
298
 
273
- if (len <= (size_t) (file->last - file->pos)) {
299
+ if (len <= (size_t) (buffer->last - buffer->pos)) {
274
300
 
275
- p = file->pos;
301
+ p = buffer->pos;
302
+
303
+ if (buffer->event && p == buffer->start) {
304
+ ngx_add_timer(buffer->event, buffer->flush);
305
+ }
276
306
 
277
307
  for (i = 0; i < log[l].format->ops->nelts; i++) {
278
308
  p = op[i].run(r, p, &op[i]);
@@ -280,10 +310,14 @@ ngx_http_log_handler(ngx_http_request_t *r)
280
310
 
281
311
  ngx_linefeed(p);
282
312
 
283
- file->pos = p;
313
+ buffer->pos = p;
284
314
 
285
315
  continue;
286
316
  }
317
+
318
+ if (buffer->event && buffer->event->timer_set) {
319
+ ngx_del_timer(buffer->event);
320
+ }
287
321
  }
288
322
 
289
323
  line = ngx_pnalloc(r->pool, len);
@@ -310,14 +344,29 @@ static void
310
344
  ngx_http_log_write(ngx_http_request_t *r, ngx_http_log_t *log, u_char *buf,
311
345
  size_t len)
312
346
  {
313
- u_char *name;
314
- time_t now;
315
- ssize_t n;
316
- ngx_err_t err;
347
+ u_char *name;
348
+ time_t now;
349
+ ssize_t n;
350
+ ngx_err_t err;
351
+ #if (NGX_ZLIB)
352
+ ngx_http_log_buf_t *buffer;
353
+ #endif
317
354
 
318
355
  if (log->script == NULL) {
319
356
  name = log->file->name.data;
357
+
358
+ #if (NGX_ZLIB)
359
+ buffer = log->file->data;
360
+
361
+ if (buffer && buffer->gzip) {
362
+ n = ngx_http_log_gzip(log->file->fd, buf, len, buffer->gzip,
363
+ r->connection->log);
364
+ } else {
365
+ n = ngx_write_fd(log->file->fd, buf, len);
366
+ }
367
+ #else
320
368
  n = ngx_write_fd(log->file->fd, buf, len);
369
+ #endif
321
370
 
322
371
  } else {
323
372
  name = NULL;
@@ -465,6 +514,194 @@ ngx_http_log_script_write(ngx_http_request_t *r, ngx_http_log_script_t *script,
465
514
  }
466
515
 
467
516
 
517
+ #if (NGX_ZLIB)
518
+
519
+ static ssize_t
520
+ ngx_http_log_gzip(ngx_fd_t fd, u_char *buf, size_t len, ngx_int_t level,
521
+ ngx_log_t *log)
522
+ {
523
+ int rc, wbits, memlevel;
524
+ u_char *out;
525
+ size_t size;
526
+ ssize_t n;
527
+ z_stream zstream;
528
+ ngx_err_t err;
529
+ ngx_pool_t *pool;
530
+
531
+ wbits = MAX_WBITS;
532
+ memlevel = MAX_MEM_LEVEL - 1;
533
+
534
+ while ((ssize_t) len < ((1 << (wbits - 1)) - 262)) {
535
+ wbits--;
536
+ memlevel--;
537
+ }
538
+
539
+ /*
540
+ * This is a formula from deflateBound() for conservative upper bound of
541
+ * compressed data plus 18 bytes of gzip wrapper.
542
+ */
543
+
544
+ size = len + ((len + 7) >> 3) + ((len + 63) >> 6) + 5 + 18;
545
+
546
+ ngx_memzero(&zstream, sizeof(z_stream));
547
+
548
+ pool = ngx_create_pool(256, log);
549
+ if (pool == NULL) {
550
+ /* simulate successful logging */
551
+ return len;
552
+ }
553
+
554
+ pool->log = log;
555
+
556
+ zstream.zalloc = ngx_http_log_gzip_alloc;
557
+ zstream.zfree = ngx_http_log_gzip_free;
558
+ zstream.opaque = pool;
559
+
560
+ out = ngx_pnalloc(pool, size);
561
+ if (out == NULL) {
562
+ goto done;
563
+ }
564
+
565
+ zstream.next_in = buf;
566
+ zstream.avail_in = len;
567
+ zstream.next_out = out;
568
+ zstream.avail_out = size;
569
+
570
+ rc = deflateInit2(&zstream, (int) level, Z_DEFLATED, wbits + 16, memlevel,
571
+ Z_DEFAULT_STRATEGY);
572
+
573
+ if (rc != Z_OK) {
574
+ ngx_log_error(NGX_LOG_ALERT, log, 0, "deflateInit2() failed: %d", rc);
575
+ goto done;
576
+ }
577
+
578
+ ngx_log_debug4(NGX_LOG_DEBUG_HTTP, log, 0,
579
+ "deflate in: ni:%p no:%p ai:%ud ao:%ud",
580
+ zstream.next_in, zstream.next_out,
581
+ zstream.avail_in, zstream.avail_out);
582
+
583
+ rc = deflate(&zstream, Z_FINISH);
584
+
585
+ if (rc != Z_STREAM_END) {
586
+ ngx_log_error(NGX_LOG_ALERT, log, 0,
587
+ "deflate(Z_FINISH) failed: %d", rc);
588
+ goto done;
589
+ }
590
+
591
+ ngx_log_debug5(NGX_LOG_DEBUG_HTTP, log, 0,
592
+ "deflate out: ni:%p no:%p ai:%ud ao:%ud rc:%d",
593
+ zstream.next_in, zstream.next_out,
594
+ zstream.avail_in, zstream.avail_out,
595
+ rc);
596
+
597
+ size -= zstream.avail_out;
598
+
599
+ rc = deflateEnd(&zstream);
600
+
601
+ if (rc != Z_OK) {
602
+ ngx_log_error(NGX_LOG_ALERT, log, 0, "deflateEnd() failed: %d", rc);
603
+ goto done;
604
+ }
605
+
606
+ n = ngx_write_fd(fd, out, size);
607
+
608
+ if (n != (ssize_t) size) {
609
+ err = (n == -1) ? ngx_errno : 0;
610
+
611
+ ngx_destroy_pool(pool);
612
+
613
+ ngx_set_errno(err);
614
+ return -1;
615
+ }
616
+
617
+ done:
618
+
619
+ ngx_destroy_pool(pool);
620
+
621
+ /* simulate successful logging */
622
+ return len;
623
+ }
624
+
625
+
626
+ static void *
627
+ ngx_http_log_gzip_alloc(void *opaque, u_int items, u_int size)
628
+ {
629
+ ngx_pool_t *pool = opaque;
630
+
631
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, pool->log, 0,
632
+ "gzip alloc: n:%ud s:%ud", items, size);
633
+
634
+ return ngx_palloc(pool, items * size);
635
+ }
636
+
637
+
638
+ static void
639
+ ngx_http_log_gzip_free(void *opaque, void *address)
640
+ {
641
+ #if 0
642
+ ngx_pool_t *pool = opaque;
643
+
644
+ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pool->log, 0, "gzip free: %p", address);
645
+ #endif
646
+ }
647
+
648
+ #endif
649
+
650
+
651
+ static void
652
+ ngx_http_log_flush(ngx_open_file_t *file, ngx_log_t *log)
653
+ {
654
+ size_t len;
655
+ ssize_t n;
656
+ ngx_http_log_buf_t *buffer;
657
+
658
+ buffer = file->data;
659
+
660
+ len = buffer->pos - buffer->start;
661
+
662
+ if (len == 0) {
663
+ return;
664
+ }
665
+
666
+ #if (NGX_ZLIB)
667
+ if (buffer->gzip) {
668
+ n = ngx_http_log_gzip(file->fd, buffer->start, len, buffer->gzip, log);
669
+ } else {
670
+ n = ngx_write_fd(file->fd, buffer->start, len);
671
+ }
672
+ #else
673
+ n = ngx_write_fd(file->fd, buffer->start, len);
674
+ #endif
675
+
676
+ if (n == -1) {
677
+ ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
678
+ ngx_write_fd_n " to \"%s\" failed",
679
+ file->name.data);
680
+
681
+ } else if ((size_t) n != len) {
682
+ ngx_log_error(NGX_LOG_ALERT, log, 0,
683
+ ngx_write_fd_n " to \"%s\" was incomplete: %z of %uz",
684
+ file->name.data, n, len);
685
+ }
686
+
687
+ buffer->pos = buffer->start;
688
+
689
+ if (buffer->event && buffer->event->timer_set) {
690
+ ngx_del_timer(buffer->event);
691
+ }
692
+ }
693
+
694
+
695
+ static void
696
+ ngx_http_log_flush_handler(ngx_event_t *ev)
697
+ {
698
+ ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ev->log, 0,
699
+ "http log buffer flush handler");
700
+
701
+ ngx_http_log_flush(ev->data, ev->log);
702
+ }
703
+
704
+
468
705
  static u_char *
469
706
  ngx_http_log_copy_short(ngx_http_request_t *r, u_char *buf,
470
707
  ngx_http_log_op_t *op)
@@ -848,10 +1085,13 @@ ngx_http_log_set_log(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
848
1085
  {
849
1086
  ngx_http_log_loc_conf_t *llcf = conf;
850
1087
 
851
- ssize_t buf;
1088
+ ssize_t size;
1089
+ ngx_int_t gzip;
852
1090
  ngx_uint_t i, n;
853
- ngx_str_t *value, name;
1091
+ ngx_msec_t flush;
1092
+ ngx_str_t *value, name, s;
854
1093
  ngx_http_log_t *log;
1094
+ ngx_http_log_buf_t *buffer;
855
1095
  ngx_http_log_fmt_t *fmt;
856
1096
  ngx_http_log_main_conf_t *lmcf;
857
1097
  ngx_http_script_compile_t sc;
@@ -936,54 +1176,152 @@ ngx_http_log_set_log(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
936
1176
  && ngx_strcasecmp(fmt[i].name.data, name.data) == 0)
937
1177
  {
938
1178
  log->format = &fmt[i];
939
- goto buffer;
1179
+ break;
940
1180
  }
941
1181
  }
942
1182
 
943
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
944
- "unknown log format \"%V\"", &name);
945
- return NGX_CONF_ERROR;
1183
+ if (log->format == NULL) {
1184
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1185
+ "unknown log format \"%V\"", &name);
1186
+ return NGX_CONF_ERROR;
1187
+ }
1188
+
1189
+ size = 0;
1190
+ flush = 0;
1191
+ gzip = 0;
1192
+
1193
+ for (i = 3; i < cf->args->nelts; i++) {
1194
+
1195
+ if (ngx_strncmp(value[i].data, "buffer=", 7) == 0) {
1196
+ s.len = value[i].len - 7;
1197
+ s.data = value[i].data + 7;
1198
+
1199
+ size = ngx_parse_size(&s);
1200
+
1201
+ if (size == NGX_ERROR || size == 0) {
1202
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1203
+ "invalid buffer size \"%V\"", &s);
1204
+ return NGX_CONF_ERROR;
1205
+ }
946
1206
 
947
- buffer:
1207
+ continue;
1208
+ }
1209
+
1210
+ if (ngx_strncmp(value[i].data, "flush=", 6) == 0) {
1211
+ s.len = value[i].len - 6;
1212
+ s.data = value[i].data + 6;
1213
+
1214
+ flush = ngx_parse_time(&s, 0);
1215
+
1216
+ if (flush == (ngx_msec_t) NGX_ERROR || flush == 0) {
1217
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1218
+ "invalid flush time \"%V\"", &s);
1219
+ return NGX_CONF_ERROR;
1220
+ }
948
1221
 
949
- if (cf->args->nelts == 4) {
950
- if (ngx_strncmp(value[3].data, "buffer=", 7) != 0) {
1222
+ continue;
1223
+ }
1224
+
1225
+ if (ngx_strncmp(value[i].data, "gzip", 4) == 0
1226
+ && (value[i].len == 4 || value[i].data[4] == '='))
1227
+ {
1228
+ #if (NGX_ZLIB)
1229
+ if (size == 0) {
1230
+ size = 64 * 1024;
1231
+ }
1232
+
1233
+ if (value[i].len == 4) {
1234
+ gzip = Z_BEST_SPEED;
1235
+ continue;
1236
+ }
1237
+
1238
+ s.len = value[i].len - 5;
1239
+ s.data = value[i].data + 5;
1240
+
1241
+ gzip = ngx_atoi(s.data, s.len);
1242
+
1243
+ if (gzip < 1 || gzip > 9) {
1244
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1245
+ "invalid compression level \"%V\"", &s);
1246
+ return NGX_CONF_ERROR;
1247
+ }
1248
+
1249
+ continue;
1250
+
1251
+ #else
951
1252
  ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
952
- "invalid parameter \"%V\"", &value[3]);
1253
+ "nginx was built without zlib support");
953
1254
  return NGX_CONF_ERROR;
1255
+ #endif
954
1256
  }
955
1257
 
1258
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1259
+ "invalid parameter \"%V\"", &value[i]);
1260
+ return NGX_CONF_ERROR;
1261
+ }
1262
+
1263
+ if (flush && size == 0) {
1264
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1265
+ "no buffer is defined for access_log \"%V\"",
1266
+ &value[1]);
1267
+ return NGX_CONF_ERROR;
1268
+ }
1269
+
1270
+ if (size) {
1271
+
956
1272
  if (log->script) {
957
1273
  ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
958
1274
  "buffered logs cannot have variables in name");
959
1275
  return NGX_CONF_ERROR;
960
1276
  }
961
1277
 
962
- name.len = value[3].len - 7;
963
- name.data = value[3].data + 7;
1278
+ if (log->file->data) {
1279
+ buffer = log->file->data;
1280
+
1281
+ if (buffer->last - buffer->start != size
1282
+ || buffer->flush != flush
1283
+ || buffer->gzip != gzip)
1284
+ {
1285
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1286
+ "access_log \"%V\" already defined "
1287
+ "with conflicting parameters",
1288
+ &value[1]);
1289
+ return NGX_CONF_ERROR;
1290
+ }
964
1291
 
965
- buf = ngx_parse_size(&name);
1292
+ return NGX_CONF_OK;
1293
+ }
966
1294
 
967
- if (buf == NGX_ERROR) {
968
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
969
- "invalid buffer value \"%V\"", &name);
1295
+ buffer = ngx_pcalloc(cf->pool, sizeof(ngx_http_log_buf_t));
1296
+ if (buffer == NULL) {
970
1297
  return NGX_CONF_ERROR;
971
1298
  }
972
1299
 
973
- if (log->file->buffer && log->file->last - log->file->pos != buf) {
974
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
975
- "access_log \"%V\" already defined "
976
- "with different buffer size", &value[1]);
1300
+ buffer->start = ngx_pnalloc(cf->pool, size);
1301
+ if (buffer->start == NULL) {
977
1302
  return NGX_CONF_ERROR;
978
1303
  }
979
1304
 
980
- log->file->buffer = ngx_palloc(cf->pool, buf);
981
- if (log->file->buffer == NULL) {
982
- return NGX_CONF_ERROR;
1305
+ buffer->pos = buffer->start;
1306
+ buffer->last = buffer->start + size;
1307
+
1308
+ if (flush) {
1309
+ buffer->event = ngx_pcalloc(cf->pool, sizeof(ngx_event_t));
1310
+ if (buffer->event == NULL) {
1311
+ return NGX_CONF_ERROR;
1312
+ }
1313
+
1314
+ buffer->event->data = log->file;
1315
+ buffer->event->handler = ngx_http_log_flush_handler;
1316
+ buffer->event->log = &cf->cycle->new_log;
1317
+
1318
+ buffer->flush = flush;
983
1319
  }
984
1320
 
985
- log->file->pos = log->file->buffer;
986
- log->file->last = log->file->buffer + buf;
1321
+ buffer->gzip = gzip;
1322
+
1323
+ log->file->flush = ngx_http_log_flush;
1324
+ log->file->data = buffer;
987
1325
  }
988
1326
 
989
1327
  return NGX_CONF_OK;