summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--auto/modules1
-rw-r--r--docs/xml/nginx/changes.xml32
-rw-r--r--src/core/nginx.h2
-rw-r--r--src/core/ngx_file.c37
-rw-r--r--src/core/ngx_file.h2
-rw-r--r--src/http/modules/ngx_http_autoindex_module.c4
-rw-r--r--src/http/modules/ngx_http_dav_module.c249
-rw-r--r--src/http/modules/ngx_http_fastcgi_module.c2
-rw-r--r--src/http/modules/ngx_http_geo_module.c2
-rw-r--r--src/http/modules/ngx_http_gzip_filter_module.c2
-rw-r--r--src/http/modules/ngx_http_index_module.c4
-rw-r--r--src/http/modules/ngx_http_map_module.c2
-rw-r--r--src/http/modules/ngx_http_proxy_module.c14
-rw-r--r--src/http/modules/ngx_http_referer_module.c2
-rw-r--r--src/http/modules/ngx_http_rewrite_module.c46
-rw-r--r--src/http/modules/ngx_http_ssi_filter_module.c8
-rw-r--r--src/http/modules/ngx_http_ssl_module.c8
-rw-r--r--src/http/modules/ngx_http_userid_filter_module.c4
-rw-r--r--src/http/modules/perl/ngx_http_perl_module.c6
-rw-r--r--src/http/ngx_http.c2
-rw-r--r--src/http/ngx_http_core_module.c20
-rw-r--r--src/http/ngx_http_header_filter_module.c10
-rw-r--r--src/http/ngx_http_parse.c8
-rw-r--r--src/http/ngx_http_request.c13
-rw-r--r--src/http/ngx_http_request.h10
-rw-r--r--src/http/ngx_http_request_body.c1
-rw-r--r--src/http/ngx_http_script.c18
-rw-r--r--src/http/ngx_http_script.h8
-rw-r--r--src/http/ngx_http_special_response.c34
-rw-r--r--src/http/ngx_http_upstream.c8
-rw-r--r--src/http/ngx_http_variables.c112
-rw-r--r--src/http/ngx_http_variables.h5
-rw-r--r--src/os/unix/ngx_errno.h1
-rw-r--r--src/os/win32/ngx_errno.h1
34 files changed, 532 insertions, 146 deletions
diff --git a/auto/modules b/auto/modules
index 670404649..ffe0749e2 100644
--- a/auto/modules
+++ b/auto/modules
@@ -128,6 +128,7 @@ fi
HTTP_MODULES="$HTTP_MODULES $HTTP_STATIC_MODULE"
if [ $HTTP_DAV = YES ]; then
+ have=NGX_HTTP_DAV . auto/have
HTTP_MODULES="$HTTP_MODULES $HTTP_DAV_MODULE"
HTTP_SRCS="$HTTP_SRCS $HTTP_DAV_SRCS"
fi
diff --git a/docs/xml/nginx/changes.xml b/docs/xml/nginx/changes.xml
index 99e89f80d..20e5d0c5b 100644
--- a/docs/xml/nginx/changes.xml
+++ b/docs/xml/nginx/changes.xml
@@ -9,6 +9,38 @@
<title lang="en">nginx changelog</title>
+<changes ver="0.3.40" date="19.04.2006">
+
+<change type="feature">
+<para lang="ru">
+модуль ngx_http_dav_module поддерживает метод MKCOL.
+</para>
+<para lang="en">
+the ngx_http_dav_module supports the MKCOL method.
+</para>
+</change>
+
+<change type="feature">
+<para lang="ru">
+директива create_full_put_path.
+</para>
+<para lang="en">
+the "create_full_put_path" directive.
+</para>
+</change>
+
+<change type="feature">
+<para lang="ru">
+переменная $limit_rate.
+</para>
+<para lang="en">
+the "$limit_rate" variable.
+</para>
+</change>
+
+</changes>
+
+
<changes ver="0.3.39" date="17.04.2006">
<change type="feature">
diff --git a/src/core/nginx.h b/src/core/nginx.h
index 1da91b729..2e13e6be4 100644
--- a/src/core/nginx.h
+++ b/src/core/nginx.h
@@ -8,7 +8,7 @@
#define _NGINX_H_INCLUDED_
-#define NGINX_VER "nginx/0.3.39"
+#define NGINX_VER "nginx/0.3.40"
#define NGINX_VAR "NGINX"
#define NGX_OLDPID_EXT ".oldbin"
diff --git a/src/core/ngx_file.c b/src/core/ngx_file.c
index 0a2c37190..c3c4592a7 100644
--- a/src/core/ngx_file.c
+++ b/src/core/ngx_file.c
@@ -25,8 +25,12 @@ ngx_write_chain_to_temp_file(ngx_temp_file_t *tf, ngx_chain_t *chain)
return rc;
}
- if (!tf->persistent && tf->warn) {
- ngx_log_error(NGX_LOG_WARN, tf->file.log, 0, tf->warn);
+ if (tf->log_level == NGX_LOG_NOTICE) {
+ ngx_log_error(NGX_LOG_NOTICE, tf->file.log, 0, tf->warn);
+
+ } else if (tf->log_level == NGX_LOG_WARN) {
+ ngx_log_error(NGX_LOG_WARN, tf->file.log, 0, "%s %V",
+ tf->warn, &tf->file.name);
}
}
@@ -182,6 +186,35 @@ ngx_create_path(ngx_file_t *file, ngx_path_t *path)
}
+ngx_err_t
+ngx_create_full_path(u_char *dir)
+{
+ u_char *p, ch;
+ ngx_err_t err;
+
+ for (p = dir + 1; *p; p++) {
+ ch = *p;
+
+ if (ch != '/') {
+ continue;
+ }
+
+ *p = '\0';
+
+ if (ngx_create_dir(dir) == NGX_FILE_ERROR) {
+ err = ngx_errno;
+ if (err != NGX_EEXIST) {
+ return err;
+ }
+ }
+
+ *p = '/';
+ }
+
+ return 0;
+}
+
+
void
ngx_init_temp_number(void)
{
diff --git a/src/core/ngx_file.h b/src/core/ngx_file.h
index 488c10ad6..3ec305612 100644
--- a/src/core/ngx_file.h
+++ b/src/core/ngx_file.h
@@ -51,6 +51,7 @@ typedef struct {
ngx_uint_t mode;
+ unsigned log_level:8;
unsigned persistent:1;
} ngx_temp_file_t;
@@ -60,6 +61,7 @@ ngx_int_t ngx_create_temp_file(ngx_file_t *file, ngx_path_t *path,
ngx_pool_t *pool, ngx_uint_t persistent,ngx_uint_t mode);
void ngx_create_hashed_filename(ngx_file_t *file, ngx_path_t *path);
ngx_int_t ngx_create_path(ngx_file_t *file, ngx_path_t *path);
+ngx_err_t ngx_create_full_path(u_char *dir);
ngx_int_t ngx_add_path(ngx_conf_t *cf, ngx_path_t **slot);
ngx_int_t ngx_create_pathes(ngx_cycle_t *cycle, ngx_uid_t user);
diff --git a/src/http/modules/ngx_http_autoindex_module.c b/src/http/modules/ngx_http_autoindex_module.c
index 8e2ad0255..e1a0e86c6 100644
--- a/src/http/modules/ngx_http_autoindex_module.c
+++ b/src/http/modules/ngx_http_autoindex_module.c
@@ -162,6 +162,10 @@ ngx_http_autoindex_handler(ngx_http_request_t *r)
return NGX_DECLINED;
}
+ if (r->method != NGX_HTTP_GET && r->method != NGX_HTTP_HEAD) {
+ return NGX_DECLINED;
+ }
+
alcf = ngx_http_get_module_loc_conf(r, ngx_http_autoindex_module);
if (!alcf->enable) {
diff --git a/src/http/modules/ngx_http_dav_module.c b/src/http/modules/ngx_http_dav_module.c
index 1b982044f..e60b8cf34 100644
--- a/src/http/modules/ngx_http_dav_module.c
+++ b/src/http/modules/ngx_http_dav_module.c
@@ -13,11 +13,15 @@
typedef struct {
ngx_uint_t methods;
+ ngx_flag_t create_full_put_path;
} ngx_http_dav_loc_conf_t;
static ngx_int_t ngx_http_dav_handler(ngx_http_request_t *r);
static void ngx_http_dav_put_handler(ngx_http_request_t *r);
+static ngx_int_t ngx_http_dav_error(ngx_http_request_t *, ngx_err_t err,
+ ngx_int_t not_found, char *failed, u_char *path);
+static ngx_int_t ngx_http_dav_location(ngx_http_request_t *r, u_char *path);
static void *ngx_http_dav_create_loc_conf(ngx_conf_t *cf);
static char *ngx_http_dav_merge_loc_conf(ngx_conf_t *cf,
void *parent, void *child);
@@ -28,6 +32,7 @@ static ngx_conf_bitmask_t ngx_http_dav_methods_mask[] = {
{ ngx_string("off"), NGX_HTTP_DAV_OFF },
{ ngx_string("put"), NGX_HTTP_PUT },
{ ngx_string("delete"), NGX_HTTP_DELETE },
+ { ngx_string("mkcol"), NGX_HTTP_MKCOL },
{ ngx_null_string, 0 }
};
@@ -41,6 +46,13 @@ static ngx_command_t ngx_http_dav_commands[] = {
offsetof(ngx_http_dav_loc_conf_t, methods),
&ngx_http_dav_methods_mask },
+ { ngx_string("create_full_put_path"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
+ ngx_conf_set_flag_slot,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ offsetof(ngx_http_dav_loc_conf_t, create_full_put_path),
+ NULL },
+
ngx_null_command
};
@@ -79,8 +91,10 @@ ngx_module_t ngx_http_dav_module = {
static ngx_int_t
ngx_http_dav_handler(ngx_http_request_t *r)
{
+ char *failed;
ngx_int_t rc;
ngx_str_t path;
+ ngx_file_info_t fi;
ngx_http_dav_loc_conf_t *dlcf;
/* TODO: Win32 */
@@ -102,10 +116,15 @@ ngx_http_dav_handler(ngx_http_request_t *r)
return NGX_DECLINED;
}
+ if (r->headers_in.content_length_n < 0) {
+ return NGX_HTTP_BAD_REQUEST;
+ }
+
r->request_body_in_file_only = 1;
r->request_body_in_persistent_file = 1;
r->request_body_delete_incomplete_file = 1;
r->request_body_file_group_access = 1;
+ r->request_body_file_log_level = 0;
rc = ngx_http_read_client_request_body(r, ngx_http_dav_put_handler);
@@ -117,8 +136,14 @@ ngx_http_dav_handler(ngx_http_request_t *r)
case NGX_HTTP_DELETE:
- if (r->uri.data[r->uri.len - 1] == '/') {
- return NGX_DECLINED;
+ if (r->headers_in.content_length_n > 0) {
+ return NGX_HTTP_UNSUPPORTED_MEDIA_TYPE;
+ }
+
+ rc = ngx_http_discard_body(r);
+
+ if (rc != NGX_OK && rc != NGX_AGAIN) {
+ return rc;
}
ngx_http_map_uri_to_path(r, &path, 0);
@@ -126,14 +151,83 @@ ngx_http_dav_handler(ngx_http_request_t *r)
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"http delete filename: \"%s\"", path.data);
- if (ngx_delete_file(path.data) == NGX_FILE_ERROR) {
- ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno,
- ngx_delete_file_n " \"%s\" failed", path.data);
+ if (ngx_file_info(path.data, &fi) != -1) {
+
+ if (ngx_is_dir(&fi)) {
+
+ if (r->uri.data[r->uri.len - 1] != '/'
+ || r->headers_in.depth == NULL
+ || r->headers_in.depth->value.len != sizeof("infinity") - 1
+ || ngx_strcmp(r->headers_in.depth->value.data, "infinity")
+ != 0)
+ {
+ return NGX_HTTP_BAD_REQUEST;
+ }
+
+ if (ngx_delete_dir(path.data) != NGX_FILE_ERROR) {
+ return NGX_HTTP_NO_CONTENT;
+ }
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
+ failed = ngx_delete_dir_n;
+
+ } else {
+
+ if (r->uri.data[r->uri.len - 1] == '/') {
+ return NGX_HTTP_BAD_REQUEST;
+ }
+
+ if (r->headers_in.depth
+ && r->headers_in.depth->value.len == 1
+ && r->headers_in.depth->value.data[0] == '1')
+ {
+ return NGX_HTTP_BAD_REQUEST;
+ }
+
+ if (ngx_delete_file(path.data) != NGX_FILE_ERROR) {
+ return NGX_HTTP_NO_CONTENT;
+ }
+
+ failed = ngx_delete_file_n;
+ }
+
+ } else {
+ failed = ngx_file_info_n;
}
- return NGX_HTTP_NO_CONTENT;
+ return ngx_http_dav_error(r, ngx_errno, NGX_HTTP_NOT_FOUND, failed,
+ path.data);
+
+ case NGX_HTTP_MKCOL:
+
+ if (r->uri.data[r->uri.len - 1] != '/') {
+ return NGX_DECLINED;
+ }
+
+ if (r->headers_in.content_length_n > 0) {
+ return NGX_HTTP_UNSUPPORTED_MEDIA_TYPE;
+ }
+
+ rc = ngx_http_discard_body(r);
+
+ if (rc != NGX_OK && rc != NGX_AGAIN) {
+ return rc;
+ }
+
+ ngx_http_map_uri_to_path(r, &path, 0);
+
+ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "http mkcol path: \"%s\"", path.data);
+
+ if (ngx_create_dir(path.data) != NGX_FILE_ERROR) {
+ if (ngx_http_dav_location(r, path.data) != NGX_OK) {
+ return NGX_HTTP_INTERNAL_SERVER_ERROR;
+ }
+
+ return NGX_HTTP_CREATED;
+ }
+
+ return ngx_http_dav_error(r, ngx_errno, NGX_HTTP_CONFLICT,
+ ngx_create_dir_n, path.data);
}
return NGX_DECLINED;
@@ -143,12 +237,11 @@ ngx_http_dav_handler(ngx_http_request_t *r)
static void
ngx_http_dav_put_handler(ngx_http_request_t *r)
{
- u_char *location;
- ngx_err_t err;
- ngx_str_t *temp, path;
- ngx_uint_t status;
- ngx_file_info_t fi;
- ngx_http_core_loc_conf_t *clcf;
+ ngx_err_t err;
+ ngx_str_t *temp, path;
+ ngx_uint_t status;
+ ngx_file_info_t fi;
+ ngx_http_dav_loc_conf_t *dlcf;
ngx_http_map_uri_to_path(r, &path, 0);
@@ -164,12 +257,34 @@ ngx_http_dav_put_handler(ngx_http_request_t *r)
status = NGX_HTTP_NO_CONTENT;
}
+ if (ngx_is_dir(&fi)) {
+ ngx_http_finalize_request(r, NGX_HTTP_CONFLICT);
+ return;
+ }
+
if (ngx_rename_file(temp->data, path.data) != NGX_FILE_ERROR) {
goto ok;
}
err = ngx_errno;
+ if (err == NGX_ENOENT) {
+
+ dlcf = ngx_http_get_module_loc_conf(r, ngx_http_dav_module);
+
+ if (dlcf->create_full_put_path) {
+ err = ngx_create_full_path(path.data);
+
+ if (err == 0) {
+ if (ngx_rename_file(temp->data, path.data) != NGX_FILE_ERROR) {
+ goto ok;
+ }
+
+ err = ngx_errno;
+ }
+ }
+ }
+
#if (NGX_WIN32)
if (err == NGX_EEXIST) {
@@ -185,52 +300,97 @@ ngx_http_dav_put_handler(ngx_http_request_t *r)
#endif
- ngx_log_error(NGX_LOG_CRIT, r->connection->log, err,
- ngx_rename_file_n " \"%s\" failed", path.data);
-
- ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
+ ngx_http_finalize_request(r, ngx_http_dav_error(r, err, NGX_HTTP_CONFLICT,
+ ngx_rename_file_n,
+ path.data));
return;
ok:
if (status == NGX_HTTP_CREATED) {
-
- r->headers_out.location = ngx_palloc(r->pool, sizeof(ngx_table_elt_t));
- if (r->headers_out.location == NULL) {
+ if (ngx_http_dav_location(r, path.data) != NGX_OK) {
ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
return;
}
+ }
- clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
+ r->headers_out.status = status;
+ r->header_only = 1;
- if (!clcf->alias && clcf->root_lengths == NULL) {
- location = path.data + clcf->root.len;
+ ngx_http_finalize_request(r, ngx_http_send_header(r));
+ return;
+}
- } else {
- location = ngx_palloc(r->pool, r->uri.len);
- if (location == NULL) {
- ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
- return;
- }
- ngx_memcpy(location, r->uri.data, r->uri.len);
- }
+static ngx_int_t
+ngx_http_dav_error(ngx_http_request_t *r, ngx_err_t err, ngx_int_t not_found,
+ char *failed, u_char *path)
+{
+ ngx_int_t rc;
+ ngx_uint_t level;
+
+ if (err == NGX_ENOENT || err == NGX_ENOTDIR || err == NGX_ENAMETOOLONG) {
+ level = NGX_LOG_ERR;
+ rc = not_found;
+
+ } else if (err == NGX_EACCES || err == NGX_EPERM) {
+ level = NGX_LOG_ERR;
+ rc = NGX_HTTP_FORBIDDEN;
- /*
- * we do not need to set the r->headers_out.location->hash and
- * r->headers_out.location->key fields
- */
+ } else if (err == NGX_EEXIST) {
+ level = NGX_LOG_ERR;
+ rc = NGX_HTTP_NOT_ALLOWED;
- r->headers_out.location->value.len = r->uri.len;
- r->headers_out.location->value.data = location;
+ } else if (err == NGX_ENOSPC) {
+ level = NGX_LOG_CRIT;
+ rc = NGX_HTTP_INSUFFICIENT_STORAGE;
+ } else {
+ level = NGX_LOG_CRIT;
+ rc = NGX_HTTP_INTERNAL_SERVER_ERROR;
}
- r->headers_out.status = status;
- r->header_only = 1;
+ ngx_log_error(level, r->connection->log, err,
+ "%s \"%s\" failed", failed, path);
- ngx_http_finalize_request(r, ngx_http_send_header(r));
- return;
+ return rc;
+}
+
+
+static ngx_int_t
+ngx_http_dav_location(ngx_http_request_t *r, u_char *path)
+{
+ u_char *location;
+ ngx_http_core_loc_conf_t *clcf;
+
+ r->headers_out.location = ngx_palloc(r->pool, sizeof(ngx_table_elt_t));
+ if (r->headers_out.location == NULL) {
+ return NGX_ERROR;
+ }
+
+ clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
+
+ if (!clcf->alias && clcf->root_lengths == NULL) {
+ location = path + clcf->root.len;
+
+ } else {
+ location = ngx_palloc(r->pool, r->uri.len);
+ if (location == NULL) {
+ return NGX_ERROR;
+ }
+
+ ngx_memcpy(location, r->uri.data, r->uri.len);
+ }
+
+ /*
+ * we do not need to set the r->headers_out.location->hash and
+ * r->headers_out.location->key fields
+ */
+
+ r->headers_out.location->value.len = r->uri.len;
+ r->headers_out.location->value.data = location;
+
+ return NGX_OK;
}
@@ -250,6 +410,8 @@ ngx_http_dav_create_loc_conf(ngx_conf_t *cf)
* conf->methods = 0;
*/
+ conf->create_full_put_path = NGX_CONF_UNSET;
+
return conf;
}
@@ -261,7 +423,10 @@ ngx_http_dav_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
ngx_http_dav_loc_conf_t *conf = child;
ngx_conf_merge_bitmask_value(conf->methods, prev->methods,
- (NGX_CONF_BITMASK_SET|NGX_HTTP_DAV_OFF));
+ (NGX_CONF_BITMASK_SET|NGX_HTTP_DAV_OFF));
+
+ ngx_conf_merge_value(conf->create_full_put_path, prev->create_full_put_path,
+ 0);
return NGX_CONF_OK;
}
diff --git a/src/http/modules/ngx_http_fastcgi_module.c b/src/http/modules/ngx_http_fastcgi_module.c
index ee603d17d..f901a5223 100644
--- a/src/http/modules/ngx_http_fastcgi_module.c
+++ b/src/http/modules/ngx_http_fastcgi_module.c
@@ -1445,7 +1445,7 @@ ngx_http_fastcgi_add_variables(ngx_conf_t *cf)
return NGX_ERROR;
}
- var->handler = ngx_http_fastcgi_script_name_variable;
+ var->get_handler = ngx_http_fastcgi_script_name_variable;
return NGX_OK;
}
diff --git a/src/http/modules/ngx_http_geo_module.c b/src/http/modules/ngx_http_geo_module.c
index a6e8db301..62ef72cf9 100644
--- a/src/http/modules/ngx_http_geo_module.c
+++ b/src/http/modules/ngx_http_geo_module.c
@@ -127,7 +127,7 @@ ngx_http_geo_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
return NGX_CONF_ERROR;
}
- var->handler = ngx_http_geo_variable;
+ var->get_handler = ngx_http_geo_variable;
var->data = (uintptr_t) tree;
pool = ngx_create_pool(16384, cf->log);
diff --git a/src/http/modules/ngx_http_gzip_filter_module.c b/src/http/modules/ngx_http_gzip_filter_module.c
index 663f7f2ed..a08f31cb5 100644
--- a/src/http/modules/ngx_http_gzip_filter_module.c
+++ b/src/http/modules/ngx_http_gzip_filter_module.c
@@ -969,7 +969,7 @@ ngx_http_gzip_add_variables(ngx_conf_t *cf)
return NGX_ERROR;
}
- var->handler = ngx_http_gzip_ratio_variable;
+ var->get_handler = ngx_http_gzip_ratio_variable;
for (op = ngx_http_gzip_log_fmt_ops; op->name.len; op++) { /* void */ }
op->run = NULL;
diff --git a/src/http/modules/ngx_http_index_module.c b/src/http/modules/ngx_http_index_module.c
index 4ef291009..4326e7399 100644
--- a/src/http/modules/ngx_http_index_module.c
+++ b/src/http/modules/ngx_http_index_module.c
@@ -143,6 +143,10 @@ ngx_http_index_handler(ngx_http_request_t *r)
return NGX_DECLINED;
}
+ if (r->method != NGX_HTTP_GET && r->method != NGX_HTTP_HEAD) {
+ return NGX_DECLINED;
+ }
+
log = r->connection->log;
/*
diff --git a/src/http/modules/ngx_http_map_module.c b/src/http/modules/ngx_http_map_module.c
index 2cfb443e2..0a533c0f5 100644
--- a/src/http/modules/ngx_http_map_module.c
+++ b/src/http/modules/ngx_http_map_module.c
@@ -237,7 +237,7 @@ ngx_http_map_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
return NGX_CONF_ERROR;
}
- var->handler = ngx_http_map_variable;
+ var->get_handler = ngx_http_map_variable;
var->data = (uintptr_t) map;
pool = ngx_create_pool(16384, cf->log);
diff --git a/src/http/modules/ngx_http_proxy_module.c b/src/http/modules/ngx_http_proxy_module.c
index e96ba042e..0e3c9491c 100644
--- a/src/http/modules/ngx_http_proxy_module.c
+++ b/src/http/modules/ngx_http_proxy_module.c
@@ -366,23 +366,23 @@ static ngx_table_elt_t ngx_http_proxy_headers[] = {
static ngx_http_variable_t ngx_http_proxy_vars[] = {
- { ngx_string("proxy_host"), ngx_http_proxy_host_variable, 0,
+ { ngx_string("proxy_host"), NULL, ngx_http_proxy_host_variable, 0,
NGX_HTTP_VAR_CHANGABLE|NGX_HTTP_VAR_NOHASH, 0 },
- { ngx_string("proxy_port"), ngx_http_proxy_port_variable, 0,
+ { ngx_string("proxy_port"), NULL, ngx_http_proxy_port_variable, 0,
NGX_HTTP_VAR_CHANGABLE|NGX_HTTP_VAR_NOHASH, 0 },
- { ngx_string("proxy_add_x_forwarded_for"),
+ { ngx_string("proxy_add_x_forwarded_for"), NULL,
ngx_http_proxy_add_x_forwarded_for_variable, 0, NGX_HTTP_VAR_NOHASH, 0 },
#if 0
- { ngx_string("proxy_add_via"), NULL, 0, NGX_HTTP_VAR_NOHASH, 0 },
+ { ngx_string("proxy_add_via"), NULL, NULL, 0, NGX_HTTP_VAR_NOHASH, 0 },
#endif
- { ngx_string("proxy_internal_body_length"),
+ { ngx_string("proxy_internal_body_length"), NULL,
ngx_http_proxy_internal_body_length_variable, 0, NGX_HTTP_VAR_NOHASH, 0 },
- { ngx_null_string, NULL, 0, 0, 0 }
+ { ngx_null_string, NULL, NULL, 0, 0, 0 }
};
@@ -1382,7 +1382,7 @@ ngx_http_proxy_add_variables(ngx_conf_t *cf)
return NGX_ERROR;
}
- var->handler = v->handler;
+ var->get_handler = v->get_handler;
var->data = v->data;
}
diff --git a/src/http/modules/ngx_http_referer_module.c b/src/http/modules/ngx_http_referer_module.c
index eb01857ab..f3597a1d2 100644
--- a/src/http/modules/ngx_http_referer_module.c
+++ b/src/http/modules/ngx_http_referer_module.c
@@ -298,7 +298,7 @@ ngx_http_valid_referers(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
return NGX_CONF_ERROR;
}
- var->handler = ngx_http_referer_variable;
+ var->get_handler = ngx_http_referer_variable;
if (rlcf->keys == NULL) {
rlcf->keys = ngx_pcalloc(cf->temp_pool, sizeof(ngx_hash_keys_arrays_t));
diff --git a/src/http/modules/ngx_http_rewrite_module.c b/src/http/modules/ngx_http_rewrite_module.c
index e3b2edcfe..37266a4d8 100644
--- a/src/http/modules/ngx_http_rewrite_module.c
+++ b/src/http/modules/ngx_http_rewrite_module.c
@@ -74,15 +74,6 @@ static ngx_command_t ngx_http_rewrite_commands[] = {
0,
NULL },
-#if 0
- { ngx_string("valid_referers"),
- NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
- ngx_http_rewrite_valid_referers,
- NGX_HTTP_LOC_CONF_OFFSET,
- 0,
- NULL },
-#endif
-
{ ngx_string("set"),
NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
|NGX_CONF_TAKE2,
@@ -879,10 +870,11 @@ ngx_http_rewrite_set(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
ngx_http_rewrite_loc_conf_t *lcf = conf;
- ngx_int_t index;
- ngx_str_t *value;
- ngx_http_variable_t *v;
- ngx_http_script_var_code_t *var;
+ ngx_int_t index;
+ ngx_str_t *value;
+ ngx_http_variable_t *v;
+ ngx_http_script_var_code_t *vcode;
+ ngx_http_script_var_handler_code_t *vhcode;
value = cf->args->elts;
@@ -905,8 +897,8 @@ ngx_http_rewrite_set(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
return NGX_CONF_ERROR;
}
- if (v->handler == NULL) {
- v->handler = ngx_http_rewrite_var;
+ if (v->get_handler == NULL) {
+ v->get_handler = ngx_http_rewrite_var;
v->data = index;
}
@@ -914,14 +906,28 @@ ngx_http_rewrite_set(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
return NGX_CONF_ERROR;
}
- var = ngx_http_script_start_code(cf->pool, &lcf->codes,
- sizeof(ngx_http_script_var_code_t));
- if (var == NULL) {
+ if (v->set_handler) {
+ vhcode = ngx_http_script_start_code(cf->pool, &lcf->codes,
+ sizeof(ngx_http_script_var_handler_code_t));
+ if (vhcode == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ vhcode->code = ngx_http_script_var_set_handler_code;
+ vhcode->handler = v->set_handler;
+ vhcode->data = v->data;
+
+ return NGX_CONF_OK;
+ }
+
+ vcode = ngx_http_script_start_code(cf->pool, &lcf->codes,
+ sizeof(ngx_http_script_var_code_t));
+ if (vcode == NULL) {
return NGX_CONF_ERROR;
}
- var->code = ngx_http_script_set_var_code;
- var->index = (uintptr_t) index;
+ vcode->code = ngx_http_script_set_var_code;
+ vcode->index = (uintptr_t) index;
return NGX_CONF_OK;
}
diff --git a/src/http/modules/ngx_http_ssi_filter_module.c b/src/http/modules/ngx_http_ssi_filter_module.c
index 541b438e7..15cb0c34c 100644
--- a/src/http/modules/ngx_http_ssi_filter_module.c
+++ b/src/http/modules/ngx_http_ssi_filter_module.c
@@ -262,13 +262,13 @@ static ngx_http_ssi_command_t ngx_http_ssi_commands[] = {
static ngx_http_variable_t ngx_http_ssi_vars[] = {
- { ngx_string("date_local"), ngx_http_ssi_date_gmt_local_variable, 0,
+ { ngx_string("date_local"), NULL, ngx_http_ssi_date_gmt_local_variable, 0,
NGX_HTTP_VAR_NOCACHABLE, 0 },
- { ngx_string("date_gmt"), ngx_http_ssi_date_gmt_local_variable, 1,
+ { ngx_string("date_gmt"), NULL, ngx_http_ssi_date_gmt_local_variable, 1,
NGX_HTTP_VAR_NOCACHABLE, 0 },
- { ngx_null_string, NULL, 0, 0, 0 }
+ { ngx_null_string, NULL, NULL, 0, 0, 0 }
};
@@ -2153,7 +2153,7 @@ ngx_http_ssi_preconfiguration(ngx_conf_t *cf)
return NGX_ERROR;
}
- var->handler = v->handler;
+ var->get_handler = v->get_handler;
var->data = v->data;
}
diff --git a/src/http/modules/ngx_http_ssl_module.c b/src/http/modules/ngx_http_ssl_module.c
index a70c7f2f5..e2191ef47 100644
--- a/src/http/modules/ngx_http_ssl_module.c
+++ b/src/http/modules/ngx_http_ssl_module.c
@@ -136,13 +136,13 @@ ngx_module_t ngx_http_ssl_module = {
static ngx_http_variable_t ngx_http_ssl_vars[] = {
- { ngx_string("ssl_protocol"), ngx_http_ssl_variable,
+ { ngx_string("ssl_protocol"), NULL, ngx_http_ssl_variable,
(uintptr_t) ngx_ssl_get_protocol, NGX_HTTP_VAR_CHANGABLE, 0 },
- { ngx_string("ssl_cipher"), ngx_http_ssl_variable,
+ { ngx_string("ssl_cipher"), NULL, ngx_http_ssl_variable,
(uintptr_t) ngx_ssl_get_cipher_name, NGX_HTTP_VAR_CHANGABLE, 0 },
- { ngx_null_string, NULL, 0, 0, 0 }
+ { ngx_null_string, NULL, NULL, 0, 0, 0 }
};
@@ -190,7 +190,7 @@ ngx_http_ssl_add_variables(ngx_conf_t *cf)
return NGX_ERROR;
}
- var->handler = v->handler;
+ var->get_handler = v->get_handler;
var->data = v->data;
}
diff --git a/src/http/modules/ngx_http_userid_filter_module.c b/src/http/modules/ngx_http_userid_filter_module.c
index a7cda3218..810eb3ad1 100644
--- a/src/http/modules/ngx_http_userid_filter_module.c
+++ b/src/http/modules/ngx_http_userid_filter_module.c
@@ -559,7 +559,7 @@ ngx_http_userid_add_variables(ngx_conf_t *cf)
return NGX_ERROR;
}
- var->handler = ngx_http_userid_variable;
+ var->get_handler = ngx_http_userid_variable;
var->data = offsetof(ngx_http_userid_ctx_t, uid_got);
var = ngx_http_add_variable(cf, &ngx_http_userid_set, NGX_HTTP_VAR_NOHASH);
@@ -567,7 +567,7 @@ ngx_http_userid_add_variables(ngx_conf_t *cf)
return NGX_ERROR;
}
- var->handler = ngx_http_userid_variable;
+ var->get_handler = ngx_http_userid_variable;
var->data = offsetof(ngx_http_userid_ctx_t, uid_set);
diff --git a/src/http/modules/perl/ngx_http_perl_module.c b/src/http/modules/perl/ngx_http_perl_module.c
index 198971dc9..136bac397 100644
--- a/src/http/modules/perl/ngx_http_perl_module.c
+++ b/src/http/modules/perl/ngx_http_perl_module.c
@@ -190,6 +190,10 @@ ngx_http_perl_handler(ngx_http_request_t *r)
r->request_body_in_persistent_file = 1;
r->request_body_delete_incomplete_file = 1;
+ if (r->request_body_in_file_only) {
+ r->request_body_file_log_level = 0;
+ }
+
rc = ngx_http_read_client_request_body(r, ngx_http_perl_handle_request);
if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
@@ -1011,7 +1015,7 @@ ngx_http_perl_set(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
}
- v->handler = ngx_http_perl_variable;
+ v->get_handler = ngx_http_perl_variable;
v->data = (uintptr_t) pv;
return NGX_CONF_OK;
diff --git a/src/http/ngx_http.c b/src/http/ngx_http.c
index 5a23d1dbb..5c1e0a041 100644
--- a/src/http/ngx_http.c
+++ b/src/http/ngx_http.c
@@ -373,7 +373,7 @@ ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
cmcf->phases[NGX_HTTP_LOG_PHASE].type = NGX_OK;
- cmcf->headers_in_hash.max_size = 100;
+ cmcf->headers_in_hash.max_size = 200;
cmcf->headers_in_hash.bucket_limit = 1;
cmcf->headers_in_hash.bucket_size = sizeof(ngx_http_header_t);
cmcf->headers_in_hash.name = "http headers_in";
diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c
index b897fe19c..4a9c2085b 100644
--- a/src/http/ngx_http_core_module.c
+++ b/src/http/ngx_http_core_module.c
@@ -753,6 +753,10 @@ ngx_http_update_location_config(ngx_http_request_t *r)
if (clcf->client_body_in_file_only) {
r->request_body_in_file_only = 1;
r->request_body_in_persistent_file = 1;
+ r->request_body_file_log_level = NGX_LOG_NOTICE;
+
+ } else {
+ r->request_body_file_log_level = NGX_LOG_WARN;
}
if (r->keepalive && clcf->keepalive_timeout == 0) {
@@ -1692,9 +1696,18 @@ ngx_http_core_cmp_locations(const void *one, const void *two)
static char *
ngx_http_core_types(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
+ ngx_http_core_loc_conf_t *lcf = conf;
+
char *rv;
ngx_conf_t save;
+ if (lcf->types == NULL) {
+ lcf->types = ngx_array_create(cf->pool, 64, sizeof(ngx_hash_key_t));
+ if (lcf->types == NULL) {
+ return NGX_CONF_ERROR;
+ }
+ }
+
save = *cf;
cf->handler = ngx_http_core_type;
cf->handler_conf = conf;
@@ -1716,13 +1729,6 @@ ngx_http_core_type(ngx_conf_t *cf, ngx_command_t *dummy, void *conf)
ngx_uint_t i, n;
ngx_hash_key_t *type;
- if (lcf->types == NULL) {
- lcf->types = ngx_array_create(cf->pool, 64, sizeof(ngx_hash_key_t));
- if (lcf->types == NULL) {
- return NGX_CONF_ERROR;
- }
- }
-
content_type = ngx_palloc(cf->pool, sizeof(ngx_str_t));
if (content_type == NULL) {
return NGX_CONF_ERROR;
diff --git a/src/http/ngx_http_header_filter_module.c b/src/http/ngx_http_header_filter_module.c
index 69b624b11..77a9224f5 100644
--- a/src/http/ngx_http_header_filter_module.c
+++ b/src/http/ngx_http_header_filter_module.c
@@ -93,7 +93,7 @@ static ngx_str_t ngx_http_status_lines[] = {
* because we treat such requests as the HTTP/0.9
* requests and send only a body without a header
*/
- ngx_null_string, /* "415 Unsupported Media Type" */
+ ngx_string("415 Unsupported Media Type"),
ngx_string("416 Requested Range Not Satisfiable"),
/* ngx_null_string, */ /* "417 Expectation Failed" */
@@ -111,11 +111,11 @@ static ngx_str_t ngx_http_status_lines[] = {
ngx_string("501 Method Not Implemented"),
ngx_string("502 Bad Gateway"),
ngx_string("503 Service Temporarily Unavailable"),
- ngx_string("504 Gateway Time-out")
+ ngx_string("504 Gateway Time-out"),
- /* ngx_null_string, */ /* "505 HTTP Version Not Supported" */
- /* ngx_null_string, */ /* "506 Variant Also Negotiates" */
- /* ngx_null_string, */ /* "507 Insufficient Storage" */
+ ngx_null_string, /* "505 HTTP Version Not Supported" */
+ ngx_null_string, /* "506 Variant Also Negotiates" */
+ ngx_string("507 Insufficient Storage"),
/* ngx_null_string, */ /* "508 unused" */
/* ngx_null_string, */ /* "509 unused" */
/* ngx_null_string, */ /* "510 Not Extended" */
diff --git a/src/http/ngx_http_parse.c b/src/http/ngx_http_parse.c
index c8431774f..11c163290 100644
--- a/src/http/ngx_http_parse.c
+++ b/src/http/ngx_http_parse.c
@@ -89,6 +89,14 @@ ngx_http_parse_request_line(ngx_http_request_t *r, ngx_buf_t *b)
r->method = NGX_HTTP_HEAD;
}
+ } else if (p - m == 5) {
+
+ if (m[0] == 'M' && m[1] == 'K'
+ && m[2] == 'C' && m[3] == 'O' && m[4] == 'L')
+ {
+ r->method = NGX_HTTP_MKCOL;
+ }
+
} else if (p - m == 6) {
if (m[0] == 'D' && m[1] == 'E' && m[2] == 'L'
diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c
index f47fde38c..6bbaf446a 100644
--- a/src/http/ngx_http_request.c
+++ b/src/http/ngx_http_request.c
@@ -133,6 +133,14 @@ ngx_http_header_t ngx_http_headers_in[] = {
ngx_http_process_header_line },
#endif
+#if (NGX_HTTP_DAV)
+ { ngx_string("Depth"), offsetof(ngx_http_headers_in_t, depth),
+ ngx_http_process_header_line },
+
+ { ngx_string("Destination"), offsetof(ngx_http_headers_in_t, destination),
+ ngx_http_process_header_line },
+#endif
+
{ ngx_string("Cookie"), 0, ngx_http_process_cookie },
{ ngx_null_string, 0, NULL }
@@ -1403,7 +1411,10 @@ ngx_http_finalize_request(ngx_http_request_t *r, ngx_int_t rc)
return;
}
- if (rc >= NGX_HTTP_SPECIAL_RESPONSE || rc == NGX_HTTP_NO_CONTENT) {
+ if (rc >= NGX_HTTP_SPECIAL_RESPONSE
+ || rc == NGX_HTTP_CREATED
+ || rc == NGX_HTTP_NO_CONTENT)
+ {
if (rc == NGX_HTTP_CLOSE) {
ngx_http_close_request(r, rc);
diff --git a/src/http/ngx_http_request.h b/src/http/ngx_http_request.h
index 182e57d27..cc40f449a 100644
--- a/src/http/ngx_http_request.h
+++ b/src/http/ngx_http_request.h
@@ -25,6 +25,7 @@
#define NGX_HTTP_POST 0x0008
#define NGX_HTTP_PUT 0x0010
#define NGX_HTTP_DELETE 0x0020
+#define NGX_HTTP_MKCOL 0x0040
#define NGX_HTTP_CONNECTION_CLOSE 1
#define NGX_HTTP_CONNECTION_KEEP_ALIVE 2
@@ -61,9 +62,11 @@
#define NGX_HTTP_NOT_FOUND 404
#define NGX_HTTP_NOT_ALLOWED 405
#define NGX_HTTP_REQUEST_TIME_OUT 408
+#define NGX_HTTP_CONFLICT 409
#define NGX_HTTP_LENGTH_REQUIRED 411
#define NGX_HTTP_REQUEST_ENTITY_TOO_LARGE 413
#define NGX_HTTP_REQUEST_URI_TOO_LARGE 414
+#define NGX_HTTP_UNSUPPORTED_MEDIA_TYPE 415
#define NGX_HTTP_RANGE_NOT_SATISFIABLE 416
@@ -96,6 +99,7 @@
#define NGX_HTTP_BAD_GATEWAY 502
#define NGX_HTTP_SERVICE_UNAVAILABLE 503
#define NGX_HTTP_GATEWAY_TIME_OUT 504
+#define NGX_HTTP_INSUFFICIENT_STORAGE 507
#define NGX_HTTP_LOWLEVEL_BUFFERED 0x000000f0
@@ -170,6 +174,11 @@ typedef struct {
ngx_table_elt_t *accept_language;
#endif
+#if (NGX_HTTP_DAV)
+ ngx_table_elt_t *depth;
+ ngx_table_elt_t *destination;
+#endif
+
ngx_str_t user;
ngx_str_t passwd;
@@ -384,6 +393,7 @@ struct ngx_http_request_s {
unsigned request_body_in_persistent_file:1;
unsigned request_body_delete_incomplete_file:1;
unsigned request_body_file_group_access:1;
+ unsigned request_body_file_log_level:3;
unsigned fast_subrequest:1;
diff --git a/src/http/ngx_http_request_body.c b/src/http/ngx_http_request_body.c
index cda7f7d8d..605c8ad52 100644
--- a/src/http/ngx_http_request_body.c
+++ b/src/http/ngx_http_request_body.c
@@ -354,6 +354,7 @@ ngx_http_write_request_body(ngx_http_request_t *r, ngx_chain_t *body)
tf->path = clcf->client_body_temp_path;
tf->pool = r->pool;
tf->warn = "a client request body is buffered to a temporary file";
+ tf->log_level = r->request_body_file_log_level;
tf->persistent = r->request_body_in_persistent_file;
if (r->request_body_file_group_access) {
diff --git a/src/http/ngx_http_script.c b/src/http/ngx_http_script.c
index ab6f3a0e4..5a5245667 100644
--- a/src/http/ngx_http_script.c
+++ b/src/http/ngx_http_script.c
@@ -1074,6 +1074,24 @@ ngx_http_script_set_var_code(ngx_http_script_engine_t *e)
void
+ngx_http_script_var_set_handler_code(ngx_http_script_engine_t *e)
+{
+ ngx_http_script_var_handler_code_t *code;
+
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
+ "http script set var handler");
+
+ code = (ngx_http_script_var_handler_code_t *) e->ip;
+
+ e->ip += sizeof(ngx_http_script_var_handler_code_t);
+
+ e->sp--;
+
+ code->handler(e->request, e->sp, code->data);
+}
+
+
+void
ngx_http_script_var_code(ngx_http_script_engine_t *e)
{
ngx_http_variable_value_t *value;
diff --git a/src/http/ngx_http_script.h b/src/http/ngx_http_script.h
index abbbf43f4..3ef4d42e3 100644
--- a/src/http/ngx_http_script.h
+++ b/src/http/ngx_http_script.h
@@ -76,6 +76,13 @@ typedef struct {
typedef struct {
+ ngx_http_script_code_pt code;
+ ngx_http_set_variable_pt handler;
+ uintptr_t data;
+} ngx_http_script_var_handler_code_t;
+
+
+typedef struct {
ngx_http_script_code_pt code;
uintptr_t n;
} ngx_http_script_copy_capture_code_t;
@@ -193,6 +200,7 @@ void ngx_http_script_file_code(ngx_http_script_engine_t *e);
void ngx_http_script_complex_value_code(ngx_http_script_engine_t *e);
void ngx_http_script_value_code(ngx_http_script_engine_t *e);
void ngx_http_script_set_var_code(ngx_http_script_engine_t *e);
+void ngx_http_script_var_set_handler_code(ngx_http_script_engine_t *e);
void ngx_http_script_var_code(ngx_http_script_engine_t *e);
void ngx_http_script_nop_code(ngx_http_script_engine_t *e);
diff --git a/src/http/ngx_http_special_response.c b/src/http/ngx_http_special_response.c
index f221276c6..d1072a9af 100644
--- a/src/http/ngx_http_special_response.c
+++ b/src/http/ngx_http_special_response.c
@@ -107,6 +107,14 @@ static char error_408_page[] =
;
+static char error_409_page[] =
+"<html>" CRLF
+"<head><title>409 Conflict</title></head>" CRLF
+"<body bgcolor=\"white\">" CRLF
+"<center><h1>409 Conflict</h1></center>" CRLF
+;
+
+
static char error_410_page[] =
"<html>" CRLF
"<head><title>410 Gone</title></head>" CRLF
@@ -139,6 +147,14 @@ static char error_414_page[] =
;
+static char error_415_page[] =
+"<html>" CRLF
+"<head><title>415 Unsupported Media Type</title></head>" CRLF
+"<body bgcolor=\"white\">" CRLF
+"<center><h1>415 Unsupported Media Type</h1></center>" CRLF
+;
+
+
static char error_416_page[] =
"<html>" CRLF
"<head><title>416 Requested Range Not Satisfiable</title></head>" CRLF
@@ -197,6 +213,14 @@ static char error_504_page[] =
;
+static char error_507_page[] =
+"<html>" CRLF
+"<head><title>507 Insufficient Storage</title></head>" CRLF
+"<body bgcolor=\"white\">" CRLF
+"<center><h1>507 Insufficient Storage</h1></center>" CRLF
+;
+
+
static ngx_str_t error_pages[] = {
ngx_null_string, /* 201, 204 */
@@ -219,13 +243,13 @@ static ngx_str_t error_pages[] = {
ngx_string(error_406_page),
ngx_null_string, /* 407 */
ngx_string(error_408_page),
- ngx_null_string, /* 409 */
+ ngx_string(error_409_page),
ngx_string(error_410_page),
ngx_string(error_411_page),
ngx_null_string, /* 412 */
ngx_string(error_413_page),
ngx_string(error_414_page),
- ngx_null_string, /* 415 */
+ ngx_string(error_415_page),
ngx_string(error_416_page),
#define NGX_HTTP_LEVEL_400 17
@@ -238,7 +262,10 @@ static ngx_str_t error_pages[] = {
ngx_string(error_501_page),
ngx_string(error_502_page),
ngx_string(error_503_page),
- ngx_string(error_504_page)
+ ngx_string(error_504_page),
+ ngx_null_string, /* 505 */
+ ngx_null_string, /* 506 */
+ ngx_string(error_507_page)
};
@@ -323,6 +350,7 @@ ngx_http_special_response_handler(ngx_http_request_t *r, ngx_int_t error)
if (error == NGX_HTTP_CREATED) {
/* 201 */
err = 0;
+ r->header_only = 1;
} else if (error == NGX_HTTP_NO_CONTENT) {
/* 204 */
diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c
index bfaed70a5..997038c9c 100644
--- a/src/http/ngx_http_upstream.c
+++ b/src/http/ngx_http_upstream.c
@@ -249,13 +249,13 @@ static ngx_http_log_op_name_t ngx_http_upstream_log_fmt_ops[] = {
static ngx_http_variable_t ngx_http_upstream_vars[] = {
- { ngx_string("upstream_status"),
+ { ngx_string("upstream_status"), NULL,
ngx_http_upstream_status_variable, 0, NGX_HTTP_VAR_NOHASH, 0 },
- { ngx_string("upstream_response_time"),
+ { ngx_string("upstream_response_time"), NULL,
ngx_http_upstream_response_time_variable, 0, NGX_HTTP_VAR_NOHASH, 0 },
- { ngx_null_string, NULL, 0, 0, 0 }
+ { ngx_null_string, NULL, NULL, 0, 0, 0 }
};
@@ -2399,7 +2399,7 @@ ngx_http_upstream_add_variables(ngx_conf_t *cf)
return NGX_ERROR;
}
- var->handler = v->handler;
+ var->get_handler = v->get_handler;
var->data = v->data;
}
diff --git a/src/http/ngx_http_variables.c b/src/http/ngx_http_variables.c
index 9d300e69e..69bfe3a5e 100644
--- a/src/http/ngx_http_variables.c
+++ b/src/http/ngx_http_variables.c
@@ -12,6 +12,8 @@
static ngx_int_t ngx_http_variable_request(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data);
+static void ngx_http_variable_request_set_size(ngx_http_request_t *r,
+ ngx_http_variable_value_t *v, uintptr_t data);
static ngx_int_t ngx_http_variable_header(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data);
static ngx_int_t ngx_http_variable_headers(ngx_http_request_t *r,
@@ -59,88 +61,97 @@ static ngx_int_t ngx_http_variable_request_completion(ngx_http_request_t *r,
static ngx_http_variable_t ngx_http_core_variables[] = {
- { ngx_string("http_host"), ngx_http_variable_header,
+ { ngx_string("http_host"), NULL, ngx_http_variable_header,
offsetof(ngx_http_request_t, headers_in.host), 0, 0 },
- { ngx_string("http_user_agent"), ngx_http_variable_header,
+ { ngx_string("http_user_agent"), NULL, ngx_http_variable_header,
offsetof(ngx_http_request_t, headers_in.user_agent), 0, 0 },
- { ngx_string("http_referer"), ngx_http_variable_header,
+ { ngx_string("http_referer"), NULL, ngx_http_variable_header,
offsetof(ngx_http_request_t, headers_in.referer), 0, 0 },
#if (NGX_HTTP_GZIP)
- { ngx_string("http_via"), ngx_http_variable_header,
+ { ngx_string("http_via"), NULL, ngx_http_variable_header,
offsetof(ngx_http_request_t, headers_in.via), 0, 0 },
#endif
#if (NGX_HTTP_PROXY)
- { ngx_string("http_x_forwarded_for"), ngx_http_variable_header,
+ { ngx_string("http_x_forwarded_for"), NULL, ngx_http_variable_header,
offsetof(ngx_http_request_t, headers_in.x_forwarded_for), 0, 0 },
#endif
- { ngx_string("http_cookie"), ngx_http_variable_headers,
+ { ngx_string("http_cookie"), NULL, ngx_http_variable_headers,
offsetof(ngx_http_request_t, headers_in.cookies), 0, 0 },
- { ngx_string("content_length"), ngx_http_variable_header,
+ { ngx_string("content_length"), NULL, ngx_http_variable_header,
offsetof(ngx_http_request_t, headers_in.content_length), 0, 0 },
- { ngx_string("content_type"), ngx_http_variable_header,
+ { ngx_string("content_type"), NULL, ngx_http_variable_header,
offsetof(ngx_http_request_t, headers_in.content_type), 0, 0 },
- { ngx_string("host"), ngx_http_variable_host, 0, 0, 0 },
+ { ngx_string("host"), NULL, ngx_http_variable_host, 0, 0, 0 },
- { ngx_string("remote_addr"), ngx_http_variable_remote_addr, 0, 0, 0 },
+ { ngx_string("remote_addr"), NULL, ngx_http_variable_remote_addr, 0, 0, 0 },
- { ngx_string("remote_port"), ngx_http_variable_remote_port, 0, 0, 0 },
+ { ngx_string("remote_port"), NULL, ngx_http_variable_remote_port, 0, 0, 0 },
- { ngx_string("server_addr"), ngx_http_variable_server_addr, 0, 0, 0 },
+ { ngx_string("server_addr"), NULL, ngx_http_variable_server_addr, 0, 0, 0 },
- { ngx_string("server_port"), ngx_http_variable_server_port, 0, 0, 0 },
+ { ngx_string("server_port"), NULL, ngx_http_variable_server_port, 0, 0, 0 },
- { ngx_string("server_protocol"), ngx_http_variable_request,
+ { ngx_string("server_protocol"), NULL, ngx_http_variable_request,
offsetof(ngx_http_request_t, http_protocol), 0, 0 },
- { ngx_string("request_uri"), ngx_http_variable_request,
+ { ngx_string("request_uri"), NULL, ngx_http_variable_request,
offsetof(ngx_http_request_t, unparsed_uri), 0, 0 },
- { ngx_string("uri"), ngx_http_variable_request,
+ { ngx_string("uri"), NULL, ngx_http_variable_request,
offsetof(ngx_http_request_t, uri),
NGX_HTTP_VAR_NOCACHABLE, 0 },
- { ngx_string("document_uri"), ngx_http_variable_request,
+ { ngx_string("document_uri"), NULL, ngx_http_variable_request,
offsetof(ngx_http_request_t, uri),
NGX_HTTP_VAR_NOCACHABLE, 0 },
- { ngx_string("request"), ngx_http_variable_request,
+ { ngx_string("request"), NULL, ngx_http_variable_request,
offsetof(ngx_http_request_t, request_line), 0, 0 },
- { ngx_string("document_root"), ngx_http_variable_document_root, 0, 0, 0 },
+ { ngx_string("document_root"), NULL,
+ ngx_http_variable_document_root, 0, 0, 0 },
- { ngx_string("query_string"), ngx_http_variable_request,
+ { ngx_string("query_string"), NULL, ngx_http_variable_request,
offsetof(ngx_http_request_t, args),
NGX_HTTP_VAR_NOCACHABLE, 0 },
- { ngx_string("args"), ngx_http_variable_request,
+ { ngx_string("args"), NULL, ngx_http_variable_request,
offsetof(ngx_http_request_t, args),
NGX_HTTP_VAR_NOCACHABLE, 0 },
- { ngx_string("request_filename"), ngx_http_variable_request_filename, 0,
+ { ngx_string("request_filename"), NULL,
+ ngx_http_variable_request_filename, 0,
NGX_HTTP_VAR_NOCACHABLE, 0 },
- { ngx_string("server_name"), ngx_http_variable_request,
+ { ngx_string("server_name"), NULL, ngx_http_variable_request,
offsetof(ngx_http_request_t, server_name), 0, 0 },
- { ngx_string("request_method"), ngx_http_variable_request_method, 0, 0, 0 },
+ { ngx_string("request_method"), NULL,
+ ngx_http_variable_request_method, 0, 0, 0 },
- { ngx_string("remote_user"), ngx_http_variable_remote_user, 0, 0, 0 },
+ { ngx_string("remote_user"), NULL, ngx_http_variable_remote_user, 0, 0, 0 },
- { ngx_string("body_bytes_sent"), ngx_http_variable_body_bytes_sent,
+ { ngx_string("body_bytes_sent"), NULL, ngx_http_variable_body_bytes_sent,
0, 0, 0 },
- { ngx_string("request_completion"), ngx_http_variable_request_completion,
+ { ngx_string("request_completion"), NULL,
+ ngx_http_variable_request_completion,
0, 0, 0 },
- { ngx_null_string, NULL, 0, 0, 0 }
+ { ngx_string("limit_rate"), ngx_http_variable_request_set_size,
+ ngx_http_variable_request,
+ offsetof(ngx_http_request_t, limit_rate),
+ NGX_HTTP_VAR_CHANGABLE|NGX_HTTP_VAR_NOCACHABLE, 0 },
+
+ { ngx_null_string, NULL, NULL, 0, 0, 0 }
};
@@ -195,7 +206,8 @@ ngx_http_add_variable(ngx_conf_t *cf, ngx_str_t *name, ngx_uint_t flags)
v->name.data[i] = ngx_tolower(name->data[i]);
}
- v->handler = NULL;
+ v->set_handler = NULL;
+ v->get_handler = NULL;
v->data = 0;
v->flags = flags;
v->index = 0;
@@ -261,7 +273,8 @@ ngx_http_get_variable_index(ngx_conf_t *cf, ngx_str_t *name)
v->name.data[i] = ngx_tolower(name->data[i]);
}
- v->handler = NULL;
+ v->set_handler = NULL;
+ v->get_handler = NULL;
v->data = 0;
v->flags = 0;
v->index = cmcf->variables.nelts - 1;
@@ -290,8 +303,9 @@ ngx_http_get_indexed_variable(ngx_http_request_t *r, ngx_uint_t index)
v = cmcf->variables.elts;
- if (v[index].handler(r, &r->variables[index], v[index].data) == NGX_OK) {
-
+ if (v[index].get_handler(r, &r->variables[index], v[index].data)
+ == NGX_OK)
+ {
if (v[index].flags & NGX_HTTP_VAR_NOCACHABLE) {
r->variables[index].no_cachable = 1;
}
@@ -343,7 +357,7 @@ ngx_http_get_variable(ngx_http_request_t *r, ngx_str_t *name, ngx_uint_t key,
vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t));
- if (vv && v->handler(r, vv, v->data) == NGX_OK) {
+ if (vv && v->get_handler(r, vv, v->data) == NGX_OK) {
return vv;
}
@@ -412,6 +426,32 @@ ngx_http_variable_request(ngx_http_request_t *r, ngx_http_variable_value_t *v,
}
+static void
+ngx_http_variable_request_set_size(ngx_http_request_t *r,
+ ngx_http_variable_value_t *v, uintptr_t data)
+{
+ ssize_t s, *sp;
+ ngx_str_t val;
+
+ val.len = v->len & 0xffff;
+ val.data = v->data;
+
+ s = ngx_parse_size(&val);
+
+ if (s == NGX_ERROR) {
+ ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
+ "invalid size \"%V\"", &val);
+ return;
+ }
+
+ sp = (ssize_t *) ((char *) r + data);
+
+ *sp = s;
+
+ return;
+}
+
+
static ngx_int_t
ngx_http_variable_header(ngx_http_request_t *r, ngx_http_variable_value_t *v,
uintptr_t data)
@@ -900,7 +940,7 @@ ngx_http_variables_init_vars(ngx_conf_t *cf)
{
av = key[n].value;
- v[i].handler = av->handler;
+ v[i].get_handler = av->get_handler;
v[i].data = av->data;
av->flags |= NGX_HTTP_VAR_INDEXED;
@@ -913,14 +953,14 @@ ngx_http_variables_init_vars(ngx_conf_t *cf)
}
if (ngx_strncmp(v[i].name.data, "http_", 5) == 0) {
- v[i].handler = ngx_http_variable_unknown_header_in;
+ v[i].get_handler = ngx_http_variable_unknown_header_in;
v[i].data = (uintptr_t) &v[i].name;
continue;
}
if (ngx_strncmp(v[i].name.data, "sent_http_", 10) == 0) {
- v[i].handler = ngx_http_variable_unknown_header_out;
+ v[i].get_handler = ngx_http_variable_unknown_header_out;
v[i].data = (uintptr_t) &v[i].name;
continue;
diff --git a/src/http/ngx_http_variables.h b/src/http/ngx_http_variables.h
index 2043a0518..8a24ffbc7 100644
--- a/src/http/ngx_http_variables.h
+++ b/src/http/ngx_http_variables.h
@@ -28,6 +28,8 @@ typedef struct {
typedef struct ngx_http_variable_s ngx_http_variable_t;
+typedef void (*ngx_http_set_variable_pt) (ngx_http_request_t *r,
+ ngx_http_variable_value_t *v, uintptr_t data);
typedef ngx_int_t (*ngx_http_get_variable_pt) (ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data);
@@ -40,7 +42,8 @@ typedef ngx_int_t (*ngx_http_get_variable_pt) (ngx_http_request_t *r,
struct ngx_http_variable_s {
ngx_str_t name; /* must be first to build the hash */
- ngx_http_get_variable_pt handler;
+ ngx_http_set_variable_pt set_handler;
+ ngx_http_get_variable_pt get_handler;
uintptr_t data;
ngx_uint_t flags;
ngx_uint_t index;
diff --git a/src/os/unix/ngx_errno.h b/src/os/unix/ngx_errno.h
index dae9571e2..e0c4a19a1 100644
--- a/src/os/unix/ngx_errno.h
+++ b/src/os/unix/ngx_errno.h
@@ -14,6 +14,7 @@
typedef int ngx_err_t;
+#define NGX_EPERM EPERM
#define NGX_ENOENT ENOENT
#define NGX_ESRCH ESRCH
#define NGX_EINTR EINTR
diff --git a/src/os/win32/ngx_errno.h b/src/os/win32/ngx_errno.h
index 97565760b..9b6c7b51a 100644
--- a/src/os/win32/ngx_errno.h
+++ b/src/os/win32/ngx_errno.h
@@ -19,6 +19,7 @@ typedef DWORD ngx_err_t;
#define ngx_socket_errno WSAGetLastError()
#define ngx_set_socket_errno(err) WSASetLastError(err)
+#define NGX_EPERM ERROR_ACCESS_DENIED
#define NGX_ENOENT ERROR_FILE_NOT_FOUND
#define NGX_EACCES ERROR_ACCESS_DENIED
#if 0