aboutsummaryrefslogtreecommitdiff
path: root/src/http/modules
diff options
context:
space:
mode:
Diffstat (limited to 'src/http/modules')
-rw-r--r--src/http/modules/ngx_http_gzip_filter.c1
-rw-r--r--src/http/modules/ngx_http_range_filter.c94
-rw-r--r--src/http/modules/ngx_http_static_handler.c35
-rw-r--r--src/http/modules/proxy/ngx_http_proxy_handler.c240
-rw-r--r--src/http/modules/proxy/ngx_http_proxy_handler.h12
5 files changed, 280 insertions, 102 deletions
diff --git a/src/http/modules/ngx_http_gzip_filter.c b/src/http/modules/ngx_http_gzip_filter.c
index 7e5e67d53..a32714da4 100644
--- a/src/http/modules/ngx_http_gzip_filter.c
+++ b/src/http/modules/ngx_http_gzip_filter.c
@@ -168,7 +168,6 @@ static int ngx_http_gzip_header_filter(ngx_http_request_t *r)
if (!conf->enable
|| r->headers_out.status != NGX_HTTP_OK
|| r->header_only
- || r->main
/* TODO: conf->http_version */
|| (r->headers_out.content_encoding
&& r->headers_out.content_encoding->value.len)
diff --git a/src/http/modules/ngx_http_range_filter.c b/src/http/modules/ngx_http_range_filter.c
index 61669ca29..9233605a1 100644
--- a/src/http/modules/ngx_http_range_filter.c
+++ b/src/http/modules/ngx_http_range_filter.c
@@ -4,6 +4,41 @@
#include <ngx_http.h>
+/*
+ * the single part format:
+ *
+ * "HTTP/1.0 206 Partial Content" CRLF
+ * ... header ...
+ * "Content-Type: image/jpeg" CRLF
+ * "Content-Length: SIZE" CRLF
+ * "Content-Range: bytes START-END/SIZE" CRLF
+ * CRLF
+ * ... data ...
+ *
+ *
+ * the mutlipart format:
+ *
+ * "HTTP/1.0 206 Partial Content" CRLF
+ * ... header ...
+ * "Content-Type: multipart/byteranges; boundary=0123456789" CRLF
+ * CRLF
+ * CRLF
+ * "--0123456789" CRLF
+ * "Content-Type: image/jpeg" CRLF
+ * "Content-Range: bytes START0-END0/SIZE" CRLF
+ * CRLF
+ * ... data ...
+ * CRLF
+ * "--0123456789" CRLF
+ * "Content-Type: image/jpeg" CRLF
+ * "Content-Range: bytes START1-END1/SIZE" CRLF
+ * CRLF
+ * ... data ...
+ * CRLF
+ * "--0123456789--" CRLF
+ */
+
+
typedef struct {
ngx_str_t boundary_header;
} ngx_http_range_filter_ctx_t;
@@ -46,11 +81,12 @@ static int ngx_http_range_header_filter(ngx_http_request_t *r)
ngx_http_range_t *range;
ngx_http_range_filter_ctx_t *ctx;
- if (r->main
- || r->http_version < NGX_HTTP_VERSION_10
+ if (r->http_version < NGX_HTTP_VERSION_10
|| r->headers_out.status != NGX_HTTP_OK
|| r->headers_out.content_length_n == -1
+
/* STUB: we currently support ranges for file hunks only */
+ || !r->sendfile
|| r->filter & NGX_HTTP_FILTER_NEED_IN_MEMORY)
{
return ngx_http_next_header_filter(r);
@@ -75,11 +111,8 @@ static int ngx_http_range_header_filter(ngx_http_request_t *r)
ngx_init_array(r->headers_out.ranges, r->pool, 5, sizeof(ngx_http_range_t),
NGX_ERROR);
-#if (NGX_SUPPRESS_WARN)
- range = NULL;
-#endif
-
rc = 0;
+ range = NULL;
p = r->headers_in.range->value.data + 6;
for ( ;; ) {
@@ -156,6 +189,9 @@ static int ngx_http_range_header_filter(ngx_http_request_t *r)
}
if (rc) {
+
+ /* rc == NGX_HTTP_RANGE_NOT_SATISFIABLE */
+
r->headers_out.status = rc;
r->headers_out.ranges.nelts = 0;
@@ -189,6 +225,8 @@ static int ngx_http_range_header_filter(ngx_http_request_t *r)
ngx_palloc(r->pool, 6 + 20 + 1 + 20 + 1 + 20 + 1),
NGX_ERROR);
+ /* "Content-Range: bytes SSSS-EEEE/TTTT" header */
+
r->headers_out.content_range->value.len =
ngx_snprintf(r->headers_out.content_range->value.data,
6 + 20 + 1 + 20 + 1 + 20 + 1,
@@ -222,6 +260,14 @@ static int ngx_http_range_header_filter(ngx_http_request_t *r)
boundary = ngx_next_temp_number(0);
+ /*
+ * The boundary header of the range:
+ * CRLF
+ * "--0123456789" CRLF
+ * "Content-Type: image/jpeg" CRLF
+ * "Content-Range: bytes "
+ */
+
if (r->headers_out.charset.len) {
ctx->boundary_header.len =
ngx_snprintf(ctx->boundary_header.data, len,
@@ -248,30 +294,34 @@ static int ngx_http_range_header_filter(ngx_http_request_t *r)
ngx_palloc(r->pool, 31 + 10 + 1),
NGX_ERROR);
+ /* "Content-Type: multipart/byteranges; boundary=0123456789" */
+
r->headers_out.content_type->value.len =
ngx_snprintf(r->headers_out.content_type->value.data,
31 + 10 + 1,
"multipart/byteranges; boundary=%010u",
boundary);
- /* the last "CRLF--BOUNDARY--CRLF" */
+ /* the size of the last boundary CRLF "--0123456789--" CRLF */
len = 4 + 10 + 4;
range = r->headers_out.ranges.elts;
for (i = 0; i < r->headers_out.ranges.nelts; i++) {
- ngx_test_null(range[i].content_range.data,
- ngx_palloc(r->pool, 20 + 1 + 20 + 1 + 20 + 5),
- NGX_ERROR);
+ ngx_test_null(range[i].content_range.data,
+ ngx_palloc(r->pool, 20 + 1 + 20 + 1 + 20 + 5),
+ NGX_ERROR);
+
+ /* the size of the range: "SSSS-EEEE/TTTT" CRLF CRLF */
- range[i].content_range.len =
+ range[i].content_range.len =
ngx_snprintf(range[i].content_range.data,
20 + 1 + 20 + 1 + 20 + 5,
OFF_FMT "-" OFF_FMT "/" OFF_FMT CRLF CRLF,
range[i].start, range[i].end - 1,
r->headers_out.content_length_n);
- len += ctx->boundary_header.len + range[i].content_range.len
- + (size_t) (range[i].end - range[i].start);
+ len += ctx->boundary_header.len + range[i].content_range.len
+ + (size_t) (range[i].end - range[i].start);
}
r->headers_out.content_length_n = len;
@@ -304,8 +354,9 @@ static int ngx_http_range_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
&& in->hunk->type & NGX_HUNK_FILE
&& in->hunk->type & NGX_HUNK_LAST)
{
+ range = r->headers_out.ranges.elts;
+
if (r->headers_out.ranges.nelts == 1) {
- range = r->headers_out.ranges.elts;
in->hunk->file_pos = range->start;
in->hunk->file_last = range->end;
@@ -315,9 +366,16 @@ static int ngx_http_range_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
ctx = ngx_http_get_module_ctx(r, ngx_http_range_filter_module);
ll = &out;
- range = r->headers_out.ranges.elts;
for (i = 0; i < r->headers_out.ranges.nelts; i++) {
+ /*
+ * The boundary header of the range:
+ * CRLF
+ * "--0123456789" CRLF
+ * "Content-Type: image/jpeg" CRLF
+ * "Content-Range: bytes "
+ */
+
ngx_test_null(h, ngx_calloc_hunk(r->pool), NGX_ERROR);
h->type = NGX_HUNK_IN_MEMORY|NGX_HUNK_MEMORY;
h->pos = ctx->boundary_header.data;
@@ -326,6 +384,8 @@ static int ngx_http_range_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
ngx_test_null(hcl, ngx_alloc_chain_link(r->pool), NGX_ERROR);
hcl->hunk = h;
+ /* "SSSS-EEEE/TTTT" CRLF CRLF */
+
ngx_test_null(h, ngx_calloc_hunk(r->pool), NGX_ERROR);
h->type = NGX_HUNK_IN_MEMORY|NGX_HUNK_TEMP;
h->pos = range[i].content_range.data;
@@ -334,6 +394,8 @@ static int ngx_http_range_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
ngx_test_null(rcl, ngx_alloc_chain_link(r->pool), NGX_ERROR);
rcl->hunk = h;
+ /* the range data */
+
ngx_test_null(h, ngx_calloc_hunk(r->pool), NGX_ERROR);
h->type = NGX_HUNK_FILE;
h->file_pos = range[i].start;
@@ -348,6 +410,8 @@ static int ngx_http_range_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
ll = &dcl->next;
}
+ /* the last boundary CRLF "--0123456789--" CRLF */
+
ngx_test_null(h, ngx_calloc_hunk(r->pool), NGX_ERROR);
h->type = NGX_HUNK_IN_MEMORY|NGX_HUNK_TEMP|NGX_HUNK_LAST;
ngx_test_null(h->pos, ngx_palloc(r->pool, 4 + 10 + 4), NGX_ERROR);
diff --git a/src/http/modules/ngx_http_static_handler.c b/src/http/modules/ngx_http_static_handler.c
index f4955ef3d..0eb789cbe 100644
--- a/src/http/modules/ngx_http_static_handler.c
+++ b/src/http/modules/ngx_http_static_handler.c
@@ -88,7 +88,7 @@ ngx_log_debug(r->connection->log, "HTTP filename: '%s'" _ r->file.name.data);
/*
* There is no way to open a file or a directory in Win9X with
* one syscall: Win9X has no FILE_FLAG_BACKUP_SEMANTICS flag.
- * so we need to check its type before the opening
+ * So we need to check its type before the opening
*/
r->file.info.dwFileAttributes = GetFileAttributes(r->file.name.data);
@@ -151,6 +151,21 @@ ngx_log_debug(r->connection->log, "FILE: %d" _ r->file.fd);
r->file.info_valid = 1;
}
+
+#if !(WIN32) /* the not regular files are probably Unix specific */
+
+ if (!ngx_is_file(r->file.info)) {
+ ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno,
+ "%s is not a regular file", r->file.name.data);
+
+ if (ngx_close_file(r->file.fd) == NGX_FILE_ERROR)
+ ngx_log_error(NGX_LOG_ALERT, r->connection->log, ngx_errno,
+ ngx_close_file_n " %s failed", r->file.name.data);
+
+ return NGX_HTTP_NOT_FOUND;
+ }
+
+#endif
#endif
if (ngx_is_dir(r->file.info)) {
@@ -163,6 +178,7 @@ ngx_log_debug(r->connection->log, "HTTP DIR: '%s'" _ r->file.name.data);
}
r->file.fd = NGX_INVALID_FILE;
+ r->file.info_valid = 0;
#endif
ngx_test_null(h, ngx_push_table(r->headers_out.headers),
@@ -203,7 +219,7 @@ static int ngx_http_static_handler(ngx_http_request_t *r)
}
ctx = r->connection->log->data;
- ctx->action = "sending response";
+ ctx->action = "sending response to client";
if (r->file.fd == NGX_INVALID_FILE) {
r->file.fd = ngx_open_file(r->file.name.data,
@@ -242,21 +258,6 @@ static int ngx_http_static_handler(ngx_http_request_t *r)
r->file.info_valid = 1;
}
-#if !(WIN32) /* the not regular files are probably Unix specific */
-
- if (!ngx_is_file(r->file.info)) {
- ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno,
- "%s is not regular file", r->file.name.data);
-
- if (ngx_close_file(r->file.fd) == NGX_FILE_ERROR)
- ngx_log_error(NGX_LOG_ALERT, r->connection->log, ngx_errno,
- ngx_close_file_n " %s failed", r->file.name.data);
-
- return NGX_HTTP_NOT_FOUND;
- }
-
-#endif
-
r->headers_out.status = NGX_HTTP_OK;
r->headers_out.content_length_n = ngx_file_size(r->file.info);
r->headers_out.last_modified_time = ngx_file_mtime(r->file.info);
diff --git a/src/http/modules/proxy/ngx_http_proxy_handler.c b/src/http/modules/proxy/ngx_http_proxy_handler.c
index be0307487..ae6d5d148 100644
--- a/src/http/modules/proxy/ngx_http_proxy_handler.c
+++ b/src/http/modules/proxy/ngx_http_proxy_handler.c
@@ -10,6 +10,7 @@
static int ngx_http_proxy_handler(ngx_http_request_t *r);
+static void ngx_http_proxy_init_request(void *data);
static ngx_chain_t *ngx_http_proxy_create_request(ngx_http_proxy_ctx_t *p);
static void ngx_http_proxy_send_request_handler(ngx_event_t *wev);
static void ngx_http_proxy_send_request(ngx_http_proxy_ctx_t *p);
@@ -20,7 +21,7 @@ static void ngx_http_proxy_send_response(ngx_http_proxy_ctx_t *p);
static void ngx_http_proxy_process_body(ngx_event_t *ev);
static int ngx_http_proxy_parse_status_line(ngx_http_proxy_ctx_t *p);
-static void ngx_http_proxy_next_upstream(ngx_http_proxy_ctx_t *p);
+static void ngx_http_proxy_next_upstream(ngx_http_proxy_ctx_t *p, int ft_type);
static void ngx_http_proxy_finalize_request(ngx_http_proxy_ctx_t *p, int rc);
static void ngx_http_proxy_close_connection(ngx_connection_t *c);
@@ -46,6 +47,13 @@ static ngx_command_t ngx_http_proxy_commands[] = {
0,
NULL},
+ {ngx_string("proxy_request_buffer_size"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+ ngx_conf_set_size_slot,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ offsetof(ngx_http_proxy_loc_conf_t, request_buffer_size),
+ NULL},
+
{ngx_string("proxy_connect_timeout"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
ngx_conf_set_msec_slot,
@@ -135,13 +143,10 @@ static ngx_str_t http_methods[] = {
};
-#if 0
-static char *header_errors[] = {
- "upstream sent too long status line",
+static char *upstream_header_errors[] = {
"upstream sent invalid header",
"upstream sent too long header line"
};
-#endif
static ngx_http_header_t headers_in[] = {
@@ -170,6 +175,7 @@ static char connection_close_header[] = "Connection: close" CRLF;
static int ngx_http_proxy_handler(ngx_http_request_t *r)
{
+ int rc;
ngx_http_proxy_ctx_t *p;
ngx_http_create_ctx(r, p, ngx_http_proxy_module,
@@ -186,20 +192,89 @@ static int ngx_http_proxy_handler(ngx_http_request_t *r)
/* TODO: we currently support reverse proxy only */
p->accel = 1;
- ngx_test_null(p->request_hunks, ngx_http_proxy_create_request(p),
- NGX_HTTP_INTERNAL_SERVER_ERROR);
+ if (r->headers_in.content_length_n > 0) {
+ ngx_test_null(r->temp_file,
+ ngx_pcalloc(r->pool, sizeof(ngx_temp_file_t)),
+ NGX_HTTP_INTERNAL_SERVER_ERROR);
+
+ r->temp_file->file.fd = NGX_INVALID_FILE;
+ r->temp_file->file.log = r->connection->log;
+ r->temp_file->path = *p->lcf->temp_path;
+ r->temp_file->pool = r->pool;
+ r->temp_file->warn = "a client request body is buffered "
+ "to a temporary file";
+ /* STUB */ r->temp_file->persistent = 1;
+
+ r->request_body_handler = ngx_http_proxy_init_request;
+ r->data = p;
+
+ rc = ngx_http_read_client_request_body(r, p->lcf->request_buffer_size);
+
+ if (rc != NGX_OK) {
+ return rc;
+ }
+ }
+
+ ngx_http_proxy_init_request(p);
+
+ return NGX_DONE;
+}
+
+
+static void ngx_http_proxy_init_request(void *data)
+{
+ ngx_http_proxy_ctx_t *p = data;
- /* TODO: read request body */
+ ngx_chain_t *cl;
+ ngx_http_request_t *r;
+ ngx_output_chain_ctx_t *ctx;
+
+
+ r = p->request;
+
+ cl = ngx_http_proxy_create_request(p);
+ if (cl == NULL) {
+ ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
+ return;
+ }
+
+ if (r->request_hunks) {
+ cl->next = r->request_hunks;
+ }
+
+ r->request_hunks = cl;
p->upstream.log = r->connection->log;
p->saved_ctx = r->connection->log->data;
- r->connection->log->data = p;;
+ p->saved_handler = r->connection->log->handler;
+ r->connection->log->data = p;
r->connection->log->handler = ngx_http_proxy_log_error;
p->action = "connecting to upstream";
- ngx_http_proxy_send_request(p);
+ ctx = ngx_pcalloc(r->pool, sizeof(ngx_output_chain_ctx_t));
+ if (ctx == NULL) {
+ ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR);
+ }
- return NGX_DONE;
+ p->output_chain_ctx = ctx;
+
+ if (r->request_body_hunk) {
+ ctx->free = ngx_alloc_chain_link(r->pool);
+ if (ctx->free == NULL) {
+ ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR);
+ }
+ ctx->free->hunk = r->request_body_hunk;
+ ctx->free->next = NULL;
+ }
+
+ ctx->sendfile = r->sendfile;
+ ctx->copy_chain = 1;
+ ctx->pool = r->pool;
+ ctx->bufs.num = 1;
+ ctx->tag = (ngx_hunk_tag_t) &ngx_http_proxy_module;
+ ctx->output_filter = (ngx_output_chain_filter_pt) ngx_write_chain;
+
+ ngx_http_proxy_send_request(p);
}
@@ -324,9 +399,11 @@ static void ngx_http_proxy_send_request_handler(ngx_event_t *wev)
c = wev->data;
p = c->data;
+ p->action = "sending request to upstream";
+
if (wev->timedout) {
p->timedout = 1;
- ngx_http_proxy_next_upstream(p);
+ ngx_http_proxy_next_upstream(p, NGX_HTTP_PROXY_FT_TIMEOUT);
return;
}
@@ -338,30 +415,43 @@ static void ngx_http_proxy_send_request_handler(ngx_event_t *wev)
static void ngx_http_proxy_send_request(ngx_http_proxy_ctx_t *p)
{
- int rc;
- ngx_chain_t *chain, *cl, *tl, **ll;
- ngx_connection_t *c;
+ int rc;
+ ngx_chain_t *cl;
+ ngx_connection_t *c;
c = p->upstream.connection;
for ( ;; ) {
if (c) {
- chain = ngx_write_chain(c, p->work_request_hunks);
+ p->output_chain_ctx->output_ctx = c;
+ rc = ngx_output_chain(p->output_chain_ctx,
+ p->request->request_hunks);
- if (chain != NGX_CHAIN_ERROR) {
- p->work_request_hunks = chain;
+ if (rc != NGX_ERROR) {
p->request_sent = 1;
if (c->write->timer_set) {
ngx_del_timer(c->write);
}
- if (chain) {
+ if (rc == NGX_AGAIN) {
ngx_add_timer(c->write, p->lcf->send_timeout);
} else {
/* TODO: del event */
+
+ if (c->tcp_nopush) {
+ if (ngx_tcp_push(c->fd) == NGX_ERROR) {
+ ngx_log_error(NGX_LOG_CRIT, c->log,
+ ngx_socket_errno,
+ ngx_tcp_push_n " failed");
+ ngx_http_proxy_finalize_request(p,
+ NGX_HTTP_INTERNAL_SERVER_ERROR);
+ return;
+ }
+ c->tcp_nopush = 0;
+ }
}
return;
@@ -404,34 +494,9 @@ static void ngx_http_proxy_send_request(ngx_http_proxy_ctx_t *p)
/* reinit the request chain */
- p->work_request_hunks = ngx_alloc_chain_link(p->request->pool);
- if (p->work_request_hunks == NULL) {
- ngx_http_proxy_finalize_request(p,
- NGX_HTTP_INTERNAL_SERVER_ERROR);
- return;
- }
-
- tl = p->work_request_hunks;
- ll = &p->work_request_hunks;
-
- for (cl = p->request_hunks; cl; cl = cl->next) {
- tl->hunk = cl->hunk;
- *ll = tl;
- ll = &tl->next;
+ for (cl = p->request->request_hunks; cl; cl = cl->next) {
cl->hunk->pos = cl->hunk->start;
-
- tl = ngx_alloc_chain_link(p->request->pool);
- if (tl == NULL) {
- ngx_http_proxy_finalize_request(p,
- NGX_HTTP_INTERNAL_SERVER_ERROR);
- return;
- }
}
-
- *ll = NULL;
-
- } else {
- p->work_request_hunks = p->request_hunks;
}
p->request_sent = 0;
@@ -461,11 +526,13 @@ static void ngx_http_proxy_process_upstream_status_line(ngx_event_t *rev)
c = rev->data;
p = c->data;
+ p->action = "reading upstream status line";
+
ngx_log_debug(rev->log, "http proxy process status line");
if (rev->timedout) {
p->timedout = 1;
- ngx_http_proxy_next_upstream(p);
+ ngx_http_proxy_next_upstream(p, NGX_HTTP_PROXY_FT_TIMEOUT);
return;
}
@@ -483,7 +550,7 @@ static void ngx_http_proxy_process_upstream_status_line(ngx_event_t *rev)
n = ngx_http_proxy_read_upstream_header(p);
if (n == NGX_ERROR) {
- ngx_http_proxy_next_upstream(p);
+ ngx_http_proxy_next_upstream(p, NGX_HTTP_PROXY_FT_ERROR);
return;
}
@@ -496,21 +563,39 @@ static void ngx_http_proxy_process_upstream_status_line(ngx_event_t *rev)
if (rc == NGX_AGAIN) {
if (p->header_in->pos == p->header_in->last) {
ngx_log_error(NGX_LOG_ERR, rev->log, 0,
- "upstream sent too big header");
- ngx_http_proxy_finalize_request(p, NGX_HTTP_BAD_GATEWAY);
- return;
+ "upstream sent too long status line");
+ ngx_http_proxy_next_upstream(p, NGX_HTTP_PROXY_FT_HTTP_HEADER);
}
return;
}
if (rc == NGX_HTTP_PROXY_PARSE_NO_HEADER) {
- /* TODO: HTTP/0.9 */
+ ngx_log_error(NGX_LOG_ERR, rev->log, 0,
+ "upstream sent no valid HTTP/1.0 header");
+
+ if (p->accel) {
+ ngx_http_proxy_next_upstream(p, NGX_HTTP_PROXY_FT_HTTP_HEADER);
+
+ } else {
+ p->request->http_version = NGX_HTTP_VERSION_9;
+ p->status = NGX_HTTP_OK;
+ ngx_http_proxy_send_response(p);
+ }
+
return;
}
/* rc == NGX_OK */
+ if (p->status == NGX_HTTP_INTERNAL_SERVER_ERROR
+ && p->upstream.tries > 1
+ && (p->lcf->next_upstream & NGX_HTTP_PROXY_FT_HTTP_500))
+ {
+ ngx_http_proxy_next_upstream(p, NGX_HTTP_PROXY_FT_HTTP_500);
+ return;
+ }
+
p->status_line.len = p->status_end - p->status_start;
p->status_line.data = ngx_palloc(p->request->pool, p->status_line.len + 1);
if (p->status_line.data == NULL) {
@@ -522,7 +607,6 @@ static void ngx_http_proxy_process_upstream_status_line(ngx_event_t *rev)
ngx_log_debug(rev->log, "http proxy status %d '%s'" _
p->status _ p->status_line.data);
-
if (p->headers_in.headers) {
p->headers_in.headers->nelts = 0;
} else {
@@ -549,11 +633,13 @@ static void ngx_http_proxy_process_upstream_headers(ngx_event_t *rev)
p = c->data;
r = p->request;
+ p->action = "reading upstream headers";
+
ngx_log_debug(rev->log, "http proxy process header line");
if (rev->timedout) {
p->timedout = 1;
- ngx_http_proxy_next_upstream(p);
+ ngx_http_proxy_next_upstream(p, NGX_HTTP_PROXY_FT_TIMEOUT);
return;
}
@@ -564,7 +650,7 @@ static void ngx_http_proxy_process_upstream_headers(ngx_event_t *rev)
n = ngx_http_proxy_read_upstream_header(p);
if (n == NGX_ERROR) {
- ngx_http_proxy_next_upstream(p);
+ ngx_http_proxy_next_upstream(p, NGX_HTTP_PROXY_FT_ERROR);
return;
}
@@ -609,6 +695,7 @@ static void ngx_http_proxy_process_upstream_headers(ngx_event_t *rev)
if (ngx_strcasecmp(headers_in[i].name.data, h->key.data) == 0) {
*((ngx_table_elt_t **)
((char *) &p->headers_in + headers_in[i].offset)) = h;
+ break;
}
}
@@ -631,7 +718,10 @@ static void ngx_http_proxy_process_upstream_headers(ngx_event_t *rev)
/* there was error while a header line parsing */
- ngx_http_proxy_finalize_request(p, NGX_HTTP_BAD_GATEWAY);
+ ngx_log_error(NGX_LOG_ERR, rev->log, 0,
+ upstream_header_errors[rc - NGX_HTTP_PARSE_HEADER_ERROR]);
+
+ ngx_http_proxy_next_upstream(p, NGX_HTTP_PROXY_FT_HTTP_HEADER);
return;
}
@@ -640,7 +730,8 @@ static void ngx_http_proxy_process_upstream_headers(ngx_event_t *rev)
if (p->header_in->last == p->header_in->end) {
ngx_log_error(NGX_LOG_ERR, rev->log, 0,
"upstream sent too big header");
- ngx_http_proxy_finalize_request(p, NGX_HTTP_BAD_GATEWAY);
+
+ ngx_http_proxy_next_upstream(p, NGX_HTTP_PROXY_FT_HTTP_HEADER);
return;
}
}
@@ -679,7 +770,7 @@ static ssize_t ngx_http_proxy_read_upstream_header(ngx_http_proxy_ctx_t *p)
}
if (n == 0) {
- ngx_log_error(NGX_LOG_INFO, rev->log, 0,
+ ngx_log_error(NGX_LOG_ERR, rev->log, 0,
"upstream closed prematurely connection");
}
@@ -834,11 +925,6 @@ static void ngx_http_proxy_send_response(ngx_http_proxy_ctx_t *p)
p->event_pipe = ep;
-#if 0
- lcx = p->log->data;
- lcx->action = "reading an upstream";
-#endif
-
p->upstream.connection->read->event_handler = ngx_http_proxy_process_body;
r->connection->write->event_handler = ngx_http_proxy_process_body;
@@ -861,11 +947,13 @@ static void ngx_http_proxy_process_body(ngx_event_t *ev)
ngx_log_debug(ev->log, "http proxy process downstream");
r = c->data;
p = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
+ p->action = "sending to client";
} else {
ngx_log_debug(ev->log, "http proxy process upstream");
p = c->data;
r = p->request;
+ p->action = "reading upstream body";
}
ep = p->event_pipe;
@@ -1123,7 +1211,7 @@ static int ngx_http_proxy_parse_status_line(ngx_http_proxy_ctx_t *p)
}
-static void ngx_http_proxy_next_upstream(ngx_http_proxy_ctx_t *p)
+static void ngx_http_proxy_next_upstream(ngx_http_proxy_ctx_t *p, int ft_type)
{
ngx_event_connect_peer_failed(&p->upstream);
@@ -1137,7 +1225,7 @@ static void ngx_http_proxy_next_upstream(ngx_http_proxy_ctx_t *p)
p->upstream.connection = NULL;
}
- if (p->upstream.tries == 0) {
+ if (p->upstream.tries == 0 || !(p->lcf->next_upstream & ft_type)) {
ngx_http_proxy_finalize_request(p,
p->timedout ? NGX_HTTP_GATEWAY_TIME_OUT:
NGX_HTTP_BAD_GATEWAY);
@@ -1146,8 +1234,11 @@ static void ngx_http_proxy_next_upstream(ngx_http_proxy_ctx_t *p)
if (!p->fatal_error) {
ngx_http_proxy_send_request(p);
+ return;
}
+ngx_log_debug(p->request->connection->log, "FATAL ERROR IN NEXT UPSTREAM");
+
return;
}
@@ -1164,6 +1255,9 @@ static void ngx_http_proxy_finalize_request(ngx_http_proxy_ctx_t *p, int rc)
rc = 0;
}
+ p->request->connection->log->data = p->saved_ctx;
+ p->request->connection->log->handler = p->saved_handler;
+
ngx_http_finalize_request(p->request, rc);
p->fatal_error = 1;
@@ -1223,11 +1317,15 @@ static size_t ngx_http_proxy_log_error(void *data, char *buf, size_t len)
ngx_http_proxy_ctx_t *p = data;
return ngx_snprintf(buf, len,
- " while %s, upstream: %s, client: %s, URL: %s",
+ " while %s, client: %s, URL: %s, upstream: %s%s%s%s%s",
p->action,
- p->upstream.peers->peers[p->upstream.cur_peer].addr_port_text.data,
p->request->connection->addr_text.data,
- p->request->unparsed_uri.data);
+ p->request->unparsed_uri.data,
+ p->upstream.peers->peers[p->upstream.cur_peer].addr_port_text.data,
+ p->lcf->upstream->uri.data,
+ p->request->uri.data + p->lcf->upstream->location->len,
+ p->request->args.len ? "?" : "",
+ p->request->args.len ? p->request->args.data : "");
}
@@ -1250,6 +1348,7 @@ static void *ngx_http_proxy_create_loc_conf(ngx_conf_t *cf)
*/
+ conf->request_buffer_size = NGX_CONF_UNSET;
conf->connect_timeout = NGX_CONF_UNSET;
conf->send_timeout = NGX_CONF_UNSET;
conf->header_buffer_size = NGX_CONF_UNSET;
@@ -1267,6 +1366,8 @@ static void *ngx_http_proxy_create_loc_conf(ngx_conf_t *cf)
/* "proxy_cyclic_temp_file" is disabled */
conf->cyclic_temp_file = 0;
+ conf->next_upstream = NGX_CONF_UNSET;
+
return conf;
}
@@ -1277,6 +1378,8 @@ static char *ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf,
ngx_http_proxy_loc_conf_t *prev = parent;
ngx_http_proxy_loc_conf_t *conf = child;
+ ngx_conf_merge_size_value(conf->request_buffer_size,
+ prev->request_buffer_size, 8192);
ngx_conf_merge_msec_value(conf->connect_timeout,
prev->connect_timeout, 60000);
ngx_conf_merge_msec_value(conf->send_timeout, prev->send_timeout, 30000);
@@ -1297,6 +1400,9 @@ static char *ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf,
ngx_conf_merge_size_value(conf->temp_file_write_size,
prev->temp_file_write_size, 16384);
+ ngx_conf_merge_value(conf->next_upstream, prev->next_upstream,
+ (NGX_HTTP_PROXY_FT_ERROR|NGX_HTTP_PROXY_FT_TIMEOUT));
+
ngx_conf_merge_path_value(conf->temp_path, prev->temp_path,
"temp", 1, 2, 0, cf->pool);
diff --git a/src/http/modules/proxy/ngx_http_proxy_handler.h b/src/http/modules/proxy/ngx_http_proxy_handler.h
index c891058f8..0f43f4f3b 100644
--- a/src/http/modules/proxy/ngx_http_proxy_handler.h
+++ b/src/http/modules/proxy/ngx_http_proxy_handler.h
@@ -19,6 +19,7 @@ typedef struct {
typedef struct {
+ ssize_t request_buffer_size;
ngx_msec_t connect_timeout;
ngx_msec_t send_timeout;
ssize_t header_buffer_size;
@@ -31,6 +32,8 @@ typedef struct {
ssize_t temp_file_write_size;
int cyclic_temp_file;
+ int next_upstream;
+
ngx_path_t *temp_path;
ngx_http_proxy_upstream_t *upstream;
@@ -67,8 +70,7 @@ struct ngx_http_proxy_ctx_s {
int status;
ngx_str_t status_line;
- ngx_chain_t *work_request_hunks;
- ngx_chain_t *request_hunks;
+ ngx_output_chain_ctx_t *output_chain_ctx;
int method;
@@ -89,10 +91,16 @@ struct ngx_http_proxy_ctx_s {
char *action;
ngx_http_log_ctx_t *saved_ctx;
+ ngx_log_handler_pt saved_handler;
};
#define NGX_HTTP_PROXY_PARSE_NO_HEADER 20
+#define NGX_HTTP_PROXY_FT_ERROR 1
+#define NGX_HTTP_PROXY_FT_TIMEOUT 2
+#define NGX_HTTP_PROXY_FT_HTTP_HEADER 4
+#define NGX_HTTP_PROXY_FT_HTTP_500 8
+
#endif /* _NGX_HTTP_PROXY_HANDLER_H_INCLUDED_ */