Mercurial > hg > nginx-mail
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 |