nginxtra 1.2.6.8 → 1.2.7.8

Sign up to get free protection for your applications and to get access to all the features.
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;