comparison src/http/modules/ngx_http_fastcgi_module.c @ 5394:8c827bb1b2b6

FastCGI: non-buffered mode support.
author Maxim Dounin <mdounin@mdounin.ru>
date Fri, 27 Sep 2013 16:50:40 +0400
parents e65be17e3a3e
children 43ccaf8e8728
comparison
equal deleted inserted replaced
5393:1a070e89b97a 5394:8c827bb1b2b6
136 static ngx_int_t ngx_http_fastcgi_reinit_request(ngx_http_request_t *r); 136 static ngx_int_t ngx_http_fastcgi_reinit_request(ngx_http_request_t *r);
137 static ngx_int_t ngx_http_fastcgi_process_header(ngx_http_request_t *r); 137 static ngx_int_t ngx_http_fastcgi_process_header(ngx_http_request_t *r);
138 static ngx_int_t ngx_http_fastcgi_input_filter_init(void *data); 138 static ngx_int_t ngx_http_fastcgi_input_filter_init(void *data);
139 static ngx_int_t ngx_http_fastcgi_input_filter(ngx_event_pipe_t *p, 139 static ngx_int_t ngx_http_fastcgi_input_filter(ngx_event_pipe_t *p,
140 ngx_buf_t *buf); 140 ngx_buf_t *buf);
141 static ngx_int_t ngx_http_fastcgi_non_buffered_filter(void *data,
142 ssize_t bytes);
141 static ngx_int_t ngx_http_fastcgi_process_record(ngx_http_request_t *r, 143 static ngx_int_t ngx_http_fastcgi_process_record(ngx_http_request_t *r,
142 ngx_http_fastcgi_ctx_t *f); 144 ngx_http_fastcgi_ctx_t *f);
143 static void ngx_http_fastcgi_abort_request(ngx_http_request_t *r); 145 static void ngx_http_fastcgi_abort_request(ngx_http_request_t *r);
144 static void ngx_http_fastcgi_finalize_request(ngx_http_request_t *r, 146 static void ngx_http_fastcgi_finalize_request(ngx_http_request_t *r,
145 ngx_int_t rc); 147 ngx_int_t rc);
229 { ngx_string("fastcgi_store_access"), 231 { ngx_string("fastcgi_store_access"),
230 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE123, 232 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE123,
231 ngx_conf_set_access_slot, 233 ngx_conf_set_access_slot,
232 NGX_HTTP_LOC_CONF_OFFSET, 234 NGX_HTTP_LOC_CONF_OFFSET,
233 offsetof(ngx_http_fastcgi_loc_conf_t, upstream.store_access), 235 offsetof(ngx_http_fastcgi_loc_conf_t, upstream.store_access),
236 NULL },
237
238 { ngx_string("fastcgi_buffering"),
239 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
240 ngx_conf_set_flag_slot,
241 NGX_HTTP_LOC_CONF_OFFSET,
242 offsetof(ngx_http_fastcgi_loc_conf_t, upstream.buffering),
234 NULL }, 243 NULL },
235 244
236 { ngx_string("fastcgi_ignore_client_abort"), 245 { ngx_string("fastcgi_ignore_client_abort"),
237 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, 246 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
238 ngx_conf_set_flag_slot, 247 ngx_conf_set_flag_slot,
577 ngx_int_t rc; 586 ngx_int_t rc;
578 ngx_http_upstream_t *u; 587 ngx_http_upstream_t *u;
579 ngx_http_fastcgi_ctx_t *f; 588 ngx_http_fastcgi_ctx_t *f;
580 ngx_http_fastcgi_loc_conf_t *flcf; 589 ngx_http_fastcgi_loc_conf_t *flcf;
581 590
582 if (r->subrequest_in_memory) {
583 ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
584 "ngx_http_fastcgi_module does not support "
585 "subrequest in memory");
586 return NGX_HTTP_INTERNAL_SERVER_ERROR;
587 }
588
589 if (ngx_http_upstream_create(r) != NGX_OK) { 591 if (ngx_http_upstream_create(r) != NGX_OK) {
590 return NGX_HTTP_INTERNAL_SERVER_ERROR; 592 return NGX_HTTP_INTERNAL_SERVER_ERROR;
591 } 593 }
592 594
593 f = ngx_pcalloc(r->pool, sizeof(ngx_http_fastcgi_ctx_t)); 595 f = ngx_pcalloc(r->pool, sizeof(ngx_http_fastcgi_ctx_t));
620 u->process_header = ngx_http_fastcgi_process_header; 622 u->process_header = ngx_http_fastcgi_process_header;
621 u->abort_request = ngx_http_fastcgi_abort_request; 623 u->abort_request = ngx_http_fastcgi_abort_request;
622 u->finalize_request = ngx_http_fastcgi_finalize_request; 624 u->finalize_request = ngx_http_fastcgi_finalize_request;
623 r->state = 0; 625 r->state = 0;
624 626
625 u->buffering = 1; 627 u->buffering = flcf->upstream.buffering;
626 628
627 u->pipe = ngx_pcalloc(r->pool, sizeof(ngx_event_pipe_t)); 629 u->pipe = ngx_pcalloc(r->pool, sizeof(ngx_event_pipe_t));
628 if (u->pipe == NULL) { 630 if (u->pipe == NULL) {
629 return NGX_HTTP_INTERNAL_SERVER_ERROR; 631 return NGX_HTTP_INTERNAL_SERVER_ERROR;
630 } 632 }
631 633
632 u->pipe->input_filter = ngx_http_fastcgi_input_filter; 634 u->pipe->input_filter = ngx_http_fastcgi_input_filter;
633 u->pipe->input_ctx = r; 635 u->pipe->input_ctx = r;
634 636
635 u->input_filter_init = ngx_http_fastcgi_input_filter_init; 637 u->input_filter_init = ngx_http_fastcgi_input_filter_init;
638 u->input_filter = ngx_http_fastcgi_non_buffered_filter;
639 u->input_filter_ctx = r;
636 640
637 rc = ngx_http_read_client_request_body(r, ngx_http_upstream_init); 641 rc = ngx_http_read_client_request_body(r, ngx_http_upstream_init);
638 642
639 if (rc >= NGX_HTTP_SPECIAL_RESPONSE) { 643 if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
640 return rc; 644 return rc;
1913 return NGX_OK; 1917 return NGX_OK;
1914 } 1918 }
1915 1919
1916 1920
1917 static ngx_int_t 1921 static ngx_int_t
1922 ngx_http_fastcgi_non_buffered_filter(void *data, ssize_t bytes)
1923 {
1924 u_char *m, *msg;
1925 ngx_int_t rc;
1926 ngx_buf_t *b, *buf;
1927 ngx_chain_t *cl, **ll;
1928 ngx_http_request_t *r;
1929 ngx_http_upstream_t *u;
1930 ngx_http_fastcgi_ctx_t *f;
1931
1932 r = data;
1933 f = ngx_http_get_module_ctx(r, ngx_http_fastcgi_module);
1934
1935 u = r->upstream;
1936 buf = &u->buffer;
1937
1938 buf->pos = buf->last;
1939 buf->last += bytes;
1940
1941 for (cl = u->out_bufs, ll = &u->out_bufs; cl; cl = cl->next) {
1942 ll = &cl->next;
1943 }
1944
1945 f->pos = buf->pos;
1946 f->last = buf->last;
1947
1948 for ( ;; ) {
1949 if (f->state < ngx_http_fastcgi_st_data) {
1950
1951 rc = ngx_http_fastcgi_process_record(r, f);
1952
1953 if (rc == NGX_AGAIN) {
1954 break;
1955 }
1956
1957 if (rc == NGX_ERROR) {
1958 return NGX_ERROR;
1959 }
1960
1961 if (f->type == NGX_HTTP_FASTCGI_STDOUT && f->length == 0) {
1962 f->state = ngx_http_fastcgi_st_padding;
1963
1964 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1965 "http fastcgi closed stdout");
1966
1967 continue;
1968 }
1969 }
1970
1971 if (f->state == ngx_http_fastcgi_st_padding) {
1972
1973 if (f->type == NGX_HTTP_FASTCGI_END_REQUEST) {
1974
1975 if (f->pos + f->padding < f->last) {
1976 u->length = 0;
1977 break;
1978 }
1979
1980 if (f->pos + f->padding == f->last) {
1981 u->length = 0;
1982 u->keepalive = 1;
1983 break;
1984 }
1985
1986 f->padding -= f->last - f->pos;
1987
1988 break;
1989 }
1990
1991 if (f->pos + f->padding < f->last) {
1992 f->state = ngx_http_fastcgi_st_version;
1993 f->pos += f->padding;
1994
1995 continue;
1996 }
1997
1998 if (f->pos + f->padding == f->last) {
1999 f->state = ngx_http_fastcgi_st_version;
2000
2001 break;
2002 }
2003
2004 f->padding -= f->last - f->pos;
2005
2006 break;
2007 }
2008
2009
2010 /* f->state == ngx_http_fastcgi_st_data */
2011
2012 if (f->type == NGX_HTTP_FASTCGI_STDERR) {
2013
2014 if (f->length) {
2015
2016 if (f->pos == f->last) {
2017 break;
2018 }
2019
2020 msg = f->pos;
2021
2022 if (f->pos + f->length <= f->last) {
2023 f->pos += f->length;
2024 f->length = 0;
2025 f->state = ngx_http_fastcgi_st_padding;
2026
2027 } else {
2028 f->length -= f->last - f->pos;
2029 f->pos = f->last;
2030 }
2031
2032 for (m = f->pos - 1; msg < m; m--) {
2033 if (*m != LF && *m != CR && *m != '.' && *m != ' ') {
2034 break;
2035 }
2036 }
2037
2038 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
2039 "FastCGI sent in stderr: \"%*s\"",
2040 m + 1 - msg, msg);
2041
2042 } else {
2043 f->state = ngx_http_fastcgi_st_padding;
2044 }
2045
2046 continue;
2047 }
2048
2049 if (f->type == NGX_HTTP_FASTCGI_END_REQUEST) {
2050
2051 if (f->pos + f->length <= f->last) {
2052 f->state = ngx_http_fastcgi_st_padding;
2053 f->pos += f->length;
2054
2055 continue;
2056 }
2057
2058 f->length -= f->last - f->pos;
2059
2060 break;
2061 }
2062
2063
2064 /* f->type == NGX_HTTP_FASTCGI_STDOUT */
2065
2066 if (f->pos == f->last) {
2067 break;
2068 }
2069
2070 cl = ngx_chain_get_free_buf(r->pool, &u->free_bufs);
2071 if (cl == NULL) {
2072 return NGX_ERROR;
2073 }
2074
2075 *ll = cl;
2076 ll = &cl->next;
2077
2078 b = cl->buf;
2079
2080 b->flush = 1;
2081 b->memory = 1;
2082
2083 b->pos = f->pos;
2084 b->tag = u->output.tag;
2085
2086 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2087 "http fastcgi output buf %p", b->pos);
2088
2089 if (f->pos + f->length <= f->last) {
2090 f->state = ngx_http_fastcgi_st_padding;
2091 f->pos += f->length;
2092 b->last = f->pos;
2093
2094 continue;
2095 }
2096
2097 f->length -= f->last - f->pos;
2098 b->last = f->last;
2099
2100 break;
2101 }
2102
2103 /* provide continuous buffer for subrequests in memory */
2104
2105 if (r->subrequest_in_memory) {
2106
2107 cl = u->out_bufs;
2108
2109 if (cl) {
2110 buf->pos = cl->buf->pos;
2111 }
2112
2113 buf->last = buf->pos;
2114
2115 for (cl = u->out_bufs; cl; cl = cl->next) {
2116 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2117 "http fastcgi in memory %p-%p %uz",
2118 cl->buf->pos, cl->buf->last, ngx_buf_size(cl->buf));
2119
2120 if (buf->last == cl->buf->pos) {
2121 buf->last = cl->buf->last;
2122 continue;
2123 }
2124
2125 buf->last = ngx_movemem(buf->last, cl->buf->pos,
2126 cl->buf->last - cl->buf->pos);
2127
2128 cl->buf->pos = buf->last - (cl->buf->last - cl->buf->pos);
2129 cl->buf->last = buf->last;
2130 }
2131 }
2132
2133 return NGX_OK;
2134 }
2135
2136
2137 static ngx_int_t
1918 ngx_http_fastcgi_process_record(ngx_http_request_t *r, 2138 ngx_http_fastcgi_process_record(ngx_http_request_t *r,
1919 ngx_http_fastcgi_ctx_t *f) 2139 ngx_http_fastcgi_ctx_t *f)
1920 { 2140 {
1921 u_char ch, *p; 2141 u_char ch, *p;
1922 ngx_http_fastcgi_state_e state; 2142 ngx_http_fastcgi_state_e state;
2124 conf->upstream.intercept_errors = NGX_CONF_UNSET; 2344 conf->upstream.intercept_errors = NGX_CONF_UNSET;
2125 2345
2126 /* "fastcgi_cyclic_temp_file" is disabled */ 2346 /* "fastcgi_cyclic_temp_file" is disabled */
2127 conf->upstream.cyclic_temp_file = 0; 2347 conf->upstream.cyclic_temp_file = 0;
2128 2348
2349 conf->upstream.change_buffering = 1;
2350
2129 conf->catch_stderr = NGX_CONF_UNSET_PTR; 2351 conf->catch_stderr = NGX_CONF_UNSET_PTR;
2130 2352
2131 conf->keep_conn = NGX_CONF_UNSET; 2353 conf->keep_conn = NGX_CONF_UNSET;
2132 2354
2133 ngx_str_set(&conf->upstream.module, "fastcgi"); 2355 ngx_str_set(&conf->upstream.module, "fastcgi");