Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nginx/nginx.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIgor Sysoev <igor@sysoev.ru>2005-11-26 13:11:11 +0300
committerIgor Sysoev <igor@sysoev.ru>2005-11-26 13:11:11 +0300
commitc31a9bb5e336b15f48c875e1f448f71d68f3feb9 (patch)
tree31ae2b332d1b263c858bab6ee4c21778403f181d /src/http/ngx_http_upstream.c
parent99d9a4b4c547800d582a96871416797fb446b02b (diff)
nginx-0.3.12-RELEASE importrelease-0.3.12
*) Security: if nginx was built with the ngx_http_realip_module and the "satisfy_any on" directive was used, then access and authorization directives did not work. The ngx_http_realip_module was not built and is not built by default. *) Change: the "$time_gmt" variable name was changed to "$time_local". *) Change: the "proxy_header_buffer_size" and "fastcgi_header_buffer_size" directives was renamed to the "proxy_buffer_size" and "fastcgi_buffer_size" directives. *) Feature: the ngx_http_memcached_module. *) Feature: the "proxy_buffering" directive. *) Bugfix: the changes in accept mutex handling when the "rtsig" method was used; the bug had appeared in 0.3.0. *) Bugfix: if the client sent the "Transfer-Encoding: chunked" header line, then nginx returns the 411 error. *) Bugfix: if the "auth_basic" directive was inherited from the http level, then the realm in the "WWW-Authenticate" header line was without the "Basic realm" text. *) Bugfix: if the "combined" format was explicitly specified in the "access_log" directive, then the empty lines was written to the log; the bug had appeared in 0.3.8. *) Bugfix: nginx did not run on the sparc platform under any OS except Solaris. *) Bugfix: now it is not necessary to place space between the quoted string and closing bracket in the "if" directive.
Diffstat (limited to 'src/http/ngx_http_upstream.c')
-rw-r--r--src/http/ngx_http_upstream.c327
1 files changed, 289 insertions, 38 deletions
diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c
index 62f5d9eae..37e979a9d 100644
--- a/src/http/ngx_http_upstream.c
+++ b/src/http/ngx_http_upstream.c
@@ -6,7 +6,6 @@
#include <ngx_config.h>
#include <ngx_core.h>
-#include <ngx_event_connect.h>
#include <ngx_http.h>
@@ -24,6 +23,12 @@ static void ngx_http_upstream_send_request_handler(ngx_event_t *wev);
static void ngx_http_upstream_process_header(ngx_event_t *rev);
static void ngx_http_upstream_send_response(ngx_http_request_t *r,
ngx_http_upstream_t *u);
+static void
+ ngx_http_upstream_process_non_buffered_downstream(ngx_http_request_t *r);
+static void ngx_http_upstream_process_non_buffered_body(ngx_event_t *ev);
+static ngx_int_t ngx_http_upstream_non_buffered_filter_init(void *data);
+static ngx_int_t ngx_http_upstream_non_buffered_filter(void *data,
+ ssize_t bytes);
static void ngx_http_upstream_process_downstream(ngx_http_request_t *r);
static void ngx_http_upstream_process_body(ngx_event_t *ev);
static void ngx_http_upstream_dummy_handler(ngx_event_t *wev);
@@ -699,21 +704,21 @@ ngx_http_upstream_reinit(ngx_http_request_t *r, ngx_http_upstream_t *u)
u->output.in = NULL;
u->output.busy = NULL;
- /* reinit u->header_in buffer */
+ /* reinit u->buffer */
#if 0
if (u->cache) {
- u->header_in.pos = u->header_in.start + u->cache->ctx.header_size;
- u->header_in.last = u->header_in.pos;
+ u->buffer.pos = u->buffer.start + u->cache->ctx.header_size;
+ u->buffer.last = u->buffer.pos;
} else {
- u->header_in.pos = u->header_in.start;
- u->header_in.last = u->header_in.start;
+ u->buffer.pos = u->buffer.start;
+ u->buffer.last = u->buffer.start;
}
#else
- u->header_in.pos = u->header_in.start;
- u->header_in.last = u->header_in.start;
+ u->buffer.pos = u->buffer.start;
+ u->buffer.last = u->buffer.start;
#endif
@@ -881,23 +886,24 @@ ngx_http_upstream_process_header(ngx_event_t *rev)
return;
}
- if (u->header_in.start == NULL) {
- u->header_in.start = ngx_palloc(r->pool, u->conf->header_buffer_size);
- if (u->header_in.start == NULL) {
+ if (u->buffer.start == NULL) {
+ u->buffer.start = ngx_palloc(r->pool, u->conf->buffer_size);
+ if (u->buffer.start == NULL) {
ngx_http_upstream_finalize_request(r, u,
NGX_HTTP_INTERNAL_SERVER_ERROR);
return;
}
- u->header_in.pos = u->header_in.start;
- u->header_in.last = u->header_in.start;
- u->header_in.end = u->header_in.start + u->conf->header_buffer_size;
- u->header_in.temporary = 1;
+ u->buffer.pos = u->buffer.start;
+ u->buffer.last = u->buffer.start;
+ u->buffer.end = u->buffer.start + u->conf->buffer_size;
+ u->buffer.temporary = 1;
- u->header_in.tag = u->output.tag;
+ u->buffer.tag = u->output.tag;
if (ngx_list_init(&r->upstream->headers_in.headers, r->pool, 8,
- sizeof(ngx_table_elt_t)) == NGX_ERROR)
+ sizeof(ngx_table_elt_t))
+ != NGX_OK)
{
ngx_http_upstream_finalize_request(r, u,
NGX_HTTP_INTERNAL_SERVER_ERROR);
@@ -906,14 +912,14 @@ ngx_http_upstream_process_header(ngx_event_t *rev)
#if 0
if (u->cache) {
- u->header_in.pos += u->cache->ctx.header_size;
- u->header_in.last = u->header_in.pos;
+ u->buffer.pos += u->cache->ctx.header_size;
+ u->buffer.last = u->buffer.pos;
}
#endif
}
- n = u->peer.connection->recv(u->peer.connection, u->header_in.last,
- u->header_in.end - u->header_in.last);
+ n = u->peer.connection->recv(u->peer.connection, u->buffer.last,
+ u->buffer.end - u->buffer.last);
if (n == NGX_AGAIN) {
#if 0
@@ -939,7 +945,7 @@ ngx_http_upstream_process_header(ngx_event_t *rev)
return;
}
- u->header_in.last += n;
+ u->buffer.last += n;
#if 0
u->valid_header_in = 0;
@@ -954,7 +960,7 @@ ngx_http_upstream_process_header(ngx_event_t *rev)
ngx_add_timer(rev, u->read_timeout);
#endif
- if (u->header_in.pos == u->header_in.end) {
+ if (u->buffer.pos == u->buffer.end) {
ngx_log_error(NGX_LOG_ERR, rev->log, 0,
"upstream sent too big header");
@@ -1020,6 +1026,13 @@ ngx_http_upstream_process_header(ngx_event_t *rev)
&& u->conf->redirect_errors
&& r->err_ctx == NULL)
{
+ if (u->headers_in.status_n == NGX_HTTP_NOT_FOUND
+ && u->conf->redirect_404)
+ {
+ ngx_http_upstream_finalize_request(r, u, 404);
+ return;
+ }
+
clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
if (clcf->error_pages) {
@@ -1112,6 +1125,7 @@ ngx_http_upstream_process_header(ngx_event_t *rev)
static void
ngx_http_upstream_send_response(ngx_http_request_t *r, ngx_http_upstream_t *u)
{
+ ssize_t size;
ngx_int_t rc;
ngx_uint_t i, key;
ngx_list_part_t *part;
@@ -1165,6 +1179,13 @@ ngx_http_upstream_send_response(ngx_http_request_t *r, ngx_http_upstream_t *u)
r->headers_out.status = u->headers_in.status_n;
r->headers_out.status_line = u->headers_in.status_line;
+ if (r->headers_out.content_length_n != -1) {
+ u->length = (size_t) r->headers_out.content_length_n;
+
+ } else {
+ u->length = NGX_MAX_SIZE_T_VALUE;
+ }
+
rc = ngx_http_send_header(r);
if (rc == NGX_ERROR || rc > NGX_OK) {
@@ -1188,6 +1209,53 @@ ngx_http_upstream_send_response(ngx_http_request_t *r, ngx_http_upstream_t *u)
}
}
+ clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
+
+ if (u->pipe == NULL) {
+
+ if (u->input_filter == NULL) {
+ u->input_filter_init = ngx_http_upstream_non_buffered_filter_init;
+ u->input_filter = ngx_http_upstream_non_buffered_filter;
+ u->input_filter_ctx = r;
+ }
+
+ u->peer.connection->read->handler =
+ ngx_http_upstream_process_non_buffered_body;
+ r->write_event_handler =
+ ngx_http_upstream_process_non_buffered_downstream;
+
+ r->limit_rate = 0;
+
+ if (u->input_filter_init(u->input_filter_ctx) == NGX_ERROR) {
+ ngx_http_upstream_finalize_request(r, u, 0);
+ return;
+ }
+
+ size = u->buffer.last - u->buffer.pos;
+
+ if (size) {
+ u->buffer.last = u->buffer.pos;
+
+ if (u->input_filter(u->input_filter_ctx, size) == NGX_ERROR) {
+ ngx_http_upstream_finalize_request(r, u, 0);
+ return;
+ }
+
+ ngx_http_upstream_process_non_buffered_body(r->connection->write);
+
+ } else {
+ u->buffer.pos = u->buffer.start;
+ u->buffer.last = u->buffer.start;
+
+ if (ngx_http_send_special(r, NGX_HTTP_FLUSH) == NGX_ERROR) {
+ ngx_http_upstream_finalize_request(r, u, 0);
+ return;
+ }
+ }
+
+ return;
+ }
+
/* TODO: preallocate event_pipe bufs, look "Content-Length" */
#if 0
@@ -1201,7 +1269,7 @@ ngx_http_upstream_send_response(ngx_http_request_t *r, ngx_http_upstream_t *u)
}
if (u->cachable) {
- header = (ngx_http_cache_header_t *) u->header_in->start;
+ header = (ngx_http_cache_header_t *) u->buffer->start;
header->expires = u->cache->ctx.expires;
header->last_modified = u->cache->ctx.last_modified;
@@ -1216,7 +1284,7 @@ ngx_http_upstream_send_response(ngx_http_request_t *r, ngx_http_upstream_t *u)
#endif
- p = &u->pipe;
+ p = u->pipe;
p->output_filter = (ngx_event_pipe_output_filter_pt) ngx_http_output_filter;
p->output_ctx = r;
@@ -1256,11 +1324,11 @@ ngx_http_upstream_send_response(ngx_http_request_t *r, ngx_http_upstream_t *u)
ngx_http_upstream_finalize_request(r, u, 0);
return;
}
- p->preread_bufs->buf = &u->header_in;
+ p->preread_bufs->buf = &u->buffer;
p->preread_bufs->next = NULL;
- u->header_in.recycled = 1;
+ u->buffer.recycled = 1;
- p->preread_size = u->header_in.last - u->header_in.pos;
+ p->preread_size = u->buffer.last - u->buffer.pos;
if (u->cachable) {
p->buf_to_file = ngx_calloc_buf(r->pool);
@@ -1268,8 +1336,8 @@ ngx_http_upstream_send_response(ngx_http_request_t *r, ngx_http_upstream_t *u)
ngx_http_upstream_finalize_request(r, u, 0);
return;
}
- p->buf_to_file->pos = u->header_in.start;
- p->buf_to_file->last = u->header_in.pos;
+ p->buf_to_file->pos = u->buffer.start;
+ p->buf_to_file->last = u->buffer.pos;
p->buf_to_file->temporary = 1;
}
@@ -1282,10 +1350,10 @@ ngx_http_upstream_send_response(ngx_http_request_t *r, ngx_http_upstream_t *u)
p->free_bufs = 1;
/*
- * event_pipe would do u->header_in.last += p->preread_size
+ * event_pipe would do u->buffer.last += p->preread_size
* as though these bytes were read
*/
- u->header_in.last = u->header_in.pos;
+ u->buffer.last = u->buffer.pos;
if (u->conf->cyclic_temp_file) {
@@ -1302,8 +1370,6 @@ ngx_http_upstream_send_response(ngx_http_request_t *r, ngx_http_upstream_t *u)
p->cyclic_temp_file = 0;
}
- clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
-
p->read_timeout = u->conf->read_timeout;
p->send_timeout = clcf->send_timeout;
p->send_lowat = clcf->send_lowat;
@@ -1316,6 +1382,191 @@ ngx_http_upstream_send_response(ngx_http_request_t *r, ngx_http_upstream_t *u)
static void
+ngx_http_upstream_process_non_buffered_downstream(ngx_http_request_t *r)
+{
+ ngx_http_upstream_process_non_buffered_body(r->connection->write);
+}
+
+
+static void
+ngx_http_upstream_process_non_buffered_body(ngx_event_t *ev)
+{
+ size_t size;
+ ssize_t n;
+ ngx_buf_t *b;
+ ngx_uint_t do_write;
+ ngx_connection_t *c;
+ ngx_http_request_t *r;
+ ngx_http_upstream_t *u;
+ ngx_http_core_loc_conf_t *clcf;
+
+ c = ev->data;
+
+ if (ev->write) {
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
+ "http upstream process non buffered downstream");
+ c->log->action = "sending to client";
+
+ } else {
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
+ "http upstream process non buffered upstream");
+ c->log->action = "reading upstream";
+ }
+
+ if (ev->timedout) {
+ if (ev->write) {
+ c->timedout = 1;
+ ngx_log_error(NGX_LOG_ERR, c->log, NGX_ETIMEDOUT,
+ "client timed out");
+ } else {
+ ngx_log_error(NGX_LOG_ERR, c->log, NGX_ETIMEDOUT,
+ "upstream timed out");
+ }
+ }
+
+ r = c->data;
+ u = r->upstream;
+
+ b = &u->buffer;
+
+ clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
+
+ do_write = ev->write;
+
+ for ( ;; ) {
+
+ if (do_write) {
+
+ if (u->out_bufs || u->busy_bufs) {
+ if (ngx_http_output_filter(r, u->out_bufs) == NGX_ERROR) {
+ ngx_http_upstream_finalize_request(r, u, 0);
+ return;
+ }
+
+ ngx_chain_update_chains(&u->free_bufs, &u->busy_bufs,
+ &u->out_bufs, u->output.tag);
+ }
+
+ if (u->busy_bufs == NULL) {
+
+ if (u->length == 0
+ || u->peer.connection->read->eof
+ || u->peer.connection->read->error)
+ {
+ ngx_http_upstream_finalize_request(r, u, 0);
+ return;
+ }
+
+ b->pos = b->start;
+ b->last = b->start;
+ }
+ }
+
+ size = b->end - b->last;
+
+ if (size > u->length) {
+ size = u->length;
+ }
+
+ if (size && u->peer.connection->read->ready) {
+ n = u->peer.connection->recv(u->peer.connection, b->last, size);
+
+ if (n == NGX_AGAIN) {
+ break;
+ }
+
+ if (n > 0) {
+ if (u->input_filter(u->input_filter_ctx, n) == NGX_ERROR) {
+ ngx_http_upstream_finalize_request(r, u, 0);
+ return;
+ }
+ }
+
+ do_write = 1;
+
+ continue;
+ }
+
+ break;
+ }
+
+ if (ngx_handle_write_event(r->connection->write, clcf->send_lowat)
+ == NGX_ERROR)
+ {
+ ngx_http_upstream_finalize_request(r, u, 0);
+ return;
+ }
+
+ if (r->connection->write->active) {
+ ngx_add_timer(r->connection->write, clcf->send_timeout);
+
+ } else if (r->connection->write->timer_set) {
+ ngx_del_timer(r->connection->write);
+ }
+
+ if (ngx_handle_read_event(u->peer.connection->read, 0) == NGX_ERROR) {
+ ngx_http_upstream_finalize_request(r, u, 0);
+ return;
+ }
+
+ if (u->peer.connection->read->active) {
+ ngx_add_timer(u->peer.connection->read, u->conf->read_timeout);
+
+ } else if (r->connection->read->timer_set) {
+ ngx_del_timer(r->connection->read);
+ }
+}
+
+
+static ngx_int_t
+ngx_http_upstream_non_buffered_filter_init(void *data)
+{
+ return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_http_upstream_non_buffered_filter(void *data, ssize_t bytes)
+{
+ ngx_http_request_t *r = data;
+
+ ngx_buf_t *b;
+ ngx_chain_t *cl, **ll;
+ ngx_http_upstream_t *u;
+
+ u = r->upstream;
+
+ for (cl = u->out_bufs, ll = &u->out_bufs; cl; cl = cl->next) {
+ ll = &cl->next;
+ }
+
+ cl = ngx_chain_get_free_buf(r->pool, &u->free_bufs);
+ if (cl == NULL) {
+ return NGX_ERROR;
+ }
+
+ *ll = cl;
+
+ cl->buf->flush = 1;
+ cl->buf->memory = 1;
+
+ b = &u->buffer;
+
+ cl->buf->pos = b->last;
+ b->last += bytes;
+ cl->buf->last = b->last;
+
+ if (u->length == NGX_MAX_SIZE_T_VALUE) {
+ return NGX_OK;
+ }
+
+ u->length -= bytes;
+
+ return NGX_OK;
+}
+
+
+static void
ngx_http_upstream_process_downstream(ngx_http_request_t *r)
{
ngx_http_upstream_process_body(r->connection->write);
@@ -1345,7 +1596,7 @@ ngx_http_upstream_process_body(ngx_event_t *ev)
c->log->action = "reading upstream";
}
- p = &u->pipe;
+ p = u->pipe;
if (ev->timedout) {
if (ev->write) {
@@ -1614,10 +1865,10 @@ ngx_http_upstream_finalize_request(ngx_http_request_t *r,
rc = 0;
}
- if (u->pipe.temp_file) {
+ if (u->pipe && u->pipe->temp_file) {
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"http upstream temp fd: %d",
- u->pipe.temp_file->file.fd);
+ u->pipe->temp_file->file.fd);
}
#if 0
@@ -1637,7 +1888,7 @@ ngx_http_upstream_finalize_request(ngx_http_request_t *r,
r->connection->log->action = "sending to client";
if (rc == 0 && r->main == r) {
- rc = ngx_http_send_last(r);
+ rc = ngx_http_send_special(r, NGX_HTTP_LAST);
}
ngx_http_finalize_request(r, rc);