comparison src/http/ngx_http_upstream.c @ 260:0effe91f6083 NGINX_0_5_0

nginx 0.5.0 *) Change: the parameters in the "%name" form in the "log_format" directive are not supported anymore. *) Change: the "proxy_upstream_max_fails", "proxy_upstream_fail_timeout", "fastcgi_upstream_max_fails", "fastcgi_upstream_fail_timeout", "memcached_upstream_max_fails", and "memcached_upstream_fail_timeout" directives are not supported anymore. *) Feature: the "server" directive in the "upstream" context supports the "max_fails", "fail_timeout", and "down" parameters. *) Feature: the "ip_hash" directive inside the "upstream" block. *) Feature: the WAIT status in the "Auth-Status" header line of the IMAP/POP3 proxy authentication server response. *) Bugfix: nginx could not be built on 64-bit platforms; bug appeared in 0.4.14.
author Igor Sysoev <http://sysoev.ru>
date Mon, 04 Dec 2006 00:00:00 +0300
parents 6ae1357b7b7c
children e0b1d0a6c629
comparison
equal deleted inserted replaced
259:c68f18041059 260:0effe91f6083
68 #if (NGX_HTTP_GZIP) 68 #if (NGX_HTTP_GZIP)
69 static ngx_int_t ngx_http_upstream_copy_content_encoding(ngx_http_request_t *r, 69 static ngx_int_t ngx_http_upstream_copy_content_encoding(ngx_http_request_t *r,
70 ngx_table_elt_t *h, ngx_uint_t offset); 70 ngx_table_elt_t *h, ngx_uint_t offset);
71 #endif 71 #endif
72 72
73 static size_t ngx_http_upstream_log_status_getlen(ngx_http_request_t *r,
74 uintptr_t data);
75 static u_char *ngx_http_upstream_log_status(ngx_http_request_t *r,
76 u_char *buf, ngx_http_log_op_t *op);
77 static size_t ngx_http_upstream_log_response_time_getlen(ngx_http_request_t *r,
78 uintptr_t data);
79 static u_char *ngx_http_upstream_log_response_time(ngx_http_request_t *r,
80 u_char *buf, ngx_http_log_op_t *op);
81
82 static ngx_int_t ngx_http_upstream_add_variables(ngx_conf_t *cf); 73 static ngx_int_t ngx_http_upstream_add_variables(ngx_conf_t *cf);
83 static ngx_int_t ngx_http_upstream_status_variable(ngx_http_request_t *r, 74 static ngx_int_t ngx_http_upstream_status_variable(ngx_http_request_t *r,
84 ngx_http_variable_value_t *v, uintptr_t data); 75 ngx_http_variable_value_t *v, uintptr_t data);
85 static ngx_int_t ngx_http_upstream_response_time_variable(ngx_http_request_t *r, 76 static ngx_int_t ngx_http_upstream_response_time_variable(ngx_http_request_t *r,
86 ngx_http_variable_value_t *v, uintptr_t data); 77 ngx_http_variable_value_t *v, uintptr_t data);
94 85
95 #if (NGX_HTTP_SSL) 86 #if (NGX_HTTP_SSL)
96 static void ngx_http_upstream_ssl_init_connection(ngx_http_request_t *, 87 static void ngx_http_upstream_ssl_init_connection(ngx_http_request_t *,
97 ngx_http_upstream_t *u, ngx_connection_t *c); 88 ngx_http_upstream_t *u, ngx_connection_t *c);
98 static void ngx_http_upstream_ssl_handshake(ngx_connection_t *c); 89 static void ngx_http_upstream_ssl_handshake(ngx_connection_t *c);
99 static void ngx_http_upstream_ssl_shutdown(ngx_connection_t *c,
100 ngx_peer_t *peer);
101 #endif 90 #endif
102 91
103 92
104 ngx_http_upstream_header_t ngx_http_upstream_headers_in[] = { 93 ngx_http_upstream_header_t ngx_http_upstream_headers_in[] = {
105 94
222 0, 211 0,
223 0, 212 0,
224 NULL }, 213 NULL },
225 214
226 { ngx_string("server"), 215 { ngx_string("server"),
227 NGX_HTTP_UPS_CONF|NGX_CONF_TAKE12, 216 NGX_HTTP_UPS_CONF|NGX_CONF_1MORE,
228 ngx_http_upstream_server, 217 ngx_http_upstream_server,
229 NGX_HTTP_SRV_CONF_OFFSET, 218 NGX_HTTP_SRV_CONF_OFFSET,
230 0, 219 0,
231 NULL }, 220 NULL },
232 221
263 NULL, /* exit master */ 252 NULL, /* exit master */
264 NGX_MODULE_V1_PADDING 253 NGX_MODULE_V1_PADDING
265 }; 254 };
266 255
267 256
268 static ngx_http_log_op_name_t ngx_http_upstream_log_fmt_ops[] = {
269 { ngx_string("upstream_status"), 0, NULL,
270 ngx_http_upstream_log_status_getlen,
271 ngx_http_upstream_log_status },
272 { ngx_string("upstream_response_time"), 0, NULL,
273 ngx_http_upstream_log_response_time_getlen,
274 ngx_http_upstream_log_response_time },
275 { ngx_null_string, 0, NULL, NULL, NULL }
276 };
277
278
279 static ngx_http_variable_t ngx_http_upstream_vars[] = { 257 static ngx_http_variable_t ngx_http_upstream_vars[] = {
280 258
281 { ngx_string("upstream_status"), NULL, 259 { ngx_string("upstream_status"), NULL,
282 ngx_http_upstream_status_variable, 0, NGX_HTTP_VAR_NOHASH, 0 }, 260 ngx_http_upstream_status_variable, 0, NGX_HTTP_VAR_NOHASH, 0 },
283 261
326 304
327 if (r->request_body) { 305 if (r->request_body) {
328 u->request_bufs = r->request_body->bufs; 306 u->request_bufs = r->request_body->bufs;
329 } 307 }
330 308
309 if (u->conf->upstream->peer.init(r, u->conf->upstream) != NGX_OK) {
310 ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
311 return;
312 }
313
331 if (u->create_request(r) != NGX_OK) { 314 if (u->create_request(r) != NGX_OK) {
332 ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); 315 ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
333 return; 316 return;
334 } 317 }
335
336 u->peer.log = r->connection->log;
337 318
338 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); 319 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
339 320
340 u->output.sendfile = r->connection->sendfile; 321 u->output.sendfile = r->connection->sendfile;
341 u->output.pool = r->pool; 322 u->output.pool = r->pool;
344 u->output.output_filter = ngx_chain_writer; 325 u->output.output_filter = ngx_chain_writer;
345 u->output.filter_ctx = &u->writer; 326 u->output.filter_ctx = &u->writer;
346 327
347 u->writer.pool = r->pool; 328 u->writer.pool = r->pool;
348 329
349 if (ngx_array_init(&u->states, r->pool, u->peer.peers->number, 330 if (ngx_array_init(&u->states, r->pool, 1,
350 sizeof(ngx_http_upstream_state_t)) 331 sizeof(ngx_http_upstream_state_t))
351 != NGX_OK) 332 != NGX_OK)
352 { 333 {
353 ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); 334 ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
354 return; 335 return;
546 ngx_http_upstream_finalize_request(r, u, 527 ngx_http_upstream_finalize_request(r, u,
547 NGX_HTTP_INTERNAL_SERVER_ERROR); 528 NGX_HTTP_INTERNAL_SERVER_ERROR);
548 return; 529 return;
549 } 530 }
550 531
551 u->state->peer = &u->peer.peers->peer[u->peer.cur_peer].name; 532 u->state->peer = u->peer.name;
552 533
553 if (rc == NGX_BUSY) { 534 if (rc == NGX_BUSY) {
554 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "no live upstreams"); 535 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "no live upstreams");
555 } 536 }
556 537
635 616
636 static void 617 static void
637 ngx_http_upstream_ssl_init_connection(ngx_http_request_t *r, 618 ngx_http_upstream_ssl_init_connection(ngx_http_request_t *r,
638 ngx_http_upstream_t *u, ngx_connection_t *c) 619 ngx_http_upstream_t *u, ngx_connection_t *c)
639 { 620 {
640 ngx_int_t rc; 621 ngx_int_t rc;
641 ngx_peer_t *peer;
642 622
643 if (ngx_ssl_create_connection(u->conf->ssl, c, 623 if (ngx_ssl_create_connection(u->conf->ssl, c,
644 NGX_SSL_BUFFER|NGX_SSL_CLIENT) 624 NGX_SSL_BUFFER|NGX_SSL_CLIENT)
645 == NGX_ERROR) 625 == NGX_ERROR)
646 { 626 {
650 } 630 }
651 631
652 c->sendfile = 0; 632 c->sendfile = 0;
653 u->output.sendfile = 0; 633 u->output.sendfile = 0;
654 634
655 peer = &u->peer.peers->peer[u->peer.cur_peer]; 635 if (ngx_ssl_set_session(c, u->peer.ssl_session) != NGX_OK) {
656
657 if (ngx_ssl_set_session(c, peer->ssl_session) != NGX_OK) {
658 ngx_http_upstream_finalize_request(r, u, 636 ngx_http_upstream_finalize_request(r, u,
659 NGX_HTTP_INTERNAL_SERVER_ERROR); 637 NGX_HTTP_INTERNAL_SERVER_ERROR);
660 return; 638 return;
661 } 639 }
662 640
681 659
682 r = c->data; 660 r = c->data;
683 u = r->upstream; 661 u = r->upstream;
684 662
685 if (c->ssl->handshaked) { 663 if (c->ssl->handshaked) {
664
665 u->peer.save_session(&u->peer, u->peer.data);
686 666
687 c->write->handler = ngx_http_upstream_send_request_handler; 667 c->write->handler = ngx_http_upstream_send_request_handler;
688 c->read->handler = ngx_http_upstream_process_header; 668 c->read->handler = ngx_http_upstream_process_header;
689 669
690 ngx_http_upstream_send_request(r, u); 670 ngx_http_upstream_send_request(r, u);
990 } 970 }
991 #endif 971 #endif
992 } 972 }
993 973
994 n = u->peer.connection->recv(u->peer.connection, u->buffer.last, 974 n = u->peer.connection->recv(u->peer.connection, u->buffer.last,
995 u->buffer.end - u->buffer.last); 975 u->buffer.end - u->buffer.last);
996 976
997 if (n == NGX_AGAIN) { 977 if (n == NGX_AGAIN) {
998 #if 0 978 #if 0
999 ngx_add_timer(rev, u->read_timeout); 979 ngx_add_timer(rev, u->read_timeout);
1000 #endif 980 #endif
1603 size_t size; 1583 size_t size;
1604 ssize_t n; 1584 ssize_t n;
1605 ngx_buf_t *b; 1585 ngx_buf_t *b;
1606 ngx_int_t rc; 1586 ngx_int_t rc;
1607 ngx_uint_t do_write; 1587 ngx_uint_t do_write;
1608 ngx_connection_t *c, *client; 1588 ngx_connection_t *c, *downstream, *upstream;
1609 ngx_http_request_t *r; 1589 ngx_http_request_t *r;
1610 ngx_http_upstream_t *u; 1590 ngx_http_upstream_t *u;
1611 ngx_http_core_loc_conf_t *clcf; 1591 ngx_http_core_loc_conf_t *clcf;
1612 1592
1613 c = ev->data; 1593 c = ev->data;
1636 1616
1637 ngx_http_upstream_finalize_request(r, u, 0); 1617 ngx_http_upstream_finalize_request(r, u, 0);
1638 return; 1618 return;
1639 } 1619 }
1640 1620
1641 client = r->connection; 1621 downstream = r->connection;
1622 upstream = u->peer.connection;
1642 1623
1643 b = &u->buffer; 1624 b = &u->buffer;
1644 1625
1645 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); 1626 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
1646 1627
1651 if (do_write) { 1632 if (do_write) {
1652 1633
1653 if (u->out_bufs || u->busy_bufs) { 1634 if (u->out_bufs || u->busy_bufs) {
1654 rc = ngx_http_output_filter(r, u->out_bufs); 1635 rc = ngx_http_output_filter(r, u->out_bufs);
1655 1636
1656 if (client->destroyed) { 1637 if (downstream->destroyed) {
1657 return; 1638 return;
1658 } 1639 }
1659 1640
1660 if (rc == NGX_ERROR) { 1641 if (rc == NGX_ERROR) {
1661 ngx_http_upstream_finalize_request(r, u, 0); 1642 ngx_http_upstream_finalize_request(r, u, 0);
1667 } 1648 }
1668 1649
1669 if (u->busy_bufs == NULL) { 1650 if (u->busy_bufs == NULL) {
1670 1651
1671 if (u->length == 0 1652 if (u->length == 0
1672 || u->peer.connection->read->eof 1653 || upstream->read->eof
1673 || u->peer.connection->read->error) 1654 || upstream->read->error)
1674 { 1655 {
1675 ngx_http_upstream_finalize_request(r, u, 0); 1656 ngx_http_upstream_finalize_request(r, u, 0);
1676 return; 1657 return;
1677 } 1658 }
1678 1659
1685 1666
1686 if (size > u->length) { 1667 if (size > u->length) {
1687 size = u->length; 1668 size = u->length;
1688 } 1669 }
1689 1670
1690 if (size && u->peer.connection->read->ready) { 1671 if (size && upstream->read->ready) {
1691 1672
1692 n = u->peer.connection->recv(u->peer.connection, b->last, size); 1673 n = upstream->recv(upstream, b->last, size);
1693 1674
1694 if (n == NGX_AGAIN) { 1675 if (n == NGX_AGAIN) {
1695 break; 1676 break;
1696 } 1677 }
1697 1678
1708 } 1689 }
1709 1690
1710 break; 1691 break;
1711 } 1692 }
1712 1693
1713 if (client->data == r) { 1694 if (downstream->data == r) {
1714 if (ngx_handle_write_event(client->write, clcf->send_lowat) 1695 if (ngx_handle_write_event(downstream->write, clcf->send_lowat)
1715 == NGX_ERROR) 1696 == NGX_ERROR)
1716 { 1697 {
1717 ngx_http_upstream_finalize_request(r, u, 0); 1698 ngx_http_upstream_finalize_request(r, u, 0);
1718 return; 1699 return;
1719 } 1700 }
1720 } 1701 }
1721 1702
1722 if (client->write->active) { 1703 if (downstream->write->active) {
1723 ngx_add_timer(client->write, clcf->send_timeout); 1704 ngx_add_timer(downstream->write, clcf->send_timeout);
1724 1705
1725 } else if (client->write->timer_set) { 1706 } else if (downstream->write->timer_set) {
1726 ngx_del_timer(client->write); 1707 ngx_del_timer(downstream->write);
1727 } 1708 }
1728 1709
1729 if (ngx_handle_read_event(u->peer.connection->read, 0) == NGX_ERROR) { 1710 if (ngx_handle_read_event(upstream->read, 0) == NGX_ERROR) {
1730 ngx_http_upstream_finalize_request(r, u, 0); 1711 ngx_http_upstream_finalize_request(r, u, 0);
1731 return; 1712 return;
1732 } 1713 }
1733 1714
1734 if (u->peer.connection->read->active) { 1715 if (upstream->read->active) {
1735 ngx_add_timer(u->peer.connection->read, u->conf->read_timeout); 1716 ngx_add_timer(upstream->read, u->conf->read_timeout);
1736 1717
1737 } else if (u->peer.connection->read->timer_set) { 1718 } else if (upstream->read->timer_set) {
1738 ngx_del_timer(u->peer.connection->read); 1719 ngx_del_timer(upstream->read);
1739 } 1720 }
1740 } 1721 }
1741 1722
1742 1723
1743 static ngx_int_t 1724 static ngx_int_t
1940 1921
1941 static void 1922 static void
1942 ngx_http_upstream_next(ngx_http_request_t *r, ngx_http_upstream_t *u, 1923 ngx_http_upstream_next(ngx_http_request_t *r, ngx_http_upstream_t *u,
1943 ngx_uint_t ft_type) 1924 ngx_uint_t ft_type)
1944 { 1925 {
1945 ngx_uint_t status, down; 1926 ngx_uint_t status, state;
1946 1927
1947 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, 1928 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1948 "http next upstream, %xD", ft_type); 1929 "http next upstream, %xi", ft_type);
1949 1930
1950 #if 0 1931 #if 0
1951 ngx_http_busy_unlock(u->conf->busy_lock, &u->busy_lock); 1932 ngx_http_busy_unlock(u->conf->busy_lock, &u->busy_lock);
1952 #endif 1933 #endif
1953 1934
1954 if (ft_type == NGX_HTTP_UPSTREAM_FT_HTTP_404) { 1935 if (ft_type == NGX_HTTP_UPSTREAM_FT_HTTP_404) {
1955 down = 0; 1936 state = NGX_PEER_NEXT;
1956 } else { 1937 } else {
1957 down = 1; 1938 state = NGX_PEER_FAILED;
1958 } 1939 }
1959 1940
1960 ngx_event_connect_peer_failed(&u->peer, down); 1941 u->peer.free(&u->peer, u->peer.data, state);
1961 1942
1962 if (ft_type == NGX_HTTP_UPSTREAM_FT_TIMEOUT) { 1943 if (ft_type == NGX_HTTP_UPSTREAM_FT_TIMEOUT) {
1963 ngx_log_error(NGX_LOG_ERR, r->connection->log, NGX_ETIMEDOUT, 1944 ngx_log_error(NGX_LOG_ERR, r->connection->log, NGX_ETIMEDOUT,
1964 "upstream timed out"); 1945 "upstream timed out");
1965 } 1946 }
2021 if (u->peer.connection) { 2002 if (u->peer.connection) {
2022 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, 2003 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2023 "close http upstream connection: %d", 2004 "close http upstream connection: %d",
2024 u->peer.connection->fd); 2005 u->peer.connection->fd);
2025 #if (NGX_HTTP_SSL) 2006 #if (NGX_HTTP_SSL)
2007
2026 if (u->peer.connection->ssl) { 2008 if (u->peer.connection->ssl) {
2027 ngx_http_upstream_ssl_shutdown(u->peer.connection, 2009 u->peer.connection->ssl->no_wait_shutdown = 1;
2028 &u->peer.peers->peer[u->peer.cur_peer]); 2010 u->peer.connection->ssl->no_send_shutdown = 1;
2011
2012 (void) ngx_ssl_shutdown(u->peer.connection);
2029 } 2013 }
2030 #endif 2014 #endif
2015
2031 ngx_close_connection(u->peer.connection); 2016 ngx_close_connection(u->peer.connection);
2032 } 2017 }
2033 2018
2034 #if 0 2019 #if 0
2035 if (u->conf->busy_lock && !u->busy_locked) { 2020 if (u->conf->busy_lock && !u->busy_locked) {
2072 u->state->response_time = (ms >= 0) ? ms : 0; 2057 u->state->response_time = (ms >= 0) ? ms : 0;
2073 } 2058 }
2074 2059
2075 u->finalize_request(r, rc); 2060 u->finalize_request(r, rc);
2076 2061
2062 u->peer.free(&u->peer, u->peer.data, 0);
2063
2077 if (u->peer.connection) { 2064 if (u->peer.connection) {
2065
2066 #if (NGX_HTTP_SSL)
2067
2068 /* TODO: do not shutdown persistent connection */
2069
2070 if (u->peer.connection->ssl) {
2071
2072 /*
2073 * We send the "close notify" shutdown alert to the upstream only
2074 * and do not wait its "close notify" shutdown alert.
2075 * It is acceptable according to the TLS standard.
2076 */
2077
2078 u->peer.connection->ssl->no_wait_shutdown = 1;
2079
2080 (void) ngx_ssl_shutdown(u->peer.connection);
2081 }
2082 #endif
2083
2078 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, 2084 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2079 "close http upstream connection: %d", 2085 "close http upstream connection: %d",
2080 u->peer.connection->fd); 2086 u->peer.connection->fd);
2081 #if (NGX_HTTP_SSL) 2087
2082
2083 /* TODO: do not shutdown persistent connection */
2084
2085 if (u->peer.connection->ssl) {
2086 ngx_http_upstream_ssl_shutdown(u->peer.connection,
2087 &u->peer.peers->peer[u->peer.cur_peer]);
2088 }
2089 #endif
2090 ngx_close_connection(u->peer.connection); 2088 ngx_close_connection(u->peer.connection);
2091 } 2089 }
2092 2090
2093 u->peer.connection = NULL; 2091 u->peer.connection = NULL;
2094 2092
2123 2121
2124 ngx_http_finalize_request(r, rc); 2122 ngx_http_finalize_request(r, rc);
2125 } 2123 }
2126 2124
2127 2125
2128 #if (NGX_HTTP_SSL)
2129
2130 static void
2131 ngx_http_upstream_ssl_shutdown(ngx_connection_t *c, ngx_peer_t *peer)
2132 {
2133 /* lock peer mutex */
2134
2135 if (peer->ssl_session) {
2136 ngx_ssl_free_session(peer->ssl_session);
2137 }
2138
2139 peer->ssl_session = ngx_ssl_get_session(c);
2140
2141 /* unlock peer mutex */
2142
2143 /*
2144 * We send the "close notify" shutdown alert to the upstream only
2145 * and do not wait its "close notify" shutdown alert.
2146 * It is acceptable according to the TLS standard.
2147 */
2148
2149 c->ssl->no_wait_shutdown = 1;
2150
2151 (void) ngx_ssl_shutdown(c);
2152 }
2153
2154 #endif
2155
2156
2157 static ngx_int_t 2126 static ngx_int_t
2158 ngx_http_upstream_process_header_line(ngx_http_request_t *r, ngx_table_elt_t *h, 2127 ngx_http_upstream_process_header_line(ngx_http_request_t *r, ngx_table_elt_t *h,
2159 ngx_uint_t offset) 2128 ngx_uint_t offset)
2160 { 2129 {
2161 ngx_table_elt_t **ph; 2130 ngx_table_elt_t **ph;
2479 } 2448 }
2480 2449
2481 #endif 2450 #endif
2482 2451
2483 2452
2484 static size_t
2485 ngx_http_upstream_log_status_getlen(ngx_http_request_t *r, uintptr_t data)
2486 {
2487 if (r->upstream) {
2488 return r->upstream->states.nelts * (3 + 2);
2489 }
2490
2491 return 1;
2492 }
2493
2494
2495 static u_char *
2496 ngx_http_upstream_log_status(ngx_http_request_t *r, u_char *buf,
2497 ngx_http_log_op_t *op)
2498 {
2499 ngx_uint_t i;
2500 ngx_http_upstream_t *u;
2501 ngx_http_upstream_state_t *state;
2502
2503 u = r->upstream;
2504
2505 if (u == NULL || u->states.nelts == 0) {
2506 *buf = '-';
2507 return buf + 1;
2508 }
2509
2510 i = 0;
2511 state = u->states.elts;
2512
2513 for ( ;; ) {
2514 if (state[i].status == 0) {
2515 *buf++ = '-';
2516
2517 } else {
2518 buf = ngx_sprintf(buf, "%ui", state[i].status);
2519 }
2520
2521 if (++i == u->states.nelts) {
2522 return buf;
2523 }
2524
2525 *buf++ = ',';
2526 *buf++ = ' ';
2527 }
2528 }
2529
2530
2531 static size_t
2532 ngx_http_upstream_log_response_time_getlen(ngx_http_request_t *r,
2533 uintptr_t data)
2534 {
2535 if (r->upstream) {
2536 return r->upstream->states.nelts * (NGX_TIME_T_LEN + 4 + 2);
2537 }
2538
2539 return 1;
2540 }
2541
2542
2543 static u_char *
2544 ngx_http_upstream_log_response_time(ngx_http_request_t *r, u_char *buf,
2545 ngx_http_log_op_t *op)
2546 {
2547 ngx_uint_t i;
2548 ngx_http_upstream_t *u;
2549 ngx_http_upstream_state_t *state;
2550
2551 u = r->upstream;
2552
2553 if (u == NULL || u->states.nelts == 0) {
2554 *buf = '-';
2555 return buf + 1;
2556 }
2557
2558 i = 0;
2559 state = u->states.elts;
2560
2561 for ( ;; ) {
2562 if (state[i].status == 0) {
2563 *buf++ = '-';
2564
2565 } else {
2566 buf = ngx_sprintf(buf, "%d.%03d",
2567 state[i].response_time / 1000,
2568 state[i].response_time % 1000);
2569 }
2570
2571 if (++i == u->states.nelts) {
2572 return buf;
2573 }
2574
2575 *buf++ = ',';
2576 *buf++ = ' ';
2577 }
2578 }
2579
2580
2581 static ngx_int_t 2453 static ngx_int_t
2582 ngx_http_upstream_add_variables(ngx_conf_t *cf) 2454 ngx_http_upstream_add_variables(ngx_conf_t *cf)
2583 { 2455 {
2584 ngx_http_variable_t *var, *v; 2456 ngx_http_variable_t *var, *v;
2585 ngx_http_log_op_name_t *op;
2586 2457
2587 for (v = ngx_http_upstream_vars; v->name.len; v++) { 2458 for (v = ngx_http_upstream_vars; v->name.len; v++) {
2588 var = ngx_http_add_variable(cf, &v->name, v->flags); 2459 var = ngx_http_add_variable(cf, &v->name, v->flags);
2589 if (var == NULL) { 2460 if (var == NULL) {
2590 return NGX_ERROR; 2461 return NGX_ERROR;
2591 } 2462 }
2592 2463
2593 var->get_handler = v->get_handler; 2464 var->get_handler = v->get_handler;
2594 var->data = v->data; 2465 var->data = v->data;
2595 } 2466 }
2596
2597 for (op = ngx_http_upstream_log_fmt_ops; op->name.len; op++) { /* void */ }
2598 op->run = NULL;
2599
2600 for (op = ngx_http_log_fmt_ops; op->run; op++) {
2601 if (op->name.len == 0) {
2602 op = (ngx_http_log_op_name_t *) op->run;
2603 }
2604 }
2605
2606 op->run = (ngx_http_log_op_run_pt) ngx_http_upstream_log_fmt_ops;
2607 2467
2608 return NGX_OK; 2468 return NGX_OK;
2609 } 2469 }
2610 2470
2611 2471
2722 2582
2723 2583
2724 static char * 2584 static char *
2725 ngx_http_upstream(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy) 2585 ngx_http_upstream(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy)
2726 { 2586 {
2727 char *rv; 2587 char *rv;
2728 void *mconf; 2588 void *mconf;
2729 ngx_str_t *value; 2589 ngx_str_t *value;
2730 ngx_url_t u; 2590 ngx_url_t u;
2731 ngx_uint_t i, j, m, n; 2591 ngx_uint_t m;
2732 ngx_conf_t pcf; 2592 ngx_conf_t pcf;
2733 ngx_peers_t **peers; 2593 ngx_http_module_t *module;
2734 ngx_http_module_t *module; 2594 ngx_http_conf_ctx_t *ctx, *http_ctx;
2735 ngx_http_conf_ctx_t *ctx; 2595 ngx_http_upstream_srv_conf_t *uscf;
2736 ngx_http_upstream_srv_conf_t *uscf; 2596
2597 ngx_memzero(&u, sizeof(ngx_url_t));
2598
2599 value = cf->args->elts;
2600 u.host = value[1];
2601 u.upstream = 1;
2602 u.no_resolve = 1;
2603
2604 uscf = ngx_http_upstream_add(cf, &u, NGX_HTTP_UPSTREAM_CREATE
2605 |NGX_HTTP_UPSTREAM_WEIGHT
2606 |NGX_HTTP_UPSTREAM_MAX_FAILS
2607 |NGX_HTTP_UPSTREAM_FAIL_TIMEOUT
2608 |NGX_HTTP_UPSTREAM_DOWN
2609 |NGX_HTTP_UPSTREAM_BACKUP);
2610 if (uscf == NULL) {
2611 return NGX_CONF_ERROR;
2612 }
2613
2737 2614
2738 ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t)); 2615 ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t));
2739 if (ctx == NULL) { 2616 if (ctx == NULL) {
2740 return NGX_CONF_ERROR; 2617 return NGX_CONF_ERROR;
2741 } 2618 }
2742 2619
2743 ngx_memzero(&u, sizeof(ngx_url_t)); 2620 http_ctx = cf->ctx;
2744 2621 ctx->main_conf = http_ctx->main_conf;
2745 value = cf->args->elts;
2746 u.host = value[1];
2747
2748 uscf = ngx_http_upstream_add(cf, &u);
2749 if (uscf == NULL) {
2750 return NGX_CONF_ERROR;
2751 }
2752 2622
2753 /* the upstream{}'s srv_conf */ 2623 /* the upstream{}'s srv_conf */
2754 2624
2755 ctx->srv_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module); 2625 ctx->srv_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module);
2756 if (ctx->srv_conf == NULL) { 2626 if (ctx->srv_conf == NULL) {
2757 return NGX_CONF_ERROR; 2627 return NGX_CONF_ERROR;
2758 } 2628 }
2759 2629
2760 ctx->srv_conf[ngx_http_upstream_module.ctx_index] = uscf; 2630 ctx->srv_conf[ngx_http_upstream_module.ctx_index] = uscf;
2761 2631
2632 uscf->srv_conf = ctx->srv_conf;
2633
2762 2634
2763 /* the upstream{}'s loc_conf */ 2635 /* the upstream{}'s loc_conf */
2764 2636
2765 ctx->loc_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module); 2637 ctx->loc_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module);
2766 if (ctx->loc_conf == NULL) { 2638 if (ctx->loc_conf == NULL) {
2771 if (ngx_modules[m]->type != NGX_HTTP_MODULE) { 2643 if (ngx_modules[m]->type != NGX_HTTP_MODULE) {
2772 continue; 2644 continue;
2773 } 2645 }
2774 2646
2775 module = ngx_modules[m]->ctx; 2647 module = ngx_modules[m]->ctx;
2648
2649 if (module->create_srv_conf) {
2650 mconf = module->create_srv_conf(cf);
2651 if (mconf == NULL) {
2652 return NGX_CONF_ERROR;
2653 }
2654
2655 ctx->srv_conf[ngx_modules[m]->ctx_index] = mconf;
2656 }
2776 2657
2777 if (module->create_loc_conf) { 2658 if (module->create_loc_conf) {
2778 mconf = module->create_loc_conf(cf); 2659 mconf = module->create_loc_conf(cf);
2779 if (mconf == NULL) { 2660 if (mconf == NULL) {
2780 return NGX_CONF_ERROR; 2661 return NGX_CONF_ERROR;
2803 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, 2684 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
2804 "no servers are inside upstream"); 2685 "no servers are inside upstream");
2805 return NGX_CONF_ERROR; 2686 return NGX_CONF_ERROR;
2806 } 2687 }
2807 2688
2808 peers = uscf->servers->elts;
2809
2810 if (uscf->servers->nelts == 1) {
2811 uscf->peers = peers[0];
2812 }
2813
2814 n = 0;
2815
2816 for (i = 0; i < uscf->servers->nelts; i++) {
2817 n += peers[i]->number;
2818 }
2819
2820 uscf->peers = ngx_pcalloc(cf->pool,
2821 sizeof(ngx_peers_t) + sizeof(ngx_peer_t) * (n - 1));
2822 if (uscf->peers == NULL) {
2823 return NGX_CONF_ERROR;
2824 }
2825
2826 uscf->peers->number = n;
2827
2828 n = 0;
2829
2830 for (i = 0; i < uscf->servers->nelts; i++) {
2831 for (j = 0; j < peers[i]->number; j++) {
2832 uscf->peers->peer[n++] = peers[i]->peer[j];
2833 }
2834 }
2835
2836 return rv; 2689 return rv;
2837 } 2690 }
2838 2691
2839 2692
2840 static char * 2693 static char *
2841 ngx_http_upstream_server(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) 2694 ngx_http_upstream_server(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
2842 { 2695 {
2843 ngx_http_upstream_srv_conf_t *uscf = conf; 2696 ngx_http_upstream_srv_conf_t *uscf = conf;
2844 2697
2845 ngx_str_t *value; 2698 time_t fail_timeout;
2846 ngx_url_t u; 2699 ngx_str_t *value, s;
2847 ngx_int_t weight; 2700 ngx_url_t u;
2848 ngx_uint_t i; 2701 ngx_int_t weight, max_fails;
2849 ngx_peers_t **peers; 2702 ngx_uint_t i;
2703 ngx_http_upstream_server_t *us;
2850 2704
2851 if (uscf->servers == NULL) { 2705 if (uscf->servers == NULL) {
2852 uscf->servers = ngx_array_create(cf->pool, 4, sizeof(ngx_peers_t *)); 2706 uscf->servers = ngx_array_create(cf->pool, 4,
2707 sizeof(ngx_http_upstream_server_t));
2853 if (uscf->servers == NULL) { 2708 if (uscf->servers == NULL) {
2854 return NGX_CONF_ERROR; 2709 return NGX_CONF_ERROR;
2855 } 2710 }
2856 } 2711 }
2857 2712
2858 peers = ngx_array_push(uscf->servers); 2713 us = ngx_array_push(uscf->servers);
2859 if (peers == NULL) { 2714 if (us == NULL) {
2860 return NGX_CONF_ERROR; 2715 return NGX_CONF_ERROR;
2861 } 2716 }
2717
2718 ngx_memzero(us, sizeof(ngx_http_upstream_server_t));
2862 2719
2863 value = cf->args->elts; 2720 value = cf->args->elts;
2864 2721
2865 ngx_memzero(&u, sizeof(ngx_url_t)); 2722 ngx_memzero(&u, sizeof(ngx_url_t));
2866 2723
2875 2732
2876 return NGX_CONF_ERROR; 2733 return NGX_CONF_ERROR;
2877 } 2734 }
2878 2735
2879 weight = 1; 2736 weight = 1;
2880 2737 max_fails = 1;
2881 if (cf->args->nelts == 3) { 2738 fail_timeout = 10;
2882 2739
2883 value = &value[2]; 2740 for (i = 2; i < cf->args->nelts; i++) {
2884 2741
2885 if (ngx_strncmp(value->data, "weight=", 7) == 0) { 2742 if (ngx_strncmp(value[i].data, "weight=", 7) == 0) {
2886 2743
2887 weight = ngx_atoi(&value->data[7], value->len - 7); 2744 if (!(uscf->flags & NGX_HTTP_UPSTREAM_WEIGHT)) {
2745 goto invalid;
2746 }
2747
2748 weight = ngx_atoi(&value[i].data[7], value[i].len - 7);
2888 2749
2889 if (weight == NGX_ERROR || weight == 0) { 2750 if (weight == NGX_ERROR || weight == 0) {
2890 goto invalid; 2751 goto invalid;
2891 } 2752 }
2892 2753
2893 } else { 2754 continue;
2894 goto invalid; 2755 }
2895 } 2756
2896 } 2757 if (ngx_strncmp(value[i].data, "max_fails=", 10) == 0) {
2897 2758
2898 for (i = 0; i < u.peers->number; i++) { 2759 if (!(uscf->flags & NGX_HTTP_UPSTREAM_MAX_FAILS)) {
2899 u.peers->peer[i].weight = weight; 2760 goto invalid;
2900 u.peers->peer[i].current_weight = weight; 2761 }
2901 u.peers->peer[i].max_fails = NGX_CONF_UNSET_UINT; 2762
2902 u.peers->peer[i].fail_timeout = NGX_CONF_UNSET; 2763 max_fails = ngx_atoi(&value[i].data[10], value[i].len - 10);
2903 } 2764
2904 2765 if (max_fails == NGX_ERROR) {
2905 *peers = u.peers; 2766 goto invalid;
2767 }
2768
2769 continue;
2770 }
2771
2772 if (ngx_strncmp(value[i].data, "fail_timeout=", 13) == 0) {
2773
2774 if (!(uscf->flags & NGX_HTTP_UPSTREAM_FAIL_TIMEOUT)) {
2775 goto invalid;
2776 }
2777
2778 s.len = value[i].len - 13;
2779 s.data = &value[i].data[13];
2780
2781 fail_timeout = ngx_parse_time(&s, 1);
2782
2783 if (fail_timeout < 0) {
2784 goto invalid;
2785 }
2786
2787 continue;
2788 }
2789
2790 if (ngx_strncmp(value[i].data, "down", 4) == 0) {
2791
2792 if (!(uscf->flags & NGX_HTTP_UPSTREAM_DOWN)) {
2793 goto invalid;
2794 }
2795
2796 us->down = 1;
2797
2798 continue;
2799 }
2800
2801 goto invalid;
2802 }
2803
2804 us->addrs = u.addrs;
2805 us->naddrs = u.naddrs;
2806 us->weight = weight;
2807 us->max_fails = max_fails;
2808 us->fail_timeout = fail_timeout;
2906 2809
2907 return NGX_CONF_OK; 2810 return NGX_CONF_OK;
2908 2811
2909 invalid: 2812 invalid:
2910 2813
2911 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid parameter \"%V\"", value); 2814 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
2815 "invalid parameter \"%V\"", &value[i]);
2912 2816
2913 return NGX_CONF_ERROR; 2817 return NGX_CONF_ERROR;
2914 } 2818 }
2915 2819
2916 2820
2917 ngx_http_upstream_srv_conf_t * 2821 ngx_http_upstream_srv_conf_t *
2918 ngx_http_upstream_add(ngx_conf_t *cf, ngx_url_t *u) 2822 ngx_http_upstream_add(ngx_conf_t *cf, ngx_url_t *u, ngx_uint_t flags)
2919 { 2823 {
2920 ngx_uint_t i; 2824 ngx_uint_t i;
2825 ngx_http_upstream_server_t *us;
2921 ngx_http_upstream_srv_conf_t *uscf, **uscfp; 2826 ngx_http_upstream_srv_conf_t *uscf, **uscfp;
2922 ngx_http_upstream_main_conf_t *umcf; 2827 ngx_http_upstream_main_conf_t *umcf;
2923 2828
2924 if (u->upstream) { 2829 if (!(flags & NGX_HTTP_UPSTREAM_CREATE)) {
2830
2925 if (ngx_parse_url(cf, u) != NGX_OK) { 2831 if (ngx_parse_url(cf, u) != NGX_OK) {
2926 if (u->err) { 2832 if (u->err) {
2927 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, 2833 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
2928 "%s in upstream \"%V\"", u->err, &u->url); 2834 "%s in upstream \"%V\"", u->err, &u->url);
2929 } 2835 }
2930 2836
2931 return NULL; 2837 return NULL;
2932 } 2838 }
2933
2934 if (u->peers) {
2935 uscf = ngx_pcalloc(cf->pool, sizeof(ngx_http_upstream_srv_conf_t));
2936 if (uscf == NULL) {
2937 return NULL;
2938 }
2939
2940 uscf->peers = u->peers;
2941
2942 return uscf;
2943 }
2944 } 2839 }
2945 2840
2946 umcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_upstream_module); 2841 umcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_upstream_module);
2947 2842
2948 uscfp = umcf->upstreams.elts; 2843 uscfp = umcf->upstreams.elts;
2949 2844
2950 for (i = 0; i < umcf->upstreams.nelts; i++) { 2845 for (i = 0; i < umcf->upstreams.nelts; i++) {
2951 if (uscfp[i]->host.len != u->host.len) { 2846 if (uscfp[i]->host.len != u->host.len
2847 || ngx_strncasecmp(uscfp[i]->host.data, u->host.data, u->host.len)
2848 != 0)
2849 {
2952 continue; 2850 continue;
2953 } 2851 }
2954 2852
2955 if (ngx_strncasecmp(uscfp[i]->host.data, u->host.data, u->host.len) 2853 if ((flags & NGX_HTTP_UPSTREAM_CREATE)
2956 == 0) 2854 && (uscfp[i]->flags & NGX_HTTP_UPSTREAM_CREATE))
2957 { 2855 {
2958 return uscfp[i]; 2856 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
2959 } 2857 "duplicate upstream \"%V\"", &u->host);
2858 return NULL;
2859 }
2860
2861 if (uscfp[i]->port == 0 && u->portn && !u->no_port) {
2862 ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
2863 "upstream \"%V\" port %d is ignored",
2864 &u->host, u->portn);
2865 }
2866
2867 return uscfp[i];
2960 } 2868 }
2961 2869
2962 uscf = ngx_pcalloc(cf->pool, sizeof(ngx_http_upstream_srv_conf_t)); 2870 uscf = ngx_pcalloc(cf->pool, sizeof(ngx_http_upstream_srv_conf_t));
2963 if (uscf == NULL) { 2871 if (uscf == NULL) {
2964 return NULL; 2872 return NULL;
2965 } 2873 }
2966 2874
2875 uscf->flags = flags;
2967 uscf->host = u->host; 2876 uscf->host = u->host;
2968 uscf->file_name = cf->conf_file->file.name; 2877 uscf->file_name = cf->conf_file->file.name;
2969 uscf->line = cf->conf_file->line; 2878 uscf->line = cf->conf_file->line;
2970 uscf->port = u->default_portn; 2879 uscf->port = u->portn;
2880
2881 if (u->naddrs == 1) {
2882 uscf->servers = ngx_array_create(cf->pool, 1,
2883 sizeof(ngx_http_upstream_server_t));
2884 if (uscf->servers == NULL) {
2885 return NGX_CONF_ERROR;
2886 }
2887
2888 us = ngx_array_push(uscf->servers);
2889 if (us == NULL) {
2890 return NGX_CONF_ERROR;
2891 }
2892
2893 ngx_memzero(us, sizeof(ngx_http_upstream_server_t));
2894
2895 us->addrs = u->addrs;
2896 us->naddrs = u->naddrs;
2897 }
2971 2898
2972 uscfp = ngx_array_push(&umcf->upstreams); 2899 uscfp = ngx_array_push(&umcf->upstreams);
2973 if (uscfp == NULL) { 2900 if (uscfp == NULL) {
2974 return NULL; 2901 return NULL;
2975 } 2902 }
3008 2935
3009 ngx_uint_t i; 2936 ngx_uint_t i;
3010 ngx_array_t headers_in; 2937 ngx_array_t headers_in;
3011 ngx_hash_key_t *hk; 2938 ngx_hash_key_t *hk;
3012 ngx_hash_init_t hash; 2939 ngx_hash_init_t hash;
2940 ngx_http_upstream_init_pt init;
3013 ngx_http_upstream_header_t *header; 2941 ngx_http_upstream_header_t *header;
3014 ngx_http_upstream_srv_conf_t **uscfp; 2942 ngx_http_upstream_srv_conf_t **uscfp;
3015 2943
3016 uscfp = umcf->upstreams.elts; 2944 uscfp = umcf->upstreams.elts;
3017 2945
3018 for (i = 0; i < umcf->upstreams.nelts; i++) { 2946 for (i = 0; i < umcf->upstreams.nelts; i++) {
3019 if (uscfp[i]->peers) { 2947
3020 continue; 2948 init = uscfp[i]->peer.init_upstream ? uscfp[i]->peer.init_upstream:
3021 } 2949 ngx_http_upstream_init_round_robin;
3022 2950
3023 uscfp[i]->peers = ngx_inet_resolve_peer(cf, &uscfp[i]->host, 2951 if (init(cf, uscfp[i]) != NGX_OK) {
3024 uscfp[i]->port);
3025 if (uscfp[i]->peers == NULL) {
3026 return NGX_CONF_ERROR; 2952 return NGX_CONF_ERROR;
3027 } 2953 }
3028 2954 }
3029 if (uscfp[i]->peers == NGX_CONF_ERROR) { 2955
3030 ngx_log_error(NGX_LOG_EMERG, cf->log, 0, 2956
3031 "upstream host \"%V\" is not found in %s:%ui", 2957 /* upstream_headers_in_hash */
3032 &uscfp[i]->host, uscfp[i]->file_name.data,
3033 uscfp[i]->line);
3034 return NGX_CONF_ERROR;
3035 }
3036 }
3037
3038 2958
3039 if (ngx_array_init(&headers_in, cf->temp_pool, 32, sizeof(ngx_hash_key_t)) 2959 if (ngx_array_init(&headers_in, cf->temp_pool, 32, sizeof(ngx_hash_key_t))
3040 != NGX_OK) 2960 != NGX_OK)
3041 { 2961 {
3042 return NGX_CONF_ERROR; 2962 return NGX_CONF_ERROR;