comparison src/http/modules/ngx_http_log_module.c @ 694:88a1b4797f2e NGINX_1_3_10

nginx 1.3.10 *) Change: domain names specified in configuration file are now resolved to IPv6 addresses as well as IPv4 ones. *) Change: now if the "include" directive with mask is used on Unix systems, included files are sorted in alphabetical order. *) Change: the "add_header" directive adds headers to 201 responses. *) Feature: the "geo" directive now supports IPv6 addresses in CIDR notation. *) Feature: the "flush" and "gzip" parameters of the "access_log" directive. *) Feature: variables support in the "auth_basic" directive. *) Bugfix: nginx could not be built with the ngx_http_perl_module in some cases. *) Bugfix: a segmentation fault might occur in a worker process if the ngx_http_xslt_module was used. *) Bugfix: nginx could not be built on MacOSX in some cases. Thanks to Piotr Sikora. *) Bugfix: the "limit_rate" directive with high rates might result in truncated responses on 32-bit platforms. Thanks to Alexey Antropov. *) Bugfix: a segmentation fault might occur in a worker process if the "if" directive was used. Thanks to Piotr Sikora. *) Bugfix: a "100 Continue" response was issued with "413 Request Entity Too Large" responses. *) Bugfix: the "image_filter", "image_filter_jpeg_quality" and "image_filter_sharpen" directives might be inherited incorrectly. Thanks to Ian Babrou. *) Bugfix: "crypt_r() failed" errors might appear if the "auth_basic" directive was used on Linux. *) Bugfix: in backup servers handling. Thanks to Thomas Chen. *) Bugfix: proxied HEAD requests might return incorrect response if the "gzip" directive was used.
author Igor Sysoev <http://sysoev.ru>
date Tue, 25 Dec 2012 00:00:00 +0400
parents b5b7eea22fda
children
comparison
equal deleted inserted replaced
693:cfd4279acc6e 694:88a1b4797f2e
6 6
7 7
8 #include <ngx_config.h> 8 #include <ngx_config.h>
9 #include <ngx_core.h> 9 #include <ngx_core.h>
10 #include <ngx_http.h> 10 #include <ngx_http.h>
11
12 #if (NGX_ZLIB)
13 #include <zlib.h>
14 #endif
11 15
12 16
13 typedef struct ngx_http_log_op_s ngx_http_log_op_t; 17 typedef struct ngx_http_log_op_s ngx_http_log_op_t;
14 18
15 typedef u_char *(*ngx_http_log_op_run_pt) (ngx_http_request_t *r, u_char *buf, 19 typedef u_char *(*ngx_http_log_op_run_pt) (ngx_http_request_t *r, u_char *buf,
36 40
37 typedef struct { 41 typedef struct {
38 ngx_array_t formats; /* array of ngx_http_log_fmt_t */ 42 ngx_array_t formats; /* array of ngx_http_log_fmt_t */
39 ngx_uint_t combined_used; /* unsigned combined_used:1 */ 43 ngx_uint_t combined_used; /* unsigned combined_used:1 */
40 } ngx_http_log_main_conf_t; 44 } ngx_http_log_main_conf_t;
45
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;
41 56
42 57
43 typedef struct { 58 typedef struct {
44 ngx_array_t *lengths; 59 ngx_array_t *lengths;
45 ngx_array_t *values; 60 ngx_array_t *values;
75 90
76 static void ngx_http_log_write(ngx_http_request_t *r, ngx_http_log_t *log, 91 static void ngx_http_log_write(ngx_http_request_t *r, ngx_http_log_t *log,
77 u_char *buf, size_t len); 92 u_char *buf, size_t len);
78 static ssize_t ngx_http_log_script_write(ngx_http_request_t *r, 93 static ssize_t ngx_http_log_script_write(ngx_http_request_t *r,
79 ngx_http_log_script_t *script, u_char **name, u_char *buf, size_t len); 94 ngx_http_log_script_t *script, u_char **name, u_char *buf, size_t len);
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);
80 106
81 static u_char *ngx_http_log_pipe(ngx_http_request_t *r, u_char *buf, 107 static u_char *ngx_http_log_pipe(ngx_http_request_t *r, u_char *buf,
82 ngx_http_log_op_t *op); 108 ngx_http_log_op_t *op);
83 static u_char *ngx_http_log_time(ngx_http_request_t *r, u_char *buf, 109 static u_char *ngx_http_log_time(ngx_http_request_t *r, u_char *buf,
84 ngx_http_log_op_t *op); 110 ngx_http_log_op_t *op);
130 0, 156 0,
131 NULL }, 157 NULL },
132 158
133 { ngx_string("access_log"), 159 { ngx_string("access_log"),
134 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF 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 ngx_http_log_set_log, 162 ngx_http_log_set_log,
137 NGX_HTTP_LOC_CONF_OFFSET, 163 NGX_HTTP_LOC_CONF_OFFSET,
138 0, 164 0,
139 NULL }, 165 NULL },
140 166
214 { 240 {
215 u_char *line, *p; 241 u_char *line, *p;
216 size_t len; 242 size_t len;
217 ngx_uint_t i, l; 243 ngx_uint_t i, l;
218 ngx_http_log_t *log; 244 ngx_http_log_t *log;
219 ngx_open_file_t *file;
220 ngx_http_log_op_t *op; 245 ngx_http_log_op_t *op;
246 ngx_http_log_buf_t *buffer;
221 ngx_http_log_loc_conf_t *lcf; 247 ngx_http_log_loc_conf_t *lcf;
222 248
223 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, 249 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
224 "http log handler"); 250 "http log handler");
225 251
256 } 282 }
257 } 283 }
258 284
259 len += NGX_LINEFEED_SIZE; 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, 293 ngx_http_log_write(r, &log[l], buffer->start,
268 file->pos - file->buffer); 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 for (i = 0; i < log[l].format->ops->nelts; i++) { 307 for (i = 0; i < log[l].format->ops->nelts; i++) {
278 p = op[i].run(r, p, &op[i]); 308 p = op[i].run(r, p, &op[i]);
279 } 309 }
280 310
281 ngx_linefeed(p); 311 ngx_linefeed(p);
282 312
283 file->pos = p; 313 buffer->pos = p;
284 314
285 continue; 315 continue;
316 }
317
318 if (buffer->event && buffer->event->timer_set) {
319 ngx_del_timer(buffer->event);
286 } 320 }
287 } 321 }
288 322
289 line = ngx_pnalloc(r->pool, len); 323 line = ngx_pnalloc(r->pool, len);
290 if (line == NULL) { 324 if (line == NULL) {
308 342
309 static void 343 static void
310 ngx_http_log_write(ngx_http_request_t *r, ngx_http_log_t *log, u_char *buf, 344 ngx_http_log_write(ngx_http_request_t *r, ngx_http_log_t *log, u_char *buf,
311 size_t len) 345 size_t len)
312 { 346 {
313 u_char *name; 347 u_char *name;
314 time_t now; 348 time_t now;
315 ssize_t n; 349 ssize_t n;
316 ngx_err_t err; 350 ngx_err_t err;
351 #if (NGX_ZLIB)
352 ngx_http_log_buf_t *buffer;
353 #endif
317 354
318 if (log->script == NULL) { 355 if (log->script == NULL) {
319 name = log->file->name.data; 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 n = ngx_write_fd(log->file->fd, buf, len); 368 n = ngx_write_fd(log->file->fd, buf, len);
369 #endif
321 370
322 } else { 371 } else {
323 name = NULL; 372 name = NULL;
324 n = ngx_http_log_script_write(r, log->script, &name, buf, len); 373 n = ngx_http_log_script_write(r, log->script, &name, buf, len);
325 } 374 }
463 512
464 return n; 513 return n;
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 static u_char * 705 static u_char *
469 ngx_http_log_copy_short(ngx_http_request_t *r, u_char *buf, 706 ngx_http_log_copy_short(ngx_http_request_t *r, u_char *buf,
470 ngx_http_log_op_t *op) 707 ngx_http_log_op_t *op)
471 { 708 {
472 size_t len; 709 size_t len;
846 static char * 1083 static char *
847 ngx_http_log_set_log(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) 1084 ngx_http_log_set_log(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
848 { 1085 {
849 ngx_http_log_loc_conf_t *llcf = conf; 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 ngx_uint_t i, n; 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 ngx_http_log_t *log; 1093 ngx_http_log_t *log;
1094 ngx_http_log_buf_t *buffer;
855 ngx_http_log_fmt_t *fmt; 1095 ngx_http_log_fmt_t *fmt;
856 ngx_http_log_main_conf_t *lmcf; 1096 ngx_http_log_main_conf_t *lmcf;
857 ngx_http_script_compile_t sc; 1097 ngx_http_script_compile_t sc;
858 1098
859 value = cf->args->elts; 1099 value = cf->args->elts;
934 for (i = 0; i < lmcf->formats.nelts; i++) { 1174 for (i = 0; i < lmcf->formats.nelts; i++) {
935 if (fmt[i].name.len == name.len 1175 if (fmt[i].name.len == name.len
936 && ngx_strcasecmp(fmt[i].name.data, name.data) == 0) 1176 && ngx_strcasecmp(fmt[i].name.data, name.data) == 0)
937 { 1177 {
938 log->format = &fmt[i]; 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, 1183 if (log->format == NULL) {
944 "unknown log format \"%V\"", &name); 1184 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
945 return NGX_CONF_ERROR; 1185 "unknown log format \"%V\"", &name);
946 1186 return NGX_CONF_ERROR;
947 buffer: 1187 }
948 1188
949 if (cf->args->nelts == 4) { 1189 size = 0;
950 if (ngx_strncmp(value[3].data, "buffer=", 7) != 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 }
1206
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 }
1221
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 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, 1252 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
952 "invalid parameter \"%V\"", &value[3]); 1253 "nginx was built without zlib support");
953 return NGX_CONF_ERROR; 1254 return NGX_CONF_ERROR;
954 } 1255 #endif
1256 }
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) {
955 1271
956 if (log->script) { 1272 if (log->script) {
957 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, 1273 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
958 "buffered logs cannot have variables in name"); 1274 "buffered logs cannot have variables in name");
959 return NGX_CONF_ERROR; 1275 return NGX_CONF_ERROR;
960 } 1276 }
961 1277
962 name.len = value[3].len - 7; 1278 if (log->file->data) {
963 name.data = value[3].data + 7; 1279 buffer = log->file->data;
964 1280
965 buf = ngx_parse_size(&name); 1281 if (buffer->last - buffer->start != size
966 1282 || buffer->flush != flush
967 if (buf == NGX_ERROR) { 1283 || buffer->gzip != gzip)
968 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, 1284 {
969 "invalid buffer value \"%V\"", &name); 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 }
1291
1292 return NGX_CONF_OK;
1293 }
1294
1295 buffer = ngx_pcalloc(cf->pool, sizeof(ngx_http_log_buf_t));
1296 if (buffer == NULL) {
970 return NGX_CONF_ERROR; 1297 return NGX_CONF_ERROR;
971 } 1298 }
972 1299
973 if (log->file->buffer && log->file->last - log->file->pos != buf) { 1300 buffer->start = ngx_pnalloc(cf->pool, size);
974 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, 1301 if (buffer->start == NULL) {
975 "access_log \"%V\" already defined "
976 "with different buffer size", &value[1]);
977 return NGX_CONF_ERROR; 1302 return NGX_CONF_ERROR;
978 } 1303 }
979 1304
980 log->file->buffer = ngx_palloc(cf->pool, buf); 1305 buffer->pos = buffer->start;
981 if (log->file->buffer == NULL) { 1306 buffer->last = buffer->start + size;
982 return NGX_CONF_ERROR; 1307
983 } 1308 if (flush) {
984 1309 buffer->event = ngx_pcalloc(cf->pool, sizeof(ngx_event_t));
985 log->file->pos = log->file->buffer; 1310 if (buffer->event == NULL) {
986 log->file->last = log->file->buffer + buf; 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;
1319 }
1320
1321 buffer->gzip = gzip;
1322
1323 log->file->flush = ngx_http_log_flush;
1324 log->file->data = buffer;
987 } 1325 }
988 1326
989 return NGX_CONF_OK; 1327 return NGX_CONF_OK;
990 } 1328 }
991 1329