summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIgor Sysoev <igor@sysoev.ru>2008-12-15 11:30:58 +0000
committerJonathan Kolb <jon@b0g.us>2008-12-15 11:30:58 +0000
commitaccf374de9a9b1fdc8df617172bb7e7eed62c83c (patch)
treee570222469fa41eac7977de79c9deb141cc444be
parent37eb9af78547c075879b3c3bc5e85b9b584fe324 (diff)
downloadnginx-0.7.27.tar.gz
Changes with nginx 0.7.27 15 Dec 2008v0.7.27
*) Feature: the "try_files" directive. *) Feature: variables support in the "fastcgi_pass" directive. *) Feature: now the $geo variable may get an address from a variable. Thanks to Andrei Nigmatulin. *) Feature: now a location's modifier may be used without space before name. *) Feature: the $upstream_response_length variable. *) Bugfix: now a "add_header" directive does not add an empty value. *) Bugfix: if zero length static file was requested, then nginx just closed connection; the bug had appeared in 0.7.25. *) Bugfix: a MOVE method could not move file in non-existent directory. *) Bugfix: a segmentation fault occurred in worker process, if no one named location was defined in server, but some one was used in an error_page directive. Thanks to Sergey Bochenkov.
-rw-r--r--CHANGES28
-rw-r--r--CHANGES.ru29
-rw-r--r--src/core/nginx.h2
-rw-r--r--src/core/ngx_file.c18
-rw-r--r--src/core/ngx_file.h3
-rw-r--r--src/core/ngx_log.c12
-rw-r--r--src/event/ngx_event_openssl.c20
-rw-r--r--src/event/ngx_event_pipe.c4
-rw-r--r--src/http/modules/ngx_http_dav_module.c28
-rw-r--r--src/http/modules/ngx_http_fastcgi_module.c122
-rw-r--r--src/http/modules/ngx_http_geo_module.c171
-rw-r--r--src/http/modules/ngx_http_headers_filter_module.c16
-rw-r--r--src/http/modules/ngx_http_index_module.c10
-rw-r--r--src/http/modules/ngx_http_memcached_module.c20
-rw-r--r--src/http/modules/ngx_http_proxy_module.c12
-rw-r--r--src/http/modules/ngx_http_static_module.c2
-rw-r--r--src/http/modules/perl/nginx.pm2
-rw-r--r--src/http/modules/perl/ngx_http_perl_module.c2
-rw-r--r--src/http/ngx_http.c11
-rw-r--r--src/http/ngx_http_core_module.c418
-rw-r--r--src/http/ngx_http_core_module.h13
-rw-r--r--src/http/ngx_http_request.c34
-rw-r--r--src/http/ngx_http_request_body.c6
-rw-r--r--src/http/ngx_http_script.c61
-rw-r--r--src/http/ngx_http_upstream.c217
-rw-r--r--src/http/ngx_http_upstream.h11
-rw-r--r--src/mail/ngx_mail_auth_http_module.c8
-rw-r--r--src/mail/ngx_mail_handler.c6
-rw-r--r--src/mail/ngx_mail_imap_handler.c2
-rw-r--r--src/mail/ngx_mail_pop3_handler.c2
-rw-r--r--src/mail/ngx_mail_proxy_module.c12
-rw-r--r--src/mail/ngx_mail_smtp_handler.c6
-rw-r--r--src/os/unix/ngx_errno.h1
33 files changed, 969 insertions, 340 deletions
diff --git a/CHANGES b/CHANGES
index d2bdff20f..d39554432 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,4 +1,32 @@
+Changes with nginx 0.7.27 15 Dec 2008
+
+ *) Feature: the "try_files" directive.
+
+ *) Feature: variables support in the "fastcgi_pass" directive.
+
+ *) Feature: now the $geo variable may get an address from a
+ variable.
+ Thanks to Andrei Nigmatulin.
+
+ *) Feature: now a location's modifier may be used without space before
+ name.
+
+ *) Feature: the $upstream_response_length variable.
+
+ *) Bugfix: now a "add_header" directive does not add an empty value.
+
+ *) Bugfix: if zero length static file was requested, then nginx just
+ closed connection; the bug had appeared in 0.7.25.
+
+ *) Bugfix: a MOVE method could not move file in non-existent directory.
+
+ *) Bugfix: a segmentation fault occurred in worker process, if no one
+ named location was defined in server, but some one was used in an
+ error_page directive.
+ Thanks to Sergey Bochenkov.
+
+
Changes with nginx 0.7.26 08 Dec 2008
*) Bugfix: in subrequest processing; the bug had appeared in 0.7.25.
diff --git a/CHANGES.ru b/CHANGES.ru
index 9fd02f20c..8501082d1 100644
--- a/CHANGES.ru
+++ b/CHANGES.ru
@@ -1,4 +1,33 @@
+Изменения в nginx 0.7.27 15.12.2008
+
+ *) Добавление: директива try_files.
+
+ *) Добавление: директива fastcgi_pass поддерживает переменные.
+
+ *) Добавление: теперь директива geo может брать адрес из переменной.
+ Спасибо Андрею Нигматулину.
+
+ *) Добавление: теперь модификатор location'а можно указывать без
+ пробела перед названием.
+
+ *) Добавление: переменная $upstream_response_length.
+
+ *) Исправление: теперь директива add_header не добавляет пустое
+ значение.
+
+ *) Исправление: при запросе файла нулевой длины nginx закрывал
+ соединение, ничего не передав; ошибка появилась в 0.7.25.
+
+ *) Исправление: метод MOVE не мог перемещать файл в несуществующий
+ каталог.
+
+ *) Исправление: если в сервере не был описан ни один именованный
+ location, но такой location использовался в директиве error_page, то
+ в рабочем процессе происходил segmentation fault.
+ Спасибо Сергею Боченкову.
+
+
Изменения в nginx 0.7.26 08.12.2008
*) Исправление: в обработке подзапросов; ошибка появилась в 0.7.25.
diff --git a/src/core/nginx.h b/src/core/nginx.h
index b4235db8d..81c3a9007 100644
--- a/src/core/nginx.h
+++ b/src/core/nginx.h
@@ -8,7 +8,7 @@
#define _NGINX_H_INCLUDED_
-#define NGINX_VERSION "0.7.26"
+#define NGINX_VERSION "0.7.27"
#define NGINX_VER "nginx/" NGINX_VERSION
#define NGINX_VAR "NGINX"
diff --git a/src/core/ngx_file.c b/src/core/ngx_file.c
index 28980df85..fdefacf50 100644
--- a/src/core/ngx_file.c
+++ b/src/core/ngx_file.c
@@ -487,11 +487,13 @@ ngx_ext_rename_file(ngx_str_t *src, ngx_str_t *to, ngx_ext_rename_file_t *ext)
#if !(NGX_WIN32)
- if (ngx_change_file_access(src->data, ext->access) == NGX_FILE_ERROR) {
- ngx_log_error(NGX_LOG_CRIT, ext->log, ngx_errno,
- ngx_change_file_access_n " \"%s\" failed", src->data);
- err = 0;
- goto failed;
+ if (ext->access) {
+ if (ngx_change_file_access(src->data, ext->access) == NGX_FILE_ERROR) {
+ ngx_log_error(NGX_LOG_CRIT, ext->log, ngx_errno,
+ ngx_change_file_access_n " \"%s\" failed", src->data);
+ err = 0;
+ goto failed;
+ }
}
#endif
@@ -517,7 +519,7 @@ ngx_ext_rename_file(ngx_str_t *src, ngx_str_t *to, ngx_ext_rename_file_t *ext)
goto failed;
}
- err = ngx_create_full_path(to->data, ngx_dir_access(ext->access));
+ err = ngx_create_full_path(to->data, ngx_dir_access(ext->path_access));
if (err) {
ngx_log_error(NGX_LOG_CRIT, ext->log, err,
@@ -561,12 +563,14 @@ failed:
}
}
- if (err) {
+ if (err && ext->log_rename_error) {
ngx_log_error(NGX_LOG_CRIT, ext->log, err,
ngx_rename_file_n " \"%s\" to \"%s\" failed",
src->data, to->data);
}
+ ext->rename_error = err;
+
return NGX_ERROR;
}
diff --git a/src/core/ngx_file.h b/src/core/ngx_file.h
index 8e0839829..344da0957 100644
--- a/src/core/ngx_file.h
+++ b/src/core/ngx_file.h
@@ -60,11 +60,14 @@ typedef struct {
typedef struct {
ngx_uint_t access;
+ ngx_uint_t path_access;
time_t time;
ngx_fd_t fd;
+ ngx_err_t rename_error;
unsigned create_path:1;
unsigned delete_file:1;
+ unsigned log_rename_error:1;
ngx_log_t *log;
} ngx_ext_rename_file_t;
diff --git a/src/core/ngx_log.c b/src/core/ngx_log.c
index e3abcd780..cc38b02da 100644
--- a/src/core/ngx_log.c
+++ b/src/core/ngx_log.c
@@ -127,18 +127,10 @@ ngx_log_error_core(ngx_uint_t level, ngx_log_t *log, ngx_err_t err,
}
#if (NGX_WIN32)
-
- if ((unsigned) err >= 0x80000000) {
- p = ngx_snprintf(p, last - p, " (%Xd: ", err);
-
- } else {
- p = ngx_snprintf(p, last - p, " (%d: ", err);
- }
-
+ p = ngx_snprintf(p, last - p, ((unsigned) err < 0x80000000)
+ ? " (%d: " : " (%Xd: ", err);
#else
-
p = ngx_snprintf(p, last - p, " (%d: ", err);
-
#endif
p = ngx_strerror_r(err, p, last - p);
diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c
index f6a8ff2ce..c963c9597 100644
--- a/src/event/ngx_event_openssl.c
+++ b/src/event/ngx_event_openssl.c
@@ -498,11 +498,11 @@ ngx_ssl_handshake(ngx_connection_t *c)
if (n == 1) {
- if (ngx_handle_read_event(c->read, 0) == NGX_ERROR) {
+ if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
return NGX_ERROR;
}
- if (ngx_handle_write_event(c->write, 0) == NGX_ERROR) {
+ if (ngx_handle_write_event(c->write, 0) != NGX_OK) {
return NGX_ERROR;
}
@@ -569,7 +569,7 @@ ngx_ssl_handshake(ngx_connection_t *c)
c->read->handler = ngx_ssl_handshake_handler;
c->write->handler = ngx_ssl_handshake_handler;
- if (ngx_handle_read_event(c->read, 0) == NGX_ERROR) {
+ if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
return NGX_ERROR;
}
@@ -581,7 +581,7 @@ ngx_ssl_handshake(ngx_connection_t *c)
c->read->handler = ngx_ssl_handshake_handler;
c->write->handler = ngx_ssl_handshake_handler;
- if (ngx_handle_write_event(c->write, 0) == NGX_ERROR) {
+ if (ngx_handle_write_event(c->write, 0) != NGX_OK) {
return NGX_ERROR;
}
@@ -767,7 +767,7 @@ ngx_ssl_handle_recv(ngx_connection_t *c, int n)
c->ssl->saved_write_handler = NULL;
c->write->ready = 1;
- if (ngx_handle_write_event(c->write, 0) == NGX_ERROR) {
+ if (ngx_handle_write_event(c->write, 0) != NGX_OK) {
return NGX_ERROR;
}
@@ -795,7 +795,7 @@ ngx_ssl_handle_recv(ngx_connection_t *c, int n)
c->write->ready = 0;
- if (ngx_handle_write_event(c->write, 0) == NGX_ERROR) {
+ if (ngx_handle_write_event(c->write, 0) != NGX_OK) {
return NGX_ERROR;
}
@@ -1019,7 +1019,7 @@ ngx_ssl_write(ngx_connection_t *c, u_char *data, size_t size)
c->ssl->saved_read_handler = NULL;
c->read->ready = 1;
- if (ngx_handle_read_event(c->read, 0) == NGX_ERROR) {
+ if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
return NGX_ERROR;
}
@@ -1047,7 +1047,7 @@ ngx_ssl_write(ngx_connection_t *c, u_char *data, size_t size)
c->read->ready = 0;
- if (ngx_handle_read_event(c->read, 0) == NGX_ERROR) {
+ if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
return NGX_ERROR;
}
@@ -1147,11 +1147,11 @@ ngx_ssl_shutdown(ngx_connection_t *c)
c->read->handler = ngx_ssl_shutdown_handler;
c->write->handler = ngx_ssl_shutdown_handler;
- if (ngx_handle_read_event(c->read, 0) == NGX_ERROR) {
+ if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
return NGX_ERROR;
}
- if (ngx_handle_write_event(c->write, 0) == NGX_ERROR) {
+ if (ngx_handle_write_event(c->write, 0) != NGX_OK) {
return NGX_ERROR;
}
diff --git a/src/event/ngx_event_pipe.c b/src/event/ngx_event_pipe.c
index a9cb21ecb..ca18d7cae 100644
--- a/src/event/ngx_event_pipe.c
+++ b/src/event/ngx_event_pipe.c
@@ -56,7 +56,7 @@ ngx_event_pipe(ngx_event_pipe_t *p, ngx_int_t do_write)
flags = (rev->eof || rev->error) ? NGX_CLOSE_EVENT : 0;
- if (ngx_handle_read_event(rev, flags) == NGX_ERROR) {
+ if (ngx_handle_read_event(rev, flags) != NGX_OK) {
return NGX_ABORT;
}
@@ -70,7 +70,7 @@ ngx_event_pipe(ngx_event_pipe_t *p, ngx_int_t do_write)
if (p->downstream->fd != -1 && p->downstream->data == p->output_ctx) {
wev = p->downstream->write;
- if (ngx_handle_write_event(wev, p->send_lowat) == NGX_ERROR) {
+ if (ngx_handle_write_event(wev, p->send_lowat) != NGX_OK) {
return NGX_ABORT;
}
diff --git a/src/http/modules/ngx_http_dav_module.c b/src/http/modules/ngx_http_dav_module.c
index 33bb2e9c1..d1dcc229a 100644
--- a/src/http/modules/ngx_http_dav_module.c
+++ b/src/http/modules/ngx_http_dav_module.c
@@ -246,9 +246,11 @@ ngx_http_dav_put_handler(ngx_http_request_t *r)
dlcf = ngx_http_get_module_loc_conf(r, ngx_http_dav_module);
ext.access = dlcf->access;
+ ext.path_access = dlcf->access;
ext.time = -1;
ext.create_path = dlcf->create_full_put_path;
ext.delete_file = 1;
+ ext.log_rename_error = 1;
ext.log = r->connection->log;
if (r->headers_in.date) {
@@ -521,6 +523,7 @@ ngx_http_dav_copy_move_handler(ngx_http_request_t *r)
ngx_tree_ctx_t tree;
ngx_file_info_t fi;
ngx_table_elt_t *dest, *over;
+ ngx_ext_rename_file_t ext;
ngx_http_dav_copy_ctx_t copy;
ngx_http_dav_loc_conf_t *dlcf;
@@ -781,9 +784,32 @@ overwrite_done:
} else {
if (r->method == NGX_HTTP_MOVE) {
- if (ngx_rename_file(path.data, copy.path.data) != NGX_FILE_ERROR) {
+
+ dlcf = ngx_http_get_module_loc_conf(r, ngx_http_dav_module);
+
+ ext.access = 0;
+ ext.path_access = dlcf->access;
+ ext.time = -1;
+ ext.create_path = 1;
+ ext.delete_file = 0;
+ ext.log_rename_error = 0;
+ ext.log = r->connection->log;
+
+ if (ngx_ext_rename_file(&path, &copy.path, &ext) == NGX_OK) {
return NGX_HTTP_NO_CONTENT;
}
+
+ if (ext.rename_error != NGX_EXDEV) {
+
+ if (ext.rename_error) {
+ ngx_log_error(NGX_LOG_CRIT, r->connection->log,
+ ext.rename_error,
+ ngx_rename_file_n " \"%s\" to \"%s\" failed",
+ path.data, copy.path.data);
+ }
+
+ return NGX_HTTP_INTERNAL_SERVER_ERROR;
+ }
}
dlcf = ngx_http_get_module_loc_conf(r, ngx_http_dav_module);
diff --git a/src/http/modules/ngx_http_fastcgi_module.c b/src/http/modules/ngx_http_fastcgi_module.c
index b4a07d011..957927741 100644
--- a/src/http/modules/ngx_http_fastcgi_module.c
+++ b/src/http/modules/ngx_http_fastcgi_module.c
@@ -19,6 +19,9 @@ typedef struct {
ngx_array_t *params;
ngx_array_t *params_source;
ngx_array_t *catch_stderr;
+
+ ngx_array_t *fastcgi_lengths;
+ ngx_array_t *fastcgi_values;
} ngx_http_fastcgi_loc_conf_t;
@@ -103,6 +106,8 @@ typedef struct {
} ngx_http_fastcgi_request_start_t;
+static ngx_int_t ngx_http_fastcgi_eval(ngx_http_request_t *r,
+ ngx_http_fastcgi_loc_conf_t *flcf);
static ngx_int_t ngx_http_fastcgi_create_request(ngx_http_request_t *r);
static ngx_int_t ngx_http_fastcgi_reinit_request(ngx_http_request_t *r);
static ngx_int_t ngx_http_fastcgi_process_header(ngx_http_request_t *r);
@@ -414,14 +419,25 @@ ngx_http_fastcgi_handler(ngx_http_request_t *r)
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
- flcf = ngx_http_get_module_loc_conf(r, ngx_http_fastcgi_module);
+ ngx_http_set_ctx(r, NULL, ngx_http_fastcgi_module);
u = ngx_pcalloc(r->pool, sizeof(ngx_http_upstream_t));
if (u == NULL) {
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
- u->schema = flcf->upstream.schema;
+ r->upstream = u;
+
+ flcf = ngx_http_get_module_loc_conf(r, ngx_http_fastcgi_module);
+
+ if (flcf->fastcgi_lengths) {
+ if (ngx_http_fastcgi_eval(r, flcf) != NGX_OK) {
+ return NGX_HTTP_INTERNAL_SERVER_ERROR;
+ }
+ }
+
+ u->schema.len = sizeof("fastcgi://") - 1;
+ u->schema.data = (u_char *) "fastcgi://";
u->peer.log = r->connection->log;
u->peer.log_error = NGX_ERROR_ERR;
@@ -449,8 +465,6 @@ ngx_http_fastcgi_handler(ngx_http_request_t *r)
u->pipe->input_filter = ngx_http_fastcgi_input_filter;
u->pipe->input_ctx = r;
- r->upstream = u;
-
rc = ngx_http_read_client_request_body(r, ngx_http_upstream_init);
if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
@@ -462,6 +476,50 @@ ngx_http_fastcgi_handler(ngx_http_request_t *r)
static ngx_int_t
+ngx_http_fastcgi_eval(ngx_http_request_t *r, ngx_http_fastcgi_loc_conf_t *flcf)
+{
+ ngx_url_t u;
+
+ ngx_memzero(&u, sizeof(ngx_url_t));
+
+ if (ngx_http_script_run(r, &u.url, flcf->fastcgi_lengths->elts, 0,
+ flcf->fastcgi_values->elts)
+ == NULL)
+ {
+ return NGX_ERROR;
+ }
+
+ u.no_resolve = 1;
+
+ if (ngx_parse_url(r->pool, &u) != NGX_OK) {
+ if (u.err) {
+ ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
+ "%s in upstream \"%V\"", u.err, &u.url);
+ }
+
+ return NGX_ERROR;
+ }
+
+ if (u.no_port) {
+ ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
+ "no port in upstream \"%V\"", &u.url);
+ return NGX_ERROR;
+ }
+
+ r->upstream->resolved = ngx_pcalloc(r->pool,
+ sizeof(ngx_http_upstream_resolved_t));
+ if (r->upstream->resolved == NULL) {
+ return NGX_ERROR;
+ }
+
+ r->upstream->resolved->host = u.host;
+ r->upstream->resolved->port = u.port;
+
+ return NGX_OK;
+}
+
+
+static ngx_int_t
ngx_http_fastcgi_create_request(ngx_http_request_t *r)
{
off_t file_pos;
@@ -1631,7 +1689,6 @@ ngx_http_fastcgi_create_loc_conf(ngx_conf_t *cf)
* conf->upstream.next_upstream = 0;
* conf->upstream.temp_path = NULL;
* conf->upstream.hide_headers_hash = { NULL, 0 };
- * conf->upstream.schema = { 0, NULL };
* conf->upstream.uri = { 0, NULL };
* conf->upstream.location = NULL;
* conf->upstream.store_lengths = NULL;
@@ -1861,7 +1918,11 @@ ngx_http_fastcgi_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
if (conf->upstream.upstream == NULL) {
conf->upstream.upstream = prev->upstream.upstream;
- conf->upstream.schema = prev->upstream.schema;
+ }
+
+ if (conf->fastcgi_lengths == NULL) {
+ conf->fastcgi_lengths = prev->fastcgi_lengths;
+ conf->fastcgi_values = prev->fastcgi_values;
}
if (conf->params_source == NULL) {
@@ -2044,35 +2105,56 @@ ngx_http_fastcgi_script_name_variable(ngx_http_request_t *r,
static char *
ngx_http_fastcgi_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
- ngx_http_fastcgi_loc_conf_t *lcf = conf;
+ ngx_http_fastcgi_loc_conf_t *flcf = conf;
- ngx_url_t u;
- ngx_str_t *value;
- ngx_http_core_loc_conf_t *clcf;
+ ngx_url_t u;
+ ngx_str_t *value, *url;
+ ngx_uint_t n;
+ ngx_http_core_loc_conf_t *clcf;
+ ngx_http_script_compile_t sc;
- if (lcf->upstream.schema.len) {
+ if (flcf->upstream.upstream || flcf->fastcgi_lengths) {
return "is duplicate";
}
+ clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
+ clcf->handler = ngx_http_fastcgi_handler;
+
value = cf->args->elts;
+ url = &value[1];
+
+ n = ngx_http_script_variables_count(url);
+
+ if (n) {
+
+ ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
+
+ sc.cf = cf;
+ sc.source = url;
+ sc.lengths = &flcf->fastcgi_lengths;
+ sc.values = &flcf->fastcgi_values;
+ sc.variables = n;
+ sc.complete_lengths = 1;
+ sc.complete_values = 1;
+
+ if (ngx_http_script_compile(&sc) != NGX_OK) {
+ return NGX_CONF_ERROR;
+ }
+
+ return NGX_CONF_OK;
+ }
+
ngx_memzero(&u, sizeof(ngx_url_t));
u.url = value[1];
u.no_resolve = 1;
- lcf->upstream.upstream = ngx_http_upstream_add(cf, &u, 0);
- if (lcf->upstream.upstream == NULL) {
+ flcf->upstream.upstream = ngx_http_upstream_add(cf, &u, 0);
+ if (flcf->upstream.upstream == NULL) {
return NGX_CONF_ERROR;
}
- lcf->upstream.schema.len = sizeof("fastcgi://") - 1;
- lcf->upstream.schema.data = (u_char *) "fastcgi://";
-
- clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
-
- clcf->handler = ngx_http_fastcgi_handler;
-
if (clcf->name.data[clcf->name.len - 1] == '/') {
clcf->auto_redirect = 1;
}
diff --git a/src/http/modules/ngx_http_geo_module.c b/src/http/modules/ngx_http_geo_module.c
index 4c2b679e2..d570e3009 100644
--- a/src/http/modules/ngx_http_geo_module.c
+++ b/src/http/modules/ngx_http_geo_module.c
@@ -10,36 +10,48 @@
typedef struct {
- u_short start;
- u_short end;
- ngx_http_variable_value_t *value;
+ u_short start;
+ u_short end;
+ ngx_http_variable_value_t *value;
} ngx_http_geo_range_t;
typedef struct {
- ngx_http_geo_range_t *ranges;
- ngx_uint_t n;
+ ngx_http_geo_range_t *ranges;
+ ngx_uint_t n;
} ngx_http_geo_low_ranges_t;
typedef struct {
- ngx_http_geo_low_ranges_t low[0x10000];
- ngx_http_variable_value_t *default_value;
+ ngx_http_geo_low_ranges_t low[0x10000];
+ ngx_http_variable_value_t *default_value;
} ngx_http_geo_high_ranges_t;
typedef struct {
- ngx_http_variable_value_t *value;
- ngx_str_t *net;
- ngx_http_geo_high_ranges_t *high;
- ngx_radix_tree_t *tree;
- ngx_rbtree_t rbtree;
- ngx_rbtree_node_t sentinel;
- ngx_pool_t *pool;
- ngx_pool_t *temp_pool;
+ ngx_http_variable_value_t *value;
+ ngx_str_t *net;
+ ngx_http_geo_high_ranges_t *high;
+ ngx_radix_tree_t *tree;
+ ngx_rbtree_t rbtree;
+ ngx_rbtree_node_t sentinel;
+ ngx_pool_t *pool;
+ ngx_pool_t *temp_pool;
} ngx_http_geo_conf_ctx_t;
+typedef struct {
+ union {
+ ngx_radix_tree_t *tree;
+ ngx_http_geo_high_ranges_t *high;
+ } u;
+
+ ngx_int_t index;
+} ngx_http_geo_ctx_t;
+
+
+static in_addr_t ngx_http_geo_addr(ngx_http_request_t *r,
+ ngx_http_geo_ctx_t *ctx);
static char *ngx_http_geo_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
static char *ngx_http_geo(ngx_conf_t *cf, ngx_command_t *dummy, void *conf);
static char *ngx_http_geo_range(ngx_conf_t *cf, ngx_http_geo_conf_ctx_t *ctx,
@@ -57,7 +69,7 @@ static ngx_http_variable_value_t *ngx_http_geo_value(ngx_conf_t *cf,
static ngx_command_t ngx_http_geo_commands[] = {
{ ngx_string("geo"),
- NGX_HTTP_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_TAKE1,
+ NGX_HTTP_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_TAKE12,
ngx_http_geo_block,
NGX_HTTP_MAIN_CONF_OFFSET,
0,
@@ -104,23 +116,17 @@ static ngx_int_t
ngx_http_geo_cidr_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v,
uintptr_t data)
{
- ngx_radix_tree_t *tree = (ngx_radix_tree_t *) data;
+ ngx_http_geo_ctx_t *ctx = (ngx_http_geo_ctx_t *) data;
- struct sockaddr_in *sin;
ngx_http_variable_value_t *vv;
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http geo started");
-
- sin = (struct sockaddr_in *) r->connection->sockaddr;
-
vv = (ngx_http_variable_value_t *)
- ngx_radix32tree_find(tree, ntohl(sin->sin_addr.s_addr));
+ ngx_radix32tree_find(ctx->u.tree, ngx_http_geo_addr(r, ctx));
*v = *vv;
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http geo: %V %v", &r->connection->addr_text, v);
+ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "http geo: %v", v);
return NGX_OK;
}
@@ -130,27 +136,21 @@ static ngx_int_t
ngx_http_geo_range_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v,
uintptr_t data)
{
- ngx_http_geo_high_ranges_t *high = (ngx_http_geo_high_ranges_t *) data;
+ ngx_http_geo_ctx_t *ctx = (ngx_http_geo_ctx_t *) data;
in_addr_t addr;
ngx_uint_t i, n;
- struct sockaddr_in *sin;
ngx_http_geo_range_t *range;
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http geo started");
-
- sin = (struct sockaddr_in *) r->connection->sockaddr;
-
- *v = *high->default_value;
+ *v = *ctx->u.high->default_value;
- addr = ntohl(sin->sin_addr.s_addr);
+ addr = ngx_http_geo_addr(r, ctx);
- range = high->low[addr >> 16].ranges;
+ range = ctx->u.high->low[addr >> 16].ranges;
n = addr & 0xffff;
- for (i = 0; i < high->low[addr >> 16].n; i++) {
+ for (i = 0; i < ctx->u.high->low[addr >> 16].n; i++) {
if (n >= (ngx_uint_t) range[i].start
&& n <= (ngx_uint_t) range[i].end)
{
@@ -158,13 +158,43 @@ ngx_http_geo_range_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v,
}
}
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http geo: %V %v", &r->connection->addr_text, v);
+ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "http geo: %v", v);
return NGX_OK;
}
+static in_addr_t
+ngx_http_geo_addr(ngx_http_request_t *r, ngx_http_geo_ctx_t *ctx)
+{
+ struct sockaddr_in *sin;
+ ngx_http_variable_value_t *v;
+
+ if (ctx->index == -1) {
+ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "http geo started: %V", &r->connection->addr_text);
+
+ sin = (struct sockaddr_in *) r->connection->sockaddr;
+ return ntohl(sin->sin_addr.s_addr);
+ }
+
+ v = ngx_http_get_flushed_variable(r, ctx->index);
+
+ if (v == NULL || v->not_found) {
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "http geo not found");
+
+ return 0;
+ }
+
+ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "http geo started: %v", v);
+
+ return ntohl(ngx_inet_addr(v->data, v->len));
+}
+
+
static char *
ngx_http_geo_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
@@ -176,19 +206,33 @@ ngx_http_geo_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
ngx_pool_t *pool;
ngx_array_t *a;
ngx_http_variable_t *var;
+ ngx_http_geo_ctx_t *geo;
ngx_http_geo_conf_ctx_t ctx;
value = cf->args->elts;
+ geo = ngx_palloc(cf->pool, sizeof(ngx_http_geo_ctx_t));
+ if (geo == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
name = value[1];
+ name.len--;
+ name.data++;
- if (name.data[0] != '$') {
- ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
- "\"%V\" variable name should start with '$'",
- &value[1]);
- } else {
+ if (cf->args->nelts == 3) {
+
+ geo->index = ngx_http_get_variable_index(cf, &name);
+ if (geo->index == NGX_ERROR) {
+ return NGX_CONF_ERROR;
+ }
+
+ name = value[2];
name.len--;
name.data++;
+
+ } else {
+ geo->index = -1;
}
var = ngx_http_add_variable(cf, &name, NGX_HTTP_VAR_CHANGEABLE);
@@ -244,8 +288,10 @@ ngx_http_geo_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
ngx_memcpy(ctx.high->low[i].ranges, a->elts, len);
}
+ geo->u.high = ctx.high;
+
var->get_handler = ngx_http_geo_range_variable;
- var->data = (uintptr_t) ctx.high;
+ var->data = (uintptr_t) geo;
ngx_destroy_pool(ctx.temp_pool);
ngx_destroy_pool(pool);
@@ -262,8 +308,10 @@ ngx_http_geo_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
}
}
+ geo->u.tree = ctx.tree;
+
var->get_handler = ngx_http_geo_cidr_variable;
- var->data = (uintptr_t) ctx.tree;
+ var->data = (uintptr_t) geo;
ngx_destroy_pool(ctx.temp_pool);
ngx_destroy_pool(pool);
@@ -644,21 +692,28 @@ ngx_http_geo_cidr(ngx_conf_t *cf, ngx_http_geo_conf_ctx_t *ctx,
del = 0;
}
- rc = ngx_ptocidr(net, &cidrin);
+ if (ngx_strcmp(net->data, "255.255.255.255") == 0) {
+ cidrin.addr = 0xffffffff;
+ cidrin.mask = 0xffffffff;
- if (rc == NGX_ERROR) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "invalid network \"%V\"", net);
- return NGX_CONF_ERROR;
- }
+ } else {
+ rc = ngx_ptocidr(net, &cidrin);
- if (rc == NGX_DONE) {
- ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
- "low address bits of %V are meaningless", net);
- }
+ if (rc == NGX_ERROR) {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "invalid network \"%V\"", net);
+ return NGX_CONF_ERROR;
+ }
+
+ if (rc == NGX_DONE) {
+ ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
+ "low address bits of %V are meaningless",
+ net);
+ }
- cidrin.addr = ntohl(cidrin.addr);
- cidrin.mask = ntohl(cidrin.mask);
+ cidrin.addr = ntohl(cidrin.addr);
+ cidrin.mask = ntohl(cidrin.mask);
+ }
if (del) {
if (ngx_radix32tree_delete(ctx->tree, cidrin.addr, cidrin.mask)
diff --git a/src/http/modules/ngx_http_headers_filter_module.c b/src/http/modules/ngx_http_headers_filter_module.c
index f4a6fe76f..764ddc94c 100644
--- a/src/http/modules/ngx_http_headers_filter_module.c
+++ b/src/http/modules/ngx_http_headers_filter_module.c
@@ -325,14 +325,16 @@ ngx_http_add_header(ngx_http_request_t *r, ngx_http_header_val_t *hv,
{
ngx_table_elt_t *h;
- h = ngx_list_push(&r->headers_out.headers);
- if (h == NULL) {
- return NGX_ERROR;
- }
+ if (value->len) {
+ h = ngx_list_push(&r->headers_out.headers);
+ if (h == NULL) {
+ return NGX_ERROR;
+ }
- h->hash = hv->value.hash;
- h->key = hv->value.key;
- h->value = *value;
+ h->hash = hv->value.hash;
+ h->key = hv->value.key;
+ h->value = *value;
+ }
return NGX_OK;
}
diff --git a/src/http/modules/ngx_http_index_module.c b/src/http/modules/ngx_http_index_module.c
index 434ae60c5..936ec8db9 100644
--- a/src/http/modules/ngx_http_index_module.c
+++ b/src/http/modules/ngx_http_index_module.c
@@ -99,7 +99,6 @@ ngx_http_index_handler(ngx_http_request_t *r)
size_t len, nlen, root, allocated;
ngx_int_t rc;
ngx_str_t path, uri;
- ngx_log_t *log;
ngx_uint_t i, dir_tested;
ngx_http_index_t *index;
ngx_open_file_info_t of;
@@ -122,8 +121,6 @@ ngx_http_index_handler(ngx_http_request_t *r)
return NGX_DECLINED;
}
- log = r->connection->log;
-
ilcf = ngx_http_get_module_loc_conf(r, ngx_http_index_module);
clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
@@ -206,7 +203,8 @@ ngx_http_index_handler(ngx_http_request_t *r)
*e.pos++ = '\0';
}
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0, "open index \"%V\"", &path);
+ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "open index \"%V\"", &path);
ngx_memzero(&of, sizeof(ngx_open_file_info_t));
@@ -219,7 +217,7 @@ ngx_http_index_handler(ngx_http_request_t *r)
if (ngx_open_cached_file(clcf->open_file_cache, &path, &of, r->pool)
!= NGX_OK)
{
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, of.err,
+ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, of.err,
ngx_open_file_n " \"%s\" failed", path.data);
if (of.err == 0) {
@@ -244,7 +242,7 @@ ngx_http_index_handler(ngx_http_request_t *r)
continue;
}
- ngx_log_error(NGX_LOG_ERR, log, of.err,
+ ngx_log_error(NGX_LOG_ERR, r->connection->log, of.err,
ngx_open_file_n " \"%s\" failed", path.data);
return NGX_HTTP_INTERNAL_SERVER_ERROR;
diff --git a/src/http/modules/ngx_http_memcached_module.c b/src/http/modules/ngx_http_memcached_module.c
index 9a6fb1646..f68be1e44 100644
--- a/src/http/modules/ngx_http_memcached_module.c
+++ b/src/http/modules/ngx_http_memcached_module.c
@@ -183,7 +183,8 @@ ngx_http_memcached_handler(ngx_http_request_t *r)
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
- u->schema = mlcf->upstream.schema;
+ u->schema.len = sizeof("memcached://") - 1;
+ u->schema.data = (u_char *) "memcached://";
u->peer.log = r->connection->log;
u->peer.log_error = NGX_ERROR_ERR;
@@ -521,7 +522,6 @@ ngx_http_memcached_create_loc_conf(ngx_conf_t *cf)
* conf->upstream.bufs.num = 0;
* conf->upstream.next_upstream = 0;
* conf->upstream.temp_path = NULL;
- * conf->upstream.schema = { 0, NULL };
* conf->upstream.uri = { 0, NULL };
* conf->upstream.location = NULL;
*/
@@ -584,7 +584,6 @@ ngx_http_memcached_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
if (conf->upstream.upstream == NULL) {
conf->upstream.upstream = prev->upstream.upstream;
- conf->upstream.schema = prev->upstream.schema;
}
if (conf->index == NGX_CONF_UNSET) {
@@ -598,13 +597,13 @@ ngx_http_memcached_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
static char *
ngx_http_memcached_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
- ngx_http_memcached_loc_conf_t *lcf = conf;
+ ngx_http_memcached_loc_conf_t *mlcf = conf;
ngx_str_t *value;
ngx_url_t u;
ngx_http_core_loc_conf_t *clcf;
- if (lcf->upstream.schema.len) {
+ if (mlcf->upstream.upstream) {
return "is duplicate";
}
@@ -615,14 +614,11 @@ ngx_http_memcached_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
u.url = value[1];
u.no_resolve = 1;
- lcf->upstream.upstream = ngx_http_upstream_add(cf, &u, 0);
- if (lcf->upstream.upstream == NULL) {
+ mlcf->upstream.upstream = ngx_http_upstream_add(cf, &u, 0);
+ if (mlcf->upstream.upstream == NULL) {
return NGX_CONF_ERROR;
}
- lcf->upstream.schema.len = sizeof("memcached://") - 1;
- lcf->upstream.schema.data = (u_char *) "memcached://";
-
clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
clcf->handler = ngx_http_memcached_handler;
@@ -631,9 +627,9 @@ ngx_http_memcached_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
clcf->auto_redirect = 1;
}
- lcf->index = ngx_http_get_variable_index(cf, &ngx_http_memcached_key);
+ mlcf->index = ngx_http_get_variable_index(cf, &ngx_http_memcached_key);
- if (lcf->index == NGX_ERROR) {
+ if (mlcf->index == NGX_ERROR) {
return NGX_CONF_ERROR;
}
diff --git a/src/http/modules/ngx_http_proxy_module.c b/src/http/modules/ngx_http_proxy_module.c
index 5e98ad9d4..2cf009bd9 100644
--- a/src/http/modules/ngx_http_proxy_module.c
+++ b/src/http/modules/ngx_http_proxy_module.c
@@ -32,6 +32,7 @@ struct ngx_http_proxy_redirect_s {
typedef struct {
+ ngx_str_t schema;
ngx_str_t host_header;
ngx_str_t port;
ngx_str_t uri;
@@ -480,7 +481,7 @@ ngx_http_proxy_handler(ngx_http_request_t *r)
if (plcf->proxy_lengths == 0) {
ctx->vars = plcf->vars;
- u->schema = plcf->upstream.schema;
+ u->schema = plcf->vars.schema;
#if (NGX_HTTP_SSL)
u->ssl = (plcf->upstream.ssl != NULL);
#endif
@@ -1631,7 +1632,6 @@ ngx_http_proxy_create_loc_conf(ngx_conf_t *cf)
* conf->upstream.next_upstream = 0;
* conf->upstream.temp_path = NULL;
* conf->upstream.hide_headers_hash = { NULL, 0 };
- * conf->upstream.schema = { 0, NULL };
* conf->upstream.uri = { 0, NULL };
* conf->upstream.location = NULL;
* conf->upstream.store_lengths = NULL;
@@ -1931,9 +1931,7 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
if (conf->upstream.upstream == NULL) {
conf->upstream.upstream = prev->upstream.upstream;
-
conf->vars = prev->vars;
- conf->upstream.schema = prev->upstream.schema;
}
@@ -2216,7 +2214,7 @@ ngx_http_proxy_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
ngx_http_core_loc_conf_t *clcf;
ngx_http_script_compile_t sc;
- if (plcf->upstream.schema.len) {
+ if (plcf->upstream.upstream || plcf->proxy_lengths) {
return "is duplicate";
}
@@ -2296,8 +2294,8 @@ ngx_http_proxy_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
return NGX_CONF_ERROR;
}
- plcf->upstream.schema.len = add;
- plcf->upstream.schema.data = url->data;
+ plcf->vars.schema.len = add;
+ plcf->vars.schema.data = url->data;
plcf->location = clcf->name;
clcf->handler = ngx_http_proxy_handler;
diff --git a/src/http/modules/ngx_http_static_module.c b/src/http/modules/ngx_http_static_module.c
index e90d83c57..9ff1f817f 100644
--- a/src/http/modules/ngx_http_static_module.c
+++ b/src/http/modules/ngx_http_static_module.c
@@ -217,7 +217,7 @@ ngx_http_static_handler(ngx_http_request_t *r)
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
- if (of.size == 0) {
+ if (r != r->main && of.size == 0) {
return ngx_http_send_header(r);
}
diff --git a/src/http/modules/perl/nginx.pm b/src/http/modules/perl/nginx.pm
index d1c895b2b..283b2b3b3 100644
--- a/src/http/modules/perl/nginx.pm
+++ b/src/http/modules/perl/nginx.pm
@@ -47,7 +47,7 @@ our @EXPORT = qw(
HTTP_INSUFFICIENT_STORAGE
);
-our $VERSION = '0.7.26';
+our $VERSION = '0.7.27';
require XSLoader;
XSLoader::load('nginx', $VERSION);
diff --git a/src/http/modules/perl/ngx_http_perl_module.c b/src/http/modules/perl/ngx_http_perl_module.c
index 262794256..bad2454ee 100644
--- a/src/http/modules/perl/ngx_http_perl_module.c
+++ b/src/http/modules/perl/ngx_http_perl_module.c
@@ -285,7 +285,7 @@ ngx_http_perl_sleep_handler(ngx_http_request_t *r)
return;
}
- if (ngx_handle_write_event(wev, 0) == NGX_ERROR) {
+ if (ngx_handle_write_event(wev, 0) != NGX_OK) {
ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
}
}
diff --git a/src/http/ngx_http.c b/src/http/ngx_http.c
index 3d8915767..615788811 100644
--- a/src/http/ngx_http.c
+++ b/src/http/ngx_http.c
@@ -489,7 +489,7 @@ ngx_http_init_phase_handlers(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf)
use_rewrite = cmcf->phases[NGX_HTTP_REWRITE_PHASE].handlers.nelts ? 1 : 0;
use_access = cmcf->phases[NGX_HTTP_ACCESS_PHASE].handlers.nelts ? 1 : 0;
- n = use_rewrite + use_access + 1; /* find config phase */
+ n = use_rewrite + use_access + cmcf->try_files + 1 /* find config phase */;
for (i = 0; i < NGX_HTTP_LOG_PHASE; i++) {
n += cmcf->phases[i].handlers.nelts;
@@ -558,6 +558,15 @@ ngx_http_init_phase_handlers(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf)
continue;
+ case NGX_HTTP_TRY_FILES_PHASE:
+ if (cmcf->try_files) {
+ ph->checker = ngx_http_core_try_files_phase;
+ n++;
+ ph++;
+ }
+
+ continue;
+
case NGX_HTTP_CONTENT_PHASE:
checker = ngx_http_core_content_phase;
break;
diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c
index 01dd513e3..4f2b32578 100644
--- a/src/http/ngx_http_core_module.c
+++ b/src/http/ngx_http_core_module.c
@@ -39,6 +39,8 @@ static char *ngx_http_core_server(ngx_conf_t *cf, ngx_command_t *cmd,
void *dummy);
static char *ngx_http_core_location(ngx_conf_t *cf, ngx_command_t *cmd,
void *dummy);
+static ngx_int_t ngx_http_core_regex_location(ngx_conf_t *cf,
+ ngx_http_core_loc_conf_t *clcf, ngx_str_t *regex, ngx_uint_t caseless);
static char *ngx_http_core_types(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
@@ -56,6 +58,8 @@ static char *ngx_http_core_directio(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
static char *ngx_http_core_error_page(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
+static char *ngx_http_core_try_files(ngx_conf_t *cf, ngx_command_t *cmd,
+ void *conf);
static char *ngx_http_core_open_file_cache(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
static char *ngx_http_core_error_log(ngx_conf_t *cf, ngx_command_t *cmd,
@@ -537,6 +541,13 @@ static ngx_command_t ngx_http_core_commands[] = {
0,
NULL },
+ { ngx_string("try_files"),
+ NGX_HTTP_LOC_CONF|NGX_CONF_2MORE,
+ ngx_http_core_try_files,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ 0,
+ NULL },
+
{ ngx_string("post_action"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
|NGX_CONF_TAKE1,
@@ -1030,6 +1041,177 @@ ngx_http_core_post_access_phase(ngx_http_request_t *r,
ngx_int_t
+ngx_http_core_try_files_phase(ngx_http_request_t *r,
+ ngx_http_phase_handler_t *ph)
+{
+ size_t len, root, alias;
+ ssize_t reserve, allocated;
+ u_char *p, *name;
+ ngx_str_t path;
+ ngx_http_try_file_t *tf;
+ ngx_open_file_info_t of;
+ ngx_http_script_code_pt code;
+ ngx_http_script_engine_t e;
+ ngx_http_core_loc_conf_t *clcf;
+ ngx_http_script_len_code_pt lcode;
+
+ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "try files phase: %ui", r->phase_handler);
+
+ clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
+
+ if (clcf->try_files == NULL) {
+ r->phase_handler++;
+ return NGX_AGAIN;
+ }
+
+ allocated = 0;
+ root = 0;
+ name = NULL;
+ path.len = 0;
+ path.data = NULL;
+
+ tf = clcf->try_files;
+
+ alias = clcf->alias ? clcf->name.len : 0;
+
+ for ( ;; ) {
+
+ if (tf->lengths) {
+ ngx_memzero(&e, sizeof(ngx_http_script_engine_t));
+
+ e.ip = tf->lengths->elts;
+ e.request = r;
+ e.flushed = 1;
+
+ /* 1 is for terminating '\0' as in static names */
+ len = 1;
+
+ while (*(uintptr_t *) e.ip) {
+ lcode = *(ngx_http_script_len_code_pt *) e.ip;
+ len += lcode(&e);
+ }
+
+ } else {
+ len = tf->name.len;
+ }
+
+ reserve = len - r->uri.len;
+
+ /* 16 bytes are preallocation */
+ reserve = reserve < 16 ? 16 : reserve + 16;
+
+ reserve += alias;
+
+ if (reserve > allocated) {
+
+ /* we just need to allocate path and to copy a root */
+
+ if (ngx_http_map_uri_to_path(r, &path, &root, reserve) == NULL) {
+ ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
+ return NGX_OK;
+ }
+
+ name = path.data + root;
+ allocated = path.len - root - (r->uri.len - alias);
+ }
+
+ if (tf->values == NULL) {
+
+ /* tf->name.len includes the terminating '\0' */
+
+ ngx_memcpy(name, tf->name.data, tf->name.len);
+
+ path.len = (name + tf->name.len - 1) - path.data;
+
+ } else {
+ e.ip = tf->values->elts;
+ e.pos = name;
+
+ while (*(uintptr_t *) e.ip) {
+ code = *(ngx_http_script_code_pt *) e.ip;
+ code((ngx_http_script_engine_t *) &e);
+ }
+
+ path.len = e.pos - path.data;
+
+ *e.pos++ = '\0';
+
+ if (alias && ngx_strncmp(name, clcf->name.data, alias) == 0) {
+ ngx_memcpy(name, name + alias, len - alias);
+ path.len -= alias;
+ }
+ }
+
+ tf++;
+
+ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "try to use file: \"%s\"", name);
+
+ if (tf->lengths == NULL && tf->name.len == 0) {
+
+ path.len -= root;
+ path.data += root;
+
+ if (path.data[0] == '@') {
+ (void) ngx_http_named_location(r, &path);
+
+ } else {
+ (void) ngx_http_internal_redirect(r, &path, NULL);
+ }
+
+ return NGX_OK;
+ }
+
+ ngx_memzero(&of, sizeof(ngx_open_file_info_t));
+
+ of.directio = clcf->directio;
+ of.valid = clcf->open_file_cache_valid;
+ of.min_uses = clcf->open_file_cache_min_uses;
+ of.errors = clcf->open_file_cache_errors;
+ of.events = clcf->open_file_cache_events;
+
+ if (ngx_open_cached_file(clcf->open_file_cache, &path, &of, r->pool)
+ != NGX_OK)
+ {
+ if (of.err != NGX_ENOENT && of.err != NGX_ENOTDIR) {
+ ngx_log_error(NGX_LOG_CRIT, r->connection->log, of.err,
+ ngx_open_file_n " \"%s\" failed", path.data);
+ }
+
+ continue;
+ }
+
+ path.len -= root;
+ path.data += root;
+
+ if (!alias) {
+ r->uri = path;
+
+ } else {
+ r->uri.len = alias + path.len;
+ r->uri.data = ngx_pnalloc(r->pool, r->uri.len);
+ if (r->uri.data == NULL) {
+ ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
+ return NGX_OK;
+ }
+
+ p = ngx_copy(r->uri.data, clcf->name.data, alias);
+ ngx_memcpy(p, name, path.len);
+ }
+
+ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "try file uri: \"%V\"", &r->uri);
+
+ r->phase_handler++;
+ return NGX_AGAIN;
+ }
+
+ /* not reached */
+}
+
+
+ngx_int_t
ngx_http_core_content_phase(ngx_http_request_t *r,
ngx_http_phase_handler_t *ph)
{
@@ -2015,33 +2197,37 @@ ngx_http_named_location(ngx_http_request_t *r, ngx_str_t *name)
cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
- for (clcfp = cscf->named_locations; *clcfp; clcfp++) {
+ if (cscf->named_locations) {
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "test location: \"%V\"", &(*clcfp)->name);
+ for (clcfp = cscf->named_locations; *clcfp; clcfp++) {
- if (name->len != (*clcfp)->name.len
- || ngx_strncmp(name->data, (*clcfp)->name.data, name->len) != 0)
- {
- continue;
- }
+ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "test location: \"%V\"", &(*clcfp)->name);
- ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "using location: %V \"%V?%V\"", name, &r->uri, &r->args);
+ if (name->len != (*clcfp)->name.len
+ || ngx_strncmp(name->data, (*clcfp)->name.data, name->len) != 0)
+ {
+ continue;
+ }
- r->internal = 1;
- r->content_handler = NULL;
- r->loc_conf = (*clcfp)->loc_conf;
+ ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "using location: %V \"%V?%V\"",
+ name, &r->uri, &r->args);
- ngx_http_update_location_config(r);
+ r->internal = 1;
+ r->content_handler = NULL;
+ r->loc_conf = (*clcfp)->loc_conf;
- cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
+ ngx_http_update_location_config(r);
- r->phase_handler = cmcf->phase_engine.location_rewrite_index;
+ cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
- ngx_http_core_run_phases(r);
+ r->phase_handler = cmcf->phase_engine.location_rewrite_index;
- return NGX_DONE;
+ ngx_http_core_run_phases(r);
+
+ return NGX_DONE;
+ }
}
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
@@ -2182,8 +2368,10 @@ static char *
ngx_http_core_location(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy)
{
char *rv;
+ u_char *mod;
+ size_t len;
+ ngx_str_t *value, *name;
ngx_uint_t i;
- ngx_str_t *value;
ngx_conf_t save;
ngx_http_module_t *module;
ngx_http_conf_ctx_t *ctx, *pctx;
@@ -2225,46 +2413,33 @@ ngx_http_core_location(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy)
value = cf->args->elts;
if (cf->args->nelts == 3) {
- if (value[1].len == 1 && value[1].data[0] == '=') {
- clcf->name = value[2];
+
+ len = value[1].len;
+ mod = value[1].data;
+ name = &value[2];
+
+ if (len == 1 && mod[0] == '=') {
+
+ clcf->name = *name;
clcf->exact_match = 1;
- } else if (value[1].len == 2
- && value[1].data[0] == '^'
- && value[1].data[1] == '~')
- {
- clcf->name = value[2];
+ } else if (len == 2 && mod[0] == '^' && mod[1] == '~') {
+
+ clcf->name = *name;
clcf->noregex = 1;
- } else if ((value[1].len == 1 && value[1].data[0] == '~')
- || (value[1].len == 2
- && value[1].data[0] == '~'
- && value[1].data[1] == '*'))
- {
-#if (NGX_PCRE)
- ngx_str_t err;
- u_char errstr[NGX_MAX_CONF_ERRSTR];
+ } else if (len == 1 && mod[0] == '~') {
- err.len = NGX_MAX_CONF_ERRSTR;
- err.data = errstr;
+ if (ngx_http_core_regex_location(cf, clcf, name, 0) != NGX_OK) {
+ return NGX_CONF_ERROR;
+ }
- clcf->regex = ngx_regex_compile(&value[2],
- value[1].len == 2 ? NGX_REGEX_CASELESS: 0,
- cf->pool, &err);
+ } else if (len == 2 && mod[0] == '~' && mod[1] == '*') {
- if (clcf->regex == NULL) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%s", err.data);
+ if (ngx_http_core_regex_location(cf, clcf, name, 1) != NGX_OK) {
return NGX_CONF_ERROR;
}
- clcf->name = value[2];
-#else
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "the using of the regex \"%V\" "
- "requires PCRE library", &value[2]);
- return NGX_CONF_ERROR;
-#endif
-
} else {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"invalid location modifier \"%V\"", &value[1]);
@@ -2273,10 +2448,47 @@ ngx_http_core_location(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy)
} else {
- clcf->name = value[1];
+ name = &value[1];
+
+ if (name->data[0] == '=') {
+
+ clcf->name.len = name->len - 1;
+ clcf->name.data = name->data + 1;
+ clcf->exact_match = 1;
+
+ } else if (name->data[0] == '^' && name->data[1] == '~') {
- if (value[1].data[0] == '@') {
- clcf->named = 1;
+ clcf->name.len = name->len - 2;
+ clcf->name.data = name->data + 2;
+ clcf->noregex = 1;
+
+ } else if (name->data[0] == '~') {
+
+ name->len--;
+ name->data++;
+
+ if (name->data[0] == '*') {
+
+ name->len--;
+ name->data++;
+
+ if (ngx_http_core_regex_location(cf, clcf, name, 1) != NGX_OK) {
+ return NGX_CONF_ERROR;
+ }
+
+ } else {
+ if (ngx_http_core_regex_location(cf, clcf, name, 0) != NGX_OK) {
+ return NGX_CONF_ERROR;
+ }
+ }
+
+ } else {
+
+ clcf->name = *name;
+
+ if (name->data[0] == '@') {
+ clcf->named = 1;
+ }
}
}
@@ -2314,13 +2526,13 @@ ngx_http_core_location(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy)
return NGX_CONF_ERROR;
}
+ len = pclcf->name.len;
+
#if (NGX_PCRE)
if (clcf->regex == NULL
- && ngx_strncmp(clcf->name.data, pclcf->name.data, pclcf->name.len)
- != 0)
+ && ngx_strncmp(clcf->name.data, pclcf->name.data, len) != 0)
#else
- if (ngx_strncmp(clcf->name.data, pclcf->name.data, pclcf->name.len)
- != 0)
+ if (ngx_strncmp(clcf->name.data, pclcf->name.data, len) != 0)
#endif
{
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
@@ -2346,6 +2558,40 @@ ngx_http_core_location(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy)
}
+static ngx_int_t
+ngx_http_core_regex_location(ngx_conf_t *cf, ngx_http_core_loc_conf_t *clcf,
+ ngx_str_t *regex, ngx_uint_t caseless)
+{
+#if (NGX_PCRE)
+ ngx_str_t err;
+ u_char errstr[NGX_MAX_CONF_ERRSTR];
+
+ err.len = NGX_MAX_CONF_ERRSTR;
+ err.data = errstr;
+
+ clcf->regex = ngx_regex_compile(regex, caseless ? NGX_REGEX_CASELESS: 0,
+ cf->pool, &err);
+
+ if (clcf->regex == NULL) {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%s", err.data);
+ return NGX_ERROR;
+ }
+
+ clcf->name = *regex;
+
+ return NGX_OK;
+
+#else
+
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "the using of the regex \"%V\" requires PCRE library",
+ regex);
+ return NGX_ERROR;
+
+#endif
+}
+
+
static char *
ngx_http_core_types(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
@@ -2644,6 +2890,7 @@ ngx_http_core_create_loc_conf(ngx_conf_t *cf)
* lcf->default_type = { 0, NULL };
* lcf->err_log = NULL;
* lcf->error_pages = NULL;
+ * lcf->try_files = NULL;
* lcf->client_body_path = NULL;
* lcf->regex = NULL;
* lcf->exact_match = 0;
@@ -3619,6 +3866,65 @@ ngx_http_core_error_page(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
static char *
+ngx_http_core_try_files(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
+{
+ ngx_http_core_loc_conf_t *clcf = conf;
+
+ ngx_str_t *value;
+ ngx_uint_t i, n;
+ ngx_http_try_file_t *tf;
+ ngx_http_script_compile_t sc;
+ ngx_http_core_main_conf_t *cmcf;
+
+ if (clcf->try_files) {
+ return "is duplicate";
+ }
+
+ cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
+
+ cmcf->try_files = 1;
+
+ tf = ngx_pcalloc(cf->pool, cf->args->nelts * sizeof(ngx_http_try_file_t));
+ if (tf == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ clcf->try_files = tf;
+
+ value = cf->args->elts;
+
+ for (i = 0; i < cf->args->nelts - 1; i++) {
+
+ tf[i].name = value[i + 1];
+
+ n = ngx_http_script_variables_count(&tf[i].name);
+
+ if (n) {
+ ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
+
+ sc.cf = cf;
+ sc.source = &tf[i].name;
+ sc.lengths = &tf[i].lengths;
+ sc.values = &tf[i].values;
+ sc.variables = n;
+ sc.complete_lengths = 1;
+ sc.complete_values = 1;
+
+ if (ngx_http_script_compile(&sc) != NGX_OK) {
+ return NGX_CONF_ERROR;
+ }
+
+ } else {
+ /* add trailing '\0' to length */
+ tf[i].name.len++;
+ }
+ }
+
+ return NGX_CONF_OK;
+}
+
+
+static char *
ngx_http_core_open_file_cache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
ngx_http_core_loc_conf_t *lcf = conf;
diff --git a/src/http/ngx_http_core_module.h b/src/http/ngx_http_core_module.h
index 032d07a6b..5be856123 100644
--- a/src/http/ngx_http_core_module.h
+++ b/src/http/ngx_http_core_module.h
@@ -81,6 +81,7 @@ typedef enum {
NGX_HTTP_ACCESS_PHASE,
NGX_HTTP_POST_ACCESS_PHASE,
+ NGX_HTTP_TRY_FILES_PHASE,
NGX_HTTP_CONTENT_PHASE,
NGX_HTTP_LOG_PHASE
@@ -129,6 +130,8 @@ typedef struct {
ngx_hash_keys_arrays_t *variables_keys;
+ ngx_uint_t try_files; /* unsigned try_files:1 */
+
ngx_http_phase_t phases[NGX_HTTP_LOG_PHASE + 1];
} ngx_http_core_main_conf_t;
@@ -238,6 +241,13 @@ typedef struct {
} ngx_http_err_page_t;
+typedef struct {
+ ngx_array_t *lengths;
+ ngx_array_t *values;
+ ngx_str_t name;
+} ngx_http_try_file_t;
+
+
struct ngx_http_core_loc_conf_s {
ngx_str_t name; /* location name */
@@ -328,6 +338,7 @@ struct ngx_http_core_loc_conf_s {
#endif
ngx_array_t *error_pages; /* error_page */
+ ngx_http_try_file_t *try_files; /* try_files */
ngx_path_t *client_body_temp_path; /* client_body_temp_path */
@@ -386,6 +397,8 @@ ngx_int_t ngx_http_core_access_phase(ngx_http_request_t *r,
ngx_http_phase_handler_t *ph);
ngx_int_t ngx_http_core_post_access_phase(ngx_http_request_t *r,
ngx_http_phase_handler_t *ph);
+ngx_int_t ngx_http_core_try_files_phase(ngx_http_request_t *r,
+ ngx_http_phase_handler_t *ph);
ngx_int_t ngx_http_core_content_phase(ngx_http_request_t *r,
ngx_http_phase_handler_t *ph);
diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c
index 2faa79195..1a774e434 100644
--- a/src/http/ngx_http_request.c
+++ b/src/http/ngx_http_request.c
@@ -215,7 +215,7 @@ ngx_http_init_connection(ngx_connection_t *c)
ngx_add_timer(rev, c->listening->post_accept_timeout);
- if (ngx_handle_read_event(rev, 0) == NGX_ERROR) {
+ if (ngx_handle_read_event(rev, 0) != NGX_OK) {
#if (NGX_STAT_STUB)
ngx_atomic_fetch_add(ngx_stat_reading, -1);
#endif
@@ -504,7 +504,7 @@ ngx_http_ssl_handshake(ngx_event_t *rev)
ngx_add_timer(rev, c->listening->post_accept_timeout);
}
- if (ngx_handle_read_event(rev, 0) == NGX_ERROR) {
+ if (ngx_handle_read_event(rev, 0) != NGX_OK) {
ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
}
@@ -1038,7 +1038,7 @@ ngx_http_read_request_header(ngx_http_request_t *r)
ngx_add_timer(rev, cscf->client_header_timeout);
}
- if (ngx_handle_read_event(rev, 0) == NGX_ERROR) {
+ if (ngx_handle_read_event(rev, 0) != NGX_OK) {
ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
return NGX_ERROR;
}
@@ -1883,8 +1883,6 @@ ngx_http_finalize_request(ngx_http_request_t *r, ngx_int_t rc)
"http wake parent request: \"%V?%V\"",
&pr->uri, &pr->args);
- ngx_http_run_posted_requests(c);
-
return;
}
@@ -1973,7 +1971,7 @@ ngx_http_set_write_handler(ngx_http_request_t *r)
ngx_add_timer(wev, clcf->send_timeout);
}
- if (ngx_handle_write_event(wev, clcf->send_lowat) == NGX_ERROR) {
+ if (ngx_handle_write_event(wev, clcf->send_lowat) != NGX_OK) {
ngx_http_close_request(r, 0);
return NGX_ERROR;
}
@@ -2014,7 +2012,7 @@ ngx_http_writer(ngx_http_request_t *r)
if (!wev->ready) {
ngx_add_timer(wev, clcf->send_timeout);
- if (ngx_handle_write_event(wev, clcf->send_lowat) == NGX_ERROR) {
+ if (ngx_handle_write_event(wev, clcf->send_lowat) != NGX_OK) {
ngx_http_close_request(r, 0);
}
@@ -2026,7 +2024,7 @@ ngx_http_writer(ngx_http_request_t *r)
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, wev->log, 0,
"http writer delayed");
- if (ngx_handle_write_event(wev, clcf->send_lowat) == NGX_ERROR) {
+ if (ngx_handle_write_event(wev, clcf->send_lowat) != NGX_OK) {
ngx_http_close_request(r, 0);
}
@@ -2050,7 +2048,7 @@ ngx_http_writer(ngx_http_request_t *r)
ngx_add_timer(wev, clcf->send_timeout);
}
- if (ngx_handle_write_event(wev, clcf->send_lowat) == NGX_ERROR) {
+ if (ngx_handle_write_event(wev, clcf->send_lowat) != NGX_OK) {
ngx_http_close_request(r, 0);
}
@@ -2085,9 +2083,7 @@ ngx_http_block_reading(ngx_http_request_t *r)
if ((ngx_event_flags & NGX_USE_LEVEL_EVENT)
&& r->connection->read->active)
{
- if (ngx_del_event(r->connection->read, NGX_READ_EVENT, 0)
- == NGX_ERROR)
- {
+ if (ngx_del_event(r->connection->read, NGX_READ_EVENT, 0) != NGX_OK) {
ngx_http_close_request(r, 0);
}
}
@@ -2149,7 +2145,7 @@ ngx_http_test_reading(ngx_http_request_t *r)
if ((ngx_event_flags & NGX_USE_LEVEL_EVENT) && rev->active) {
- if (ngx_del_event(rev, NGX_READ_EVENT, 0) == NGX_ERROR) {
+ if (ngx_del_event(rev, NGX_READ_EVENT, 0) != NGX_OK) {
ngx_http_close_request(r, 0);
}
}
@@ -2243,7 +2239,7 @@ ngx_http_set_keepalive(ngx_http_request_t *r)
ngx_add_timer(rev, clcf->keepalive_timeout);
- if (ngx_handle_read_event(rev, 0) == NGX_ERROR) {
+ if (ngx_handle_read_event(rev, 0) != NGX_OK) {
ngx_http_close_connection(c);
return;
}
@@ -2330,7 +2326,7 @@ ngx_http_set_keepalive(ngx_http_request_t *r)
rev->handler = ngx_http_keepalive_handler;
if (wev->active && (ngx_event_flags & NGX_USE_LEVEL_EVENT)) {
- if (ngx_del_event(wev, NGX_WRITE_EVENT, 0) == NGX_ERROR) {
+ if (ngx_del_event(wev, NGX_WRITE_EVENT, 0) != NGX_OK) {
ngx_http_close_connection(c);
return;
}
@@ -2455,7 +2451,7 @@ ngx_http_keepalive_handler(ngx_event_t *rev)
c->log_error = NGX_ERROR_INFO;
if (n == NGX_AGAIN) {
- if (ngx_handle_read_event(rev, 0) == NGX_ERROR) {
+ if (ngx_handle_read_event(rev, 0) != NGX_OK) {
ngx_http_close_connection(c);
}
@@ -2508,7 +2504,7 @@ ngx_http_set_lingering_close(ngx_http_request_t *r)
r->lingering_time = ngx_time() + (time_t) (clcf->lingering_time / 1000);
ngx_add_timer(rev, clcf->lingering_timeout);
- if (ngx_handle_read_event(rev, 0) == NGX_ERROR) {
+ if (ngx_handle_read_event(rev, 0) != NGX_OK) {
ngx_http_close_request(r, 0);
return;
}
@@ -2517,7 +2513,7 @@ ngx_http_set_lingering_close(ngx_http_request_t *r)
wev->handler = ngx_http_empty_handler;
if (wev->active && (ngx_event_flags & NGX_USE_LEVEL_EVENT)) {
- if (ngx_del_event(wev, NGX_WRITE_EVENT, 0) == NGX_ERROR) {
+ if (ngx_del_event(wev, NGX_WRITE_EVENT, 0) != NGX_OK) {
ngx_http_close_request(r, 0);
return;
}
@@ -2576,7 +2572,7 @@ ngx_http_lingering_close_handler(ngx_event_t *rev)
} while (rev->ready);
- if (ngx_handle_read_event(rev, 0) == NGX_ERROR) {
+ if (ngx_handle_read_event(rev, 0) != NGX_OK) {
ngx_http_close_request(r, 0);
return;
}
diff --git a/src/http/ngx_http_request_body.c b/src/http/ngx_http_request_body.c
index 97c57ce3a..96f59dd95 100644
--- a/src/http/ngx_http_request_body.c
+++ b/src/http/ngx_http_request_body.c
@@ -327,7 +327,7 @@ ngx_http_do_read_client_request_body(ngx_http_request_t *r)
clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
ngx_add_timer(c->read, clcf->client_body_timeout);
- if (ngx_handle_read_event(c->read, 0) == NGX_ERROR) {
+ if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
@@ -462,7 +462,7 @@ ngx_http_discard_request_body(ngx_http_request_t *r)
r->read_event_handler = ngx_http_read_discarded_request_body_handler;
- if (ngx_handle_read_event(rev, 0) == NGX_ERROR) {
+ if (ngx_handle_read_event(rev, 0) != NGX_OK) {
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
@@ -519,7 +519,7 @@ ngx_http_read_discarded_request_body_handler(ngx_http_request_t *r)
/* rc == NGX_AGAIN */
- if (ngx_handle_read_event(rev, 0) == NGX_ERROR) {
+ if (ngx_handle_read_event(rev, 0) != NGX_OK) {
c->error = 1;
ngx_http_finalize_request(r, rc);
return;
diff --git a/src/http/ngx_http_script.c b/src/http/ngx_http_script.c
index 55efee7af..dd9db62fb 100644
--- a/src/http/ngx_http_script.c
+++ b/src/http/ngx_http_script.c
@@ -430,20 +430,23 @@ ngx_http_script_copy_len_code(ngx_http_script_engine_t *e)
void
ngx_http_script_copy_code(ngx_http_script_engine_t *e)
{
+ u_char *p;
ngx_http_script_copy_code_t *code;
code = (ngx_http_script_copy_code_t *) e->ip;
+ p = e->pos;
+
if (!e->skip) {
- e->pos = ngx_copy(e->pos, e->ip + sizeof(ngx_http_script_copy_code_t),
+ e->pos = ngx_copy(p, e->ip + sizeof(ngx_http_script_copy_code_t),
code->len);
}
e->ip += sizeof(ngx_http_script_copy_code_t)
+ ((code->len + sizeof(uintptr_t) - 1) & ~(sizeof(uintptr_t) - 1));
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
- "http script copy: \"%V\"", &e->buf);
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
+ "http script copy: \"%*s\"", e->pos - p, p);
}
@@ -475,6 +478,7 @@ ngx_http_script_copy_var_len_code(ngx_http_script_engine_t *e)
void
ngx_http_script_copy_var_code(ngx_http_script_engine_t *e)
{
+ u_char *p;
ngx_http_variable_value_t *value;
ngx_http_script_var_code_t *code;
@@ -492,11 +496,12 @@ ngx_http_script_copy_var_code(ngx_http_script_engine_t *e)
}
if (value && !value->not_found) {
- e->pos = ngx_copy(e->pos, value->data, value->len);
+ p = e->pos;
+ e->pos = ngx_copy(p, value->data, value->len);
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP,
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP,
e->request->connection->log, 0,
- "http script var: \"%V\"", &e->buf);
+ "http script var: \"%*s\"", e->pos - p, p);
}
}
}
@@ -532,29 +537,32 @@ ngx_http_script_copy_capture_len_code(ngx_http_script_engine_t *e)
void
ngx_http_script_copy_capture_code(ngx_http_script_engine_t *e)
{
+ u_char *p;
ngx_http_script_copy_capture_code_t *code;
code = (ngx_http_script_copy_capture_code_t *) e->ip;
e->ip += sizeof(ngx_http_script_copy_capture_code_t);
+ p = e->pos;
+
if (code->n < e->ncaptures) {
if ((e->is_args || e->quote)
&& (e->request->quoted_uri || e->request->plus_in_uri))
{
- e->pos = (u_char *) ngx_escape_uri(e->pos,
+ e->pos = (u_char *) ngx_escape_uri(p,
&e->line.data[e->captures[code->n]],
e->captures[code->n + 1] - e->captures[code->n],
NGX_ESCAPE_ARGS);
} else {
- e->pos = ngx_copy(e->pos,
+ e->pos = ngx_copy(p,
&e->line.data[e->captures[code->n]],
e->captures[code->n + 1] - e->captures[code->n]);
}
}
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
- "http script capture: \"%V\"", &e->buf);
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
+ "http script capture: \"%*s\"", e->pos - p, p);
}
@@ -612,7 +620,7 @@ ngx_http_script_regex_start_code(ngx_http_script_engine_t *e)
rc = ngx_regex_exec(code->regex, &e->line, e->captures, code->ncaptures);
if (rc == NGX_REGEX_NO_MATCHED) {
- if (e->log) {
+ if (e->log || (r->connection->log->log_level & NGX_LOG_DEBUG_HTTP)) {
ngx_log_error(NGX_LOG_NOTICE, r->connection->log, 0,
"\"%V\" does not match \"%V\"",
&code->name, &e->line);
@@ -650,7 +658,7 @@ ngx_http_script_regex_start_code(ngx_http_script_engine_t *e)
return;
}
- if (e->log) {
+ if (e->log || (r->connection->log->log_level & NGX_LOG_DEBUG_HTTP)) {
ngx_log_error(NGX_LOG_NOTICE, r->connection->log, 0,
"\"%V\" matches \"%V\"", &code->name, &e->line);
}
@@ -786,7 +794,7 @@ ngx_http_script_regex_end_code(ngx_http_script_engine_t *e)
e->buf.len = e->pos - e->buf.data;
- if (e->log) {
+ if (e->log || (r->connection->log->log_level & NGX_LOG_DEBUG_HTTP)) {
ngx_log_error(NGX_LOG_NOTICE, r->connection->log, 0,
"rewritten redirect: \"%V\"", &e->buf);
}
@@ -828,7 +836,7 @@ ngx_http_script_regex_end_code(ngx_http_script_engine_t *e)
}
}
- if (e->log) {
+ if (e->log || (r->connection->log->log_level & NGX_LOG_DEBUG_HTTP)) {
ngx_log_error(NGX_LOG_NOTICE, r->connection->log, 0,
"rewritten data: \"%V\", args: \"%V\"",
&e->buf, &r->args);
@@ -928,8 +936,8 @@ ngx_http_script_equal_code(ngx_http_script_engine_t *e)
e->ip += sizeof(uintptr_t);
- if (val->len == res->len && ngx_strncmp(val->data, res->data, res->len)
- == 0)
+ if (val->len == res->len
+ && ngx_strncmp(val->data, res->data, res->len) == 0)
{
*res = ngx_http_variable_true_value;
return;
@@ -956,8 +964,8 @@ ngx_http_script_not_equal_code(ngx_http_script_engine_t *e)
e->ip += sizeof(uintptr_t);
- if (val->len == res->len && ngx_strncmp(val->data, res->data, res->len)
- == 0)
+ if (val->len == res->len
+ && ngx_strncmp(val->data, res->data, res->len) == 0)
{
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
"http script not equal: no");
@@ -1163,9 +1171,6 @@ ngx_http_script_set_var_code(ngx_http_script_engine_t *e)
ngx_http_request_t *r;
ngx_http_script_var_code_t *code;
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
- "http script set var");
-
code = (ngx_http_script_var_code_t *) e->ip;
e->ip += sizeof(ngx_http_script_var_code_t);
@@ -1179,6 +1184,20 @@ ngx_http_script_set_var_code(ngx_http_script_engine_t *e)
r->variables[code->index].no_cacheable = 0;
r->variables[code->index].not_found = 0;
r->variables[code->index].data = e->sp->data;
+
+#if (NGX_DEBUG)
+ {
+ ngx_http_variable_t *v;
+ ngx_http_core_main_conf_t *cmcf;
+
+ cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
+
+ v = cmcf->variables.elts;
+
+ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
+ "http script set $%V", &v[code->index].name);
+ }
+#endif
}
diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c
index bd7df2c83..fac45fe35 100644
--- a/src/http/ngx_http_upstream.c
+++ b/src/http/ngx_http_upstream.c
@@ -20,19 +20,24 @@ static ngx_int_t ngx_http_upstream_reinit(ngx_http_request_t *r,
ngx_http_upstream_t *u);
static void ngx_http_upstream_send_request(ngx_http_request_t *r,
ngx_http_upstream_t *u);
-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_request_handler(ngx_http_request_t *r,
+ ngx_http_upstream_t *u);
+static void ngx_http_upstream_process_header(ngx_http_request_t *r,
+ ngx_http_upstream_t *u);
static ngx_int_t ngx_http_upstream_test_next(ngx_http_request_t *r,
ngx_http_upstream_t *u);
static ngx_int_t ngx_http_upstream_intercept_errors(ngx_http_request_t *r,
ngx_http_upstream_t *u);
static ngx_int_t ngx_http_upstream_test_connect(ngx_connection_t *c);
-static void ngx_http_upstream_process_body_in_memory(ngx_event_t *rev);
+static void ngx_http_upstream_process_body_in_memory(ngx_http_request_t *r,
+ ngx_http_upstream_t *u);
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_upstream(ngx_event_t *ev);
+static void
+ ngx_http_upstream_process_non_buffered_upstream(ngx_http_request_t *r,
+ ngx_http_upstream_t *u);
static void
ngx_http_upstream_process_non_buffered_request(ngx_http_request_t *r,
ngx_uint_t do_write);
@@ -40,11 +45,13 @@ 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_upstream(ngx_event_t *rev);
+static void ngx_http_upstream_process_upstream(ngx_http_request_t *r,
+ ngx_http_upstream_t *u);
static void ngx_http_upstream_process_request(ngx_http_request_t *r);
static void ngx_http_upstream_store(ngx_http_request_t *r,
ngx_http_upstream_t *u);
-static void ngx_http_upstream_dummy_handler(ngx_event_t *wev);
+static void ngx_http_upstream_dummy_handler(ngx_http_request_t *r,
+ ngx_http_upstream_t *u);
static void ngx_http_upstream_next(ngx_http_request_t *r,
ngx_http_upstream_t *u, ngx_uint_t ft_type);
static void ngx_http_upstream_cleanup(void *data);
@@ -89,6 +96,8 @@ static ngx_int_t ngx_http_upstream_status_variable(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data);
static ngx_int_t ngx_http_upstream_response_time_variable(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data);
+static ngx_int_t ngx_http_upstream_response_length_variable(
+ ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data);
static char *ngx_http_upstream(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy);
static char *ngx_http_upstream_server(ngx_conf_t *cf, ngx_command_t *cmd,
@@ -289,6 +298,10 @@ static ngx_http_variable_t ngx_http_upstream_vars[] = {
ngx_http_upstream_response_time_variable, 0,
NGX_HTTP_VAR_NOHASH|NGX_HTTP_VAR_NOCACHEABLE, 0 },
+ { ngx_string("upstream_response_length"), NULL,
+ ngx_http_upstream_response_length_variable, 0,
+ NGX_HTTP_VAR_NOHASH|NGX_HTTP_VAR_NOCACHEABLE, 0 },
+
{ ngx_null_string, NULL, NULL, 0, 0, 0 }
};
@@ -538,10 +551,10 @@ ngx_http_upstream_handler(ngx_event_t *ev)
"http upstream request: \"%V?%V\"", &r->uri, &r->args);
if (ev->write) {
- u->write_event_handler(ev);
+ u->write_event_handler(r, u);
} else {
- u->read_event_handler(ev);
+ u->read_event_handler(r, u);
}
ngx_http_run_posted_requests(c);
@@ -996,8 +1009,7 @@ ngx_http_upstream_send_request(ngx_http_request_t *r, ngx_http_upstream_t *u)
if (rc == NGX_AGAIN) {
ngx_add_timer(c->write, u->conf->send_timeout);
- if (ngx_handle_write_event(c->write, u->conf->send_lowat) == NGX_ERROR)
- {
+ if (ngx_handle_write_event(c->write, u->conf->send_lowat) != NGX_OK) {
ngx_http_upstream_finalize_request(r, u,
NGX_HTTP_INTERNAL_SERVER_ERROR);
return;
@@ -1034,14 +1046,14 @@ ngx_http_upstream_send_request(ngx_http_request_t *r, ngx_http_upstream_t *u)
* it's better to do here because we postpone header buffer allocation
*/
- ngx_http_upstream_process_header(c->read);
+ ngx_http_upstream_process_header(r, u);
return;
}
#endif
u->write_event_handler = ngx_http_upstream_dummy_handler;
- if (ngx_handle_write_event(c->write, 0) == NGX_ERROR) {
+ if (ngx_handle_write_event(c->write, 0) != NGX_OK) {
ngx_http_upstream_finalize_request(r, u,
NGX_HTTP_INTERNAL_SERVER_ERROR);
return;
@@ -1050,20 +1062,17 @@ ngx_http_upstream_send_request(ngx_http_request_t *r, ngx_http_upstream_t *u)
static void
-ngx_http_upstream_send_request_handler(ngx_event_t *wev)
+ngx_http_upstream_send_request_handler(ngx_http_request_t *r,
+ ngx_http_upstream_t *u)
{
- ngx_connection_t *c;
- ngx_http_request_t *r;
- ngx_http_upstream_t *u;
+ ngx_connection_t *c;
- c = wev->data;
- r = c->data;
- u = r->upstream;
+ c = u->peer.connection;
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, wev->log, 0,
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"http upstream send request handler");
- if (wev->timedout) {
+ if (c->write->timedout) {
ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_TIMEOUT);
return;
}
@@ -1080,7 +1089,7 @@ ngx_http_upstream_send_request_handler(ngx_event_t *wev)
if (u->header_sent) {
u->write_event_handler = ngx_http_upstream_dummy_handler;
- (void) ngx_handle_write_event(wev, 0);
+ (void) ngx_handle_write_event(c->write, 0);
return;
}
@@ -1090,7 +1099,7 @@ ngx_http_upstream_send_request_handler(ngx_event_t *wev)
static void
-ngx_http_upstream_process_header(ngx_event_t *rev)
+ngx_http_upstream_process_header(ngx_http_request_t *r, ngx_http_upstream_t *u)
{
ssize_t n;
ngx_int_t rc;
@@ -1099,21 +1108,17 @@ ngx_http_upstream_process_header(ngx_event_t *rev)
ngx_list_part_t *part;
ngx_table_elt_t *h;
ngx_connection_t *c;
- ngx_http_request_t *r;
- ngx_http_upstream_t *u;
ngx_http_upstream_header_t *hh;
ngx_http_upstream_main_conf_t *umcf;
- c = rev->data;
- r = c->data;
- u = r->upstream;
+ c = u->peer.connection;
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0,
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
"http upstream process header");
c->log->action = "reading response header from upstream";
- if (rev->timedout) {
+ if (c->read->timedout) {
ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_TIMEOUT);
return;
}
@@ -1164,7 +1169,7 @@ ngx_http_upstream_process_header(ngx_event_t *rev)
ngx_add_timer(rev, u->read_timeout);
#endif
- if (ngx_handle_read_event(rev, 0) == NGX_ERROR) {
+ if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
ngx_http_upstream_finalize_request(r, u,
NGX_HTTP_INTERNAL_SERVER_ERROR);
return;
@@ -1174,7 +1179,7 @@ ngx_http_upstream_process_header(ngx_event_t *rev)
}
if (n == 0) {
- ngx_log_error(NGX_LOG_ERR, rev->log, 0,
+ ngx_log_error(NGX_LOG_ERR, c->log, 0,
"upstream prematurely closed connection");
}
@@ -1196,7 +1201,7 @@ ngx_http_upstream_process_header(ngx_event_t *rev)
if (rc == NGX_AGAIN) {
if (u->buffer.pos == u->buffer.end) {
- ngx_log_error(NGX_LOG_ERR, rev->log, 0,
+ ngx_log_error(NGX_LOG_ERR, c->log, 0,
"upstream sent too big header");
ngx_http_upstream_next(r, u,
@@ -1380,6 +1385,8 @@ ngx_http_upstream_process_header(ngx_event_t *rev)
if (n) {
u->buffer.last -= n;
+ u->state->response_length += n;
+
if (u->input_filter(u->input_filter_ctx, n) == NGX_ERROR) {
ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
return;
@@ -1393,7 +1400,7 @@ ngx_http_upstream_process_header(ngx_event_t *rev)
u->read_event_handler = ngx_http_upstream_process_body_in_memory;
- ngx_http_upstream_process_body_in_memory(rev);
+ ngx_http_upstream_process_body_in_memory(r, u);
}
@@ -1537,18 +1544,17 @@ ngx_http_upstream_test_connect(ngx_connection_t *c)
static void
-ngx_http_upstream_process_body_in_memory(ngx_event_t *rev)
+ngx_http_upstream_process_body_in_memory(ngx_http_request_t *r,
+ ngx_http_upstream_t *u)
{
- size_t size;
- ssize_t n;
- ngx_buf_t *b;
- ngx_connection_t *c;
- ngx_http_request_t *r;
- ngx_http_upstream_t *u;
+ size_t size;
+ ssize_t n;
+ ngx_buf_t *b;
+ ngx_event_t *rev;
+ ngx_connection_t *c;
- c = rev->data;
- r = c->data;
- u = r->upstream;
+ c = u->peer.connection;
+ rev = c->read;
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
"http upstream process body on memory");
@@ -1583,6 +1589,8 @@ ngx_http_upstream_process_body_in_memory(ngx_event_t *rev)
return;
}
+ u->state->response_length += n;
+
if (u->input_filter(u->input_filter_ctx, n) == NGX_ERROR) {
ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
return;
@@ -1593,7 +1601,7 @@ ngx_http_upstream_process_body_in_memory(ngx_event_t *rev)
}
}
- if (ngx_handle_read_event(rev, 0) == NGX_ERROR) {
+ if (ngx_handle_read_event(rev, 0) != NGX_OK) {
ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
return;
}
@@ -1611,7 +1619,7 @@ static void
ngx_http_upstream_send_response(ngx_http_request_t *r, ngx_http_upstream_t *u)
{
int tcp_nodelay;
- ssize_t size;
+ ssize_t n;
ngx_int_t rc;
ngx_event_pipe_t *p;
ngx_connection_t *c;
@@ -1683,12 +1691,14 @@ ngx_http_upstream_send_response(ngx_http_request_t *r, ngx_http_upstream_t *u)
c->tcp_nodelay = NGX_TCP_NODELAY_SET;
}
- size = u->buffer.last - u->buffer.pos;
+ n = u->buffer.last - u->buffer.pos;
- if (size) {
+ if (n) {
u->buffer.last = u->buffer.pos;
- if (u->input_filter(u->input_filter_ctx, size) == NGX_ERROR) {
+ u->state->response_length += n;
+
+ if (u->input_filter(u->input_filter_ctx, n) == NGX_ERROR) {
ngx_http_upstream_finalize_request(r, u, 0);
return;
}
@@ -1705,8 +1715,7 @@ ngx_http_upstream_send_response(ngx_http_request_t *r, ngx_http_upstream_t *u)
}
if (u->peer.connection->read->ready) {
- ngx_http_upstream_process_non_buffered_upstream(
- u->peer.connection->read);
+ ngx_http_upstream_process_non_buffered_upstream(r, u);
}
}
@@ -1839,7 +1848,7 @@ ngx_http_upstream_send_response(ngx_http_request_t *r, ngx_http_upstream_t *u)
u->read_event_handler = ngx_http_upstream_process_upstream;
r->write_event_handler = ngx_http_upstream_process_downstream;
- ngx_http_upstream_process_upstream(u->peer.connection->read);
+ ngx_http_upstream_process_upstream(r, u);
}
@@ -1871,22 +1880,19 @@ ngx_http_upstream_process_non_buffered_downstream(ngx_http_request_t *r)
static void
-ngx_http_upstream_process_non_buffered_upstream(ngx_event_t *rev)
+ngx_http_upstream_process_non_buffered_upstream(ngx_http_request_t *r,
+ ngx_http_upstream_t *u)
{
- ngx_connection_t *c;
- ngx_http_request_t *r;
- ngx_http_upstream_t *u;
+ ngx_connection_t *c;
- c = rev->data;
- r = c->data;
- u = r->upstream;
+ c = u->peer.connection;
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
"http upstream process non buffered upstream");
c->log->action = "reading upstream";
- if (rev->timedout) {
+ if (c->read->timedout) {
ngx_connection_error(c, NGX_ETIMEDOUT, "upstream timed out");
ngx_http_upstream_finalize_request(r, u, 0);
return;
@@ -1966,6 +1972,8 @@ ngx_http_upstream_process_non_buffered_request(ngx_http_request_t *r,
}
if (n > 0) {
+ u->state->response_length += n;
+
if (u->input_filter(u->input_filter_ctx, n) == NGX_ERROR) {
ngx_http_upstream_finalize_request(r, u, 0);
return;
@@ -2142,31 +2150,26 @@ ngx_http_upstream_process_downstream(ngx_http_request_t *r)
static void
-ngx_http_upstream_process_upstream(ngx_event_t *rev)
+ngx_http_upstream_process_upstream(ngx_http_request_t *r,
+ ngx_http_upstream_t *u)
{
- ngx_connection_t *c;
- ngx_event_pipe_t *p;
- ngx_http_request_t *r;
- ngx_http_upstream_t *u;
+ ngx_connection_t *c;
- c = rev->data;
- r = c->data;
- u = r->upstream;
- p = u->pipe;
+ c = u->peer.connection;
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
"http upstream process upstream");
c->log->action = "reading upstream";
- if (rev->timedout) {
- p->upstream_error = 1;
+ if (c->read->timedout) {
+ u->pipe->upstream_error = 1;
ngx_connection_error(c, NGX_ETIMEDOUT, "upstream timed out");
} else {
c = r->connection;
- if (ngx_event_pipe(p, 0) == NGX_ABORT) {
+ if (ngx_event_pipe(u->pipe, 0) == NGX_ABORT) {
if (c->destroyed) {
return;
@@ -2299,9 +2302,11 @@ ngx_http_upstream_store(ngx_http_request_t *r, ngx_http_upstream_t *u)
}
ext.access = u->conf->store_access;
+ ext.path_access = u->conf->store_access;
ext.time = -1;
ext.create_path = 1;
ext.delete_file = 1;
+ ext.log_rename_error = 1;
ext.log = r->connection->log;
if (u->headers_in.last_modified) {
@@ -2337,9 +2342,9 @@ ngx_http_upstream_store(ngx_http_request_t *r, ngx_http_upstream_t *u)
static void
-ngx_http_upstream_dummy_handler(ngx_event_t *wev)
+ngx_http_upstream_dummy_handler(ngx_http_request_t *r, ngx_http_upstream_t *u)
{
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, wev->log, 0,
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"http upstream dummy handler");
}
@@ -2489,6 +2494,10 @@ ngx_http_upstream_finalize_request(ngx_http_request_t *r,
tp = ngx_timeofday();
u->state->response_sec = tp->sec - u->state->response_sec;
u->state->response_msec = tp->msec - u->state->response_msec;
+
+ if (u->pipe) {
+ u->state->response_length = u->pipe->read_length;
+ }
}
u->finalize_request(r, rc);
@@ -3132,6 +3141,66 @@ ngx_http_upstream_response_time_variable(ngx_http_request_t *r,
}
+static ngx_int_t
+ngx_http_upstream_response_length_variable(ngx_http_request_t *r,
+ ngx_http_variable_value_t *v, uintptr_t data)
+{
+ u_char *p;
+ size_t len;
+ ngx_uint_t i;
+ ngx_http_upstream_state_t *state;
+
+ v->valid = 1;
+ v->no_cacheable = 0;
+ v->not_found = 0;
+
+ if (r->upstream_states == NULL || r->upstream_states->nelts == 0) {
+ v->not_found = 1;
+ return NGX_OK;
+ }
+
+ len = r->upstream_states->nelts * (NGX_OFF_T_LEN + 2);
+
+ p = ngx_pnalloc(r->pool, len);
+ if (p == NULL) {
+ return NGX_ERROR;
+ }
+
+ v->data = p;
+
+ i = 0;
+ state = r->upstream_states->elts;
+
+ for ( ;; ) {
+ p = ngx_sprintf(p, "%O", state[i].response_length);
+
+ if (++i == r->upstream_states->nelts) {
+ break;
+ }
+
+ if (state[i].peer) {
+ *p++ = ',';
+ *p++ = ' ';
+
+ } else {
+ *p++ = ' ';
+ *p++ = ':';
+ *p++ = ' ';
+
+ if (++i == r->upstream_states->nelts) {
+ break;
+ }
+
+ continue;
+ }
+ }
+
+ v->len = p - v->data;
+
+ return NGX_OK;
+}
+
+
ngx_int_t
ngx_http_upstream_header_variable(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data)
diff --git a/src/http/ngx_http_upstream.h b/src/http/ngx_http_upstream.h
index 8d65a35b5..b6f2161d4 100644
--- a/src/http/ngx_http_upstream.h
+++ b/src/http/ngx_http_upstream.h
@@ -45,6 +45,7 @@ typedef struct {
ngx_uint_t status;
time_t response_sec;
ngx_uint_t response_msec;
+ off_t response_length;
ngx_str_t *peer;
} ngx_http_upstream_state_t;
@@ -144,8 +145,6 @@ typedef struct {
ngx_array_t *hide_headers;
ngx_array_t *pass_headers;
- ngx_str_t schema;
-
ngx_array_t *store_lengths;
ngx_array_t *store_values;
@@ -216,9 +215,13 @@ typedef struct {
} ngx_http_upstream_resolved_t;
+typedef void (*ngx_http_upstream_handler_pt)(ngx_http_request_t *r,
+ ngx_http_upstream_t *u);
+
+
struct ngx_http_upstream_s {
- ngx_event_handler_pt read_event_handler;
- ngx_event_handler_pt write_event_handler;
+ ngx_http_upstream_handler_pt read_event_handler;
+ ngx_http_upstream_handler_pt write_event_handler;
ngx_peer_connection_t peer;
diff --git a/src/mail/ngx_mail_auth_http_module.c b/src/mail/ngx_mail_auth_http_module.c
index 5b9f04238..ec1dcdc00 100644
--- a/src/mail/ngx_mail_auth_http_module.c
+++ b/src/mail/ngx_mail_auth_http_module.c
@@ -268,7 +268,7 @@ ngx_mail_auth_http_write_handler(ngx_event_t *wev)
ngx_del_timer(wev);
}
- if (ngx_handle_write_event(wev, 0) == NGX_ERROR) {
+ if (ngx_handle_write_event(wev, 0) != NGX_OK) {
ngx_close_connection(c);
ngx_destroy_pool(ctx->pool);
ngx_mail_session_internal_server_error(s);
@@ -894,7 +894,7 @@ ngx_mail_auth_sleep_handler(ngx_event_t *rev)
return;
}
- if (ngx_handle_read_event(rev, 0) == NGX_ERROR) {
+ if (ngx_handle_read_event(rev, 0) != NGX_OK) {
ngx_mail_close_connection(c);
}
@@ -902,7 +902,7 @@ ngx_mail_auth_sleep_handler(ngx_event_t *rev)
}
if (rev->active) {
- if (ngx_handle_read_event(rev, 0) == NGX_ERROR) {
+ if (ngx_handle_read_event(rev, 0) != NGX_OK) {
ngx_mail_close_connection(c);
}
}
@@ -1102,7 +1102,7 @@ ngx_mail_auth_http_block_read(ngx_event_t *rev)
ngx_log_debug0(NGX_LOG_DEBUG_MAIL, rev->log, 0,
"mail auth http block read");
- if (ngx_handle_read_event(rev, 0) == NGX_ERROR) {
+ if (ngx_handle_read_event(rev, 0) != NGX_OK) {
c = rev->data;
s = c->data;
diff --git a/src/mail/ngx_mail_handler.c b/src/mail/ngx_mail_handler.c
index 6915dc94f..e86877f1a 100644
--- a/src/mail/ngx_mail_handler.c
+++ b/src/mail/ngx_mail_handler.c
@@ -513,7 +513,7 @@ ngx_mail_send(ngx_event_t *wev)
}
if (s->out.len == 0) {
- if (ngx_handle_write_event(c->write, 0) == NGX_ERROR) {
+ if (ngx_handle_write_event(c->write, 0) != NGX_OK) {
ngx_mail_close_connection(c);
}
@@ -552,7 +552,7 @@ ngx_mail_send(ngx_event_t *wev)
ngx_add_timer(c->write, cscf->timeout);
- if (ngx_handle_write_event(c->write, 0) == NGX_ERROR) {
+ if (ngx_handle_write_event(c->write, 0) != NGX_OK) {
ngx_mail_close_connection(c);
return;
}
@@ -579,7 +579,7 @@ ngx_mail_read_command(ngx_mail_session_t *s, ngx_connection_t *c)
}
if (n == NGX_AGAIN) {
- if (ngx_handle_read_event(c->read, 0) == NGX_ERROR) {
+ if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
ngx_mail_session_internal_server_error(s);
return NGX_ERROR;
}
diff --git a/src/mail/ngx_mail_imap_handler.c b/src/mail/ngx_mail_imap_handler.c
index f8ca4f689..780c38fbb 100644
--- a/src/mail/ngx_mail_imap_handler.c
+++ b/src/mail/ngx_mail_imap_handler.c
@@ -46,7 +46,7 @@ ngx_mail_imap_init_session(ngx_mail_session_t *s, ngx_connection_t *c)
ngx_add_timer(c->read, cscf->timeout);
- if (ngx_handle_read_event(c->read, 0) == NGX_ERROR) {
+ if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
ngx_mail_close_connection(c);
}
diff --git a/src/mail/ngx_mail_pop3_handler.c b/src/mail/ngx_mail_pop3_handler.c
index 51763613d..c763f04ff 100644
--- a/src/mail/ngx_mail_pop3_handler.c
+++ b/src/mail/ngx_mail_pop3_handler.c
@@ -67,7 +67,7 @@ ngx_mail_pop3_init_session(ngx_mail_session_t *s, ngx_connection_t *c)
ngx_add_timer(c->read, cscf->timeout);
- if (ngx_handle_read_event(c->read, 0) == NGX_ERROR) {
+ if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
ngx_mail_close_connection(c);
}
diff --git a/src/mail/ngx_mail_proxy_module.c b/src/mail/ngx_mail_proxy_module.c
index 8890002d1..bd2bcf9ea 100644
--- a/src/mail/ngx_mail_proxy_module.c
+++ b/src/mail/ngx_mail_proxy_module.c
@@ -201,7 +201,7 @@ ngx_mail_proxy_block_read(ngx_event_t *rev)
ngx_log_debug0(NGX_LOG_DEBUG_MAIL, rev->log, 0, "mail proxy block read");
- if (ngx_handle_read_event(rev, 0) == NGX_ERROR) {
+ if (ngx_handle_read_event(rev, 0) != NGX_OK) {
c = rev->data;
s = c->data;
@@ -664,7 +664,7 @@ ngx_mail_proxy_dummy_handler(ngx_event_t *wev)
ngx_log_debug0(NGX_LOG_DEBUG_MAIL, wev->log, 0, "mail proxy dummy handler");
- if (ngx_handle_write_event(wev, 0) == NGX_ERROR) {
+ if (ngx_handle_write_event(wev, 0) != NGX_OK) {
c = wev->data;
s = c->data;
@@ -947,22 +947,22 @@ ngx_mail_proxy_handler(ngx_event_t *ev)
return;
}
- if (ngx_handle_write_event(dst->write, 0) == NGX_ERROR) {
+ if (ngx_handle_write_event(dst->write, 0) != NGX_OK) {
ngx_mail_proxy_close_session(s);
return;
}
- if (ngx_handle_read_event(dst->read, 0) == NGX_ERROR) {
+ if (ngx_handle_read_event(dst->read, 0) != NGX_OK) {
ngx_mail_proxy_close_session(s);
return;
}
- if (ngx_handle_write_event(src->write, 0) == NGX_ERROR) {
+ if (ngx_handle_write_event(src->write, 0) != NGX_OK) {
ngx_mail_proxy_close_session(s);
return;
}
- if (ngx_handle_read_event(src->read, 0) == NGX_ERROR) {
+ if (ngx_handle_read_event(src->read, 0) != NGX_OK) {
ngx_mail_proxy_close_session(s);
return;
}
diff --git a/src/mail/ngx_mail_smtp_handler.c b/src/mail/ngx_mail_smtp_handler.c
index 1a89f1749..46247239c 100644
--- a/src/mail/ngx_mail_smtp_handler.c
+++ b/src/mail/ngx_mail_smtp_handler.c
@@ -228,7 +228,7 @@ ngx_mail_smtp_greeting(ngx_mail_session_t *s, ngx_connection_t *c)
timeout = sscf->greeting_delay ? sscf->greeting_delay : cscf->timeout;
ngx_add_timer(c->read, timeout);
- if (ngx_handle_read_event(c->read, 0) == NGX_ERROR) {
+ if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
ngx_mail_close_connection(c);
}
@@ -270,7 +270,7 @@ ngx_mail_smtp_invalid_pipelining(ngx_event_t *rev)
ngx_add_timer(c->read, cscf->timeout);
- if (ngx_handle_read_event(c->read, 0) == NGX_ERROR) {
+ if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
ngx_mail_close_connection(c);
return;
}
@@ -819,7 +819,7 @@ ngx_mail_smtp_discard_command(ngx_mail_session_t *s, ngx_connection_t *c,
}
if (n == NGX_AGAIN) {
- if (ngx_handle_read_event(c->read, 0) == NGX_ERROR) {
+ if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
ngx_mail_session_internal_server_error(s);
return NGX_ERROR;
}
diff --git a/src/os/unix/ngx_errno.h b/src/os/unix/ngx_errno.h
index c50d7879a..967e15dec 100644
--- a/src/os/unix/ngx_errno.h
+++ b/src/os/unix/ngx_errno.h
@@ -23,6 +23,7 @@ typedef int ngx_err_t;
#define NGX_EACCES EACCES
#define NGX_EBUSY EBUSY
#define NGX_EEXIST EEXIST
+#define NGX_EXDEV EXDEV
#define NGX_ENOTDIR ENOTDIR
#define NGX_EISDIR EISDIR
#define NGX_EINVAL EINVAL