comparison src/http/modules/ngx_http_headers_filter_module.c @ 5942:4983f7d18fe3

Headers filter: variables support in expires (ticket #113).
author Maxim Dounin <mdounin@mdounin.ru>
date Thu, 11 Dec 2014 23:42:11 +0300
parents 36e61455a8f4
children 173561dfd567
comparison
equal deleted inserted replaced
5941:36e61455a8f4 5942:4983f7d18fe3
42 NGX_HTTP_EXPIRES_UNSET 42 NGX_HTTP_EXPIRES_UNSET
43 } ngx_http_expires_t; 43 } ngx_http_expires_t;
44 44
45 45
46 typedef struct { 46 typedef struct {
47 ngx_http_expires_t expires; 47 ngx_http_expires_t expires;
48 time_t expires_time; 48 time_t expires_time;
49 ngx_array_t *headers; 49 ngx_http_complex_value_t *expires_value;
50 ngx_array_t *headers;
50 } ngx_http_headers_conf_t; 51 } ngx_http_headers_conf_t;
51 52
52 53
53 static ngx_int_t ngx_http_set_expires(ngx_http_request_t *r, 54 static ngx_int_t ngx_http_set_expires(ngx_http_request_t *r,
54 ngx_http_headers_conf_t *conf); 55 ngx_http_headers_conf_t *conf);
56 static ngx_int_t ngx_http_parse_expires(ngx_str_t *value,
57 ngx_http_expires_t *expires, time_t *expires_time, char **err);
55 static ngx_int_t ngx_http_add_cache_control(ngx_http_request_t *r, 58 static ngx_int_t ngx_http_add_cache_control(ngx_http_request_t *r,
56 ngx_http_header_val_t *hv, ngx_str_t *value); 59 ngx_http_header_val_t *hv, ngx_str_t *value);
57 static ngx_int_t ngx_http_add_header(ngx_http_request_t *r, 60 static ngx_int_t ngx_http_add_header(ngx_http_request_t *r,
58 ngx_http_header_val_t *hv, ngx_str_t *value); 61 ngx_http_header_val_t *hv, ngx_str_t *value);
59 static ngx_int_t ngx_http_set_last_modified(ngx_http_request_t *r, 62 static ngx_int_t ngx_http_set_last_modified(ngx_http_request_t *r,
207 210
208 211
209 static ngx_int_t 212 static ngx_int_t
210 ngx_http_set_expires(ngx_http_request_t *r, ngx_http_headers_conf_t *conf) 213 ngx_http_set_expires(ngx_http_request_t *r, ngx_http_headers_conf_t *conf)
211 { 214 {
215 char *err;
212 size_t len; 216 size_t len;
213 time_t now, expires_time, max_age; 217 time_t now, expires_time, max_age;
218 ngx_str_t value;
219 ngx_int_t rc;
214 ngx_uint_t i; 220 ngx_uint_t i;
215 ngx_table_elt_t *e, *cc, **ccp; 221 ngx_table_elt_t *e, *cc, **ccp;
216 ngx_http_expires_t expires; 222 ngx_http_expires_t expires;
217 223
218 expires = conf->expires; 224 expires = conf->expires;
219 expires_time = conf->expires_time; 225 expires_time = conf->expires_time;
226
227 if (conf->expires_value != NULL) {
228
229 if (ngx_http_complex_value(r, conf->expires_value, &value) != NGX_OK) {
230 return NGX_ERROR;
231 }
232
233 rc = ngx_http_parse_expires(&value, &expires, &expires_time, &err);
234
235 if (rc != NGX_OK) {
236 return NGX_OK;
237 }
238
239 if (expires == NGX_HTTP_EXPIRES_OFF) {
240 return NGX_OK;
241 }
242 }
220 243
221 e = r->headers_out.expires; 244 e = r->headers_out.expires;
222 245
223 if (e == NULL) { 246 if (e == NULL) {
224 247
330 return NGX_OK; 353 return NGX_OK;
331 } 354 }
332 355
333 356
334 static ngx_int_t 357 static ngx_int_t
358 ngx_http_parse_expires(ngx_str_t *value, ngx_http_expires_t *expires,
359 time_t *expires_time, char **err)
360 {
361 ngx_uint_t minus;
362
363 if (*expires != NGX_HTTP_EXPIRES_MODIFIED) {
364
365 if (value->len == 5 && ngx_strncmp(value->data, "epoch", 5) == 0) {
366 *expires = NGX_HTTP_EXPIRES_EPOCH;
367 return NGX_OK;
368 }
369
370 if (value->len == 3 && ngx_strncmp(value->data, "max", 3) == 0) {
371 *expires = NGX_HTTP_EXPIRES_MAX;
372 return NGX_OK;
373 }
374
375 if (value->len == 3 && ngx_strncmp(value->data, "off", 3) == 0) {
376 *expires = NGX_HTTP_EXPIRES_OFF;
377 return NGX_OK;
378 }
379 }
380
381 if (value->data[0] == '@') {
382 value->data++;
383 value->len--;
384 minus = 0;
385
386 if (*expires == NGX_HTTP_EXPIRES_MODIFIED) {
387 *err = "daily time cannot be used with \"modified\" parameter";
388 return NGX_ERROR;
389 }
390
391 *expires = NGX_HTTP_EXPIRES_DAILY;
392
393 } else if (value->data[0] == '+') {
394 value->data++;
395 value->len--;
396 minus = 0;
397
398 } else if (value->data[0] == '-') {
399 value->data++;
400 value->len--;
401 minus = 1;
402
403 } else {
404 minus = 0;
405 }
406
407 *expires_time = ngx_parse_time(value, 1);
408
409 if (*expires_time == (time_t) NGX_ERROR) {
410 *err = "invalid value";
411 return NGX_ERROR;
412 }
413
414 if (*expires == NGX_HTTP_EXPIRES_DAILY
415 && *expires_time > 24 * 60 * 60)
416 {
417 *err = "daily time value must be less than 24 hours";
418 return NGX_ERROR;
419 }
420
421 if (minus) {
422 *expires_time = - *expires_time;
423 }
424
425 return NGX_OK;
426 }
427
428
429 static ngx_int_t
335 ngx_http_add_header(ngx_http_request_t *r, ngx_http_header_val_t *hv, 430 ngx_http_add_header(ngx_http_request_t *r, ngx_http_header_val_t *hv,
336 ngx_str_t *value) 431 ngx_str_t *value)
337 { 432 {
338 ngx_table_elt_t *h; 433 ngx_table_elt_t *h;
339 434
459 /* 554 /*
460 * set by ngx_pcalloc(): 555 * set by ngx_pcalloc():
461 * 556 *
462 * conf->headers = NULL; 557 * conf->headers = NULL;
463 * conf->expires_time = 0; 558 * conf->expires_time = 0;
559 * conf->expires_value = NULL;
464 */ 560 */
465 561
466 conf->expires = NGX_HTTP_EXPIRES_UNSET; 562 conf->expires = NGX_HTTP_EXPIRES_UNSET;
467 563
468 return conf; 564 return conf;
476 ngx_http_headers_conf_t *conf = child; 572 ngx_http_headers_conf_t *conf = child;
477 573
478 if (conf->expires == NGX_HTTP_EXPIRES_UNSET) { 574 if (conf->expires == NGX_HTTP_EXPIRES_UNSET) {
479 conf->expires = prev->expires; 575 conf->expires = prev->expires;
480 conf->expires_time = prev->expires_time; 576 conf->expires_time = prev->expires_time;
577 conf->expires_value = prev->expires_value;
481 578
482 if (conf->expires == NGX_HTTP_EXPIRES_UNSET) { 579 if (conf->expires == NGX_HTTP_EXPIRES_UNSET) {
483 conf->expires = NGX_HTTP_EXPIRES_OFF; 580 conf->expires = NGX_HTTP_EXPIRES_OFF;
484 } 581 }
485 } 582 }
505 static char * 602 static char *
506 ngx_http_headers_expires(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) 603 ngx_http_headers_expires(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
507 { 604 {
508 ngx_http_headers_conf_t *hcf = conf; 605 ngx_http_headers_conf_t *hcf = conf;
509 606
510 ngx_uint_t minus, n; 607 char *err;
511 ngx_str_t *value; 608 ngx_str_t *value;
609 ngx_int_t rc;
610 ngx_uint_t n;
611 ngx_http_complex_value_t cv;
612 ngx_http_compile_complex_value_t ccv;
512 613
513 if (hcf->expires != NGX_HTTP_EXPIRES_UNSET) { 614 if (hcf->expires != NGX_HTTP_EXPIRES_UNSET) {
514 return "is duplicate"; 615 return "is duplicate";
515 } 616 }
516 617
517 value = cf->args->elts; 618 value = cf->args->elts;
518 619
519 if (cf->args->nelts == 2) { 620 if (cf->args->nelts == 2) {
520 621
521 if (ngx_strcmp(value[1].data, "epoch") == 0) {
522 hcf->expires = NGX_HTTP_EXPIRES_EPOCH;
523 return NGX_CONF_OK;
524 }
525
526 if (ngx_strcmp(value[1].data, "max") == 0) {
527 hcf->expires = NGX_HTTP_EXPIRES_MAX;
528 return NGX_CONF_OK;
529 }
530
531 if (ngx_strcmp(value[1].data, "off") == 0) {
532 hcf->expires = NGX_HTTP_EXPIRES_OFF;
533 return NGX_CONF_OK;
534 }
535
536 hcf->expires = NGX_HTTP_EXPIRES_ACCESS; 622 hcf->expires = NGX_HTTP_EXPIRES_ACCESS;
537 623
538 n = 1; 624 n = 1;
539 625
540 } else { /* cf->args->nelts == 3 */ 626 } else { /* cf->args->nelts == 3 */
546 hcf->expires = NGX_HTTP_EXPIRES_MODIFIED; 632 hcf->expires = NGX_HTTP_EXPIRES_MODIFIED;
547 633
548 n = 2; 634 n = 2;
549 } 635 }
550 636
551 if (value[n].data[0] == '@') { 637 ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
552 value[n].data++; 638
553 value[n].len--; 639 ccv.cf = cf;
554 minus = 0; 640 ccv.value = &value[n];
555 641 ccv.complex_value = &cv;
556 if (hcf->expires == NGX_HTTP_EXPIRES_MODIFIED) { 642
557 return "daily time cannot be used with \"modified\" parameter"; 643 if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
558 } 644 return NGX_CONF_ERROR;
559 645 }
560 hcf->expires = NGX_HTTP_EXPIRES_DAILY; 646
561 647 if (cv.lengths != NULL) {
562 } else if (value[n].data[0] == '+') { 648
563 value[n].data++; 649 hcf->expires_value = ngx_palloc(cf->pool,
564 value[n].len--; 650 sizeof(ngx_http_complex_value_t));
565 minus = 0; 651 if (hcf->expires_value == NULL) {
566 652 return NGX_CONF_ERROR;
567 } else if (value[n].data[0] == '-') { 653 }
568 value[n].data++; 654
569 value[n].len--; 655 *hcf->expires_value = cv;
570 minus = 1; 656
571 657 return NGX_CONF_OK;
572 } else { 658 }
573 minus = 0; 659
574 } 660 rc = ngx_http_parse_expires(&value[n], &hcf->expires, &hcf->expires_time,
575 661 &err);
576 hcf->expires_time = ngx_parse_time(&value[n], 1); 662 if (rc != NGX_OK) {
577 663 return err;
578 if (hcf->expires_time == (time_t) NGX_ERROR) {
579 return "invalid value";
580 }
581
582 if (hcf->expires == NGX_HTTP_EXPIRES_DAILY
583 && hcf->expires_time > 24 * 60 * 60)
584 {
585 return "daily time value must be less than 24 hours";
586 }
587
588 if (minus) {
589 hcf->expires_time = - hcf->expires_time;
590 } 664 }
591 665
592 return NGX_CONF_OK; 666 return NGX_CONF_OK;
593 } 667 }
594 668