Mercurial > hg > nginx-vendor-1-0
comparison src/http/modules/ngx_http_headers_filter_module.c @ 376:edf1cb6c328e NGINX_0_7_0
nginx 0.7.0
*) Change: now the 0x00-0x1F, '"' and '\' characters are escaped as
\xXX in an access_log.
Thanks to Maxim Dounin.
*) Change: now nginx allows several "Host" request header line.
*) Feature: the "modified" flag in the "expires" directive.
*) Feature: the $uid_got and $uid_set variables may be used at any
request processing stage.
*) Feature: the $hostname variable.
Thanks to Andrei Nigmatulin.
*) Feature: DESTDIR support.
Thanks to Todd A. Fisher and Andras Voroskoi.
*) Bugfix: a segmentation fault might occur in worker process on Linux,
if keepalive was enabled.
author | Igor Sysoev <http://sysoev.ru> |
---|---|
date | Mon, 19 May 2008 00:00:00 +0400 |
parents | e10168d6e371 |
children | 984bb0b1399b |
comparison
equal
deleted
inserted
replaced
375:52f3c9c7eff0 | 376:edf1cb6c328e |
---|---|
29 ngx_array_t *lengths; | 29 ngx_array_t *lengths; |
30 ngx_array_t *values; | 30 ngx_array_t *values; |
31 }; | 31 }; |
32 | 32 |
33 | 33 |
34 #define NGX_HTTP_EXPIRES_OFF 0 | |
35 #define NGX_HTTP_EXPIRES_EPOCH 1 | |
36 #define NGX_HTTP_EXPIRES_MAX 2 | |
37 #define NGX_HTTP_EXPIRES_ACCESS 3 | |
38 #define NGX_HTTP_EXPIRES_MODIFIED 4 | |
39 | |
40 | |
34 typedef struct { | 41 typedef struct { |
35 time_t expires; | 42 ngx_uint_t expires; |
43 time_t expires_time; | |
36 ngx_array_t *headers; | 44 ngx_array_t *headers; |
37 } ngx_http_headers_conf_t; | 45 } ngx_http_headers_conf_t; |
38 | |
39 | |
40 #define NGX_HTTP_EXPIRES_UNSET -2147483647 | |
41 #define NGX_HTTP_EXPIRES_OFF -2147483646 | |
42 #define NGX_HTTP_EXPIRES_EPOCH -2147483645 | |
43 #define NGX_HTTP_EXPIRES_MAX -2147483644 | |
44 | 46 |
45 | 47 |
46 static ngx_int_t ngx_http_set_expires(ngx_http_request_t *r, | 48 static ngx_int_t ngx_http_set_expires(ngx_http_request_t *r, |
47 ngx_http_headers_conf_t *conf); | 49 ngx_http_headers_conf_t *conf); |
48 static ngx_int_t ngx_http_add_cache_control(ngx_http_request_t *r, | 50 static ngx_int_t ngx_http_add_cache_control(ngx_http_request_t *r, |
74 | 76 |
75 static ngx_command_t ngx_http_headers_filter_commands[] = { | 77 static ngx_command_t ngx_http_headers_filter_commands[] = { |
76 | 78 |
77 { ngx_string("expires"), | 79 { ngx_string("expires"), |
78 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF | 80 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF |
79 |NGX_CONF_TAKE1, | 81 |NGX_CONF_TAKE12, |
80 ngx_http_headers_expires, | 82 ngx_http_headers_expires, |
81 NGX_HTTP_LOC_CONF_OFFSET, | 83 NGX_HTTP_LOC_CONF_OFFSET, |
82 0, | 84 0, |
83 NULL}, | 85 NULL}, |
84 | 86 |
183 | 185 |
184 static ngx_int_t | 186 static ngx_int_t |
185 ngx_http_set_expires(ngx_http_request_t *r, ngx_http_headers_conf_t *conf) | 187 ngx_http_set_expires(ngx_http_request_t *r, ngx_http_headers_conf_t *conf) |
186 { | 188 { |
187 size_t len; | 189 size_t len; |
190 time_t since; | |
188 ngx_uint_t i; | 191 ngx_uint_t i; |
189 ngx_table_elt_t *expires, *cc, **ccp; | 192 ngx_table_elt_t *expires, *cc, **ccp; |
190 | 193 |
191 expires = r->headers_out.expires; | 194 expires = r->headers_out.expires; |
192 | 195 |
264 expires->value.data = ngx_palloc(r->pool, len); | 267 expires->value.data = ngx_palloc(r->pool, len); |
265 if (expires->value.data == NULL) { | 268 if (expires->value.data == NULL) { |
266 return NGX_ERROR; | 269 return NGX_ERROR; |
267 } | 270 } |
268 | 271 |
269 if (conf->expires == 0) { | 272 if (conf->expires_time == 0) { |
270 ngx_memcpy(expires->value.data, ngx_cached_http_time.data, | 273 ngx_memcpy(expires->value.data, ngx_cached_http_time.data, |
271 ngx_cached_http_time.len + 1); | 274 ngx_cached_http_time.len + 1); |
272 | 275 |
273 cc->value.len = sizeof("max-age=0") - 1; | 276 cc->value.len = sizeof("max-age=0") - 1; |
274 cc->value.data = (u_char *) "max-age=0"; | 277 cc->value.data = (u_char *) "max-age=0"; |
275 | 278 |
276 return NGX_OK; | 279 return NGX_OK; |
277 } | 280 } |
278 | 281 |
279 ngx_http_time(expires->value.data, ngx_time() + conf->expires); | 282 if (conf->expires == NGX_HTTP_EXPIRES_ACCESS |
280 | 283 || r->headers_out.last_modified_time == -1) |
281 if (conf->expires < 0) { | 284 { |
285 since = ngx_time(); | |
286 | |
287 } else { | |
288 since = r->headers_out.last_modified_time; | |
289 } | |
290 | |
291 ngx_http_time(expires->value.data, since + conf->expires_time); | |
292 | |
293 if (conf->expires_time < 0) { | |
282 cc->value.len = sizeof("no-cache") - 1; | 294 cc->value.len = sizeof("no-cache") - 1; |
283 cc->value.data = (u_char *) "no-cache"; | 295 cc->value.data = (u_char *) "no-cache"; |
284 | 296 |
285 return NGX_OK; | 297 return NGX_OK; |
286 } | 298 } |
289 sizeof("max-age=") + NGX_TIME_T_LEN + 1); | 301 sizeof("max-age=") + NGX_TIME_T_LEN + 1); |
290 if (cc->value.data == NULL) { | 302 if (cc->value.data == NULL) { |
291 return NGX_ERROR; | 303 return NGX_ERROR; |
292 } | 304 } |
293 | 305 |
294 cc->value.len = ngx_sprintf(cc->value.data, "max-age=%T", conf->expires) | 306 cc->value.len = ngx_sprintf(cc->value.data, "max-age=%T", |
307 since + conf->expires_time - ngx_time()) | |
295 - cc->value.data; | 308 - cc->value.data; |
296 | 309 |
297 return NGX_OK; | 310 return NGX_OK; |
298 } | 311 } |
299 | 312 |
411 | 424 |
412 /* | 425 /* |
413 * set by ngx_pcalloc(): | 426 * set by ngx_pcalloc(): |
414 * | 427 * |
415 * conf->headers = NULL; | 428 * conf->headers = NULL; |
429 * conf->expires_time = 0; | |
416 */ | 430 */ |
417 | 431 |
418 conf->expires = NGX_HTTP_EXPIRES_UNSET; | 432 conf->expires = NGX_CONF_UNSET_UINT; |
419 | 433 |
420 return conf; | 434 return conf; |
421 } | 435 } |
422 | 436 |
423 | 437 |
425 ngx_http_headers_merge_conf(ngx_conf_t *cf, void *parent, void *child) | 439 ngx_http_headers_merge_conf(ngx_conf_t *cf, void *parent, void *child) |
426 { | 440 { |
427 ngx_http_headers_conf_t *prev = parent; | 441 ngx_http_headers_conf_t *prev = parent; |
428 ngx_http_headers_conf_t *conf = child; | 442 ngx_http_headers_conf_t *conf = child; |
429 | 443 |
430 if (conf->expires == NGX_HTTP_EXPIRES_UNSET) { | 444 if (conf->expires == NGX_CONF_UNSET_UINT) { |
431 conf->expires = (prev->expires == NGX_HTTP_EXPIRES_UNSET) ? | 445 conf->expires = prev->expires; |
432 NGX_HTTP_EXPIRES_OFF : prev->expires; | 446 conf->expires_time = prev->expires_time; |
447 | |
448 if (conf->expires == NGX_CONF_UNSET_UINT) { | |
449 conf->expires = NGX_HTTP_EXPIRES_OFF; | |
450 } | |
433 } | 451 } |
434 | 452 |
435 if (conf->headers == NULL) { | 453 if (conf->headers == NULL) { |
436 conf->headers = prev->headers; | 454 conf->headers = prev->headers; |
437 } | 455 } |
453 static char * | 471 static char * |
454 ngx_http_headers_expires(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | 472 ngx_http_headers_expires(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) |
455 { | 473 { |
456 ngx_http_headers_conf_t *hcf = conf; | 474 ngx_http_headers_conf_t *hcf = conf; |
457 | 475 |
458 ngx_uint_t minus; | 476 ngx_uint_t minus, n; |
459 ngx_str_t *value; | 477 ngx_str_t *value; |
460 | 478 |
461 if (hcf->expires != NGX_HTTP_EXPIRES_UNSET) { | 479 if (hcf->expires != NGX_CONF_UNSET_UINT) { |
462 return "is duplicate"; | 480 return "is duplicate"; |
463 } | 481 } |
464 | 482 |
465 value = cf->args->elts; | 483 value = cf->args->elts; |
466 | 484 |
467 if (ngx_strcmp(value[1].data, "epoch") == 0) { | 485 if (cf->args->nelts == 2) { |
468 hcf->expires = NGX_HTTP_EXPIRES_EPOCH; | 486 |
469 return NGX_CONF_OK; | 487 if (ngx_strcmp(value[1].data, "epoch") == 0) { |
470 } | 488 hcf->expires = NGX_HTTP_EXPIRES_EPOCH; |
471 | 489 return NGX_CONF_OK; |
472 if (ngx_strcmp(value[1].data, "max") == 0) { | 490 } |
473 hcf->expires = NGX_HTTP_EXPIRES_MAX; | 491 |
474 return NGX_CONF_OK; | 492 if (ngx_strcmp(value[1].data, "max") == 0) { |
475 } | 493 hcf->expires = NGX_HTTP_EXPIRES_MAX; |
476 | 494 return NGX_CONF_OK; |
477 if (ngx_strcmp(value[1].data, "off") == 0) { | 495 } |
478 hcf->expires = NGX_HTTP_EXPIRES_OFF; | 496 |
479 return NGX_CONF_OK; | 497 if (ngx_strcmp(value[1].data, "off") == 0) { |
480 } | 498 hcf->expires = NGX_HTTP_EXPIRES_OFF; |
481 | 499 return NGX_CONF_OK; |
482 if (value[1].data[0] == '+') { | 500 } |
483 value[1].data++; | 501 |
484 value[1].len--; | 502 hcf->expires = NGX_HTTP_EXPIRES_ACCESS; |
503 | |
504 n = 1; | |
505 | |
506 } else { /* cf->args->nelts == 3 */ | |
507 | |
508 if (ngx_strcmp(value[1].data, "modified") != 0) { | |
509 return "invalid value"; | |
510 } | |
511 | |
512 hcf->expires = NGX_HTTP_EXPIRES_MODIFIED; | |
513 | |
514 n = 2; | |
515 } | |
516 | |
517 if (value[n].data[0] == '+') { | |
518 value[n].data++; | |
519 value[n].len--; | |
485 minus = 0; | 520 minus = 0; |
486 | 521 |
487 } else if (value[1].data[0] == '-') { | 522 } else if (value[n].data[0] == '-') { |
488 value[1].data++; | 523 value[n].data++; |
489 value[1].len--; | 524 value[n].len--; |
490 minus = 1; | 525 minus = 1; |
491 | 526 |
492 } else { | 527 } else { |
493 minus = 0; | 528 minus = 0; |
494 } | 529 } |
495 | 530 |
496 hcf->expires = ngx_parse_time(&value[1], 1); | 531 hcf->expires_time = ngx_parse_time(&value[n], 1); |
497 | 532 |
498 if (hcf->expires == NGX_ERROR) { | 533 if (hcf->expires_time == NGX_ERROR) { |
499 return "invalid value"; | 534 return "invalid value"; |
500 } | 535 } |
501 | 536 |
502 if (hcf->expires == NGX_PARSE_LARGE_TIME) { | 537 if (hcf->expires_time == NGX_PARSE_LARGE_TIME) { |
503 return "value must be less than 68 years"; | 538 return "value must be less than 68 years"; |
504 } | 539 } |
505 | 540 |
506 if (minus) { | 541 if (minus) { |
507 hcf->expires = - hcf->expires; | 542 hcf->expires_time = - hcf->expires_time; |
508 } | 543 } |
509 | 544 |
510 return NGX_CONF_OK; | 545 return NGX_CONF_OK; |
511 } | 546 } |
512 | 547 |