# HG changeset patch # User Igor Sysoev # Date 1145390400 -14400 # Node ID 54aabf2b0bc69490d120648af07aafb1661a5118 # Parent a9c5dc369ffed9e18c8b5d50d4e2009a73965b69 nginx 0.3.40 *) Feature: the ngx_http_dav_module supports the MKCOL method. *) Feature: the "create_full_put_path" directive. *) Feature: the "$limit_rate" variable. diff --git a/CHANGES b/CHANGES --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,13 @@ +Changes with nginx 0.3.40 19 Apr 2006 + + *) Feature: the ngx_http_dav_module supports the MKCOL method. + + *) Feature: the "create_full_put_path" directive. + + *) Feature: the "$limit_rate" variable. + + Changes with nginx 0.3.39 17 Apr 2006 *) Feature: the "uninitialized_variable_warn" directive; the logging diff --git a/CHANGES.ru b/CHANGES.ru --- a/CHANGES.ru +++ b/CHANGES.ru @@ -1,4 +1,13 @@ +Изменения в nginx 0.3.40 19.04.2006 + + *) Добавление: модуль ngx_http_dav_module поддерживает метод MKCOL. + + *) Добавление: директива create_full_put_path. + + *) Добавление: переменная $limit_rate. + + Изменения в nginx 0.3.39 17.04.2006 *) Добавление: директива uninitialized_variable_warn; уровень diff --git a/auto/modules b/auto/modules --- 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/src/core/nginx.h b/src/core/nginx.h --- 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 --- a/src/core/ngx_file.c +++ b/src/core/ngx_file.c @@ -25,8 +25,12 @@ ngx_write_chain_to_temp_file(ngx_temp_fi 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_pa } +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 --- 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_ 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 --- 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_requ 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 --- 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_ { 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_comma 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 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 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 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; + } + + failed = ngx_delete_dir_n; + + } else { - return NGX_HTTP_INTERNAL_SERVER_ERROR; + 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 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_reques 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,45 +300,18 @@ ngx_http_dav_put_handler(ngx_http_reques #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); - - if (!clcf->alias && clcf->root_lengths == NULL) { - location = path.data + clcf->root.len; - - } 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); - } - - /* - * 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; - } r->headers_out.status = status; @@ -234,6 +322,78 @@ ok: } +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; + + } else if (err == NGX_EEXIST) { + level = NGX_LOG_ERR; + rc = NGX_HTTP_NOT_ALLOWED; + + } 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; + } + + ngx_log_error(level, r->connection->log, err, + "%s \"%s\" failed", failed, path); + + 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; +} + + static void * ngx_http_dav_create_loc_conf(ngx_conf_t *cf) { @@ -250,6 +410,8 @@ ngx_http_dav_create_loc_conf(ngx_conf_t * 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 * 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 --- 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_ 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 --- 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_c 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 --- 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 * 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 --- 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_ 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 --- 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_c 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 --- 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_h 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 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 --- 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, 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 --- 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_c 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 { 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 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 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 --- 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_ 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 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 --- 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 *c 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 --- 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 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 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 --- 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->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_co } - 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 --- a/src/http/ngx_http.c +++ b/src/http/ngx_http.c @@ -373,7 +373,7 @@ ngx_http_block(ngx_conf_t *cf, ngx_comma 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 --- 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 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 * 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_c 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 --- 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 --- 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_req 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 --- 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_reque 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 --- 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 --- 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_req 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 --- 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_sc 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 --- 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_ 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 --- 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[] = +"" CRLF +"409 Conflict" CRLF +"" CRLF +"

409 Conflict

" CRLF +; + + static char error_410_page[] = "" CRLF "410 Gone" CRLF @@ -139,6 +147,14 @@ static char error_414_page[] = ; +static char error_415_page[] = +"" CRLF +"415 Unsupported Media Type" CRLF +"" CRLF +"

415 Unsupported Media Type

" CRLF +; + + static char error_416_page[] = "" CRLF "416 Requested Range Not Satisfiable" CRLF @@ -197,6 +213,14 @@ static char error_504_page[] = ; +static char error_507_page[] = +"" CRLF +"507 Insufficient Storage" CRLF +"" CRLF +"

507 Insufficient Storage

" 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_ht 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 --- 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_ 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 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 --- 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_reque 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"), NULL, ngx_http_variable_request, offsetof(ngx_http_request_t, uri), NGX_HTTP_VAR_NOCACHABLE, 0 }, - { ngx_string("document_uri"), 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, ng 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 * 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_r 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 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_reque } +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 { 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 } 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 --- 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_variabl 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 --- 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