comparison src/http/ngx_http_variables.c @ 665:0b460e61bdcd default tip

Merge with nginx 1.0.0.
author Maxim Dounin <mdounin@mdounin.ru>
date Mon, 25 Apr 2011 04:22:17 +0400
parents 8214eaef3530
children
comparison
equal deleted inserted replaced
572:06419a2298a9 665:0b460e61bdcd
11 11
12 12
13 static ngx_int_t ngx_http_variable_request(ngx_http_request_t *r, 13 static ngx_int_t ngx_http_variable_request(ngx_http_request_t *r,
14 ngx_http_variable_value_t *v, uintptr_t data); 14 ngx_http_variable_value_t *v, uintptr_t data);
15 static void ngx_http_variable_request_set(ngx_http_request_t *r, 15 static void ngx_http_variable_request_set(ngx_http_request_t *r,
16 ngx_http_variable_value_t *v, uintptr_t data);
17 static ngx_int_t ngx_http_variable_request_get_size(ngx_http_request_t *r,
16 ngx_http_variable_value_t *v, uintptr_t data); 18 ngx_http_variable_value_t *v, uintptr_t data);
17 static void ngx_http_variable_request_set_size(ngx_http_request_t *r, 19 static void ngx_http_variable_request_set_size(ngx_http_request_t *r,
18 ngx_http_variable_value_t *v, uintptr_t data); 20 ngx_http_variable_value_t *v, uintptr_t data);
19 static ngx_int_t ngx_http_variable_header(ngx_http_request_t *r, 21 static ngx_int_t ngx_http_variable_header(ngx_http_request_t *r,
20 ngx_http_variable_value_t *v, uintptr_t data); 22 ngx_http_variable_value_t *v, uintptr_t data);
192 NGX_HTTP_VAR_NOCACHEABLE, 0 }, 194 NGX_HTTP_VAR_NOCACHEABLE, 0 },
193 195
194 { ngx_string("server_name"), NULL, ngx_http_variable_server_name, 0, 0, 0 }, 196 { ngx_string("server_name"), NULL, ngx_http_variable_server_name, 0, 0, 0 },
195 197
196 { ngx_string("request_method"), NULL, 198 { ngx_string("request_method"), NULL,
197 ngx_http_variable_request_method, 0, 0, 0 }, 199 ngx_http_variable_request_method, 0,
200 NGX_HTTP_VAR_NOCACHEABLE, 0 },
198 201
199 { ngx_string("remote_user"), NULL, ngx_http_variable_remote_user, 0, 0, 0 }, 202 { ngx_string("remote_user"), NULL, ngx_http_variable_remote_user, 0, 0, 0 },
200 203
201 { ngx_string("body_bytes_sent"), NULL, ngx_http_variable_body_bytes_sent, 204 { ngx_string("body_bytes_sent"), NULL, ngx_http_variable_body_bytes_sent,
202 0, 0, 0 }, 205 0, 0, 0 },
236 239
237 { ngx_string("sent_http_cache_control"), NULL, ngx_http_variable_headers, 240 { ngx_string("sent_http_cache_control"), NULL, ngx_http_variable_headers,
238 offsetof(ngx_http_request_t, headers_out.cache_control), 0, 0 }, 241 offsetof(ngx_http_request_t, headers_out.cache_control), 0, 0 },
239 242
240 { ngx_string("limit_rate"), ngx_http_variable_request_set_size, 243 { ngx_string("limit_rate"), ngx_http_variable_request_set_size,
241 ngx_http_variable_request, 244 ngx_http_variable_request_get_size,
242 offsetof(ngx_http_request_t, limit_rate), 245 offsetof(ngx_http_request_t, limit_rate),
243 NGX_HTTP_VAR_CHANGEABLE|NGX_HTTP_VAR_NOCACHEABLE, 0 }, 246 NGX_HTTP_VAR_CHANGEABLE|NGX_HTTP_VAR_NOCACHEABLE, 0 },
244 247
245 { ngx_string("nginx_version"), NULL, ngx_http_variable_nginx_version, 248 { ngx_string("nginx_version"), NULL, ngx_http_variable_nginx_version,
246 0, 0, 0 }, 249 0, 0, 0 },
436 return ngx_http_get_indexed_variable(r, index); 439 return ngx_http_get_indexed_variable(r, index);
437 } 440 }
438 441
439 442
440 ngx_http_variable_value_t * 443 ngx_http_variable_value_t *
441 ngx_http_get_variable(ngx_http_request_t *r, ngx_str_t *name, ngx_uint_t key, 444 ngx_http_get_variable(ngx_http_request_t *r, ngx_str_t *name, ngx_uint_t key)
442 ngx_uint_t nowarn)
443 { 445 {
444 ngx_http_variable_t *v; 446 ngx_http_variable_t *v;
445 ngx_http_variable_value_t *vv; 447 ngx_http_variable_value_t *vv;
446 ngx_http_core_main_conf_t *cmcf; 448 ngx_http_core_main_conf_t *cmcf;
447 449
449 451
450 v = ngx_hash_find(&cmcf->variables_hash, key, name->data, name->len); 452 v = ngx_hash_find(&cmcf->variables_hash, key, name->data, name->len);
451 453
452 if (v) { 454 if (v) {
453 if (v->flags & NGX_HTTP_VAR_INDEXED) { 455 if (v->flags & NGX_HTTP_VAR_INDEXED) {
454 return ngx_http_get_indexed_variable(r, v->index); 456 return ngx_http_get_flushed_variable(r, v->index);
455 457
456 } else { 458 } else {
457 459
458 vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t)); 460 vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t));
459 461
490 } 492 }
491 493
492 return NULL; 494 return NULL;
493 } 495 }
494 496
495 if (ngx_strncmp(name->data, "upstream_http_", 10) == 0) { 497 if (ngx_strncmp(name->data, "upstream_http_", 14) == 0) {
496 498
497 if (ngx_http_upstream_header_variable(r, vv, (uintptr_t) name) 499 if (ngx_http_upstream_header_variable(r, vv, (uintptr_t) name)
498 == NGX_OK) 500 == NGX_OK)
499 { 501 {
500 return vv; 502 return vv;
520 522
521 return NULL; 523 return NULL;
522 } 524 }
523 525
524 vv->not_found = 1; 526 vv->not_found = 1;
525
526 if (nowarn == 0) {
527 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
528 "unknown \"%V\" variable", name);
529 }
530 527
531 return vv; 528 return vv;
532 } 529 }
533 530
534 531
566 s->len = v->len; 563 s->len = v->len;
567 s->data = v->data; 564 s->data = v->data;
568 } 565 }
569 566
570 567
568 static ngx_int_t
569 ngx_http_variable_request_get_size(ngx_http_request_t *r,
570 ngx_http_variable_value_t *v, uintptr_t data)
571 {
572 size_t *sp;
573
574 sp = (size_t *) ((char *) r + data);
575
576 v->data = ngx_pnalloc(r->pool, NGX_SIZE_T_LEN);
577 if (v->data == NULL) {
578 return NGX_ERROR;
579 }
580
581 v->len = ngx_sprintf(v->data, "%uz", *sp) - v->data;
582 v->valid = 1;
583 v->no_cacheable = 0;
584 v->not_found = 0;
585
586 return NGX_OK;
587 }
588
589
571 static void 590 static void
572 ngx_http_variable_request_set_size(ngx_http_request_t *r, 591 ngx_http_variable_request_set_size(ngx_http_request_t *r,
573 ngx_http_variable_value_t *v, uintptr_t data) 592 ngx_http_variable_value_t *v, uintptr_t data)
574 { 593 {
575 ssize_t s, *sp; 594 ssize_t s, *sp;
885 904
886 v->len = sizeof(struct in6_addr); 905 v->len = sizeof(struct in6_addr);
887 v->valid = 1; 906 v->valid = 1;
888 v->no_cacheable = 0; 907 v->no_cacheable = 0;
889 v->not_found = 0; 908 v->not_found = 0;
890 v->data = (u_char *) &sin6->sin6_addr; 909 v->data = sin6->sin6_addr.s6_addr;
891 910
892 break; 911 break;
893 #endif 912 #endif
894 913
895 default: /* AF_INET */ 914 default: /* AF_INET */
1369 v->data = r->headers_out.location->value.data; 1388 v->data = r->headers_out.location->value.data;
1370 1389
1371 return NGX_OK; 1390 return NGX_OK;
1372 } 1391 }
1373 1392
1374 name.len = sizeof("sent_http_location") - 1; 1393 ngx_str_set(&name, "sent_http_location");
1375 name.data = (u_char *) "sent_http_location";
1376 1394
1377 return ngx_http_variable_unknown_header(v, &name, 1395 return ngx_http_variable_unknown_header(v, &name,
1378 &r->headers_out.headers.part, 1396 &r->headers_out.headers.part,
1379 sizeof("sent_http_") - 1); 1397 sizeof("sent_http_") - 1);
1380 } 1398 }
1638 v->not_found = 0; 1656 v->not_found = 0;
1639 v->data = p; 1657 v->data = p;
1640 1658
1641 return NGX_OK; 1659 return NGX_OK;
1642 } 1660 }
1661
1662
1663 void *
1664 ngx_http_map_find(ngx_http_request_t *r, ngx_http_map_t *map, ngx_uint_t key,
1665 u_char *text, size_t len, ngx_str_t *match)
1666 {
1667 void *p;
1668
1669 p = ngx_hash_find_combined(&map->hash, key, text, len);
1670 if (p) {
1671 return p;
1672 }
1673
1674 #if (NGX_PCRE)
1675
1676 if (len && map->nregex) {
1677 ngx_int_t n;
1678 ngx_uint_t i;
1679 ngx_http_map_regex_t *reg;
1680
1681 reg = map->regex;
1682
1683 for (i = 0; i < map->nregex; i++) {
1684
1685 n = ngx_http_regex_exec(r, reg[i].regex, match);
1686
1687 if (n == NGX_OK) {
1688 return reg[i].value;
1689 }
1690
1691 if (n == NGX_DECLINED) {
1692 continue;
1693 }
1694
1695 /* NGX_ERROR */
1696
1697 return NULL;
1698 }
1699 }
1700
1701 #endif
1702
1703 return NULL;
1704 }
1705
1706
1707 #if (NGX_PCRE)
1708
1709 static ngx_int_t
1710 ngx_http_variable_not_found(ngx_http_request_t *r, ngx_http_variable_value_t *v,
1711 uintptr_t data)
1712 {
1713 v->not_found = 1;
1714 return NGX_OK;
1715 }
1716
1717
1718 ngx_http_regex_t *
1719 ngx_http_regex_compile(ngx_conf_t *cf, ngx_regex_compile_t *rc)
1720 {
1721 u_char *p;
1722 size_t size;
1723 ngx_str_t name;
1724 ngx_uint_t i, n;
1725 ngx_http_variable_t *v;
1726 ngx_http_regex_t *re;
1727 ngx_http_regex_variable_t *rv;
1728 ngx_http_core_main_conf_t *cmcf;
1729
1730 rc->pool = cf->pool;
1731
1732 if (ngx_regex_compile(rc) != NGX_OK) {
1733 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%V", &rc->err);
1734 return NULL;
1735 }
1736
1737 re = ngx_pcalloc(cf->pool, sizeof(ngx_http_regex_t));
1738 if (re == NULL) {
1739 return NULL;
1740 }
1741
1742 re->regex = rc->regex;
1743 re->ncaptures = rc->captures;
1744
1745 cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
1746 cmcf->ncaptures = ngx_max(cmcf->ncaptures, re->ncaptures);
1747
1748 n = (ngx_uint_t) rc->named_captures;
1749
1750 if (n == 0) {
1751 return re;
1752 }
1753
1754 rv = ngx_palloc(rc->pool, n * sizeof(ngx_http_regex_variable_t));
1755 if (rv == NULL) {
1756 return NULL;
1757 }
1758
1759 re->variables = rv;
1760 re->nvariables = n;
1761 re->name = rc->pattern;
1762
1763 size = rc->name_size;
1764 p = rc->names;
1765
1766 for (i = 0; i < n; i++) {
1767 rv[i].capture = 2 * ((p[0] << 8) + p[1]);
1768
1769 name.data = &p[2];
1770 name.len = ngx_strlen(name.data);
1771
1772 v = ngx_http_add_variable(cf, &name, NGX_HTTP_VAR_CHANGEABLE);
1773 if (v == NULL) {
1774 return NULL;
1775 }
1776
1777 rv[i].index = ngx_http_get_variable_index(cf, &name);
1778 if (rv[i].index == NGX_ERROR) {
1779 return NULL;
1780 }
1781
1782 v->get_handler = ngx_http_variable_not_found;
1783
1784 p += size;
1785 }
1786
1787 return re;
1788 }
1789
1790
1791 ngx_int_t
1792 ngx_http_regex_exec(ngx_http_request_t *r, ngx_http_regex_t *re, ngx_str_t *s)
1793 {
1794 ngx_int_t rc, index;
1795 ngx_uint_t i, n, len;
1796 ngx_http_variable_value_t *vv;
1797 ngx_http_core_main_conf_t *cmcf;
1798
1799 cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
1800
1801 if (re->ncaptures) {
1802 len = cmcf->ncaptures;
1803
1804 if (r->captures == NULL) {
1805 r->captures = ngx_palloc(r->pool, len * sizeof(int));
1806 if (r->captures == NULL) {
1807 return NGX_ERROR;
1808 }
1809 }
1810
1811 } else {
1812 len = 0;
1813 }
1814
1815 rc = ngx_regex_exec(re->regex, s, r->captures, len);
1816
1817 if (rc == NGX_REGEX_NO_MATCHED) {
1818 return NGX_DECLINED;
1819 }
1820
1821 if (rc < 0) {
1822 ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
1823 ngx_regex_exec_n " failed: %i on \"%V\" using \"%V\"",
1824 rc, s, &re->name);
1825 return NGX_ERROR;
1826 }
1827
1828 for (i = 0; i < re->nvariables; i++) {
1829
1830 n = re->variables[i].capture;
1831 index = re->variables[i].index;
1832 vv = &r->variables[index];
1833
1834 vv->len = r->captures[n + 1] - r->captures[n];
1835 vv->valid = 1;
1836 vv->no_cacheable = 0;
1837 vv->not_found = 0;
1838 vv->data = &s->data[r->captures[n]];
1839
1840 #if (NGX_DEBUG)
1841 {
1842 ngx_http_variable_t *v;
1843
1844 v = cmcf->variables.elts;
1845
1846 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1847 "http regex set $%V to \"%*s\"",
1848 &v[index].name, vv->len, vv->data);
1849 }
1850 #endif
1851 }
1852
1853 r->ncaptures = rc * 2;
1854 r->captures_data = s->data;
1855
1856 return NGX_OK;
1857 }
1858
1859 #endif
1643 1860
1644 1861
1645 ngx_int_t 1862 ngx_int_t
1646 ngx_http_variables_add_core_vars(ngx_conf_t *cf) 1863 ngx_http_variables_add_core_vars(ngx_conf_t *cf)
1647 { 1864 {
1755 } 1972 }
1756 1973
1757 if (ngx_strncmp(v[i].name.data, "arg_", 4) == 0) { 1974 if (ngx_strncmp(v[i].name.data, "arg_", 4) == 0) {
1758 v[i].get_handler = ngx_http_variable_argument; 1975 v[i].get_handler = ngx_http_variable_argument;
1759 v[i].data = (uintptr_t) &v[i].name; 1976 v[i].data = (uintptr_t) &v[i].name;
1977 v[i].flags = NGX_HTTP_VAR_NOCACHEABLE;
1760 1978
1761 continue; 1979 continue;
1762 } 1980 }
1763 1981
1764 ngx_log_error(NGX_LOG_EMERG, cf->log, 0, 1982 ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
1797 2015
1798 cmcf->variables_keys = NULL; 2016 cmcf->variables_keys = NULL;
1799 2017
1800 return NGX_OK; 2018 return NGX_OK;
1801 } 2019 }
1802
1803
1804 void
1805 ngx_http_variable_value_rbtree_insert(ngx_rbtree_node_t *temp,
1806 ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel)
1807 {
1808 ngx_rbtree_node_t **p;
1809 ngx_http_variable_value_node_t *vvn, *vvt;
1810
1811 for ( ;; ) {
1812
1813 vvn = (ngx_http_variable_value_node_t *) node;
1814 vvt = (ngx_http_variable_value_node_t *) temp;
1815
1816 if (node->key != temp->key) {
1817
1818 p = (node->key < temp->key) ? &temp->left : &temp->right;
1819
1820 } else if (vvn->len != vvt->len) {
1821
1822 p = (vvn->len < vvt->len) ? &temp->left : &temp->right;
1823
1824 } else {
1825 p = (ngx_memcmp(vvn->value->data, vvt->value->data, vvn->len) < 0)
1826 ? &temp->left : &temp->right;
1827 }
1828
1829 if (*p == sentinel) {
1830 break;
1831 }
1832
1833 temp = *p;
1834 }
1835
1836 *p = node;
1837 node->parent = temp;
1838 node->left = sentinel;
1839 node->right = sentinel;
1840 ngx_rbt_red(node);
1841 }
1842
1843
1844 ngx_http_variable_value_t *
1845 ngx_http_variable_value_lookup(ngx_rbtree_t *rbtree, ngx_str_t *val,
1846 uint32_t hash)
1847 {
1848 ngx_int_t rc;
1849 ngx_rbtree_node_t *node, *sentinel;
1850 ngx_http_variable_value_node_t *vvn;
1851
1852 node = rbtree->root;
1853 sentinel = rbtree->sentinel;
1854
1855 while (node != sentinel) {
1856
1857 vvn = (ngx_http_variable_value_node_t *) node;
1858
1859 if (hash != node->key) {
1860 node = (hash < node->key) ? node->left : node->right;
1861 continue;
1862 }
1863
1864 if (val->len != vvn->len) {
1865 node = (val->len < vvn->len) ? node->left : node->right;
1866 continue;
1867 }
1868
1869 rc = ngx_memcmp(val->data, vvn->value->data, val->len);
1870
1871 if (rc < 0) {
1872 node = node->left;
1873 continue;
1874 }
1875
1876 if (rc > 0) {
1877 node = node->right;
1878 continue;
1879 }
1880
1881 return vvn->value;
1882 }
1883
1884 return NULL;
1885 }