comparison src/http/modules/ngx_http_fastcgi_module.c @ 4122:c7fae0daeb57

Keepalive support in fastcgi. By default follow the old behaviour, i.e. FASTCGI_KEEP_CONN flag isn't set in request and application is responsible for closing connection once request is done. To keep connections alive fastcgi_keep_conn must be activated.
author Maxim Dounin <mdounin@mdounin.ru>
date Thu, 15 Sep 2011 19:05:23 +0000
parents e0a435f5f504
children 7898857ff34b
comparison
equal deleted inserted replaced
4121:16c60162c35b 4122:c7fae0daeb57
23 ngx_array_t *fastcgi_lengths; 23 ngx_array_t *fastcgi_lengths;
24 ngx_array_t *fastcgi_values; 24 ngx_array_t *fastcgi_values;
25 25
26 ngx_hash_t headers_hash; 26 ngx_hash_t headers_hash;
27 ngx_uint_t header_params; 27 ngx_uint_t header_params;
28
29 ngx_flag_t keep_conn;
28 30
29 #if (NGX_HTTP_CACHE) 31 #if (NGX_HTTP_CACHE)
30 ngx_http_complex_value_t cache_key; 32 ngx_http_complex_value_t cache_key;
31 #endif 33 #endif
32 34
75 } ngx_http_fastcgi_ctx_t; 77 } ngx_http_fastcgi_ctx_t;
76 78
77 79
78 #define NGX_HTTP_FASTCGI_RESPONDER 1 80 #define NGX_HTTP_FASTCGI_RESPONDER 1
79 81
82 #define NGX_HTTP_FASTCGI_KEEP_CONN 1
83
80 #define NGX_HTTP_FASTCGI_BEGIN_REQUEST 1 84 #define NGX_HTTP_FASTCGI_BEGIN_REQUEST 1
81 #define NGX_HTTP_FASTCGI_ABORT_REQUEST 2 85 #define NGX_HTTP_FASTCGI_ABORT_REQUEST 2
82 #define NGX_HTTP_FASTCGI_END_REQUEST 3 86 #define NGX_HTTP_FASTCGI_END_REQUEST 3
83 #define NGX_HTTP_FASTCGI_PARAMS 4 87 #define NGX_HTTP_FASTCGI_PARAMS 4
84 #define NGX_HTTP_FASTCGI_STDIN 5 88 #define NGX_HTTP_FASTCGI_STDIN 5
128 static ngx_int_t ngx_http_fastcgi_create_key(ngx_http_request_t *r); 132 static ngx_int_t ngx_http_fastcgi_create_key(ngx_http_request_t *r);
129 #endif 133 #endif
130 static ngx_int_t ngx_http_fastcgi_create_request(ngx_http_request_t *r); 134 static ngx_int_t ngx_http_fastcgi_create_request(ngx_http_request_t *r);
131 static ngx_int_t ngx_http_fastcgi_reinit_request(ngx_http_request_t *r); 135 static ngx_int_t ngx_http_fastcgi_reinit_request(ngx_http_request_t *r);
132 static ngx_int_t ngx_http_fastcgi_process_header(ngx_http_request_t *r); 136 static ngx_int_t ngx_http_fastcgi_process_header(ngx_http_request_t *r);
137 static ngx_int_t ngx_http_fastcgi_input_filter_init(void *data);
133 static ngx_int_t ngx_http_fastcgi_input_filter(ngx_event_pipe_t *p, 138 static ngx_int_t ngx_http_fastcgi_input_filter(ngx_event_pipe_t *p,
134 ngx_buf_t *buf); 139 ngx_buf_t *buf);
135 static ngx_int_t ngx_http_fastcgi_process_record(ngx_http_request_t *r, 140 static ngx_int_t ngx_http_fastcgi_process_record(ngx_http_request_t *r,
136 ngx_http_fastcgi_ctx_t *f); 141 ngx_http_fastcgi_ctx_t *f);
137 static void ngx_http_fastcgi_abort_request(ngx_http_request_t *r); 142 static void ngx_http_fastcgi_abort_request(ngx_http_request_t *r);
433 { ngx_string("fastcgi_catch_stderr"), 438 { ngx_string("fastcgi_catch_stderr"),
434 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, 439 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
435 ngx_conf_set_str_array_slot, 440 ngx_conf_set_str_array_slot,
436 NGX_HTTP_LOC_CONF_OFFSET, 441 NGX_HTTP_LOC_CONF_OFFSET,
437 offsetof(ngx_http_fastcgi_loc_conf_t, catch_stderr), 442 offsetof(ngx_http_fastcgi_loc_conf_t, catch_stderr),
443 NULL },
444
445 { ngx_string("fastcgi_keep_conn"),
446 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
447 ngx_conf_set_flag_slot,
448 NGX_HTTP_LOC_CONF_OFFSET,
449 offsetof(ngx_http_fastcgi_loc_conf_t, keep_conn),
438 NULL }, 450 NULL },
439 451
440 ngx_null_command 452 ngx_null_command
441 }; 453 };
442 454
597 return NGX_HTTP_INTERNAL_SERVER_ERROR; 609 return NGX_HTTP_INTERNAL_SERVER_ERROR;
598 } 610 }
599 611
600 u->pipe->input_filter = ngx_http_fastcgi_input_filter; 612 u->pipe->input_filter = ngx_http_fastcgi_input_filter;
601 u->pipe->input_ctx = r; 613 u->pipe->input_ctx = r;
614
615 u->input_filter_init = ngx_http_fastcgi_input_filter_init;
602 616
603 rc = ngx_http_read_client_request_body(r, ngx_http_upstream_init); 617 rc = ngx_http_read_client_request_body(r, ngx_http_upstream_init);
604 618
605 if (rc >= NGX_HTTP_SPECIAL_RESPONSE) { 619 if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
606 return rc; 620 return rc;
839 return NGX_ERROR; 853 return NGX_ERROR;
840 } 854 }
841 855
842 cl->buf = b; 856 cl->buf = b;
843 857
858 ngx_http_fastcgi_request_start.br.flags =
859 flcf->keep_conn ? NGX_HTTP_FASTCGI_KEEP_CONN : 0;
860
844 ngx_memcpy(b->pos, &ngx_http_fastcgi_request_start, 861 ngx_memcpy(b->pos, &ngx_http_fastcgi_request_start,
845 sizeof(ngx_http_fastcgi_request_start_t)); 862 sizeof(ngx_http_fastcgi_request_start_t));
846 863
847 h = (ngx_http_fastcgi_header_t *) 864 h = (ngx_http_fastcgi_header_t *)
848 (b->pos + sizeof(ngx_http_fastcgi_header_t) 865 (b->pos + sizeof(ngx_http_fastcgi_header_t)
1572 } 1589 }
1573 } 1590 }
1574 1591
1575 1592
1576 static ngx_int_t 1593 static ngx_int_t
1594 ngx_http_fastcgi_input_filter_init(void *data)
1595 {
1596 ngx_http_request_t *r = data;
1597 ngx_http_fastcgi_loc_conf_t *flcf;
1598
1599 flcf = ngx_http_get_module_loc_conf(r, ngx_http_fastcgi_module);
1600
1601 r->upstream->pipe->length = flcf->keep_conn ?
1602 (off_t) sizeof(ngx_http_fastcgi_header_t) : -1;
1603
1604 return NGX_OK;
1605 }
1606
1607
1608 static ngx_int_t
1577 ngx_http_fastcgi_input_filter(ngx_event_pipe_t *p, ngx_buf_t *buf) 1609 ngx_http_fastcgi_input_filter(ngx_event_pipe_t *p, ngx_buf_t *buf)
1578 { 1610 {
1579 u_char *m, *msg; 1611 u_char *m, *msg;
1580 ngx_int_t rc; 1612 ngx_int_t rc;
1581 ngx_buf_t *b, **prev; 1613 ngx_buf_t *b, **prev;
1582 ngx_chain_t *cl; 1614 ngx_chain_t *cl;
1583 ngx_http_request_t *r; 1615 ngx_http_request_t *r;
1584 ngx_http_fastcgi_ctx_t *f; 1616 ngx_http_fastcgi_ctx_t *f;
1617 ngx_http_fastcgi_loc_conf_t *flcf;
1585 1618
1586 if (buf->pos == buf->last) { 1619 if (buf->pos == buf->last) {
1587 return NGX_OK; 1620 return NGX_OK;
1588 } 1621 }
1589 1622
1590 r = p->input_ctx; 1623 r = p->input_ctx;
1591 f = ngx_http_get_module_ctx(r, ngx_http_fastcgi_module); 1624 f = ngx_http_get_module_ctx(r, ngx_http_fastcgi_module);
1625 flcf = ngx_http_get_module_loc_conf(r, ngx_http_fastcgi_module);
1592 1626
1593 b = NULL; 1627 b = NULL;
1594 prev = &buf->shadow; 1628 prev = &buf->shadow;
1595 1629
1596 f->pos = buf->pos; 1630 f->pos = buf->pos;
1609 return NGX_ERROR; 1643 return NGX_ERROR;
1610 } 1644 }
1611 1645
1612 if (f->type == NGX_HTTP_FASTCGI_STDOUT && f->length == 0) { 1646 if (f->type == NGX_HTTP_FASTCGI_STDOUT && f->length == 0) {
1613 f->state = ngx_http_fastcgi_st_version; 1647 f->state = ngx_http_fastcgi_st_version;
1614 p->upstream_done = 1; 1648
1649 if (!flcf->keep_conn) {
1650 p->upstream_done = 1;
1651 }
1615 1652
1616 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, p->log, 0, 1653 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, p->log, 0,
1617 "http fastcgi closed stdout"); 1654 "http fastcgi closed stdout");
1618 1655
1619 continue; 1656 continue;
1620 } 1657 }
1621 1658
1622 if (f->type == NGX_HTTP_FASTCGI_END_REQUEST) { 1659 if (f->type == NGX_HTTP_FASTCGI_END_REQUEST) {
1623 f->state = ngx_http_fastcgi_st_version; 1660 f->state = ngx_http_fastcgi_st_version;
1624 p->upstream_done = 1; 1661 p->upstream_done = 1;
1662
1663 if (flcf->keep_conn) {
1664 r->upstream->keepalive = 1;
1665 }
1625 1666
1626 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, p->log, 0, 1667 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, p->log, 0,
1627 "http fastcgi sent end request"); 1668 "http fastcgi sent end request");
1628 1669
1629 break; 1670 break;
1777 1818
1778 b->last = f->last; 1819 b->last = f->last;
1779 1820
1780 break; 1821 break;
1781 1822
1823 }
1824
1825 if (flcf->keep_conn) {
1826
1827 /* set p->length, minimal amount of data we want to see */
1828
1829 if (f->state < ngx_http_fastcgi_st_data) {
1830 p->length = 1;
1831
1832 } else if (f->state == ngx_http_fastcgi_st_padding) {
1833 p->length = f->padding;
1834
1835 } else {
1836 /* ngx_http_fastcgi_st_data */
1837
1838 p->length = f->length;
1839 }
1782 } 1840 }
1783 1841
1784 if (b) { 1842 if (b) {
1785 b->shadow = buf; 1843 b->shadow = buf;
1786 b->last_shadow = 1; 1844 b->last_shadow = 1;
2009 /* "fastcgi_cyclic_temp_file" is disabled */ 2067 /* "fastcgi_cyclic_temp_file" is disabled */
2010 conf->upstream.cyclic_temp_file = 0; 2068 conf->upstream.cyclic_temp_file = 0;
2011 2069
2012 conf->catch_stderr = NGX_CONF_UNSET_PTR; 2070 conf->catch_stderr = NGX_CONF_UNSET_PTR;
2013 2071
2072 conf->keep_conn = NGX_CONF_UNSET;
2073
2014 ngx_str_set(&conf->upstream.module, "fastcgi"); 2074 ngx_str_set(&conf->upstream.module, "fastcgi");
2015 2075
2016 return conf; 2076 return conf;
2017 } 2077 }
2018 2078
2252 ngx_conf_merge_value(conf->upstream.intercept_errors, 2312 ngx_conf_merge_value(conf->upstream.intercept_errors,
2253 prev->upstream.intercept_errors, 0); 2313 prev->upstream.intercept_errors, 0);
2254 2314
2255 ngx_conf_merge_ptr_value(conf->catch_stderr, prev->catch_stderr, NULL); 2315 ngx_conf_merge_ptr_value(conf->catch_stderr, prev->catch_stderr, NULL);
2256 2316
2317 ngx_conf_merge_value(conf->keep_conn, prev->keep_conn, 0);
2318
2257 2319
2258 ngx_conf_merge_str_value(conf->index, prev->index, ""); 2320 ngx_conf_merge_str_value(conf->index, prev->index, "");
2259 2321
2260 hash.max_size = 512; 2322 hash.max_size = 512;
2261 hash.bucket_size = ngx_align(64, ngx_cacheline_size); 2323 hash.bucket_size = ngx_align(64, ngx_cacheline_size);