# HG changeset patch # User Igor Sysoev # Date 1199739600 -10800 # Node ID 54fad6c4b555ce02d963e0bc98c867301affb883 # Parent 160660bad92962276f870fc654947663491f8253 nginx 0.6.25 *) Change: now the "server_name_in_redirect" directive is used instead of the "server_name" directive's special "*" parameter. *) Change: now wildcard and regex names can be used as main name in a "server_name" directive. *) Change: the "satisfy_any" directive was replaced by the "satisfy" directive. *) Workaround: old worker processes might hog CPU after reconfiguration if they was run under Linux OpenVZ. *) Feature: the "min_delete_depth" directive. *) Bugfix: the COPY and MOVE methods did not work with single files. *) Bugfix: the ngx_http_gzip_static_module did not allow the ngx_http_dav_module to work; bug appeared in 0.6.23. *) Bugfix: socket leak in HTTPS mode if deferred accept was used. Thanks to Ben Maurer. *) Bugfix: nginx could not be built without PCRE library; bug appeared in 0.6.23. diff --git a/CHANGES b/CHANGES --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,32 @@ +Changes with nginx 0.6.25 08 Jan 2008 + + *) Change: now the "server_name_in_redirect" directive is used instead + of the "server_name" directive's special "*" parameter. + + *) Change: now wildcard and regex names can be used as main name in a + "server_name" directive. + + *) Change: the "satisfy_any" directive was replaced by the "satisfy" + directive. + + *) Workaround: old worker processes might hog CPU after reconfiguration + if they was run under Linux OpenVZ. + + *) Feature: the "min_delete_depth" directive. + + *) Bugfix: the COPY and MOVE methods did not work with single files. + + *) Bugfix: the ngx_http_gzip_static_module did not allow the + ngx_http_dav_module to work; bug appeared in 0.6.23. + + *) Bugfix: socket leak in HTTPS mode if deferred accept was used. + Thanks to Ben Maurer. + + *) Bugfix: nginx could not be built without PCRE library; bug appeared + in 0.6.23. + + Changes with nginx 0.6.24 27 Dec 2007 *) Bugfix: a segmentation fault might occur in worker process if HTTPS diff --git a/CHANGES.ru b/CHANGES.ru --- a/CHANGES.ru +++ b/CHANGES.ru @@ -1,8 +1,36 @@ +Изменения в nginx 0.6.25 08.01.2008 + + *) Изменение: вместо специального параметра "*" в директиве server_name + теперь используется директива server_name_in_redirect. + + *) Изменение: в качестве основного имени в директиве server_name теперь + можно использовать имена с масками и регулярными выражениями. + + *) Изменение: директива satisfy_any заменена директивой satisfy. + + *) Изменение: после переконфигурации старые рабочие процесс могли + сильно нагружать процессор при запуске под Linux OpenVZ. + + *) Добавление: директива min_delete_depth. + + *) Исправление: методы COPY и MOVE не работали с одиночными файлами. + + *) Исправление: модуль ngx_http_gzip_static_module не позволял работать + модулю ngx_http_dav_module; ошибка появилась в 0.6.23. + + *) Исправление: утечки сокетов в режиме HTTPS при использовании + отложенного accept'а. + Спасибо Ben Maurer. + + *) Исправление: nginx не собирался без библиотеки PCRE; ошибка + появилась в 0.6.23. + + Изменения в nginx 0.6.24 27.12.2007 *) Исправление: при использовании HTTPS в рабочем процессе мог - произойти segmentation fault. ошибка появилась в 0.6.23. + произойти segmentation fault; ошибка появилась в 0.6.23. Изменения в nginx 0.6.23 27.12.2007 diff --git a/LICENSE b/LICENSE --- a/LICENSE +++ b/LICENSE @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2007 Igor Sysoev + * Copyright (C) 2002-2008 Igor Sysoev * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/auto/modules b/auto/modules --- a/auto/modules +++ b/auto/modules @@ -146,6 +146,12 @@ fi HTTP_MODULES="$HTTP_MODULES $HTTP_STATIC_MODULE" +if [ $HTTP_GZIP_STATIC = YES ]; then + have=NGX_HTTP_GZIP . auto/have + HTTP_MODULES="$HTTP_MODULES $HTTP_GZIP_STATIC_MODULE" + HTTP_SRCS="$HTTP_SRCS $HTTP_GZIP_STATIC_SRCS" +fi + if [ $HTTP_DAV = YES ]; then have=NGX_HTTP_DAV . auto/have HTTP_MODULES="$HTTP_MODULES $HTTP_DAV_MODULE" @@ -265,12 +271,6 @@ if [ $HTTP_FLV = YES ]; then HTTP_SRCS="$HTTP_SRCS $HTTP_FLV_SRCS" fi -if [ $HTTP_GZIP_STATIC = YES ]; then - have=NGX_HTTP_GZIP . auto/have - HTTP_MODULES="$HTTP_MODULES $HTTP_GZIP_STATIC_MODULE" - HTTP_SRCS="$HTTP_SRCS $HTTP_GZIP_STATIC_SRCS" -fi - if [ $HTTP_UPSTREAM_IP_HASH = YES ]; then HTTP_MODULES="$HTTP_MODULES $HTTP_UPSTREAM_IP_HASH_MODULE" HTTP_SRCS="$HTTP_SRCS $HTTP_UPSTREAM_IP_HASH_SRCS" 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_VERSION "0.6.24" +#define NGINX_VERSION "0.6.25" #define NGINX_VER "nginx/" NGINX_VERSION #define NGINX_VAR "NGINX" diff --git a/src/core/ngx_connection.c b/src/core/ngx_connection.c --- a/src/core/ngx_connection.c +++ b/src/core/ngx_connection.c @@ -537,13 +537,21 @@ ngx_close_listening_sockets(ngx_cycle_t c = ls[i].connection; - if (ngx_event_flags & NGX_USE_RTSIG_EVENT) { - if (c->read->active) { + if (c->read->active) { + if (ngx_event_flags & NGX_USE_RTSIG_EVENT) { ngx_del_conn(c, NGX_CLOSE_EVENT); - } + + } else if (ngx_event_flags & NGX_USE_EPOLL_EVENT) { - } else { - if (c->read->active) { + /* + * it seems that Linux-2.6.x OpenVZ sends events + * for closed shared listening sockets unless + * the events was explicity deleted + */ + + ngx_del_event(c->read, NGX_READ_EVENT, 0); + + } else { ngx_del_event(c->read, NGX_READ_EVENT, NGX_CLOSE_EVENT); } } 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 @@ -481,15 +481,14 @@ ngx_create_pathes(ngx_cycle_t *cycle, ng ngx_int_t -ngx_create_path_and_rename_file(ngx_str_t *src, ngx_str_t *to, - ngx_uint_t access, ngx_uint_t full_path, ngx_uint_t delete, ngx_log_t *log) +ngx_ext_rename_file(ngx_str_t *src, ngx_str_t *to, ngx_ext_rename_file_t *ext) { ngx_err_t err; #if !(NGX_WIN32) - if (ngx_change_file_access(src->data, access) == NGX_FILE_ERROR) { - ngx_log_error(NGX_LOG_CRIT, log, ngx_errno, + 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; @@ -497,6 +496,15 @@ ngx_create_path_and_rename_file(ngx_str_ #endif + if (ext->time != -1) { + if (ngx_set_file_time(src->data, ext->fd, ext->time) != NGX_OK) { + ngx_log_error(NGX_LOG_CRIT, ext->log, ngx_errno, + ngx_set_file_time_n " \"%s\" failed", src->data); + err = 0; + goto failed; + } + } + if (ngx_rename_file(src->data, to->data) != NGX_FILE_ERROR) { return NGX_OK; } @@ -505,14 +513,14 @@ ngx_create_path_and_rename_file(ngx_str_ if (err == NGX_ENOENT) { - if (!full_path) { + if (!ext->create_path) { goto failed; } - err = ngx_create_full_path(to->data, ngx_dir_access(access)); + err = ngx_create_full_path(to->data, ngx_dir_access(ext->access)); if (err) { - ngx_log_error(NGX_LOG_CRIT, log, err, + ngx_log_error(NGX_LOG_CRIT, ext->log, err, ngx_create_dir_n " \"%s\" failed", to->data); err = 0; goto failed; @@ -529,7 +537,7 @@ ngx_create_path_and_rename_file(ngx_str_ #if (NGX_WIN32) if (err == NGX_EEXIST) { - if (ngx_win32_rename_file(src, to, log) == NGX_OK) { + if (ngx_win32_rename_file(src, to, ext->log) == NGX_OK) { if (ngx_rename_file(src->data, to->data) != NGX_FILE_ERROR) { return NGX_OK; @@ -546,15 +554,15 @@ ngx_create_path_and_rename_file(ngx_str_ failed: - if (delete) { + if (ext->delete) { if (ngx_delete_file(src->data) == NGX_FILE_ERROR) { - ngx_log_error(NGX_LOG_CRIT, log, ngx_errno, + ngx_log_error(NGX_LOG_CRIT, ext->log, ngx_errno, ngx_delete_file_n " \"%s\" failed", src->data); } } if (err) { - ngx_log_error(NGX_LOG_CRIT, log, err, + ngx_log_error(NGX_LOG_CRIT, ext->log, err, ngx_rename_file_n " \"%s\" to \"%s\" failed", src->data, to->data); } 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 @@ -57,6 +57,18 @@ typedef struct { } ngx_temp_file_t; +typedef struct { + ngx_uint_t access; + time_t time; + ngx_fd_t fd; + + unsigned create_path:1; + unsigned delete:1; + + ngx_log_t *log; +} ngx_ext_rename_file_t; + + typedef struct ngx_tree_ctx_s ngx_tree_ctx_t; typedef ngx_int_t (*ngx_tree_init_handler_pt) (void *ctx, void *prev); @@ -89,8 +101,8 @@ ngx_int_t ngx_create_path(ngx_file_t *fi ngx_err_t ngx_create_full_path(u_char *dir, ngx_uint_t access); 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); -ngx_int_t ngx_create_path_and_rename_file(ngx_str_t *src, ngx_str_t *to, - ngx_uint_t access, ngx_uint_t full_path, ngx_uint_t delete, ngx_log_t *log); +ngx_int_t ngx_ext_rename_file(ngx_str_t *src, ngx_str_t *to, + ngx_ext_rename_file_t *ext); ngx_int_t ngx_walk_tree(ngx_tree_ctx_t *ctx, ngx_str_t *tree); void ngx_init_temp_number(void); diff --git a/src/core/ngx_inet.c b/src/core/ngx_inet.c --- a/src/core/ngx_inet.c +++ b/src/core/ngx_inet.c @@ -8,6 +8,9 @@ #include +static size_t ngx_sprint_uchar(u_char *text, u_char c, size_t len); + + /* AF_INET only */ in_addr_t @@ -63,50 +66,6 @@ ngx_inet_addr(u_char *text, size_t len) * than using FreeBSD libc's snprintf(). */ - -static ngx_inline size_t -ngx_sprint_uchar(u_char *text, u_char c, size_t len) -{ - size_t n; - ngx_uint_t c1, c2; - - n = 0; - - if (len == n) { - return n; - } - - c1 = c / 100; - - if (c1) { - *text++ = (u_char) (c1 + '0'); - n++; - - if (len == n) { - return n; - } - } - - c2 = (c % 100) / 10; - - if (c1 || c2) { - *text++ = (u_char) (c2 + '0'); - n++; - - if (len == n) { - return n; - } - } - - c2 = c % 10; - - *text++ = (u_char) (c2 + '0'); - n++; - - return n; -} - - /* AF_INET only */ size_t @@ -163,6 +122,7 @@ ngx_sock_ntop(int family, struct sockadd return n; } + size_t ngx_inet_ntop(int family, void *addr, u_char *text, size_t len) { @@ -216,6 +176,49 @@ ngx_inet_ntop(int family, void *addr, u_ } +static size_t +ngx_sprint_uchar(u_char *text, u_char c, size_t len) +{ + size_t n; + ngx_uint_t c1, c2; + + n = 0; + + if (len == n) { + return n; + } + + c1 = c / 100; + + if (c1) { + *text++ = (u_char) (c1 + '0'); + n++; + + if (len == n) { + return n; + } + } + + c2 = (c % 100) / 10; + + if (c1 || c2) { + *text++ = (u_char) (c2 + '0'); + n++; + + if (len == n) { + return n; + } + } + + c2 = c % 10; + + *text++ = (u_char) (c2 + '0'); + n++; + + return n; +} + + /* AF_INET only */ ngx_int_t diff --git a/src/event/ngx_event_timer.h b/src/event/ngx_event_timer.h --- a/src/event/ngx_event_timer.h +++ b/src/event/ngx_event_timer.h @@ -65,9 +65,9 @@ ngx_event_add_timer(ngx_event_t *ev, ngx if (ev->timer_set) { /* - * Use the previous timer value if a difference between them is less - * then NGX_TIMER_LAZY_DELAY milliseconds. It allows to minimize - * the rbtree operations for the fast connections. + * Use a previous timer value if difference between it and a new + * value is less than NGX_TIMER_LAZY_DELAY milliseconds: this allows + * to minimize the rbtree operations for fast connections. */ diff = (ngx_msec_int_t) (key - ev->timer.key); diff --git a/src/http/modules/ngx_http_access_module.c b/src/http/modules/ngx_http_access_module.c --- a/src/http/modules/ngx_http_access_module.c +++ b/src/http/modules/ngx_http_access_module.c @@ -116,7 +116,7 @@ ngx_http_access_handler(ngx_http_request if (rule[i].deny) { clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); - if (!clcf->satisfy_any) { + if (clcf->satisfy == NGX_HTTP_SATISFY_ALL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "access forbidden by rule"); } 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 @@ -21,8 +21,9 @@ typedef struct { ngx_uint_t methods; + ngx_uint_t access; + ngx_uint_t min_delete_depth; ngx_flag_t create_full_put_path; - ngx_uint_t access; } ngx_http_dav_loc_conf_t; @@ -37,9 +38,11 @@ static ngx_int_t ngx_http_dav_handler(ng static void ngx_http_dav_put_handler(ngx_http_request_t *r); static ngx_int_t ngx_http_dav_delete_handler(ngx_http_request_t *r); -static ngx_int_t ngx_http_dav_noop(ngx_tree_ctx_t *ctx, ngx_str_t *path); +static ngx_int_t ngx_http_dav_delete_path(ngx_http_request_t *r, + ngx_str_t *path, ngx_uint_t dir); static ngx_int_t ngx_http_dav_delete_dir(ngx_tree_ctx_t *ctx, ngx_str_t *path); static ngx_int_t ngx_http_dav_delete_file(ngx_tree_ctx_t *ctx, ngx_str_t *path); +static ngx_int_t ngx_http_dav_noop(ngx_tree_ctx_t *ctx, ngx_str_t *path); static ngx_int_t ngx_http_dav_mkcol_handler(ngx_http_request_t *r, ngx_http_dav_loc_conf_t *dlcf); @@ -48,10 +51,11 @@ static ngx_int_t ngx_http_dav_copy_move_ static ngx_int_t ngx_http_dav_copy_dir(ngx_tree_ctx_t *ctx, ngx_str_t *path); static ngx_int_t ngx_http_dav_copy_dir_time(ngx_tree_ctx_t *ctx, ngx_str_t *path); -static ngx_int_t ngx_http_dav_copy_file(ngx_tree_ctx_t *ctx, ngx_str_t *path); +static ngx_int_t ngx_http_dav_copy_tree_file(ngx_tree_ctx_t *ctx, + ngx_str_t *path); +static ngx_int_t ngx_http_dav_copy_file(ngx_tree_ctx_t *ctx, u_char *from, + u_char *to); -static ngx_int_t ngx_http_dav_delete_path(ngx_http_request_t *r, - ngx_str_t *path, ngx_uint_t dir); static ngx_int_t ngx_http_dav_depth(ngx_http_request_t *r, ngx_int_t dflt); static ngx_int_t ngx_http_dav_error(ngx_log_t *log, ngx_err_t err, ngx_int_t not_found, char *failed, u_char *path); @@ -89,6 +93,13 @@ static ngx_command_t ngx_http_dav_comma offsetof(ngx_http_dav_loc_conf_t, create_full_put_path), NULL }, + { ngx_string("min_delete_depth"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_conf_set_num_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_dav_loc_conf_t, min_delete_depth), + NULL }, + { ngx_string("dav_access"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE123, ngx_conf_set_access_slot, @@ -153,7 +164,9 @@ ngx_http_dav_handler(ngx_http_request_t case NGX_HTTP_PUT: if (r->uri.data[r->uri.len - 1] == '/') { - return NGX_HTTP_BAD_REQUEST; + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "can not PUT to a collection"); + return NGX_HTTP_CONFLICT; } r->request_body_in_file_only = 1; @@ -194,14 +207,12 @@ ngx_http_dav_handler(ngx_http_request_t static void ngx_http_dav_put_handler(ngx_http_request_t *r) { - char *failed; - u_char *name; size_t root; time_t date; - ngx_err_t err; ngx_str_t *temp, path; - ngx_uint_t status, not_found; + ngx_uint_t status; ngx_file_info_t fi; + ngx_ext_rename_file_t ext; ngx_http_dav_loc_conf_t *dlcf; ngx_http_map_uri_to_path(r, &path, &root, 0); @@ -234,94 +245,27 @@ ngx_http_dav_put_handler(ngx_http_reques dlcf = ngx_http_get_module_loc_conf(r, ngx_http_dav_module); -#if !(NGX_WIN32) - - if (ngx_change_file_access(temp->data, dlcf->access) == NGX_FILE_ERROR) { - err = ngx_errno; - not_found = NGX_HTTP_INTERNAL_SERVER_ERROR; - failed = ngx_change_file_access_n; - name = temp->data; - - goto failed; - } - -#endif + ext.access = dlcf->access; + ext.time = -1; + ext.create_path = dlcf->create_full_put_path; + ext.delete = 1; + ext.log = r->connection->log; if (r->headers_in.date) { date = ngx_http_parse_time(r->headers_in.date->value.data, r->headers_in.date->value.len); if (date != NGX_ERROR) { - if (ngx_set_file_time(temp->data, - r->request_body->temp_file->file.fd, date) - != NGX_OK) - { - err = ngx_errno; - not_found = NGX_HTTP_INTERNAL_SERVER_ERROR; - failed = ngx_set_file_time_n; - name = temp->data; - - goto failed; - } + ext.time = date; + ext.fd = r->request_body->temp_file->file.fd; } } - not_found = NGX_HTTP_CONFLICT; - failed = ngx_rename_file_n; - name = path.data; - - if (ngx_rename_file(temp->data, path.data) != NGX_FILE_ERROR) { - goto ok; - } - - err = ngx_errno; - - if (err == NGX_ENOENT) { - - if (dlcf->create_full_put_path) { - err = ngx_create_full_path(path.data, ngx_dir_access(dlcf->access)); - - if (err == 0) { - if (ngx_rename_file(temp->data, path.data) != NGX_FILE_ERROR) { - goto ok; - } - - err = ngx_errno; - } - } + if (ngx_ext_rename_file(temp, &path, &ext) != NGX_OK) { + ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); + return; } -#if (NGX_WIN32) - - if (err == NGX_EEXIST) { - if (ngx_win32_rename_file(temp, &path, r->connection->log) == NGX_OK) { - - if (ngx_rename_file(temp->data, path.data) != NGX_FILE_ERROR) { - goto ok; - } - } - - err = ngx_errno; - } - -#endif - -failed: - - if (ngx_delete_file(temp->data) == NGX_FILE_ERROR) { - ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno, - ngx_delete_file_n " \"%s\" failed", - temp->data); - } - - ngx_http_finalize_request(r, - ngx_http_dav_error(r->connection->log, err, - not_found, failed, name)); - - return; - -ok: - if (status == NGX_HTTP_CREATED) { if (ngx_http_dav_location(r, path.data) != NGX_OK) { ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); @@ -342,43 +286,67 @@ ok: static ngx_int_t ngx_http_dav_delete_handler(ngx_http_request_t *r) { - size_t root; - ngx_int_t rc, depth; - ngx_uint_t dir; - ngx_str_t path; - ngx_file_info_t fi; + size_t root; + ngx_err_t err; + ngx_int_t rc, depth; + ngx_uint_t i, d, dir; + ngx_str_t path; + ngx_file_info_t fi; + ngx_http_dav_loc_conf_t *dlcf; if (r->headers_in.content_length_n > 0) { + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "DELETE with body is unsupported"); return NGX_HTTP_UNSUPPORTED_MEDIA_TYPE; } - rc = ngx_http_discard_request_body(r); + dlcf = ngx_http_get_module_loc_conf(r, ngx_http_dav_module); + + if (dlcf->min_delete_depth) { + d = 0; - if (rc != NGX_OK) { - return rc; + for (i = 0; i < r->uri.len; /* void */) { + if (r->uri.data[i++] == '/') { + if (++d >= dlcf->min_delete_depth && i < r->uri.len) { + goto ok; + } + } + } + + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "insufficient URI depth:%i to DELETE", d); + return NGX_HTTP_CONFLICT; } +ok: + ngx_http_map_uri_to_path(r, &path, &root, 0); ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http delete filename: \"%s\"", path.data); if (ngx_file_info(path.data, &fi) == -1) { - return ngx_http_dav_error(r->connection->log, ngx_errno, - NGX_HTTP_NOT_FOUND, ngx_file_info_n, - path.data); + err = ngx_errno; + + rc = (err == NGX_ENOTDIR) ? NGX_HTTP_CONFLICT : NGX_HTTP_NOT_FOUND; + + return ngx_http_dav_error(r->connection->log, err, + rc, ngx_file_info_n, path.data); } if (ngx_is_dir(&fi)) { if (r->uri.data[r->uri.len - 1] != '/') { - /* TODO: 301 */ - return NGX_HTTP_BAD_REQUEST; + ngx_log_error(NGX_LOG_ERR, r->connection->log, NGX_EISDIR, + "DELETE \"%s\" failed", path.data); + return NGX_HTTP_CONFLICT; } depth = ngx_http_dav_depth(r, NGX_HTTP_DAV_INFINITY_DEPTH); if (depth != NGX_HTTP_DAV_INFINITY_DEPTH) { + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "\"Depth\" header must be infinity"); return NGX_HTTP_BAD_REQUEST; } @@ -388,9 +356,16 @@ ngx_http_dav_delete_handler(ngx_http_req } else { + /* + * we do not need to test (r->uri.data[r->uri.len - 1] == '/') + * because ngx_file_info("/file/") returned NGX_ENOTDIR above + */ + depth = ngx_http_dav_depth(r, 0); if (depth != 0 && depth != NGX_HTTP_DAV_INFINITY_DEPTH) { + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "\"Depth\" header must be 0 or infinity"); return NGX_HTTP_BAD_REQUEST; } @@ -408,9 +383,45 @@ ngx_http_dav_delete_handler(ngx_http_req static ngx_int_t -ngx_http_dav_noop(ngx_tree_ctx_t *ctx, ngx_str_t *path) +ngx_http_dav_delete_path(ngx_http_request_t *r, ngx_str_t *path, ngx_uint_t dir) { - return NGX_OK; + char *failed; + ngx_tree_ctx_t tree; + + if (dir) { + + tree.init_handler = NULL; + tree.file_handler = ngx_http_dav_delete_file; + tree.pre_tree_handler = ngx_http_dav_noop; + tree.post_tree_handler = ngx_http_dav_delete_dir; + tree.spec_handler = ngx_http_dav_delete_file; + tree.data = NULL; + tree.alloc = 0; + tree.log = r->connection->log; + + /* TODO: 207 */ + + if (ngx_walk_tree(&tree, path) != NGX_OK) { + return NGX_HTTP_INTERNAL_SERVER_ERROR; + } + + if (ngx_delete_dir(path->data) != NGX_FILE_ERROR) { + return NGX_OK; + } + + failed = ngx_delete_dir_n; + + } else { + + if (ngx_delete_file(path->data) != NGX_FILE_ERROR) { + return NGX_OK; + } + + failed = ngx_delete_file_n; + } + + return ngx_http_dav_error(r->connection->log, ngx_errno, + NGX_HTTP_NOT_FOUND, failed, path->data); } @@ -451,23 +462,34 @@ ngx_http_dav_delete_file(ngx_tree_ctx_t static ngx_int_t +ngx_http_dav_noop(ngx_tree_ctx_t *ctx, ngx_str_t *path) +{ + return NGX_OK; +} + + +static ngx_int_t ngx_http_dav_mkcol_handler(ngx_http_request_t *r, ngx_http_dav_loc_conf_t *dlcf) { + u_char *p; size_t root; - ngx_int_t rc; ngx_str_t path; if (r->headers_in.content_length_n > 0) { + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "MKCOL with body is unsupported"); return NGX_HTTP_UNSUPPORTED_MEDIA_TYPE; } - rc = ngx_http_discard_request_body(r); - - if (rc != NGX_OK) { - return rc; + if (r->uri.data[r->uri.len - 1] != '/') { + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "MKCOL can create a collection only"); + return NGX_HTTP_CONFLICT; } - ngx_http_map_uri_to_path(r, &path, &root, 0); + p = ngx_http_map_uri_to_path(r, &path, &root, 0); + + *(p - 1) = '\0'; ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http mkcol path: \"%s\"", path.data); @@ -483,24 +505,24 @@ ngx_http_dav_mkcol_handler(ngx_http_requ } return ngx_http_dav_error(r->connection->log, ngx_errno, - NGX_HTTP_BAD_REQUEST, ngx_create_dir_n, - path.data); + NGX_HTTP_CONFLICT, ngx_create_dir_n, path.data); } static ngx_int_t ngx_http_dav_copy_move_handler(ngx_http_request_t *r) { - u_char *p, *host, *last, ch; - size_t root; + u_char *p, *desthost, *last, ch; + size_t len, root; ngx_err_t err; ngx_int_t rc, depth; - ngx_uint_t overwrite, slash; + ngx_uint_t overwrite, slash, dir; ngx_str_t path, uri; ngx_tree_ctx_t tree; ngx_file_info_t fi; - ngx_table_elt_t *dest, *over; + ngx_table_elt_t *host, *dest, *over; ngx_http_dav_copy_ctx_t copy; + ngx_http_dav_loc_conf_t *dlcf; if (r->headers_in.content_length_n > 0) { return NGX_HTTP_UNSUPPORTED_MEDIA_TYPE; @@ -514,8 +536,12 @@ ngx_http_dav_copy_move_handler(ngx_http_ return NGX_HTTP_BAD_REQUEST; } - if (dest->value.len < sizeof("http://") - 1 + r->server_name.len + 1) { - goto invalid_destination; + host = r->headers_in.host; + + if (host == NULL) { + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "client sent no \"Host\" header"); + return NGX_HTTP_BAD_REQUEST; } #if (NGX_HTTP_SSL) @@ -527,7 +553,7 @@ ngx_http_dav_copy_move_handler(ngx_http_ goto invalid_destination; } - host = dest->value.data + sizeof("https://") - 1; + desthost = dest->value.data + sizeof("https://") - 1; } else #endif @@ -538,21 +564,22 @@ ngx_http_dav_copy_move_handler(ngx_http_ goto invalid_destination; } - host = dest->value.data + sizeof("http://") - 1; + desthost = dest->value.data + sizeof("http://") - 1; } - if (ngx_strncmp(host, r->server_name.data, r->server_name.len) != 0) { + len = r->headers_in.host_name_len; + + if (ngx_strncmp(desthost, host->value.data, len) != 0) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "Destination URI \"%V\" is handled by " + "\"Destination\" URI \"%V\" is handled by " "different repository than the source URI", &dest->value); - return NGX_HTTP_BAD_REQUEST; } last = dest->value.data + dest->value.len; - for (p = host + r->server_name.len; p < last; p++) { + for (p = desthost + len; p < last; p++) { if (*p == '/') { goto destination_done; } @@ -563,15 +590,36 @@ invalid_destination: ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "client sent invalid \"Destination\" header: \"%V\"", &dest->value); - return NGX_HTTP_BAD_REQUEST; destination_done: - depth = ngx_http_dav_depth(r, 0); + if ((r->uri.data[r->uri.len - 1] == '/' && *(last - 1) != '/') + || (r->uri.data[r->uri.len - 1] != '/' && *(last - 1) == '/')) + { + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "both URI \"%V\" and \"Destination\" URI \"%V\" " + "should be either collections or non-collections", + &r->uri, &dest->value); + return NGX_HTTP_CONFLICT; + } + + depth = ngx_http_dav_depth(r, NGX_HTTP_DAV_INFINITY_DEPTH); - if (depth != 0 && depth != NGX_HTTP_DAV_INFINITY_DEPTH) { - return NGX_HTTP_BAD_REQUEST; + if (depth != NGX_HTTP_DAV_INFINITY_DEPTH) { + + if (r->method == NGX_HTTP_COPY) { + if (depth != 0) { + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "\"Depth\" header must be 0 or infinity"); + return NGX_HTTP_BAD_REQUEST; + } + + } else { + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "\"Depth\" header must be infinity"); + return NGX_HTTP_BAD_REQUEST; + } } over = r->headers_in.overwrite; @@ -595,7 +643,6 @@ destination_done: ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "client sent invalid \"Overwrite\" header: \"%V\"", &over->value); - return NGX_HTTP_BAD_REQUEST; } @@ -603,12 +650,6 @@ destination_done: overwrite_done: - rc = ngx_http_discard_request_body(r); - - if (rc != NGX_OK) { - return rc; - } - ngx_http_map_uri_to_path(r, &path, &root, 0); ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, @@ -648,26 +689,27 @@ overwrite_done: /* destination does not exist */ + overwrite = 0; + dir = 0; + } else { /* destination exists */ if (ngx_is_dir(&fi) && !slash) { + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "\"%V\" could not be %Ved to collection \"%V\"", + &r->uri, &r->method_name, &dest->value); return NGX_HTTP_CONFLICT; } if (!overwrite) { + ngx_log_error(NGX_LOG_ERR, r->connection->log, NGX_EEXIST, + "\"%s\" could not be created", copy.path.data); return NGX_HTTP_PRECONDITION_FAILED; } - ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "http delete: \"%s\"", copy.path.data); - - rc = ngx_http_dav_delete_path(r, ©.path, ngx_is_dir(&fi)); - - if (rc != NGX_OK) { - return rc; - } + dir = ngx_is_dir(&fi); } if (ngx_file_info(path.data, &fi) == -1) { @@ -676,14 +718,28 @@ overwrite_done: path.data); } - if (ngx_is_dir(&fi)) { if (r->uri.data[r->uri.len - 1] != '/') { - /* TODO: 301 */ + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "\"%V\" is collection", &r->uri); return NGX_HTTP_BAD_REQUEST; } + if (overwrite) { + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "http delete: \"%s\"", copy.path.data); + + rc = ngx_http_dav_delete_path(r, ©.path, dir); + + if (rc != NGX_OK) { + return rc; + } + } + } + + if (ngx_is_dir(&fi)) { + path.len -= 2; /* omit "/\0" */ if (r->method == NGX_HTTP_MOVE) { @@ -703,7 +759,7 @@ overwrite_done: copy.len = path.len; tree.init_handler = NULL; - tree.file_handler = ngx_http_dav_copy_file; + tree.file_handler = ngx_http_dav_copy_tree_file; tree.pre_tree_handler = ngx_http_dav_copy_dir; tree.post_tree_handler = ngx_http_dav_copy_dir_time; tree.spec_handler = ngx_http_dav_noop; @@ -726,21 +782,21 @@ overwrite_done: } else { - if (dest->value.data[dest->value.len - 1] == '/') { - return NGX_HTTP_BAD_REQUEST; - } - if (r->method == NGX_HTTP_MOVE) { if (ngx_rename_file(path.data, copy.path.data) != NGX_FILE_ERROR) { return NGX_HTTP_NO_CONTENT; } } - tree.data = © + dlcf = ngx_http_get_module_loc_conf(r, ngx_http_dav_module); + + tree.size = ngx_file_size(&fi); + tree.mtime = ngx_file_mtime(&fi); + tree.access = dlcf->access; tree.log = r->connection->log; - if (ngx_http_dav_copy_file(&tree, &path) != NGX_FILE_ERROR) { - + if (ngx_http_dav_copy_file(&tree, path.data, copy.path.data) == NGX_OK) + { if (r->method == NGX_HTTP_MOVE) { rc = ngx_http_dav_delete_path(r, &path, 0); @@ -799,9 +855,6 @@ ngx_http_dav_copy_dir_time(ngx_tree_ctx_ u_char *p, *dir; size_t len; ngx_http_dav_copy_ctx_t *copy; -#if (WIN32) - ngx_fd_t fd; -#endif ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ctx->log, 0, "http copy dir time: \"%s\"", path->data); @@ -821,7 +874,9 @@ ngx_http_dav_copy_dir_time(ngx_tree_ctx_ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ctx->log, 0, "http copy dir time to: \"%s\"", dir); -#if (WIN32) +#if (NGX_WIN32) + { + ngx_fd_t fd; fd = ngx_open_file(dir, NGX_FILE_RDWR, NGX_FILE_OPEN, 0); @@ -839,6 +894,7 @@ ngx_http_dav_copy_dir_time(ngx_tree_ctx_ ngx_log_error(NGX_LOG_ALERT, ctx->log, ngx_errno, ngx_close_file_n " \"%s\" failed", dir); } + } failed: @@ -858,15 +914,11 @@ failed: static ngx_int_t -ngx_http_dav_copy_file(ngx_tree_ctx_t *ctx, ngx_str_t *path) +ngx_http_dav_copy_tree_file(ngx_tree_ctx_t *ctx, ngx_str_t *path) { u_char *p, *file; size_t len; - off_t size; - ssize_t n; - ngx_fd_t fd, copy_fd; ngx_http_dav_copy_ctx_t *copy; - u_char buf[NGX_HTTP_DAV_COPY_BLOCK]; ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ctx->log, 0, "http copy file: \"%s\"", path->data); @@ -886,21 +938,39 @@ ngx_http_dav_copy_file(ngx_tree_ctx_t *c ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ctx->log, 0, "http copy file to: \"%s\"", file); - fd = ngx_open_file(path->data, NGX_FILE_RDONLY, NGX_FILE_OPEN, 0); + (void) ngx_http_dav_copy_file(ctx, path->data, file); + + ngx_free(file); + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_dav_copy_file(ngx_tree_ctx_t *ctx, u_char *from, u_char *to) +{ + off_t size; + ssize_t n; + ngx_fd_t fd, cfd; + ngx_int_t rc; + u_char buf[NGX_HTTP_DAV_COPY_BLOCK]; + + fd = ngx_open_file(from, NGX_FILE_RDONLY, NGX_FILE_OPEN, 0); if (fd == NGX_INVALID_FILE) { (void) ngx_http_dav_error(ctx->log, ngx_errno, 0, ngx_open_file_n, - path->data); - goto failed; + from); + return NGX_ERROR; } - copy_fd = ngx_open_file(file, NGX_FILE_WRONLY, NGX_FILE_CREATE_OR_OPEN, - ctx->access); + cfd = ngx_open_file(to, NGX_FILE_WRONLY, NGX_FILE_CREATE_OR_OPEN, + ctx->access); - if (copy_fd == NGX_INVALID_FILE) { - (void) ngx_http_dav_error(ctx->log, ngx_errno, 0, ngx_open_file_n, - file); - goto copy_failed; + rc = NGX_ERROR; + + if (cfd == NGX_INVALID_FILE) { + (void) ngx_http_dav_error(ctx->log, ngx_errno, 0, ngx_open_file_n, to); + goto failed; } for (size = ctx->size; size > 0; size -= n) { @@ -909,81 +979,39 @@ ngx_http_dav_copy_file(ngx_tree_ctx_t *c if (n == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ALERT, ctx->log, ngx_errno, - ngx_read_fd_n " \"%s\" failed", path->data); - break; + ngx_read_fd_n " \"%s\" failed", from); + goto failed; } - if (ngx_write_fd(copy_fd, buf, n) == NGX_FILE_ERROR) { + if (ngx_write_fd(cfd, buf, n) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ALERT, ctx->log, ngx_errno, - ngx_write_fd_n " \"%s\" failed", file); + ngx_write_fd_n " \"%s\" failed", to); + goto failed; } } - if (ngx_set_file_time(file, copy_fd, ctx->mtime) != NGX_OK) { + if (ngx_set_file_time(to, cfd, ctx->mtime) != NGX_OK) { ngx_log_error(NGX_LOG_ALERT, ctx->log, ngx_errno, - ngx_set_file_time_n " \"%s\" failed", file); + ngx_set_file_time_n " \"%s\" failed", to); + goto failed; } - if (ngx_close_file(copy_fd) == NGX_FILE_ERROR) { + if (ngx_close_file(cfd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ALERT, ctx->log, ngx_errno, - ngx_close_file_n " \"%s\" failed", file); + ngx_close_file_n " \"%s\" failed", to); + goto failed; } -copy_failed: - - if (ngx_close_file(fd) == NGX_FILE_ERROR) { - ngx_log_error(NGX_LOG_ALERT, ctx->log, ngx_errno, - ngx_close_file_n " \"%s\" failed", path->data); - } + rc = NGX_OK; failed: - ngx_free(file); - - return NGX_OK; -} - - -static ngx_int_t -ngx_http_dav_delete_path(ngx_http_request_t *r, ngx_str_t *path, ngx_uint_t dir) -{ - char *failed; - ngx_tree_ctx_t tree; - - if (dir) { - - tree.init_handler = NULL; - tree.file_handler = ngx_http_dav_delete_file; - tree.pre_tree_handler = ngx_http_dav_noop; - tree.post_tree_handler = ngx_http_dav_delete_dir; - tree.spec_handler = ngx_http_dav_delete_file; - tree.data = NULL; - tree.alloc = 0; - tree.log = r->connection->log; - - /* TODO: 207 */ - - if (ngx_walk_tree(&tree, path) != NGX_OK) { - return NGX_HTTP_INTERNAL_SERVER_ERROR; - } - - if (ngx_delete_dir(path->data) != NGX_FILE_ERROR) { - return NGX_OK; - } - - failed = ngx_delete_dir_n; - - } else { - - if (ngx_delete_file(path->data) != NGX_FILE_ERROR) { - return NGX_OK; - } - - failed = ngx_delete_file_n; + if (ngx_close_file(fd) == NGX_FILE_ERROR) { + ngx_log_error(NGX_LOG_ALERT, ctx->log, ngx_errno, + ngx_close_file_n " \"%s\" failed", from); } - return ngx_http_dav_error(r->connection->log, ngx_errno, - NGX_HTTP_NOT_FOUND, failed, path->data); + return rc; } @@ -1112,8 +1140,9 @@ ngx_http_dav_create_loc_conf(ngx_conf_t * conf->methods = 0; */ + conf->min_delete_depth = NGX_CONF_UNSET; + conf->access = NGX_CONF_UNSET_UINT; conf->create_full_put_path = NGX_CONF_UNSET; - conf->access = NGX_CONF_UNSET_UINT; return conf; } @@ -1128,11 +1157,14 @@ ngx_http_dav_merge_loc_conf(ngx_conf_t * ngx_conf_merge_bitmask_value(conf->methods, prev->methods, (NGX_CONF_BITMASK_SET|NGX_HTTP_DAV_OFF)); - ngx_conf_merge_value(conf->create_full_put_path, prev->create_full_put_path, - 0); + ngx_conf_merge_uint_value(conf->min_delete_depth, + prev->min_delete_depth, 0); ngx_conf_merge_uint_value(conf->access, prev->access, 0600); + 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_flv_module.c b/src/http/modules/ngx_http_flv_module.c --- a/src/http/modules/ngx_http_flv_module.c +++ b/src/http/modules/ngx_http_flv_module.c @@ -111,10 +111,9 @@ ngx_http_flv_handler(ngx_http_request_t of.errors = clcf->open_file_cache_errors; of.events = clcf->open_file_cache_events; - rc = ngx_open_cached_file(clcf->open_file_cache, &path, &of, r->pool); - - if (rc == NGX_ERROR) { - + if (ngx_open_cached_file(clcf->open_file_cache, &path, &of, r->pool) + != NGX_OK) + { switch (of.err) { case 0: diff --git a/src/http/modules/ngx_http_gzip_static_module.c b/src/http/modules/ngx_http_gzip_static_module.c --- a/src/http/modules/ngx_http_gzip_static_module.c +++ b/src/http/modules/ngx_http_gzip_static_module.c @@ -82,7 +82,7 @@ ngx_http_gzip_static_handler(ngx_http_re ngx_http_gzip_static_conf_t *gzcf; if (!(r->method & (NGX_HTTP_GET|NGX_HTTP_HEAD))) { - return NGX_HTTP_NOT_ALLOWED; + return NGX_DECLINED; } if (r->uri.data[r->uri.len - 1] == '/') { @@ -125,10 +125,9 @@ ngx_http_gzip_static_handler(ngx_http_re of.errors = clcf->open_file_cache_errors; of.events = clcf->open_file_cache_events; - rc = ngx_open_cached_file(clcf->open_file_cache, &path, &of, r->pool); - - if (rc == NGX_ERROR) { - + if (ngx_open_cached_file(clcf->open_file_cache, &path, &of, r->pool) + != NGX_OK) + { switch (of.err) { case 0: @@ -143,20 +142,18 @@ ngx_http_gzip_static_handler(ngx_http_re case NGX_EACCES: level = NGX_LOG_ERR; - rc = NGX_DECLINED; break; default: level = NGX_LOG_CRIT; - rc = NGX_DECLINED; break; } ngx_log_error(level, log, of.err, ngx_open_file_n " \"%s\" failed", path.data); - return rc; + return NGX_DECLINED; } ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0, "http static fd: %d", of.fd); 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 @@ -214,10 +214,9 @@ ngx_http_index_handler(ngx_http_request_ of.errors = clcf->open_file_cache_errors; of.events = clcf->open_file_cache_events; - rc = ngx_open_cached_file(clcf->open_file_cache, &path, &of, r->pool); - - if (rc == NGX_ERROR) { - + 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_open_file_n " \"%s\" failed", path.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 @@ -246,7 +246,9 @@ ngx_http_referer_merge_conf(ngx_conf_t * if (conf->keys == NULL) { conf->hash = prev->hash; +#if (NGX_PCRE) ngx_conf_merge_ptr_value(conf->regex, prev->regex, NULL); +#endif ngx_conf_merge_value(conf->no_referer, prev->no_referer, 0); ngx_conf_merge_value(conf->blocked_referer, prev->blocked_referer, 0); @@ -322,7 +324,9 @@ ngx_http_referer_merge_conf(ngx_conf_t * conf->hash.wc_tail = (ngx_hash_wildcard_t *) hash.hash; } +#if (NGX_PCRE) ngx_conf_merge_ptr_value(conf->regex, prev->regex, NULL); +#endif if (conf->no_referer == NGX_CONF_UNSET) { conf->no_referer = 0; diff --git a/src/http/modules/ngx_http_static_module.c b/src/http/modules/ngx_http_static_module.c --- a/src/http/modules/ngx_http_static_module.c +++ b/src/http/modules/ngx_http_static_module.c @@ -102,10 +102,9 @@ ngx_http_static_handler(ngx_http_request of.errors = clcf->open_file_cache_errors; of.events = clcf->open_file_cache_events; - rc = ngx_open_cached_file(clcf->open_file_cache, &path, &of, r->pool); - - if (rc == NGX_ERROR) { - + if (ngx_open_cached_file(clcf->open_file_cache, &path, &of, r->pool) + != NGX_OK) + { switch (of.err) { case 0: 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 @@ -300,12 +300,10 @@ static ngx_int_t ngx_http_userid_set_uid(ngx_http_request_t *r, ngx_http_userid_ctx_t *ctx, ngx_http_userid_conf_t *conf) { - u_char *cookie, *p; - size_t len; - socklen_t slen; - struct sockaddr_in sin; - ngx_str_t src, dst; - ngx_table_elt_t *set_cookie, *p3p; + u_char *cookie, *p; + size_t len; + ngx_str_t src, dst; + ngx_table_elt_t *set_cookie, *p3p; /* * TODO: in the threaded mode the sequencers should be in TLS and their @@ -327,18 +325,8 @@ ngx_http_userid_set_uid(ngx_http_request } else { if (conf->service == NGX_CONF_UNSET) { - if (r->in_addr == 0) { - slen = sizeof(struct sockaddr_in); - if (getsockname(r->connection->fd, - (struct sockaddr *) &sin, &slen) - == -1) - { - ngx_connection_error(r->connection, ngx_socket_errno, - "getsockname() failed"); - return NGX_ERROR; - } - - r->in_addr = sin.sin_addr.s_addr; + if (ngx_http_server_addr(r, NULL) != NGX_OK) { + return NGX_ERROR; } ctx->uid_set[0] = htonl(r->in_addr); diff --git a/src/http/modules/perl/nginx.pm b/src/http/modules/perl/nginx.pm --- 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.6.24'; +our $VERSION = '0.6.25'; require XSLoader; XSLoader::load('nginx', $VERSION); diff --git a/src/http/modules/perl/nginx.xs b/src/http/modules/perl/nginx.xs --- a/src/http/modules/perl/nginx.xs +++ b/src/http/modules/perl/nginx.xs @@ -613,7 +613,6 @@ sendfile(r, filename, offset = -1, bytes char *filename; int offset; size_t bytes; - ngx_int_t rc; ngx_str_t path; ngx_buf_t *b; ngx_open_file_info_t of; @@ -657,10 +656,9 @@ sendfile(r, filename, offset = -1, bytes (void) ngx_cpystrn(path.data, filename, path.len + 1); - rc = ngx_open_cached_file(clcf->open_file_cache, &path, &of, r->pool); - - if (rc == NGX_ERROR) { - + if (ngx_open_cached_file(clcf->open_file_cache, &path, &of, r->pool) + != NGX_OK) + { if (of.err == 0) { XSRETURN_EMPTY; } diff --git a/src/http/ngx_http.h b/src/http/ngx_http.h --- a/src/http/ngx_http.h +++ b/src/http/ngx_http.h @@ -47,7 +47,7 @@ typedef u_char *(*ngx_http_log_handler_p struct ngx_http_log_ctx_s { - ngx_str_t *client; + ngx_connection_t *connection; ngx_http_request_t *request; ngx_http_request_t *current_request; }; 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 @@ -93,6 +93,10 @@ static ngx_conf_deprecated_t ngx_conf_d ngx_conf_deprecated, "open_file_cache_retest", "open_file_cache_valid" }; +static ngx_conf_deprecated_t ngx_conf_deprecated_satisfy_any = { + ngx_conf_deprecated, "satisfy_any", "satisfy" +}; + static ngx_conf_enum_t ngx_http_core_request_body_in_file[] = { { ngx_string("off"), NGX_HTTP_REQUEST_BODY_FILE_OFF }, @@ -102,6 +106,13 @@ static ngx_conf_enum_t ngx_http_core_re }; +static ngx_conf_enum_t ngx_http_core_satisfy[] = { + { ngx_string("all"), NGX_HTTP_SATISFY_ALL }, + { ngx_string("any"), NGX_HTTP_SATISFY_ANY }, + { ngx_null_string, 0 } +}; + + #if (NGX_HTTP_GZIP) static ngx_conf_enum_t ngx_http_gzip_http_version[] = { @@ -404,12 +415,19 @@ static ngx_command_t ngx_http_core_comm 0, NULL }, + { ngx_string("satisfy"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_conf_set_enum_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_core_loc_conf_t, satisfy), + &ngx_http_core_satisfy }, + { ngx_string("satisfy_any"), 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_core_loc_conf_t, satisfy_any), - NULL }, + offsetof(ngx_http_core_loc_conf_t, satisfy), + &ngx_conf_deprecated_satisfy_any }, { ngx_string("internal"), NGX_HTTP_LOC_CONF|NGX_CONF_NOARGS, @@ -439,6 +457,13 @@ static ngx_command_t ngx_http_core_comm offsetof(ngx_http_core_loc_conf_t, reset_timedout_connection), NULL }, + { ngx_string("server_name_in_redirect"), + 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_core_loc_conf_t, server_name_in_redirect), + NULL }, + { ngx_string("port_in_redirect"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, ngx_conf_set_flag_slot, @@ -911,7 +936,7 @@ ngx_http_core_access_phase(ngx_http_requ clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); - if (clcf->satisfy_any == 0) { + if (clcf->satisfy == NGX_HTTP_SATISFY_ALL) { if (rc == NGX_OK) { r->phase_handler++; @@ -1471,6 +1496,38 @@ ngx_http_auth_basic_user(ngx_http_reques } +ngx_int_t +ngx_http_server_addr(ngx_http_request_t *r, ngx_str_t *s) +{ + socklen_t len; + ngx_connection_t *c; + struct sockaddr_in sin; + + /* AF_INET only */ + + c = r->connection; + + if (r->in_addr == 0) { + len = sizeof(struct sockaddr_in); + if (getsockname(c->fd, (struct sockaddr *) &sin, &len) == -1) { + ngx_connection_error(c, ngx_socket_errno, "getsockname() failed"); + return NGX_ERROR; + } + + r->in_addr = sin.sin_addr.s_addr; + } + + if (s == NULL) { + return NGX_OK; + } + + s->len = ngx_inet_ntop(c->listening->family, &r->in_addr, + s->data, INET_ADDRSTRLEN); + + return NGX_OK; +} + + #if (NGX_HTTP_GZIP) ngx_int_t @@ -1610,7 +1667,7 @@ ok: if (clcf->gzip_disable && r->headers_in.user_agent) { - if (ngx_regex_exec_array(clcf->gzip_disable, + if (ngx_regex_exec_array(clcf->gzip_disable, &r->headers_in.user_agent->value, r->connection->log) != NGX_DECLINED) @@ -1723,7 +1780,6 @@ ngx_http_subrequest(ngx_http_request_t * sr->in_addr = r->in_addr; sr->port = r->port; sr->port_text = r->port_text; - sr->server_name = r->server_name; sr->variables = r->variables; @@ -2635,7 +2691,7 @@ ngx_http_core_create_loc_conf(ngx_conf_t lcf->client_max_body_size = NGX_CONF_UNSET; lcf->client_body_buffer_size = NGX_CONF_UNSET_SIZE; lcf->client_body_timeout = NGX_CONF_UNSET_MSEC; - lcf->satisfy_any = NGX_CONF_UNSET; + lcf->satisfy = NGX_CONF_UNSET_UINT; lcf->internal = NGX_CONF_UNSET; lcf->client_body_in_file_only = NGX_CONF_UNSET; lcf->sendfile = NGX_CONF_UNSET; @@ -2652,6 +2708,7 @@ ngx_http_core_create_loc_conf(ngx_conf_t lcf->lingering_timeout = NGX_CONF_UNSET_MSEC; lcf->resolver_timeout = NGX_CONF_UNSET_MSEC; lcf->reset_timedout_connection = NGX_CONF_UNSET; + lcf->server_name_in_redirect = NGX_CONF_UNSET; lcf->port_in_redirect = NGX_CONF_UNSET; lcf->msie_padding = NGX_CONF_UNSET; lcf->msie_refresh = NGX_CONF_UNSET; @@ -2670,8 +2727,10 @@ ngx_http_core_create_loc_conf(ngx_conf_t #if (NGX_HTTP_GZIP) lcf->gzip_vary = NGX_CONF_UNSET; lcf->gzip_http_version = NGX_CONF_UNSET_UINT; +#if (NGX_PCRE) lcf->gzip_disable = NGX_CONF_UNSET_PTR; #endif +#endif return lcf; } @@ -2817,7 +2876,8 @@ ngx_http_core_merge_loc_conf(ngx_conf_t ngx_conf_merge_msec_value(conf->client_body_timeout, prev->client_body_timeout, 60000); - ngx_conf_merge_value(conf->satisfy_any, prev->satisfy_any, 0); + ngx_conf_merge_uint_value(conf->satisfy, prev->satisfy, + NGX_HTTP_SATISFY_ALL); ngx_conf_merge_value(conf->internal, prev->internal, 0); ngx_conf_merge_value(conf->client_body_in_file_only, prev->client_body_in_file_only, 0); @@ -2861,6 +2921,8 @@ ngx_http_core_merge_loc_conf(ngx_conf_t ngx_conf_merge_value(conf->reset_timedout_connection, prev->reset_timedout_connection, 0); + ngx_conf_merge_value(conf->server_name_in_redirect, + prev->server_name_in_redirect, 1); ngx_conf_merge_value(conf->port_in_redirect, prev->port_in_redirect, 1); ngx_conf_merge_value(conf->msie_padding, prev->msie_padding, 1); ngx_conf_merge_value(conf->msie_refresh, prev->msie_refresh, 0); @@ -2891,7 +2953,9 @@ ngx_http_core_merge_loc_conf(ngx_conf_t ngx_conf_merge_bitmask_value(conf->gzip_proxied, prev->gzip_proxied, (NGX_CONF_BITMASK_SET|NGX_HTTP_GZIP_PROXIED_OFF)); +#if (NGX_PCRE) ngx_conf_merge_ptr_value(conf->gzip_disable, prev->gzip_disable, NULL); +#endif #endif @@ -3074,20 +3138,6 @@ ngx_http_core_server_name(ngx_conf_t *cf ch = value[1].data[0]; if (cscf->server_name.data == NULL && value[1].len) { - if (ngx_strchr(value[1].data, '*')) { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "first server name \"%V\" must not be wildcard", - &value[1]); - return NGX_CONF_ERROR; - } - - if (value[1].data[0] == '~') { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "first server name \"%V\" " - "must not be regular expression", &value[1]); - return NGX_CONF_ERROR; - } - name = value[1]; if (ch == '.') { @@ -3106,11 +3156,6 @@ ngx_http_core_server_name(ngx_conf_t *cf ch = value[i].data[0]; - if (value[i].len == 1 && ch == '*') { - cscf->wildcard = 1; - continue; - } - if (value[i].len == 0 || (ch == '*' && (value[i].len < 3 || value[i].data[1] != '.')) || (ch == '.' && value[i].len < 2)) @@ -3126,6 +3171,13 @@ ngx_http_core_server_name(ngx_conf_t *cf &value[i]); } + if (value[i].len == 1 && ch == '*') { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "\"server_name *\" is unsupported, use " + "\"server_name_in_redirect off\" instead"); + return NGX_CONF_ERROR; + } + sn = ngx_array_push(&cscf->server_names); if (sn == NULL) { return NGX_CONF_ERROR; diff --git a/src/http/ngx_http_core_module.h b/src/http/ngx_http_core_module.h --- a/src/http/ngx_http_core_module.h +++ b/src/http/ngx_http_core_module.h @@ -24,6 +24,10 @@ #define NGX_HTTP_GZIP_PROXIED_ANY 0x0200 +#define NGX_HTTP_SATISFY_ALL 0 +#define NGX_HTTP_SATISFY_ANY 1 + + typedef struct { unsigned default_server:1; unsigned bind:1; @@ -131,7 +135,6 @@ typedef struct { unsigned regex_start:15; unsigned named_start:15; - unsigned wildcard:1; /* array of the ngx_http_listen_t, "listen" directive */ ngx_array_t listen; @@ -287,13 +290,15 @@ struct ngx_http_core_loc_conf_s { time_t keepalive_header; /* keepalive_timeout */ - ngx_flag_t satisfy_any; /* satisfy_any */ + ngx_uint_t satisfy; /* satisfy */ + ngx_flag_t internal; /* internal */ ngx_flag_t client_body_in_file_only; /* client_body_in_file_only */ ngx_flag_t sendfile; /* sendfile */ ngx_flag_t tcp_nopush; /* tcp_nopush */ ngx_flag_t tcp_nodelay; /* tcp_nodelay */ ngx_flag_t reset_timedout_connection; /* reset_timedout_connection */ + ngx_flag_t server_name_in_redirect; /* server_name_in_redirect */ ngx_flag_t port_in_redirect; /* port_in_redirect */ ngx_flag_t msie_padding; /* msie_padding */ ngx_flag_t msie_refresh; /* msie_refresh */ @@ -352,6 +357,7 @@ ngx_int_t ngx_http_set_exten(ngx_http_re u_char *ngx_http_map_uri_to_path(ngx_http_request_t *r, ngx_str_t *name, size_t *root_length, size_t reserved); ngx_int_t ngx_http_auth_basic_user(ngx_http_request_t *r); +ngx_int_t ngx_http_server_addr(ngx_http_request_t *r, ngx_str_t *s); #if (NGX_HTTP_GZIP) ngx_int_t ngx_http_gzip_ok(ngx_http_request_t *r); #endif 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 @@ -153,12 +153,16 @@ ngx_http_header_filter(ngx_http_request_ { u_char *p; size_t len; + ngx_str_t host; ngx_buf_t *b; ngx_uint_t status, i; ngx_chain_t out; ngx_list_part_t *part; ngx_table_elt_t *header; ngx_http_core_loc_conf_t *clcf; + ngx_http_core_srv_conf_t *cscf; + /* AF_INET only */ + u_char addr[INET_ADDRSTRLEN]; r->header_sent = 1; @@ -278,10 +282,26 @@ ngx_http_header_filter(ngx_http_request_ { r->headers_out.location->hash = 0; + if (clcf->server_name_in_redirect) { + cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module); + host = cscf->server_name; + + } else if (r->headers_in.host) { + host.len = r->headers_in.host_name_len; + host.data = r->headers_in.host->value.data; + + } else { + host.data = addr; + + if (ngx_http_server_addr(r, &host) != NGX_OK) { + return NGX_ERROR; + } + } + #if (NGX_HTTP_SSL) if (r->connection->ssl) { len += sizeof("Location: https://") - 1 - + r->server_name.len + + host.len + r->headers_out.location->value.len + 2; if (clcf->port_in_redirect && r->port != 443) { @@ -292,13 +312,17 @@ ngx_http_header_filter(ngx_http_request_ #endif { len += sizeof("Location: http://") - 1 - + r->server_name.len + + host.len + r->headers_out.location->value.len + 2; if (clcf->port_in_redirect && r->port != 80) { len += r->port_text->len; } } + + } else { + host.len = 0; + host.data = NULL; } if (r->chunked) { @@ -428,10 +452,8 @@ ngx_http_header_filter(ngx_http_request_ *b->last++ = CR; *b->last++ = LF; } - if (r->headers_out.location - && r->headers_out.location->value.len - && r->headers_out.location->value.data[0] == '/') - { + if (host.data) { + p = b->last + sizeof("Location: ") - 1; b->last = ngx_cpymem(b->last, "Location: http", @@ -444,7 +466,7 @@ ngx_http_header_filter(ngx_http_request_ #endif *b->last++ = ':'; *b->last++ = '/'; *b->last++ = '/'; - b->last = ngx_copy(b->last, r->server_name.data, r->server_name.len); + b->last = ngx_copy(b->last, host.data, host.len); if (clcf->port_in_redirect) { #if (NGX_HTTP_SSL) 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 @@ -173,7 +173,7 @@ ngx_http_init_connection(ngx_connection_ return; } - ctx->client = &c->addr_text; + ctx->connection = c; ctx->request = NULL; ctx->current_request = NULL; @@ -220,9 +220,7 @@ static void ngx_http_init_request(ngx_event_t *rev) { ngx_time_t *tp; - socklen_t len; ngx_uint_t i; - struct sockaddr_in sin; ngx_connection_t *c; ngx_http_request_t *r; ngx_http_in_port_t *hip; @@ -295,6 +293,8 @@ ngx_http_init_request(ngx_event_t *rev) i = 0; + r->connection = c; + if (hip->naddrs > 1) { /* @@ -302,7 +302,7 @@ ngx_http_init_request(ngx_event_t *rev) * is the "*:port" wildcard so getsockname() is needed to determine * the server address. * - * AcceptEx() already gave this address. + * AcceptEx() already has given this address. */ #if (NGX_WIN32) @@ -313,15 +313,10 @@ ngx_http_init_request(ngx_event_t *rev) } else #endif { - len = sizeof(struct sockaddr_in); - if (getsockname(c->fd, (struct sockaddr *) &sin, &len) == -1) { - ngx_connection_error(c, ngx_socket_errno, - "getsockname() failed"); + if (ngx_http_server_addr(r, NULL) != NGX_OK) { ngx_http_close_connection(c); return; } - - r->in_addr = sin.sin_addr.s_addr; } /* the last address is "*" */ @@ -345,8 +340,6 @@ ngx_http_init_request(ngx_event_t *rev) r->srv_conf = cscf->ctx->srv_conf; r->loc_conf = cscf->ctx->loc_conf; - r->server_name = cscf->server_name; - rev->handler = ngx_http_process_request_line; #if (NGX_HTTP_SSL) @@ -426,8 +419,6 @@ ngx_http_init_request(ngx_event_t *rev) c->single_connection = 1; c->destroyed = 0; - r->connection = c; - r->main = r; tp = ngx_timeofday(); @@ -499,6 +490,11 @@ ngx_http_ssl_handshake(ngx_event_t *rev) rc = ngx_ssl_handshake(c); if (rc == NGX_AGAIN) { + + if (!rev->timer_set) { + ngx_add_timer(rev, c->listening->post_accept_timeout); + } + c->ssl->handler = ngx_http_ssl_handshake_handler; return; } @@ -1318,7 +1314,8 @@ ngx_http_process_request_header(ngx_http && r->headers_in.content_length_n == -1) { ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, - "client sent POST method without \"Content-Length\" header"); + "client sent %V method without \"Content-Length\" header", + &r->method_name); ngx_http_finalize_request(r, NGX_HTTP_LENGTH_REQUIRED); return NGX_ERROR; } @@ -1515,20 +1512,10 @@ ngx_http_find_virtual_server(ngx_http_re #endif - cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module); - - if (cscf->wildcard) { - r->server_name.len = len; - r->server_name.data = host; - } - return; found: - r->server_name.len = len; - r->server_name.data = host; - r->srv_conf = cscf->ctx->srv_conf; r->loc_conf = cscf->ctx->loc_conf; @@ -2598,13 +2585,17 @@ ngx_http_log_error(ngx_log_t *log, u_cha ctx = log->data; - p = ngx_snprintf(buf, len, ", client: %V", ctx->client); + p = ngx_snprintf(buf, len, ", client: %V", &ctx->connection->addr_text); len -= p - buf; r = ctx->request; if (r) { return r->log_handler(r, ctx->current_request, p, len); + + } else { + p = ngx_snprintf(p, len, ", server: %V", + &ctx->connection->listening->addr_text); } return p; @@ -2615,15 +2606,16 @@ static u_char * ngx_http_log_error_handler(ngx_http_request_t *r, ngx_http_request_t *sr, u_char *buf, size_t len) { - char *uri_separator; - u_char *p; - ngx_http_upstream_t *u; - - if (r->server_name.data) { - p = ngx_snprintf(buf, len, ", server: %V", &r->server_name); - len -= p - buf; - buf = p; - } + char *uri_separator; + u_char *p; + ngx_http_upstream_t *u; + ngx_http_core_srv_conf_t *cscf; + + cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module); + + p = ngx_snprintf(buf, len, ", server: %V", &cscf->server_name); + len -= p - buf; + buf = p; if (r->request_line.data == NULL && r->request_start) { for (p = r->request_start; p < r->header_in->last; p++) { 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 @@ -373,7 +373,6 @@ struct ngx_http_request_s { uint32_t in_addr; ngx_uint_t port; ngx_str_t *port_text; /* ":80" */ - ngx_str_t server_name; ngx_http_virtual_names_t *virtual_names; ngx_int_t phase_handler; 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 @@ -982,7 +982,7 @@ ngx_http_script_file_code(ngx_http_scrip of.events = clcf->open_file_cache_events; if (ngx_open_cached_file(clcf->open_file_cache, &path, &of, r->pool) - == NGX_ERROR) + != NGX_OK) { if (of.err != NGX_ENOENT && of.err != NGX_ENOTDIR) { ngx_log_error(NGX_LOG_CRIT, r->connection->log, of.err, 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 @@ -47,6 +47,8 @@ static ngx_int_t ngx_http_variable_docum ngx_http_variable_value_t *v, uintptr_t data); static ngx_int_t ngx_http_variable_request_filename(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_http_variable_server_name(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); static ngx_int_t ngx_http_variable_request_method(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); static ngx_int_t ngx_http_variable_remote_user(ngx_http_request_t *r, @@ -172,8 +174,7 @@ static ngx_http_variable_t ngx_http_cor ngx_http_variable_request_filename, 0, NGX_HTTP_VAR_NOCACHEABLE, 0 }, - { ngx_string("server_name"), NULL, ngx_http_variable_request, - offsetof(ngx_http_request_t, server_name), 0, 0 }, + { ngx_string("server_name"), NULL, ngx_http_variable_server_name, 0, 0, 0 }, { ngx_string("request_method"), NULL, ngx_http_variable_request_method, 0, 0, 0 }, @@ -709,6 +710,8 @@ static ngx_int_t ngx_http_variable_host(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data) { + ngx_http_core_srv_conf_t *cscf; + if (r->host_start == NULL) { if (r->headers_in.host) { @@ -716,8 +719,10 @@ ngx_http_variable_host(ngx_http_request_ v->data = r->headers_in.host->value.data; } else { - v->len = r->server_name.len; - v->data = r->server_name.data; + cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module); + + v->len = cscf->server_name.len; + v->data = cscf->server_name.data; } } else if (r->host_end) { @@ -808,32 +813,22 @@ static ngx_int_t ngx_http_variable_server_addr(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data) { - socklen_t len; - ngx_connection_t *c; - struct sockaddr_in sin; + ngx_str_t s; - v->data = ngx_palloc(r->pool, INET_ADDRSTRLEN); - if (v->data == NULL) { + s.data = ngx_palloc(r->pool, INET_ADDRSTRLEN); + if (s.data == NULL) { return NGX_ERROR; } - c = r->connection; - - if (r->in_addr == 0) { - len = sizeof(struct sockaddr_in); - if (getsockname(c->fd, (struct sockaddr *) &sin, &len) == -1) { - ngx_connection_error(c, ngx_socket_errno, "getsockname() failed"); - return NGX_ERROR; - } - - r->in_addr = sin.sin_addr.s_addr; + if (ngx_http_server_addr(r, &s) != NGX_OK) { + return NGX_ERROR; } - v->len = ngx_inet_ntop(c->listening->family, &r->in_addr, - v->data, INET_ADDRSTRLEN); + v->len = s.len; v->valid = 1; v->no_cacheable = 0; v->not_found = 0; + v->data = s.data; return NGX_OK; } @@ -967,6 +962,24 @@ ngx_http_variable_request_filename(ngx_h static ngx_int_t +ngx_http_variable_server_name(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ + ngx_http_core_srv_conf_t *cscf; + + cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module); + + v->len = cscf->server_name.len; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + v->data = cscf->server_name.data; + + return NGX_OK; +} + + +static ngx_int_t ngx_http_variable_request_method(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data) {