comparison src/http/ngx_http_upstream.c @ 884:4d68c486fcb0

upstream choice modules
author Igor Sysoev <igor@sysoev.ru>
date Mon, 04 Dec 2006 16:46:13 +0000
parents 3b763d36e055
children bb6e1bbcdd67
comparison
equal deleted inserted replaced
883:eac23634d614 884:4d68c486fcb0
85 85
86 #if (NGX_HTTP_SSL) 86 #if (NGX_HTTP_SSL)
87 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 *,
88 ngx_http_upstream_t *u, ngx_connection_t *c); 88 ngx_http_upstream_t *u, ngx_connection_t *c);
89 static void ngx_http_upstream_ssl_handshake(ngx_connection_t *c); 89 static void ngx_http_upstream_ssl_handshake(ngx_connection_t *c);
90 static void ngx_http_upstream_ssl_shutdown(ngx_connection_t *c,
91 ngx_peer_t *peer);
92 #endif 90 #endif
93 91
94 92
95 ngx_http_upstream_header_t ngx_http_upstream_headers_in[] = { 93 ngx_http_upstream_header_t ngx_http_upstream_headers_in[] = {
96 94
213 0, 211 0,
214 0, 212 0,
215 NULL }, 213 NULL },
216 214
217 { ngx_string("server"), 215 { ngx_string("server"),
218 NGX_HTTP_UPS_CONF|NGX_CONF_TAKE12, 216 NGX_HTTP_UPS_CONF|NGX_CONF_1MORE,
219 ngx_http_upstream_server, 217 ngx_http_upstream_server,
220 NGX_HTTP_SRV_CONF_OFFSET, 218 NGX_HTTP_SRV_CONF_OFFSET,
221 0, 219 0,
222 NULL }, 220 NULL },
223 221
306 304
307 if (r->request_body) { 305 if (r->request_body) {
308 u->request_bufs = r->request_body->bufs; 306 u->request_bufs = r->request_body->bufs;
309 } 307 }
310 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
311 if (u->create_request(r) != NGX_OK) { 314 if (u->create_request(r) != NGX_OK) {
312 ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); 315 ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
313 return; 316 return;
314 } 317 }
315
316 u->peer.log = r->connection->log;
317 318
318 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);
319 320
320 u->output.sendfile = r->connection->sendfile; 321 u->output.sendfile = r->connection->sendfile;
321 u->output.pool = r->pool; 322 u->output.pool = r->pool;
324 u->output.output_filter = ngx_chain_writer; 325 u->output.output_filter = ngx_chain_writer;
325 u->output.filter_ctx = &u->writer; 326 u->output.filter_ctx = &u->writer;
326 327
327 u->writer.pool = r->pool; 328 u->writer.pool = r->pool;
328 329
329 if (ngx_array_init(&u->states, r->pool, u->peer.peers->number, 330 if (ngx_array_init(&u->states, r->pool, 1,
330 sizeof(ngx_http_upstream_state_t)) 331 sizeof(ngx_http_upstream_state_t))
331 != NGX_OK) 332 != NGX_OK)
332 { 333 {
333 ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); 334 ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
334 return; 335 return;
526 ngx_http_upstream_finalize_request(r, u, 527 ngx_http_upstream_finalize_request(r, u,
527 NGX_HTTP_INTERNAL_SERVER_ERROR); 528 NGX_HTTP_INTERNAL_SERVER_ERROR);
528 return; 529 return;
529 } 530 }
530 531
531 u->state->peer = &u->peer.peers->peer[u->peer.cur_peer].name; 532 u->state->peer = u->peer.name;
532 533
533 if (rc == NGX_BUSY) { 534 if (rc == NGX_BUSY) {
534 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");
535 } 536 }
536 537
615 616
616 static void 617 static void
617 ngx_http_upstream_ssl_init_connection(ngx_http_request_t *r, 618 ngx_http_upstream_ssl_init_connection(ngx_http_request_t *r,
618 ngx_http_upstream_t *u, ngx_connection_t *c) 619 ngx_http_upstream_t *u, ngx_connection_t *c)
619 { 620 {
620 ngx_int_t rc; 621 ngx_int_t rc;
621 ngx_peer_t *peer;
622 622
623 if (ngx_ssl_create_connection(u->conf->ssl, c, 623 if (ngx_ssl_create_connection(u->conf->ssl, c,
624 NGX_SSL_BUFFER|NGX_SSL_CLIENT) 624 NGX_SSL_BUFFER|NGX_SSL_CLIENT)
625 == NGX_ERROR) 625 == NGX_ERROR)
626 { 626 {
630 } 630 }
631 631
632 c->sendfile = 0; 632 c->sendfile = 0;
633 u->output.sendfile = 0; 633 u->output.sendfile = 0;
634 634
635 peer = &u->peer.peers->peer[u->peer.cur_peer]; 635 if (ngx_ssl_set_session(c, u->peer.ssl_session) != NGX_OK) {
636
637 if (ngx_ssl_set_session(c, peer->ssl_session) != NGX_OK) {
638 ngx_http_upstream_finalize_request(r, u, 636 ngx_http_upstream_finalize_request(r, u,
639 NGX_HTTP_INTERNAL_SERVER_ERROR); 637 NGX_HTTP_INTERNAL_SERVER_ERROR);
640 return; 638 return;
641 } 639 }
642 640
661 659
662 r = c->data; 660 r = c->data;
663 u = r->upstream; 661 u = r->upstream;
664 662
665 if (c->ssl->handshaked) { 663 if (c->ssl->handshaked) {
664
665 u->peer.save_session(&u->peer, u->peer.data);
666 666
667 c->write->handler = ngx_http_upstream_send_request_handler; 667 c->write->handler = ngx_http_upstream_send_request_handler;
668 c->read->handler = ngx_http_upstream_process_header; 668 c->read->handler = ngx_http_upstream_process_header;
669 669
670 ngx_http_upstream_send_request(r, u); 670 ngx_http_upstream_send_request(r, u);
970 } 970 }
971 #endif 971 #endif
972 } 972 }
973 973
974 n = u->peer.connection->recv(u->peer.connection, u->buffer.last, 974 n = u->peer.connection->recv(u->peer.connection, u->buffer.last,
975 u->buffer.end - u->buffer.last); 975 u->buffer.end - u->buffer.last);
976 976
977 if (n == NGX_AGAIN) { 977 if (n == NGX_AGAIN) {
978 #if 0 978 #if 0
979 ngx_add_timer(rev, u->read_timeout); 979 ngx_add_timer(rev, u->read_timeout);
980 #endif 980 #endif
1583 size_t size; 1583 size_t size;
1584 ssize_t n; 1584 ssize_t n;
1585 ngx_buf_t *b; 1585 ngx_buf_t *b;
1586 ngx_int_t rc; 1586 ngx_int_t rc;
1587 ngx_uint_t do_write; 1587 ngx_uint_t do_write;
1588 ngx_connection_t *c, *client; 1588 ngx_connection_t *c, *downstream, *upstream;
1589 ngx_http_request_t *r; 1589 ngx_http_request_t *r;
1590 ngx_http_upstream_t *u; 1590 ngx_http_upstream_t *u;
1591 ngx_http_core_loc_conf_t *clcf; 1591 ngx_http_core_loc_conf_t *clcf;
1592 1592
1593 c = ev->data; 1593 c = ev->data;
1616 1616
1617 ngx_http_upstream_finalize_request(r, u, 0); 1617 ngx_http_upstream_finalize_request(r, u, 0);
1618 return; 1618 return;
1619 } 1619 }
1620 1620
1621 client = r->connection; 1621 downstream = r->connection;
1622 upstream = u->peer.connection;
1622 1623
1623 b = &u->buffer; 1624 b = &u->buffer;
1624 1625
1625 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);
1626 1627
1631 if (do_write) { 1632 if (do_write) {
1632 1633
1633 if (u->out_bufs || u->busy_bufs) { 1634 if (u->out_bufs || u->busy_bufs) {
1634 rc = ngx_http_output_filter(r, u->out_bufs); 1635 rc = ngx_http_output_filter(r, u->out_bufs);
1635 1636
1636 if (client->destroyed) { 1637 if (downstream->destroyed) {
1637 return; 1638 return;
1638 } 1639 }
1639 1640
1640 if (rc == NGX_ERROR) { 1641 if (rc == NGX_ERROR) {
1641 ngx_http_upstream_finalize_request(r, u, 0); 1642 ngx_http_upstream_finalize_request(r, u, 0);
1647 } 1648 }
1648 1649
1649 if (u->busy_bufs == NULL) { 1650 if (u->busy_bufs == NULL) {
1650 1651
1651 if (u->length == 0 1652 if (u->length == 0
1652 || u->peer.connection->read->eof 1653 || upstream->read->eof
1653 || u->peer.connection->read->error) 1654 || upstream->read->error)
1654 { 1655 {
1655 ngx_http_upstream_finalize_request(r, u, 0); 1656 ngx_http_upstream_finalize_request(r, u, 0);
1656 return; 1657 return;
1657 } 1658 }
1658 1659
1665 1666
1666 if (size > u->length) { 1667 if (size > u->length) {
1667 size = u->length; 1668 size = u->length;
1668 } 1669 }
1669 1670
1670 if (size && u->peer.connection->read->ready) { 1671 if (size && upstream->read->ready) {
1671 1672
1672 n = u->peer.connection->recv(u->peer.connection, b->last, size); 1673 n = upstream->recv(upstream, b->last, size);
1673 1674
1674 if (n == NGX_AGAIN) { 1675 if (n == NGX_AGAIN) {
1675 break; 1676 break;
1676 } 1677 }
1677 1678
1688 } 1689 }
1689 1690
1690 break; 1691 break;
1691 } 1692 }
1692 1693
1693 if (client->data == r) { 1694 if (downstream->data == r) {
1694 if (ngx_handle_write_event(client->write, clcf->send_lowat) 1695 if (ngx_handle_write_event(downstream->write, clcf->send_lowat)
1695 == NGX_ERROR) 1696 == NGX_ERROR)
1696 { 1697 {
1697 ngx_http_upstream_finalize_request(r, u, 0); 1698 ngx_http_upstream_finalize_request(r, u, 0);
1698 return; 1699 return;
1699 } 1700 }
1700 } 1701 }
1701 1702
1702 if (client->write->active) { 1703 if (downstream->write->active) {
1703 ngx_add_timer(client->write, clcf->send_timeout); 1704 ngx_add_timer(downstream->write, clcf->send_timeout);
1704 1705
1705 } else if (client->write->timer_set) { 1706 } else if (downstream->write->timer_set) {
1706 ngx_del_timer(client->write); 1707 ngx_del_timer(downstream->write);
1707 } 1708 }
1708 1709
1709 if (ngx_handle_read_event(u->peer.connection->read, 0) == NGX_ERROR) { 1710 if (ngx_handle_read_event(upstream->read, 0) == NGX_ERROR) {
1710 ngx_http_upstream_finalize_request(r, u, 0); 1711 ngx_http_upstream_finalize_request(r, u, 0);
1711 return; 1712 return;
1712 } 1713 }
1713 1714
1714 if (u->peer.connection->read->active) { 1715 if (upstream->read->active) {
1715 ngx_add_timer(u->peer.connection->read, u->conf->read_timeout); 1716 ngx_add_timer(upstream->read, u->conf->read_timeout);
1716 1717
1717 } else if (u->peer.connection->read->timer_set) { 1718 } else if (upstream->read->timer_set) {
1718 ngx_del_timer(u->peer.connection->read); 1719 ngx_del_timer(upstream->read);
1719 } 1720 }
1720 } 1721 }
1721 1722
1722 1723
1723 static ngx_int_t 1724 static ngx_int_t
1920 1921
1921 static void 1922 static void
1922 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,
1923 ngx_uint_t ft_type) 1924 ngx_uint_t ft_type)
1924 { 1925 {
1925 ngx_uint_t status, down; 1926 ngx_uint_t status, state;
1926 1927
1927 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, 1928 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1928 "http next upstream, %xD", ft_type); 1929 "http next upstream, %xi", ft_type);
1929 1930
1930 #if 0 1931 #if 0
1931 ngx_http_busy_unlock(u->conf->busy_lock, &u->busy_lock); 1932 ngx_http_busy_unlock(u->conf->busy_lock, &u->busy_lock);
1932 #endif 1933 #endif
1933 1934
1934 if (ft_type == NGX_HTTP_UPSTREAM_FT_HTTP_404) { 1935 if (ft_type == NGX_HTTP_UPSTREAM_FT_HTTP_404) {
1935 down = 0; 1936 state = NGX_PEER_NEXT;
1936 } else { 1937 } else {
1937 down = 1; 1938 state = NGX_PEER_FAILED;
1938 } 1939 }
1939 1940
1940 ngx_event_connect_peer_failed(&u->peer, down); 1941 u->peer.free(&u->peer, u->peer.data, state);
1941 1942
1942 if (ft_type == NGX_HTTP_UPSTREAM_FT_TIMEOUT) { 1943 if (ft_type == NGX_HTTP_UPSTREAM_FT_TIMEOUT) {
1943 ngx_log_error(NGX_LOG_ERR, r->connection->log, NGX_ETIMEDOUT, 1944 ngx_log_error(NGX_LOG_ERR, r->connection->log, NGX_ETIMEDOUT,
1944 "upstream timed out"); 1945 "upstream timed out");
1945 } 1946 }
2001 if (u->peer.connection) { 2002 if (u->peer.connection) {
2002 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, 2003 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2003 "close http upstream connection: %d", 2004 "close http upstream connection: %d",
2004 u->peer.connection->fd); 2005 u->peer.connection->fd);
2005 #if (NGX_HTTP_SSL) 2006 #if (NGX_HTTP_SSL)
2007
2006 if (u->peer.connection->ssl) { 2008 if (u->peer.connection->ssl) {
2007 ngx_http_upstream_ssl_shutdown(u->peer.connection, 2009 u->peer.connection->ssl->no_wait_shutdown = 1;
2008 &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);
2009 } 2013 }
2010 #endif 2014 #endif
2015
2011 ngx_close_connection(u->peer.connection); 2016 ngx_close_connection(u->peer.connection);
2012 } 2017 }
2013 2018
2014 #if 0 2019 #if 0
2015 if (u->conf->busy_lock && !u->busy_locked) { 2020 if (u->conf->busy_lock && !u->busy_locked) {
2052 u->state->response_time = (ms >= 0) ? ms : 0; 2057 u->state->response_time = (ms >= 0) ? ms : 0;
2053 } 2058 }
2054 2059
2055 u->finalize_request(r, rc); 2060 u->finalize_request(r, rc);
2056 2061
2062 u->peer.free(&u->peer, u->peer.data, 0);
2063
2057 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
2058 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, 2084 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2059 "close http upstream connection: %d", 2085 "close http upstream connection: %d",
2060 u->peer.connection->fd); 2086 u->peer.connection->fd);
2061 #if (NGX_HTTP_SSL) 2087
2062
2063 /* TODO: do not shutdown persistent connection */
2064
2065 if (u->peer.connection->ssl) {
2066 ngx_http_upstream_ssl_shutdown(u->peer.connection,
2067 &u->peer.peers->peer[u->peer.cur_peer]);
2068 }
2069 #endif
2070 ngx_close_connection(u->peer.connection); 2088 ngx_close_connection(u->peer.connection);
2071 } 2089 }
2072 2090
2073 u->peer.connection = NULL; 2091 u->peer.connection = NULL;
2074 2092
2103 2121
2104 ngx_http_finalize_request(r, rc); 2122 ngx_http_finalize_request(r, rc);
2105 } 2123 }
2106 2124
2107 2125
2108 #if (NGX_HTTP_SSL)
2109
2110 static void
2111 ngx_http_upstream_ssl_shutdown(ngx_connection_t *c, ngx_peer_t *peer)
2112 {
2113 /* lock peer mutex */
2114
2115 if (peer->ssl_session) {
2116 ngx_ssl_free_session(peer->ssl_session);
2117 }
2118
2119 peer->ssl_session = ngx_ssl_get_session(c);
2120
2121 /* unlock peer mutex */
2122
2123 /*
2124 * We send the "close notify" shutdown alert to the upstream only
2125 * and do not wait its "close notify" shutdown alert.
2126 * It is acceptable according to the TLS standard.
2127 */
2128
2129 c->ssl->no_wait_shutdown = 1;
2130
2131 (void) ngx_ssl_shutdown(c);
2132 }
2133
2134 #endif
2135
2136
2137 static ngx_int_t 2126 static ngx_int_t
2138 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,
2139 ngx_uint_t offset) 2128 ngx_uint_t offset)
2140 { 2129 {
2141 ngx_table_elt_t **ph; 2130 ngx_table_elt_t **ph;
2593 2582
2594 2583
2595 static char * 2584 static char *
2596 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)
2597 { 2586 {
2598 char *rv; 2587 char *rv;
2599 void *mconf; 2588 void *mconf;
2600 ngx_str_t *value; 2589 ngx_str_t *value;
2601 ngx_url_t u; 2590 ngx_url_t u;
2602 ngx_uint_t i, j, m, n; 2591 ngx_uint_t m;
2603 ngx_conf_t pcf; 2592 ngx_conf_t pcf;
2604 ngx_peers_t **peers; 2593 ngx_http_module_t *module;
2605 ngx_http_module_t *module; 2594 ngx_http_conf_ctx_t *ctx, *http_ctx;
2606 ngx_http_conf_ctx_t *ctx; 2595 ngx_http_upstream_srv_conf_t *uscf;
2607 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
2608 2614
2609 ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t)); 2615 ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t));
2610 if (ctx == NULL) { 2616 if (ctx == NULL) {
2611 return NGX_CONF_ERROR; 2617 return NGX_CONF_ERROR;
2612 } 2618 }
2613 2619
2614 ngx_memzero(&u, sizeof(ngx_url_t)); 2620 http_ctx = cf->ctx;
2615 2621 ctx->main_conf = http_ctx->main_conf;
2616 value = cf->args->elts;
2617 u.host = value[1];
2618
2619 uscf = ngx_http_upstream_add(cf, &u);
2620 if (uscf == NULL) {
2621 return NGX_CONF_ERROR;
2622 }
2623 2622
2624 /* the upstream{}'s srv_conf */ 2623 /* the upstream{}'s srv_conf */
2625 2624
2626 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);
2627 if (ctx->srv_conf == NULL) { 2626 if (ctx->srv_conf == NULL) {
2628 return NGX_CONF_ERROR; 2627 return NGX_CONF_ERROR;
2629 } 2628 }
2630 2629
2631 ctx->srv_conf[ngx_http_upstream_module.ctx_index] = uscf; 2630 ctx->srv_conf[ngx_http_upstream_module.ctx_index] = uscf;
2632 2631
2632 uscf->srv_conf = ctx->srv_conf;
2633
2633 2634
2634 /* the upstream{}'s loc_conf */ 2635 /* the upstream{}'s loc_conf */
2635 2636
2636 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);
2637 if (ctx->loc_conf == NULL) { 2638 if (ctx->loc_conf == NULL) {
2642 if (ngx_modules[m]->type != NGX_HTTP_MODULE) { 2643 if (ngx_modules[m]->type != NGX_HTTP_MODULE) {
2643 continue; 2644 continue;
2644 } 2645 }
2645 2646
2646 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 }
2647 2657
2648 if (module->create_loc_conf) { 2658 if (module->create_loc_conf) {
2649 mconf = module->create_loc_conf(cf); 2659 mconf = module->create_loc_conf(cf);
2650 if (mconf == NULL) { 2660 if (mconf == NULL) {
2651 return NGX_CONF_ERROR; 2661 return NGX_CONF_ERROR;
2674 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, 2684 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
2675 "no servers are inside upstream"); 2685 "no servers are inside upstream");
2676 return NGX_CONF_ERROR; 2686 return NGX_CONF_ERROR;
2677 } 2687 }
2678 2688
2679 peers = uscf->servers->elts;
2680
2681 if (uscf->servers->nelts == 1) {
2682 uscf->peers = peers[0];
2683 }
2684
2685 n = 0;
2686
2687 for (i = 0; i < uscf->servers->nelts; i++) {
2688 n += peers[i]->number;
2689 }
2690
2691 uscf->peers = ngx_pcalloc(cf->pool,
2692 sizeof(ngx_peers_t) + sizeof(ngx_peer_t) * (n - 1));
2693 if (uscf->peers == NULL) {
2694 return NGX_CONF_ERROR;
2695 }
2696
2697 uscf->peers->number = n;
2698
2699 n = 0;
2700
2701 for (i = 0; i < uscf->servers->nelts; i++) {
2702 for (j = 0; j < peers[i]->number; j++) {
2703 uscf->peers->peer[n++] = peers[i]->peer[j];
2704 }
2705 }
2706
2707 return rv; 2689 return rv;
2708 } 2690 }
2709 2691
2710 2692
2711 static char * 2693 static char *
2712 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)
2713 { 2695 {
2714 ngx_http_upstream_srv_conf_t *uscf = conf; 2696 ngx_http_upstream_srv_conf_t *uscf = conf;
2715 2697
2716 ngx_str_t *value; 2698 time_t fail_timeout;
2717 ngx_url_t u; 2699 ngx_str_t *value, s;
2718 ngx_int_t weight; 2700 ngx_url_t u;
2719 ngx_uint_t i; 2701 ngx_int_t weight, max_fails;
2720 ngx_peers_t **peers; 2702 ngx_uint_t i;
2703 ngx_http_upstream_server_t *us;
2721 2704
2722 if (uscf->servers == NULL) { 2705 if (uscf->servers == NULL) {
2723 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));
2724 if (uscf->servers == NULL) { 2708 if (uscf->servers == NULL) {
2725 return NGX_CONF_ERROR; 2709 return NGX_CONF_ERROR;
2726 } 2710 }
2727 } 2711 }
2728 2712
2729 peers = ngx_array_push(uscf->servers); 2713 us = ngx_array_push(uscf->servers);
2730 if (peers == NULL) { 2714 if (us == NULL) {
2731 return NGX_CONF_ERROR; 2715 return NGX_CONF_ERROR;
2732 } 2716 }
2717
2718 ngx_memzero(us, sizeof(ngx_http_upstream_server_t));
2733 2719
2734 value = cf->args->elts; 2720 value = cf->args->elts;
2735 2721
2736 ngx_memzero(&u, sizeof(ngx_url_t)); 2722 ngx_memzero(&u, sizeof(ngx_url_t));
2737 2723
2746 2732
2747 return NGX_CONF_ERROR; 2733 return NGX_CONF_ERROR;
2748 } 2734 }
2749 2735
2750 weight = 1; 2736 weight = 1;
2751 2737 max_fails = 1;
2752 if (cf->args->nelts == 3) { 2738 fail_timeout = 10;
2753 2739
2754 value = &value[2]; 2740 for (i = 2; i < cf->args->nelts; i++) {
2755 2741
2756 if (ngx_strncmp(value->data, "weight=", 7) == 0) { 2742 if (ngx_strncmp(value[i].data, "weight=", 7) == 0) {
2757 2743
2758 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);
2759 2749
2760 if (weight == NGX_ERROR || weight == 0) { 2750 if (weight == NGX_ERROR || weight == 0) {
2761 goto invalid; 2751 goto invalid;
2762 } 2752 }
2763 2753
2764 } else { 2754 continue;
2765 goto invalid; 2755 }
2766 } 2756
2767 } 2757 if (ngx_strncmp(value[i].data, "max_fails=", 10) == 0) {
2768 2758
2769 for (i = 0; i < u.peers->number; i++) { 2759 if (!(uscf->flags & NGX_HTTP_UPSTREAM_MAX_FAILS)) {
2770 u.peers->peer[i].weight = weight; 2760 goto invalid;
2771 u.peers->peer[i].current_weight = weight; 2761 }
2772 u.peers->peer[i].max_fails = NGX_CONF_UNSET_UINT; 2762
2773 u.peers->peer[i].fail_timeout = NGX_CONF_UNSET; 2763 max_fails = ngx_atoi(&value[i].data[10], value[i].len - 10);
2774 } 2764
2775 2765 if (max_fails == NGX_ERROR) {
2776 *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;
2777 2809
2778 return NGX_CONF_OK; 2810 return NGX_CONF_OK;
2779 2811
2780 invalid: 2812 invalid:
2781 2813
2782 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]);
2783 2816
2784 return NGX_CONF_ERROR; 2817 return NGX_CONF_ERROR;
2785 } 2818 }
2786 2819
2787 2820
2788 ngx_http_upstream_srv_conf_t * 2821 ngx_http_upstream_srv_conf_t *
2789 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)
2790 { 2823 {
2791 ngx_uint_t i; 2824 ngx_uint_t i;
2825 ngx_http_upstream_server_t *us;
2792 ngx_http_upstream_srv_conf_t *uscf, **uscfp; 2826 ngx_http_upstream_srv_conf_t *uscf, **uscfp;
2793 ngx_http_upstream_main_conf_t *umcf; 2827 ngx_http_upstream_main_conf_t *umcf;
2794 2828
2795 if (u->upstream) { 2829 if (!(flags & NGX_HTTP_UPSTREAM_CREATE)) {
2830
2796 if (ngx_parse_url(cf, u) != NGX_OK) { 2831 if (ngx_parse_url(cf, u) != NGX_OK) {
2797 if (u->err) { 2832 if (u->err) {
2798 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, 2833 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
2799 "%s in upstream \"%V\"", u->err, &u->url); 2834 "%s in upstream \"%V\"", u->err, &u->url);
2800 } 2835 }
2801 2836
2802 return NULL; 2837 return NULL;
2803 } 2838 }
2804
2805 if (u->peers) {
2806 uscf = ngx_pcalloc(cf->pool, sizeof(ngx_http_upstream_srv_conf_t));
2807 if (uscf == NULL) {
2808 return NULL;
2809 }
2810
2811 uscf->peers = u->peers;
2812
2813 return uscf;
2814 }
2815 } 2839 }
2816 2840
2817 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);
2818 2842
2819 uscfp = umcf->upstreams.elts; 2843 uscfp = umcf->upstreams.elts;
2820 2844
2821 for (i = 0; i < umcf->upstreams.nelts; i++) { 2845 for (i = 0; i < umcf->upstreams.nelts; i++) {
2822 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 {
2823 continue; 2850 continue;
2824 } 2851 }
2825 2852
2826 if (ngx_strncasecmp(uscfp[i]->host.data, u->host.data, u->host.len) 2853 if ((flags & NGX_HTTP_UPSTREAM_CREATE)
2827 == 0) 2854 && (uscfp[i]->flags & NGX_HTTP_UPSTREAM_CREATE))
2828 { 2855 {
2829 return uscfp[i]; 2856 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
2830 } 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];
2831 } 2868 }
2832 2869
2833 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));
2834 if (uscf == NULL) { 2871 if (uscf == NULL) {
2835 return NULL; 2872 return NULL;
2836 } 2873 }
2837 2874
2875 uscf->flags = flags;
2838 uscf->host = u->host; 2876 uscf->host = u->host;
2839 uscf->file_name = cf->conf_file->file.name; 2877 uscf->file_name = cf->conf_file->file.name;
2840 uscf->line = cf->conf_file->line; 2878 uscf->line = cf->conf_file->line;
2841 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 }
2842 2898
2843 uscfp = ngx_array_push(&umcf->upstreams); 2899 uscfp = ngx_array_push(&umcf->upstreams);
2844 if (uscfp == NULL) { 2900 if (uscfp == NULL) {
2845 return NULL; 2901 return NULL;
2846 } 2902 }
2879 2935
2880 ngx_uint_t i; 2936 ngx_uint_t i;
2881 ngx_array_t headers_in; 2937 ngx_array_t headers_in;
2882 ngx_hash_key_t *hk; 2938 ngx_hash_key_t *hk;
2883 ngx_hash_init_t hash; 2939 ngx_hash_init_t hash;
2940 ngx_http_upstream_init_pt init;
2884 ngx_http_upstream_header_t *header; 2941 ngx_http_upstream_header_t *header;
2885 ngx_http_upstream_srv_conf_t **uscfp; 2942 ngx_http_upstream_srv_conf_t **uscfp;
2886 2943
2887 uscfp = umcf->upstreams.elts; 2944 uscfp = umcf->upstreams.elts;
2888 2945
2889 for (i = 0; i < umcf->upstreams.nelts; i++) { 2946 for (i = 0; i < umcf->upstreams.nelts; i++) {
2890 if (uscfp[i]->peers) { 2947
2891 continue; 2948 init = uscfp[i]->peer.init_upstream ? uscfp[i]->peer.init_upstream:
2892 } 2949 ngx_http_upstream_init_round_robin;
2893 2950
2894 uscfp[i]->peers = ngx_inet_resolve_peer(cf, &uscfp[i]->host, 2951 if (init(cf, uscfp[i]) != NGX_OK) {
2895 uscfp[i]->port);
2896 if (uscfp[i]->peers == NULL) {
2897 return NGX_CONF_ERROR; 2952 return NGX_CONF_ERROR;
2898 } 2953 }
2899 2954 }
2900 if (uscfp[i]->peers == NGX_CONF_ERROR) { 2955
2901 ngx_log_error(NGX_LOG_EMERG, cf->log, 0, 2956
2902 "upstream host \"%V\" is not found in %s:%ui", 2957 /* upstream_headers_in_hash */
2903 &uscfp[i]->host, uscfp[i]->file_name.data,
2904 uscfp[i]->line);
2905 return NGX_CONF_ERROR;
2906 }
2907 }
2908
2909 2958
2910 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))
2911 != NGX_OK) 2960 != NGX_OK)
2912 { 2961 {
2913 return NGX_CONF_ERROR; 2962 return NGX_CONF_ERROR;