comparison src/http/ngx_http_upstream.c @ 122:d25a1d6034f1 NGINX_0_3_8

nginx 0.3.8 *) Security: nginx now checks URI got from a backend in "X-Accel-Redirect" header line or in SSI file for the "/../" paths and zeroes. *) Change: nginx now does not treat the empty user name in the "Authorization" header line as valid one. *) Feature: the "ssl_session_timeout" directives of the ngx_http_ssl_module and ngx_imap_ssl_module. *) Feature: the "auth_http_header" directive of the ngx_imap_auth_http_module. *) Feature: the "add_header" directive. *) Feature: the ngx_http_realip_module. *) Feature: the new variables to use in the "log_format" directive: $bytes_sent, $apache_bytes_sent, $status, $time_gmt, $uri, $request_time, $request_length, $upstream_status, $upstream_response_time, $gzip_ratio, $uid_got, $uid_set, $connection, $pipe, and $msec. The parameters in the "%name" form will be canceled soon. *) Change: now the false variable values in the "if" directive are the empty string "" and string starting with "0". *) Bugfix: while using proxied or FastCGI-server nginx may leave connections and temporary files with client requests in open state. *) Bugfix: the worker processes did not flush the buffered logs on graceful exit. *) Bugfix: if the request URI was changes by the "rewrite" directive and the request was proxied in location given by regular expression, then the incorrect request was transferred to backend; bug appeared in 0.2.6. *) Bugfix: the "expires" directive did not remove the previous "Expires" header. *) Bugfix: nginx may stop to accept requests if the "rtsig" method and several worker processes were used. *) Bugfix: the "\"" and "\'" escape symbols were incorrectly handled in SSI commands. *) Bugfix: if the response was ended just after the SSI command and gzipping was used, then the response did not transferred complete or did not transferred at all.
author Igor Sysoev <http://sysoev.ru>
date Wed, 09 Nov 2005 00:00:00 +0300
parents 644a7935144b
children df17fbafec8f
comparison
equal deleted inserted replaced
121:737953b238a4 122:d25a1d6034f1
65 65
66 static size_t ngx_http_upstream_log_status_getlen(ngx_http_request_t *r, 66 static size_t ngx_http_upstream_log_status_getlen(ngx_http_request_t *r,
67 uintptr_t data); 67 uintptr_t data);
68 static u_char *ngx_http_upstream_log_status(ngx_http_request_t *r, 68 static u_char *ngx_http_upstream_log_status(ngx_http_request_t *r,
69 u_char *buf, ngx_http_log_op_t *op); 69 u_char *buf, ngx_http_log_op_t *op);
70 static size_t ngx_http_upstream_log_response_time_getlen(ngx_http_request_t *r,
71 uintptr_t data);
70 static u_char *ngx_http_upstream_log_response_time(ngx_http_request_t *r, 72 static u_char *ngx_http_upstream_log_response_time(ngx_http_request_t *r,
71 u_char *buf, ngx_http_log_op_t *op); 73 u_char *buf, ngx_http_log_op_t *op);
72 74
73 static u_char *ngx_http_upstream_log_error(ngx_http_request_t *r, u_char *buf, 75 static u_char *ngx_http_upstream_log_error(ngx_http_request_t *r, u_char *buf,
74 size_t len); 76 size_t len);
75 static ngx_int_t ngx_http_upstream_add_log_formats(ngx_conf_t *cf); 77
78 static ngx_int_t ngx_http_upstream_add_variables(ngx_conf_t *cf);
79 static ngx_int_t ngx_http_upstream_status_variable(ngx_http_request_t *r,
80 ngx_http_variable_value_t *v, uintptr_t data);
81 static ngx_int_t ngx_http_upstream_response_time_variable(ngx_http_request_t *r,
82 ngx_http_variable_value_t *v, uintptr_t data);
83
76 static void *ngx_http_upstream_create_main_conf(ngx_conf_t *cf); 84 static void *ngx_http_upstream_create_main_conf(ngx_conf_t *cf);
77 static char *ngx_http_core_init_main_conf(ngx_conf_t *cf, void *conf); 85 static char *ngx_http_core_init_main_conf(ngx_conf_t *cf, void *conf);
78 86
79 87
80 ngx_http_upstream_header_t ngx_http_upstream_headers_in[] = { 88 ngx_http_upstream_header_t ngx_http_upstream_headers_in[] = {
130 { ngx_string("Cache-Control"), 138 { ngx_string("Cache-Control"),
131 ngx_http_upstream_process_multi_header_lines, 139 ngx_http_upstream_process_multi_header_lines,
132 offsetof(ngx_http_upstream_headers_in_t, cache_control), 140 offsetof(ngx_http_upstream_headers_in_t, cache_control),
133 ngx_http_upstream_copy_multi_header_lines, 141 ngx_http_upstream_copy_multi_header_lines,
134 offsetof(ngx_http_headers_out_t, cache_control), 1 }, 142 offsetof(ngx_http_headers_out_t, cache_control), 1 },
143
144 { ngx_string("Expires"),
145 ngx_http_upstream_process_header_line,
146 offsetof(ngx_http_upstream_headers_in_t, expires),
147 ngx_http_upstream_copy_header_line,
148 offsetof(ngx_http_headers_out_t, expires), 1 },
135 149
136 { ngx_string("Connection"), 150 { ngx_string("Connection"),
137 ngx_http_upstream_ignore_header_line, 0, 151 ngx_http_upstream_ignore_header_line, 0,
138 ngx_http_upstream_ignore_header_line, 0, 0 }, 152 ngx_http_upstream_ignore_header_line, 0, 0 },
139 153
171 { ngx_null_string, NULL, 0, NULL, 0, 0 } 185 { ngx_null_string, NULL, 0, NULL, 0, 0 }
172 }; 186 };
173 187
174 188
175 ngx_http_module_t ngx_http_upstream_module_ctx = { 189 ngx_http_module_t ngx_http_upstream_module_ctx = {
176 ngx_http_upstream_add_log_formats, /* preconfiguration */ 190 ngx_http_upstream_add_variables, /* preconfiguration */
177 NULL, /* postconfiguration */ 191 NULL, /* postconfiguration */
178 192
179 ngx_http_upstream_create_main_conf, /* create main configuration */ 193 ngx_http_upstream_create_main_conf, /* create main configuration */
180 ngx_http_core_init_main_conf, /* init main configuration */ 194 ngx_http_core_init_main_conf, /* init main configuration */
181 195
203 }; 217 };
204 218
205 219
206 static ngx_http_log_op_name_t ngx_http_upstream_log_fmt_ops[] = { 220 static ngx_http_log_op_name_t ngx_http_upstream_log_fmt_ops[] = {
207 { ngx_string("upstream_status"), 0, NULL, 221 { ngx_string("upstream_status"), 0, NULL,
208 ngx_http_upstream_log_status_getlen, 222 ngx_http_upstream_log_status_getlen,
209 ngx_http_upstream_log_status }, 223 ngx_http_upstream_log_status },
210 { ngx_string("upstream_response_time"), NGX_TIME_T_LEN + 4, NULL, NULL, 224 { ngx_string("upstream_response_time"), 0, NULL,
211 ngx_http_upstream_log_response_time }, 225 ngx_http_upstream_log_response_time_getlen,
226 ngx_http_upstream_log_response_time },
212 { ngx_null_string, 0, NULL, NULL, NULL } 227 { ngx_null_string, 0, NULL, NULL, NULL }
228 };
229
230
231 static ngx_http_variable_t ngx_http_upstream_vars[] = {
232
233 { ngx_string("upstream_status"),
234 ngx_http_upstream_status_variable, 0, 0, 0 },
235
236 { ngx_string("upstream_response_time"),
237 ngx_http_upstream_response_time_variable, 0, 0, 0 },
238
239 { ngx_null_string, NULL, 0, 0, 0 }
213 }; 240 };
214 241
215 242
216 char *ngx_http_upstream_header_errors[] = { 243 char *ngx_http_upstream_header_errors[] = {
217 "upstream sent invalid header", 244 "upstream sent invalid header",
507 NGX_HTTP_INTERNAL_SERVER_ERROR); 534 NGX_HTTP_INTERNAL_SERVER_ERROR);
508 return; 535 return;
509 } 536 }
510 } 537 }
511 538
512 if (r->request_body) { 539 if (r->request_body && r->request_body->temp_file && r->main == r) {
513 if (r->request_body->temp_file && r->main == r) { 540
514 541 /*
515 /* 542 * the r->request_body->buf can be reused for one request only,
516 * the r->request_body->buf can be reused for one request only, 543 * the subrequests should allocate their own temporay bufs
517 * the subrequests should allocate their own temporay bufs 544 */
518 */ 545
519 546 u->output.free = ngx_alloc_chain_link(r->pool);
520 u->output.free = ngx_alloc_chain_link(r->pool); 547 if (u->output.free == NULL) {
521 if (u->output.free == NULL) { 548 ngx_http_upstream_finalize_request(r, u,
522 ngx_http_upstream_finalize_request(r, u, 549 NGX_HTTP_INTERNAL_SERVER_ERROR);
523 NGX_HTTP_INTERNAL_SERVER_ERROR); 550 return;
524 return; 551 }
525 } 552
526 553 u->output.free->buf = r->request_body->buf;
527 u->output.free->buf = r->request_body->buf; 554 u->output.free->next = NULL;
528 u->output.free->next = NULL; 555 u->output.allocated = 1;
529 u->output.allocated = 1; 556
530 557 r->request_body->buf->pos = r->request_body->buf->start;
531 r->request_body->buf->pos = r->request_body->buf->start; 558 r->request_body->buf->last = r->request_body->buf->start;
532 r->request_body->buf->last = r->request_body->buf->start; 559 r->request_body->buf->tag = u->output.tag;
533 r->request_body->buf->tag = u->output.tag;
534 }
535 } 560 }
536 561
537 u->request_sent = 0; 562 u->request_sent = 0;
538 563
539 if (rc == NGX_AGAIN) { 564 if (rc == NGX_AGAIN) {
572 cl->buf->file_pos = 0; 597 cl->buf->file_pos = 0;
573 } 598 }
574 599
575 /* reinit the subrequest's ngx_output_chain() context */ 600 /* reinit the subrequest's ngx_output_chain() context */
576 601
577 if (r->request_body) { 602 if (r->request_body && r->request_body->temp_file
578 if (r->request_body->temp_file && r->main != r && u->output.buf) { 603 && r->main != r && u->output.buf)
579 604 {
580 u->output.free = ngx_alloc_chain_link(r->pool); 605 u->output.free = ngx_alloc_chain_link(r->pool);
581 if (u->output.free == NULL) { 606 if (u->output.free == NULL) {
582 return NGX_ERROR; 607 return NGX_ERROR;
583 } 608 }
584 609
585 u->output.free->buf = u->output.buf; 610 u->output.free->buf = u->output.buf;
586 u->output.free->next = NULL; 611 u->output.free->next = NULL;
587 612
588 u->output.buf->pos = u->output.buf->start; 613 u->output.buf->pos = u->output.buf->start;
589 u->output.buf->last = u->output.buf->start; 614 u->output.buf->last = u->output.buf->start;
590 }
591 } 615 }
592 616
593 u->output.buf = NULL; 617 u->output.buf = NULL;
594 u->output.in = NULL; 618 u->output.in = NULL;
595 u->output.busy = NULL; 619 u->output.busy = NULL;
688 NGX_HTTP_INTERNAL_SERVER_ERROR); 712 NGX_HTTP_INTERNAL_SERVER_ERROR);
689 return; 713 return;
690 } 714 }
691 715
692 c->tcp_nopush = NGX_TCP_NOPUSH_UNSET; 716 c->tcp_nopush = NGX_TCP_NOPUSH_UNSET;
693 return;
694 } 717 }
695 718
696 ngx_add_timer(c->read, u->conf->read_timeout); 719 ngx_add_timer(c->read, u->conf->read_timeout);
697 720
698 #if 1 721 #if 1
749 static void 772 static void
750 ngx_http_upstream_process_header(ngx_event_t *rev) 773 ngx_http_upstream_process_header(ngx_event_t *rev)
751 { 774 {
752 ssize_t n; 775 ssize_t n;
753 ngx_int_t rc; 776 ngx_int_t rc;
754 ngx_uint_t i, key; 777 ngx_str_t *uri, args;
778 ngx_uint_t i, key, flags;
755 ngx_list_part_t *part; 779 ngx_list_part_t *part;
756 ngx_table_elt_t *h; 780 ngx_table_elt_t *h;
757 ngx_connection_t *c; 781 ngx_connection_t *c;
758 ngx_http_request_t *r; 782 ngx_http_request_t *r;
759 ngx_http_upstream_t *u; 783 ngx_http_upstream_t *u;
980 } 1004 }
981 1005
982 } 1006 }
983 } 1007 }
984 1008
985 ngx_http_internal_redirect(r, 1009 uri = &r->upstream->headers_in.x_accel_redirect->value;
986 &r->upstream->headers_in.x_accel_redirect->value, 1010 args.len = 0;
987 NULL); 1011 args.data = NULL;
1012 flags = 0;
1013
1014 if (ngx_http_parse_unsafe_uri(r, uri, &args, &flags) != NGX_OK) {
1015 ngx_http_upstream_finalize_request(r, u, NGX_HTTP_NOT_FOUND);
1016 return;
1017 }
1018
1019 if (flags & NGX_HTTP_ZERO_IN_URI) {
1020 r->zero_in_uri = 1;
1021 }
1022
1023 ngx_http_internal_redirect(r, uri, &args);
988 return; 1024 return;
989 } 1025 }
990 1026
991 ngx_http_upstream_send_response(r, u); 1027 ngx_http_upstream_send_response(r, u);
992 } 1028 }
1055 return; 1091 return;
1056 } 1092 }
1057 1093
1058 u->header_sent = 1; 1094 u->header_sent = 1;
1059 1095
1060 if (r->request_body->temp_file) { 1096 if (r->request_body && r->request_body->temp_file) {
1061 for (cl = r->pool->cleanup; cl; cl = cl->next) { 1097 for (cl = r->pool->cleanup; cl; cl = cl->next) {
1062 if (cl->handler == ngx_pool_cleanup_file) { 1098 if (cl->handler == ngx_pool_cleanup_file) {
1063 clf = cl->data; 1099 clf = cl->data;
1064 1100
1065 if (clf->fd == r->request_body->temp_file->file.fd) { 1101 if (clf->fd == r->request_body->temp_file->file.fd) {
1584 1620
1585 static ngx_int_t 1621 static ngx_int_t
1586 ngx_http_upstream_copy_header_line(ngx_http_request_t *r, ngx_table_elt_t *h, 1622 ngx_http_upstream_copy_header_line(ngx_http_request_t *r, ngx_table_elt_t *h,
1587 ngx_uint_t offset) 1623 ngx_uint_t offset)
1588 { 1624 {
1589 ngx_table_elt_t *ho; 1625 ngx_table_elt_t *ho, **ph;
1590 1626
1591 ho = ngx_list_push(&r->headers_out.headers); 1627 ho = ngx_list_push(&r->headers_out.headers);
1592 if (ho == NULL) { 1628 if (ho == NULL) {
1593 return NGX_ERROR; 1629 return NGX_ERROR;
1594 } 1630 }
1595 1631
1596 *ho = *h; 1632 *ho = *h;
1633
1634 if (offset) {
1635 ph = (ngx_table_elt_t **) ((char *) &r->headers_out + offset);
1636 *ph = ho;
1637 }
1597 1638
1598 return NGX_OK; 1639 return NGX_OK;
1599 } 1640 }
1600 1641
1601 1642
1812 ngx_http_upstream_t *u; 1853 ngx_http_upstream_t *u;
1813 ngx_http_upstream_state_t *state; 1854 ngx_http_upstream_state_t *state;
1814 1855
1815 u = r->upstream; 1856 u = r->upstream;
1816 1857
1817 if (u == NULL) { 1858 if (u == NULL || u->states.nelts == 0) {
1818 *buf = '-'; 1859 *buf = '-';
1819 return buf + 1; 1860 return buf + 1;
1820 } 1861 }
1821 1862
1822 i = 0; 1863 i = 0;
1838 *buf++ = ' '; 1879 *buf++ = ' ';
1839 } 1880 }
1840 } 1881 }
1841 1882
1842 1883
1884 static size_t
1885 ngx_http_upstream_log_response_time_getlen(ngx_http_request_t *r,
1886 uintptr_t data)
1887 {
1888 if (r->upstream) {
1889 return r->upstream->states.nelts * (NGX_TIME_T_LEN + 4 + 2);
1890 }
1891
1892 return 1;
1893 }
1894
1895
1843 static u_char * 1896 static u_char *
1844 ngx_http_upstream_log_response_time(ngx_http_request_t *r, u_char *buf, 1897 ngx_http_upstream_log_response_time(ngx_http_request_t *r, u_char *buf,
1845 ngx_http_log_op_t *op) 1898 ngx_http_log_op_t *op)
1846 { 1899 {
1847 ngx_uint_t i; 1900 ngx_uint_t i;
1848 ngx_http_upstream_t *u; 1901 ngx_http_upstream_t *u;
1849 ngx_http_upstream_state_t *state; 1902 ngx_http_upstream_state_t *state;
1850 1903
1851 u = r->upstream; 1904 u = r->upstream;
1852 1905
1853 if (u == NULL) { 1906 if (u == NULL || u->states.nelts == 0) {
1854 *buf = '-'; 1907 *buf = '-';
1855 return buf + 1; 1908 return buf + 1;
1856 } 1909 }
1857 1910
1858 i = 0; 1911 i = 0;
1903 return ngx_http_log_error_info(r, buf, len); 1956 return ngx_http_log_error_info(r, buf, len);
1904 } 1957 }
1905 1958
1906 1959
1907 static ngx_int_t 1960 static ngx_int_t
1908 ngx_http_upstream_add_log_formats(ngx_conf_t *cf) 1961 ngx_http_upstream_add_variables(ngx_conf_t *cf)
1909 { 1962 {
1963 ngx_http_variable_t *var, *v;
1910 ngx_http_log_op_name_t *op; 1964 ngx_http_log_op_name_t *op;
1965
1966 for (v = ngx_http_upstream_vars; v->name.len; v++) {
1967 var = ngx_http_add_variable(cf, &v->name, v->flags);
1968 if (var == NULL) {
1969 return NGX_ERROR;
1970 }
1971
1972 var->handler = v->handler;
1973 var->data = v->data;
1974 }
1911 1975
1912 for (op = ngx_http_upstream_log_fmt_ops; op->name.len; op++) { /* void */ } 1976 for (op = ngx_http_upstream_log_fmt_ops; op->name.len; op++) { /* void */ }
1913 op->run = NULL; 1977 op->run = NULL;
1914 1978
1915 for (op = ngx_http_log_fmt_ops; op->run; op++) { 1979 for (op = ngx_http_log_fmt_ops; op->run; op++) {
1917 op = (ngx_http_log_op_name_t *) op->run; 1981 op = (ngx_http_log_op_name_t *) op->run;
1918 } 1982 }
1919 } 1983 }
1920 1984
1921 op->run = (ngx_http_log_op_run_pt) ngx_http_upstream_log_fmt_ops; 1985 op->run = (ngx_http_log_op_run_pt) ngx_http_upstream_log_fmt_ops;
1986
1987 return NGX_OK;
1988 }
1989
1990
1991 static ngx_int_t
1992 ngx_http_upstream_status_variable(ngx_http_request_t *r,
1993 ngx_http_variable_value_t *v, uintptr_t data)
1994 {
1995 u_char *p;
1996 size_t len;
1997 ngx_uint_t i;
1998 ngx_http_upstream_t *u;
1999 ngx_http_upstream_state_t *state;
2000
2001 v->valid = 1;
2002 v->no_cachable = 0;
2003 v->not_found = 0;
2004
2005 u = r->upstream;
2006
2007 if (u == NULL || u->states.nelts == 0) {
2008 v->not_found = 1;
2009 return NGX_OK;
2010 }
2011
2012 len = u->states.nelts * (3 + 2);
2013
2014 p = ngx_palloc(r->pool, len);
2015 if (p == NULL) {
2016 return NGX_ERROR;
2017 }
2018
2019 v->data = p;
2020
2021 i = 0;
2022 state = u->states.elts;
2023
2024 for ( ;; ) {
2025 if (state[i].status == 0) {
2026 *p++ = '-';
2027
2028 } else {
2029 p = ngx_sprintf(p, "%ui", state[i].status);
2030 }
2031
2032 if (++i == u->states.nelts) {
2033 break;
2034 }
2035
2036 *p++ = ',';
2037 *p++ = ' ';
2038 }
2039
2040 v->len = p - v->data;
2041
2042 return NGX_OK;
2043 }
2044
2045
2046 static ngx_int_t
2047 ngx_http_upstream_response_time_variable(ngx_http_request_t *r,
2048 ngx_http_variable_value_t *v, uintptr_t data)
2049 {
2050 u_char *p;
2051 size_t len;
2052 ngx_uint_t i;
2053 ngx_http_upstream_t *u;
2054 ngx_http_upstream_state_t *state;
2055
2056 v->valid = 1;
2057 v->no_cachable = 0;
2058 v->not_found = 0;
2059
2060 u = r->upstream;
2061
2062 if (u == NULL || u->states.nelts == 0) {
2063 v->not_found = 1;
2064 return NGX_OK;
2065 }
2066
2067 len = u->states.nelts * (NGX_TIME_T_LEN + 4 + 2);
2068
2069 p = ngx_palloc(r->pool, len);
2070 if (p == NULL) {
2071 return NGX_ERROR;
2072 }
2073
2074 v->data = p;
2075
2076 i = 0;
2077 state = u->states.elts;
2078
2079 for ( ;; ) {
2080 if (state[i].status == 0) {
2081 *p++ = '-';
2082
2083 } else {
2084 p = ngx_sprintf(p, "%d.%03d",
2085 state[i].response_time / 1000,
2086 state[i].response_time % 1000);
2087 }
2088
2089 if (++i == u->states.nelts) {
2090 break;
2091 }
2092
2093 *p++ = ',';
2094 *p++ = ' ';
2095 }
2096
2097 v->len = p - v->data;
1922 2098
1923 return NGX_OK; 2099 return NGX_OK;
1924 } 2100 }
1925 2101
1926 2102