comparison src/http/ngx_http_variables.c @ 578:f3a9e57d2e17

Merge with current.
author Maxim Dounin <mdounin@mdounin.ru>
date Thu, 11 Mar 2010 21:27:17 +0300
parents da3c99095432
children 566e105a89f1
comparison
equal deleted inserted replaced
539:5f4de8cf0d9d 578:f3a9e57d2e17
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); 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,
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);
21 static ngx_int_t ngx_http_variable_headers(ngx_http_request_t *r, 23 static ngx_int_t ngx_http_variable_headers(ngx_http_request_t *r,
22 ngx_http_variable_value_t *v, uintptr_t data); 24 ngx_http_variable_value_t *v, uintptr_t data);
23 25
24 static ngx_int_t ngx_http_variable_unknown_header_in(ngx_http_request_t *r, 26 static ngx_int_t ngx_http_variable_unknown_header_in(ngx_http_request_t *r,
25 ngx_http_variable_value_t *v, uintptr_t data); 27 ngx_http_variable_value_t *v, uintptr_t data);
26 static ngx_int_t ngx_http_variable_unknown_header_out(ngx_http_request_t *r, 28 static ngx_int_t ngx_http_variable_unknown_header_out(ngx_http_request_t *r,
29 ngx_http_variable_value_t *v, uintptr_t data);
30 static ngx_int_t ngx_http_variable_request_line(ngx_http_request_t *r,
27 ngx_http_variable_value_t *v, uintptr_t data); 31 ngx_http_variable_value_t *v, uintptr_t data);
28 static ngx_int_t ngx_http_variable_cookie(ngx_http_request_t *r, 32 static ngx_int_t ngx_http_variable_cookie(ngx_http_request_t *r,
29 ngx_http_variable_value_t *v, uintptr_t data); 33 ngx_http_variable_value_t *v, uintptr_t data);
30 static ngx_int_t ngx_http_variable_argument(ngx_http_request_t *r, 34 static ngx_int_t ngx_http_variable_argument(ngx_http_request_t *r,
31 ngx_http_variable_value_t *v, uintptr_t data); 35 ngx_http_variable_value_t *v, uintptr_t data);
162 166
163 { ngx_string("document_uri"), NULL, ngx_http_variable_request, 167 { ngx_string("document_uri"), NULL, ngx_http_variable_request,
164 offsetof(ngx_http_request_t, uri), 168 offsetof(ngx_http_request_t, uri),
165 NGX_HTTP_VAR_NOCACHEABLE, 0 }, 169 NGX_HTTP_VAR_NOCACHEABLE, 0 },
166 170
167 { ngx_string("request"), NULL, ngx_http_variable_request, 171 { ngx_string("request"), NULL, ngx_http_variable_request_line, 0, 0, 0 },
168 offsetof(ngx_http_request_t, request_line), 0, 0 },
169 172
170 { ngx_string("document_root"), NULL, 173 { ngx_string("document_root"), NULL,
171 ngx_http_variable_document_root, 0, NGX_HTTP_VAR_NOCACHEABLE, 0 }, 174 ngx_http_variable_document_root, 0, NGX_HTTP_VAR_NOCACHEABLE, 0 },
172 175
173 { ngx_string("realpath_root"), NULL, 176 { ngx_string("realpath_root"), NULL,
191 NGX_HTTP_VAR_NOCACHEABLE, 0 }, 194 NGX_HTTP_VAR_NOCACHEABLE, 0 },
192 195
193 { 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 },
194 197
195 { ngx_string("request_method"), NULL, 198 { ngx_string("request_method"), NULL,
196 ngx_http_variable_request_method, 0, 0, 0 }, 199 ngx_http_variable_request_method, 0,
200 NGX_HTTP_VAR_NOCACHEABLE, 0 },
197 201
198 { 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 },
199 203
200 { 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,
201 0, 0, 0 }, 205 0, 0, 0 },
235 239
236 { ngx_string("sent_http_cache_control"), NULL, ngx_http_variable_headers, 240 { ngx_string("sent_http_cache_control"), NULL, ngx_http_variable_headers,
237 offsetof(ngx_http_request_t, headers_out.cache_control), 0, 0 }, 241 offsetof(ngx_http_request_t, headers_out.cache_control), 0, 0 },
238 242
239 { ngx_string("limit_rate"), ngx_http_variable_request_set_size, 243 { ngx_string("limit_rate"), ngx_http_variable_request_set_size,
240 ngx_http_variable_request, 244 ngx_http_variable_request_get_size,
241 offsetof(ngx_http_request_t, limit_rate), 245 offsetof(ngx_http_request_t, limit_rate),
242 NGX_HTTP_VAR_CHANGEABLE|NGX_HTTP_VAR_NOCACHEABLE, 0 }, 246 NGX_HTTP_VAR_CHANGEABLE|NGX_HTTP_VAR_NOCACHEABLE, 0 },
243 247
244 { ngx_string("nginx_version"), NULL, ngx_http_variable_nginx_version, 248 { ngx_string("nginx_version"), NULL, ngx_http_variable_nginx_version,
245 0, 0, 0 }, 249 0, 0, 0 },
489 } 493 }
490 494
491 return NULL; 495 return NULL;
492 } 496 }
493 497
494 if (ngx_strncmp(name->data, "upstream_http_", 10) == 0) { 498 if (ngx_strncmp(name->data, "upstream_http_", 14) == 0) {
495 499
496 if (ngx_http_upstream_header_variable(r, vv, (uintptr_t) name) 500 if (ngx_http_upstream_header_variable(r, vv, (uintptr_t) name)
497 == NGX_OK) 501 == NGX_OK)
498 { 502 {
499 return vv; 503 return vv;
565 s->len = v->len; 569 s->len = v->len;
566 s->data = v->data; 570 s->data = v->data;
567 } 571 }
568 572
569 573
574 static ngx_int_t
575 ngx_http_variable_request_get_size(ngx_http_request_t *r,
576 ngx_http_variable_value_t *v, uintptr_t data)
577 {
578 size_t *sp;
579
580 sp = (size_t *) ((char *) r + data);
581
582 v->data = ngx_pnalloc(r->pool, NGX_SIZE_T_LEN);
583 if (v->data == NULL) {
584 return NGX_ERROR;
585 }
586
587 v->len = ngx_sprintf(v->data, "%uz", *sp) - v->data;
588 v->valid = 1;
589 v->no_cacheable = 0;
590 v->not_found = 0;
591
592 return NGX_OK;
593 }
594
595
570 static void 596 static void
571 ngx_http_variable_request_set_size(ngx_http_request_t *r, 597 ngx_http_variable_request_set_size(ngx_http_request_t *r,
572 ngx_http_variable_value_t *v, uintptr_t data) 598 ngx_http_variable_value_t *v, uintptr_t data)
573 { 599 {
574 ssize_t s, *sp; 600 ssize_t s, *sp;
749 return NGX_OK; 775 return NGX_OK;
750 } 776 }
751 777
752 778
753 static ngx_int_t 779 static ngx_int_t
780 ngx_http_variable_request_line(ngx_http_request_t *r,
781 ngx_http_variable_value_t *v, uintptr_t data)
782 {
783 u_char *p, *s;
784
785 s = r->request_line.data;
786
787 if (s == NULL) {
788 s = r->request_start;
789
790 if (s == NULL) {
791 v->not_found = 1;
792 return NGX_OK;
793 }
794
795 for (p = s; p < r->header_in->last; p++) {
796 if (*p == CR || *p == LF) {
797 break;
798 }
799 }
800
801 r->request_line.len = p - s;
802 r->request_line.data = s;
803 }
804
805 v->len = r->request_line.len;
806 v->valid = 1;
807 v->no_cacheable = 0;
808 v->not_found = 0;
809 v->data = s;
810
811 return NGX_OK;
812 }
813
814
815 static ngx_int_t
754 ngx_http_variable_cookie(ngx_http_request_t *r, ngx_http_variable_value_t *v, 816 ngx_http_variable_cookie(ngx_http_request_t *r, ngx_http_variable_value_t *v,
755 uintptr_t data) 817 uintptr_t data)
756 { 818 {
757 ngx_str_t *name = (ngx_str_t *) data; 819 ngx_str_t *name = (ngx_str_t *) data;
758 820
848 910
849 v->len = sizeof(struct in6_addr); 911 v->len = sizeof(struct in6_addr);
850 v->valid = 1; 912 v->valid = 1;
851 v->no_cacheable = 0; 913 v->no_cacheable = 0;
852 v->not_found = 0; 914 v->not_found = 0;
853 v->data = (u_char *) &sin6->sin6_addr; 915 v->data = sin6->sin6_addr.s6_addr;
854 916
855 break; 917 break;
856 #endif 918 #endif
857 919
858 default: /* AF_INET */ 920 default: /* AF_INET */
1601 v->not_found = 0; 1663 v->not_found = 0;
1602 v->data = p; 1664 v->data = p;
1603 1665
1604 return NGX_OK; 1666 return NGX_OK;
1605 } 1667 }
1668
1669
1670 #if (NGX_PCRE)
1671
1672 static ngx_int_t
1673 ngx_http_variable_not_found(ngx_http_request_t *r, ngx_http_variable_value_t *v,
1674 uintptr_t data)
1675 {
1676 v->not_found = 1;
1677 return NGX_OK;
1678 }
1679
1680
1681 ngx_http_regex_t *
1682 ngx_http_regex_compile(ngx_conf_t *cf, ngx_regex_compile_t *rc)
1683 {
1684 u_char *p;
1685 size_t size;
1686 ngx_str_t name;
1687 ngx_uint_t i, n;
1688 ngx_http_variable_t *v;
1689 ngx_http_regex_t *re;
1690 ngx_http_regex_variable_t *rv;
1691 ngx_http_core_main_conf_t *cmcf;
1692
1693 rc->pool = cf->pool;
1694
1695 if (ngx_regex_compile(rc) != NGX_OK) {
1696 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%V", &rc->err);
1697 return NULL;
1698 }
1699
1700 re = ngx_pcalloc(cf->pool, sizeof(ngx_http_regex_t));
1701 if (re == NULL) {
1702 return NULL;
1703 }
1704
1705 re->regex = rc->regex;
1706 re->ncaptures = rc->captures;
1707
1708 cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
1709 cmcf->ncaptures = ngx_max(cmcf->ncaptures, re->ncaptures);
1710
1711 n = (ngx_uint_t) rc->named_captures;
1712
1713 if (n == 0) {
1714 return re;
1715 }
1716
1717 rv = ngx_palloc(rc->pool, n * sizeof(ngx_http_regex_variable_t));
1718 if (rv == NULL) {
1719 return NULL;
1720 }
1721
1722 re->variables = rv;
1723 re->nvariables = n;
1724 re->name = rc->pattern;
1725
1726 size = rc->name_size;
1727 p = rc->names;
1728
1729 for (i = 0; i < n; i++) {
1730 rv[i].capture = 2 * ((p[0] << 8) + p[1]);
1731
1732 name.data = &p[2];
1733 name.len = ngx_strlen(name.data);
1734
1735 v = ngx_http_add_variable(cf, &name, NGX_HTTP_VAR_CHANGEABLE);
1736 if (v == NULL) {
1737 return NULL;
1738 }
1739
1740 rv[i].index = ngx_http_get_variable_index(cf, &name);
1741 if (rv[i].index == NGX_ERROR) {
1742 return NULL;
1743 }
1744
1745 v->get_handler = ngx_http_variable_not_found;
1746
1747 p += size;
1748 }
1749
1750 return re;
1751 }
1752
1753
1754 ngx_int_t
1755 ngx_http_regex_exec(ngx_http_request_t *r, ngx_http_regex_t *re, ngx_str_t *s)
1756 {
1757 ngx_int_t rc, index;
1758 ngx_uint_t i, n, len;
1759 ngx_http_variable_value_t *vv;
1760 ngx_http_core_main_conf_t *cmcf;
1761
1762 cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
1763
1764 if (re->ncaptures) {
1765 len = cmcf->ncaptures;
1766
1767 if (r->captures == NULL) {
1768 r->captures = ngx_palloc(r->pool, len * sizeof(int));
1769 if (r->captures == NULL) {
1770 return NGX_ERROR;
1771 }
1772 }
1773
1774 } else {
1775 len = 0;
1776 }
1777
1778 rc = ngx_regex_exec(re->regex, s, r->captures, len);
1779
1780 if (rc == NGX_REGEX_NO_MATCHED) {
1781 return NGX_DECLINED;
1782 }
1783
1784 if (rc < 0) {
1785 ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
1786 ngx_regex_exec_n " failed: %i on \"%V\" using \"%V\"",
1787 rc, s, &re->name);
1788 return NGX_ERROR;
1789 }
1790
1791 for (i = 0; i < re->nvariables; i++) {
1792
1793 n = re->variables[i].capture;
1794 index = re->variables[i].index;
1795 vv = &r->variables[index];
1796
1797 vv->len = r->captures[n + 1] - r->captures[n];
1798 vv->valid = 1;
1799 vv->no_cacheable = 0;
1800 vv->not_found = 0;
1801 vv->data = &s->data[r->captures[n]];
1802
1803 #if (NGX_DEBUG)
1804 {
1805 ngx_http_variable_t *v;
1806
1807 v = cmcf->variables.elts;
1808
1809 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1810 "http regex set $%V to \"%*s\"",
1811 &v[index].name, vv->len, vv->data);
1812 }
1813 #endif
1814 }
1815
1816 r->ncaptures = rc * 2;
1817 r->captures_data = s->data;
1818
1819 return NGX_OK;
1820 }
1821
1822 #endif
1606 1823
1607 1824
1608 ngx_int_t 1825 ngx_int_t
1609 ngx_http_variables_add_core_vars(ngx_conf_t *cf) 1826 ngx_http_variables_add_core_vars(ngx_conf_t *cf)
1610 { 1827 {