diff options
author | Igor Sysoev <igor@sysoev.ru> | 2005-11-09 17:25:55 +0000 |
---|---|---|
committer | Igor Sysoev <igor@sysoev.ru> | 2005-11-09 17:25:55 +0000 |
commit | 09c684b2d53b46b6ffb706c686ca4dbed62cf6da (patch) | |
tree | 28d1d57070b5e8d95c8608d45678298d63f9621d | |
parent | 51425a465a22ad2e33e7048b880aa594c376f79c (diff) | |
download | nginx-09c684b2d53b46b6ffb706c686ca4dbed62cf6da.tar.gz nginx-09c684b2d53b46b6ffb706c686ca4dbed62cf6da.zip |
nginx-0.3.8-RELEASE importrelease-0.3.8
*) Security: nginx now checks URI got from a backend in
"X-Accel-Redirect" header line or in SSI file for the "/../" paths
and zeroes.
*) Change: nginx now does not treat the empty user name in the
"Authorization" header line as valid one.
*) Feature: the "ssl_session_timeout" directives of the
ngx_http_ssl_module and ngx_imap_ssl_module.
*) Feature: the "auth_http_header" directive of the
ngx_imap_auth_http_module.
*) Feature: the "add_header" directive.
*) Feature: the ngx_http_realip_module.
*) Feature: the new variables to use in the "log_format" directive:
$bytes_sent, $apache_bytes_sent, $status, $time_gmt, $uri,
$request_time, $request_length, $upstream_status,
$upstream_response_time, $gzip_ratio, $uid_got, $uid_set,
$connection, $pipe, and $msec. The parameters in the "%name" form
will be canceled soon.
*) Change: now the false variable values in the "if" directive are the
empty string "" and string starting with "0".
*) Bugfix: while using proxied or FastCGI-server nginx may leave
connections and temporary files with client requests in open state.
*) Bugfix: the worker processes did not flush the buffered logs on
graceful exit.
*) Bugfix: if the request URI was changes by the "rewrite" directive
and the request was proxied in location given by regular expression,
then the incorrect request was transferred to backend; the bug had
appeared in 0.2.6.
*) Bugfix: the "expires" directive did not remove the previous
"Expires" header.
*) Bugfix: nginx may stop to accept requests if the "rtsig" method and
several worker processes were used.
*) Bugfix: the "\"" and "\'" escape symbols were incorrectly handled in
SSI commands.
*) Bugfix: if the response was ended just after the SSI command and
gzipping was used, then the response did not transferred complete or
did not transferred at all.
54 files changed, 2301 insertions, 997 deletions
diff --git a/auto/cc/bcc b/auto/cc/bcc index af108bb21..83b2d60dd 100644 --- a/auto/cc/bcc +++ b/auto/cc/bcc @@ -63,5 +63,9 @@ ngx_binout="-e" ngx_objext="obj" ngx_binext=".exe" +ngx_long_start='@&&| + ' +ngx_long_end='|' + ngx_regex_dirsep='\\' ngx_dirsep="\\" diff --git a/auto/cc/conf b/auto/cc/conf index 37f2d2e42..82854d804 100644 --- a/auto/cc/conf +++ b/auto/cc/conf @@ -11,6 +11,9 @@ ngx_binout="-o " ngx_objext="o" ngx_binext= +ngx_long_start= +ngx_long_end= + ngx_regex_dirsep="\/" ngx_dirsep='/' @@ -22,6 +25,9 @@ ngx_tab=' \ ' ngx_spacer= +ngx_long_regex_cont=$ngx_regex_cont +ngx_long_cont=$ngx_cont + . auto/cc/name if test -n "$CFLAGS"; then diff --git a/auto/cc/icc b/auto/cc/icc index d3a151c6e..6af9713b2 100644 --- a/auto/cc/icc +++ b/auto/cc/icc @@ -38,6 +38,7 @@ CFLAGS="$CFLAGS $IPO" CORE_LINK="$CORE_LINK $IPO" CORE_LINK="$CORE_LINK -opt_report_file=$NGX_OBJS/opt_report_file" + case $CPU in pentium) # optimize for Pentium and Athlon @@ -104,7 +105,7 @@ CFLAGS="$CFLAGS -wd1418" CFLAGS="$CFLAGS -wd1419" case "$NGX_ICC_VER" in - 8.* | 9.*) + 9.*) # "cc" clobber ignored, warnings for Liunx's htons() CFLAGS="$CFLAGS -wd1469" # explicit conversion of a 64-bit integral type to a smaller @@ -119,6 +120,15 @@ case "$NGX_ICC_VER" in CFLAGS="$CFLAGS -wd1595" ;; + 8.*) + # "cc" clobber ignored, warnings for Liunx's htons() + CFLAGS="$CFLAGS -wd1469" + + # STUB + # non-POD class type passed through ellipsis, Linux only ? + CFLAGS="$CFLAGS -wd1595" + ;; + *) ;; esac diff --git a/auto/cc/msvc b/auto/cc/msvc index 0fa5df9d7..29c40c79b 100644 --- a/auto/cc/msvc +++ b/auto/cc/msvc @@ -114,5 +114,13 @@ ngx_binout="-Fe" ngx_objext="obj" ngx_binext=".exe" +ngx_long_start='@<< + ' +ngx_long_end='<<' +ngx_long_regex_cont=' \ + ' +ngx_long_cont=' + ' + #ngx_regex_dirsep='\\' #ngx_dirsep="\\" @@ -26,7 +26,9 @@ if [ "$CC" = wcl386 ]; then echo MAKE = wmake >> $NGX_MAKEFILE ngx_regex_cont=' ' + ngx_long_regex_cont=' ' ngx_cont=' ' + ngx_long_cont=' ' ngx_tab=' ' fi @@ -170,22 +172,22 @@ ngx_deps=`echo $ngx_all_objs $ngx_modules_obj $ngx_res $LINK_DEPS \ -e "s/\//$ngx_regex_dirsep/g"` ngx_objs=`echo $ngx_all_objs $ngx_modules_obj \ - | sed -e "s/ *\([^ ][^ ]*\)/$ngx_regex_cont\1/g" \ + | sed -e "s/ *\([^ ][^ ]*\)/$ngx_long_regex_cont\1/g" \ -e "s/\//$ngx_regex_dirsep/g"` ngx_libs=${CORE_LIBS:+`echo $NGX_LD_OPT $CORE_LIBS \ - | sed -e "s/\//$ngx_regex_dirsep/g" -e "s/^/$ngx_regex_cont/"`} + | sed -e "s/\//$ngx_regex_dirsep/g" -e "s/^/$ngx_long_regex_cont/"`} ngx_link=${CORE_LINK:+`echo $CORE_LINK \ - | sed -e "s/\//$ngx_regex_dirsep/g" -e "s/^/$ngx_regex_cont/"`} + | sed -e "s/\//$ngx_regex_dirsep/g" -e "s/^/$ngx_long_regex_cont/"`} cat << END >> $NGX_MAKEFILE $NGX_OBJS${ngx_dirsep}nginx${ngx_binext}: $ngx_deps$ngx_spacer - \$(LINK) ${ngx_binout}$NGX_OBJS${ngx_dirsep}nginx$ngx_cont$ngx_objs$ngx_libs$ngx_link + \$(LINK) ${ngx_long_start}${ngx_binout}$NGX_OBJS${ngx_dirsep}nginx$ngx_long_cont$ngx_objs$ngx_libs$ngx_link $ngx_rcc - +${ngx_long_end} END diff --git a/auto/modules b/auto/modules index 46f356cc0..26b108761 100644 --- a/auto/modules +++ b/auto/modules @@ -139,6 +139,12 @@ if [ $HTTP_ACCESS = YES ]; then HTTP_SRCS="$HTTP_SRCS $HTTP_ACCESS_SRCS" fi +if [ $HTTP_REALIP = YES ]; then + have=NGX_HTTP_REALIP . auto/have + HTTP_MODULES="$HTTP_MODULES $HTTP_REALIP_MODULE" + HTTP_SRCS="$HTTP_SRCS $HTTP_REALIP_SRCS" +fi + if [ $HTTP_STATUS = YES ]; then have=NGX_HTTP_STATUS . auto/have HTTP_MODULES="$HTTP_MODULES $HTTP_STATUS_MODULE" diff --git a/auto/options b/auto/options index 2960f09c3..35c7ad300 100644 --- a/auto/options +++ b/auto/options @@ -50,6 +50,7 @@ HTTP_GZIP=YES HTTP_SSL=NO HTTP_SSI=YES HTTP_POSTPONE=NO +HTTP_REALIP=NO HTTP_ACCESS=YES HTTP_AUTH_BASIC=YES HTTP_USERID=YES @@ -125,6 +126,7 @@ do --http-fastcgi-temp-path=*) NGX_HTTP_FASTCGI_TEMP_PATH="$value" ;; --with-http_ssl_module) HTTP_SSL=YES ;; + --with-http_realip_module) HTTP_REALIP=YES ;; --without-http_charset_module) HTTP_CHARSET=NO ;; --without-http_gzip_module) HTTP_GZIP=NO ;; --without-http_ssi_module) HTTP_SSI=NO ;; diff --git a/auto/sources b/auto/sources index c4aec701c..8aa596ca2 100644 --- a/auto/sources +++ b/auto/sources @@ -310,6 +310,10 @@ HTTP_USERID_FILTER_MODULE=ngx_http_userid_filter_module HTTP_USERID_SRCS=src/http/modules/ngx_http_userid_filter_module.c +HTTP_REALIP_MODULE=ngx_http_realip_module +HTTP_REALIP_SRCS=src/http/modules/ngx_http_realip_module.c + + HTTP_ACCESS_MODULE=ngx_http_access_module HTTP_ACCESS_SRCS=src/http/modules/ngx_http_access_module.c diff --git a/conf/nginx.conf b/conf/nginx.conf index 8d65445eb..783ea2e7d 100644 --- a/conf/nginx.conf +++ b/conf/nginx.conf @@ -1,13 +1,13 @@ #user nobody; -worker_processes 3; +worker_processes 1; #error_log logs/error.log; #pid logs/nginx.pid; events { - connections 1024; + worker_connections 1024; } @@ -25,7 +25,7 @@ http { server { listen 80; - charset koi8-r; + #charset koi8-r; #access_log logs/access.log; diff --git a/docs/xml/change_log_conf.xml b/docs/xml/change_log_conf.xml index 4abb779fd..f97ef045b 100644 --- a/docs/xml/change_log_conf.xml +++ b/docs/xml/change_log_conf.xml @@ -15,6 +15,7 @@ <bugfix>Исправление</bugfix> <feature>Добавление</feature> <change>Изменение</change> + <security>Безопасность</security> <workaround>Изменение</workaround> </changes> @@ -25,6 +26,7 @@ <bugfix>Bugfix</bugfix> <feature>Feature</feature> <change>Change</change> + <security>Security</security> <workaround>Workaround</workaround> <month> Jan </month> diff --git a/docs/xml/nginx/changes.xml b/docs/xml/nginx/changes.xml index 3b1aa1088..dfac2a065 100644 --- a/docs/xml/nginx/changes.xml +++ b/docs/xml/nginx/changes.xml @@ -9,6 +9,181 @@ <title lang="en">nginx changelog</title> +<changes ver="0.3.8" date="09.11.2005"> + +<change type="security"> +<para lang="ru"> +nginx теперь проверят URI, полученные от бэкенда в строке "X-Accel-Redirect" +в заголовке ответа, или в SSI файле на наличие путей "/../" и нулей. +</para> +<para lang="en"> +nginx now checks URI got from a backend in "X-Accel-Redirect" header line +or in SSI file for the "/../" paths and zeroes. +</para> +</change> + +<change type="change"> +<para lang="ru"> +nginx теперь не воспринимает пустое имя как правильное +в строке "Authorization" в заголовке запроса. +</para> +<para lang="en"> +nginx now does not treat the empty user name in the "Authorization" header +line as valid one. +</para> +</change> + +<change type="feature"> +<para lang="ru"> +директива ssl_session_timeout модулей +ngx_http_ssl_module и ngx_imap_ssl_module. +</para> +<para lang="en"> +the "ssl_session_timeout" directives +of the ngx_http_ssl_module and ngx_imap_ssl_module. +</para> +</change> + +<change type="feature"> +<para lang="ru"> +директива auth_http_header модуля ngx_imap_auth_http_module. +</para> +<para lang="en"> +the "auth_http_header" directive of the ngx_imap_auth_http_module. +</para> +</change> + +<change type="feature"> +<para lang="ru"> +директива add_header. +</para> +<para lang="en"> +the "add_header" directive. +</para> +</change> + +<change type="feature"> +<para lang="ru"> +модуль ngx_http_realip_module. +</para> +<para lang="en"> +the ngx_http_realip_module. +directives. +</para> +</change> + +<change type="feature"> +<para lang="ru"> +новые переменные для использования в директиве log_format: +$bytes_sent, $apache_bytes_sent, $status, $time_gmt, +$uri, $request_time, $request_length, +$upstream_status, $upstream_response_time, +$gzip_ratio, +$uid_got, $uid_set, +$connection, $pipe и $msec. +Параметры в виде "%name" скоро будут упразднены. +</para> +<para lang="en"> +the new variables to use in the "log_format" directive: +$bytes_sent, $apache_bytes_sent, $status, $time_gmt, +$uri, $request_time, $request_length, +$upstream_status, $upstream_response_time, +$gzip_ratio, +$uid_got, $uid_set, +$connection, $pipe, and $msec. +The parameters in the "%name" form will be canceled soon. +</para> +</change> + +<change type="change"> +<para lang="ru"> +в директиве "if" ложными значениями переменных теперь являются +пустая строка "" и строки, начинающиеся на "0". +</para> +<para lang="en"> +now the false variable values in the "if" directive are the empty string "" +and string starting with "0". +</para> +</change> + +<change type="bugfix"> +<para lang="ru"> +при работает с проксированными или FastCGI-серверами nginx мог оставлять +открытыми соединения и временные файлы с запросами клиентов. +</para> +<para lang="en"> +while using proxied or FastCGI-server nginx may leave connections +and temporary files with client requests in open state. +</para> +</change> + +<change type="bugfix"> +<para lang="ru"> +рабочие процессы не сбрасывал буферизированные логи при плавном выходе. +</para> +<para lang="en"> +the worker processes did not flush the buffered logs on graceful exit. +</para> +</change> + +<change type="bugfix"> +<para lang="ru"> +если URI запроса изменялось с помощью rewrite, а затем запрос проксировался +в location, заданном регулярным выражением, то бэкенду передавался +неверный запрос; +ошибка появилась в 0.2.6. +</para> +<para lang="en"> +if the request URI was changes by the "rewrite" directive and the request +was proxied in location given by regular expression, then the incorrect +request was transferred to backend; +bug appeared in 0.2.6. +</para> +</change> + +<change type="bugfix"> +<para lang="ru"> +директива expires не удаляла уже установленную строку заголовка "Expires". +</para> +<para lang="en"> +the "expires" directive did not remove the previous "Expires" header. +</para> +</change> + +<change type="bugfix"> +<para lang="ru"> +при использовании метода rtsig и нескольких рабочих процессах nginx +мог перестать принимать запросы. +</para> +<para lang="en"> +nginx may stop to accept requests if the "rtsig" method and several worker +processes were used. +</para> +</change> + +<change type="bugfix"> +<para lang="ru"> +в SSI командах неверно обрабатывались строки "\"" и "\'". +</para> +<para lang="en"> +the "\"" and "\'" escape symbols were incorrectly handled in SSI commands. +</para> +</change> + +<change type="bugfix"> +<para lang="ru"> +если ответ заканчивался сразу же после SSI команды, то при использовании +сжатия ответ передавался не до конца или не передавался вообще. +</para> +<para lang="en"> +if the response was ended just after the SSI command and gzipping was used, +then the response did not transferred complete or did not transferred at all. +</para> +</change> + +</changes> + + <changes ver="0.3.7" date="27.10.2005"> <change type="feature"> diff --git a/src/core/nginx.h b/src/core/nginx.h index 78ae2a78a..966d405b0 100644 --- a/src/core/nginx.h +++ b/src/core/nginx.h @@ -8,7 +8,7 @@ #define _NGINX_H_INCLUDED_ -#define NGINX_VER "nginx/0.3.7" +#define NGINX_VER "nginx/0.3.8" #define NGINX_VAR "NGINX" #define NGX_OLDPID_EXT ".oldbin" diff --git a/src/core/ngx_conf_file.h b/src/core/ngx_conf_file.h index b09d8cc6a..adf203a6f 100644 --- a/src/core/ngx_conf_file.h +++ b/src/core/ngx_conf_file.h @@ -82,7 +82,7 @@ struct ngx_command_s { void *post; }; -#define ngx_null_command { ngx_null_string, 0, NULL, 0, 0, NULL } +#define ngx_null_command { ngx_null_string, 0, NULL, 0, 0, NULL } struct ngx_open_file_s { diff --git a/src/core/ngx_string.c b/src/core/ngx_string.c index 1164cc445..a236654d7 100644 --- a/src/core/ngx_string.c +++ b/src/core/ngx_string.c @@ -190,7 +190,9 @@ ngx_vsnprintf(u_char *buf, size_t max, const char *fmt, va_list args) case 'V': s = va_arg(args, ngx_str_t *); - len = (buf + s->len < last) ? s->len : (size_t) (last - buf); + len = s->len & 0xffff; + len = (buf + len < last) ? len : (size_t) (last - buf); + buf = ngx_cpymem(buf, s->data, len); fmt++; diff --git a/src/core/ngx_string.h b/src/core/ngx_string.h index 545c6cc85..b019e3357 100644 --- a/src/core/ngx_string.h +++ b/src/core/ngx_string.h @@ -46,7 +46,7 @@ typedef struct { #define ngx_strncmp(s1, s2, n) strncmp((const char *) s1, (const char *) s2, n) -/* msvc and icc compile strcmp() to inline loop */ +/* msvc and icc7 compile strcmp() to inline loop */ #define ngx_strcmp(s1, s2) strcmp((const char *) s1, (const char *) s2) @@ -55,20 +55,55 @@ typedef struct { /* - * msvc and icc compile memset() to the inline "rep stos" + * msvc and icc7 compile memset() to the inline "rep stos" * while ZeroMemory() and bzero() are the calls. - * icc may also inline several mov's of a zeroed register for small blocks. + * icc7 may also inline several mov's of a zeroed register for small blocks. */ #define ngx_memzero(buf, n) (void) memset(buf, 0, n) #define ngx_memset(buf, c, n) (void) memset(buf, c, n) -/* msvc and icc compile memcpy() to the inline "rep movs" */ +/* + * gcc3, msvc, and icc7 compile memcpy() to the inline "rep movs". + * gcc3 compiles memcpy(d, s, 4) to the inline "mov"es. + * icc8 compile memcpy(d, s, 4) to the inline "mov"es or XMM moves. + */ #define ngx_memcpy(dst, src, n) (void) memcpy(dst, src, n) #define ngx_cpymem(dst, src, n) ((u_char *) memcpy(dst, src, n)) + (n) -/* msvc and icc compile memcmp() to the inline loop */ +#if ( __INTEL_COMPILER >= 800 ) + +/* + * the simple inline cycle copies the variable length strings up to 16 + * bytes faster than icc8 autodetecting _intel_fast_memcpy() + */ + +static ngx_inline u_char * +ngx_copy(u_char *dst, u_char *src, size_t len) +{ + if (len < 17) { + + while (len) { + *dst++ = *src++; + len--; + } + + return dst; + + } else { + return ngx_cpymem(dst, src, len); + } +} + +#else + +#define ngx_copy ngx_cpymem + +#endif + + +/* msvc and icc7 compile memcmp() to the inline loop */ #define ngx_memcmp memcmp diff --git a/src/event/modules/ngx_rtsig_module.c b/src/event/modules/ngx_rtsig_module.c index e57a5ddc9..a3891e8d4 100644 --- a/src/event/modules/ngx_rtsig_module.c +++ b/src/event/modules/ngx_rtsig_module.c @@ -288,7 +288,7 @@ ngx_rtsig_process_events(ngx_cycle_t *cycle, ngx_msec_t timer, ngx_uint_t flags) ngx_int_t instance; ngx_err_t err; siginfo_t si; - ngx_event_t *rev, *wev; + ngx_event_t *rev, *wev, **queue; struct timespec ts, *tp; struct sigaction sa; ngx_connection_t *c; @@ -381,15 +381,32 @@ ngx_rtsig_process_events(ngx_cycle_t *cycle, ngx_msec_t timer, ngx_uint_t flags) } if ((si.si_band & (POLLIN|POLLHUP|POLLERR)) && rev->active) { + rev->ready = 1; - rev->handler(rev); + + if (flags & NGX_POST_EVENTS) { + queue = (ngx_event_t **) (rev->accept ? + &ngx_posted_accept_events : &ngx_posted_events); + + ngx_locked_post_event(rev, queue); + + } else { + rev->handler(rev); + } } wev = c->write; if ((si.si_band & (POLLOUT|POLLHUP|POLLERR)) && wev->active) { + wev->ready = 1; - wev->handler(wev); + + if (flags & NGX_POST_EVENTS) { + ngx_locked_post_event(wev, &ngx_posted_events); + + } else { + wev->handler(wev); + } } return NGX_OK; diff --git a/src/event/ngx_event.c b/src/event/ngx_event.c index 4775e5d9b..51471998a 100644 --- a/src/event/ngx_event.c +++ b/src/event/ngx_event.c @@ -48,6 +48,7 @@ ngx_atomic_t *ngx_connection_counter = &connection_counter; ngx_atomic_t *ngx_accept_mutex_ptr; +ngx_atomic_t *ngx_accept_mutex_last_owner; ngx_atomic_t *ngx_accept_mutex; ngx_uint_t ngx_accept_mutex_held; ngx_msec_t ngx_accept_mutex_delay; @@ -249,10 +250,6 @@ ngx_process_events_and_timers(ngx_cycle_t *cycle) ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "timer delta: %M", delta); - if (delta) { - ngx_event_expire_timers(); - } - if (ngx_posted_accept_events) { ngx_event_process_posted(cycle, &ngx_posted_accept_events); } @@ -261,6 +258,10 @@ ngx_process_events_and_timers(ngx_cycle_t *cycle) *ngx_accept_mutex = 0; } + if (delta) { + ngx_event_expire_timers(); + } + ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "posted events %p", ngx_posted_events); @@ -470,6 +471,7 @@ ngx_event_module_init(ngx_cycle_t *cycle) /* TODO: adjust cache line size, 128 is P4 cache line size */ size = 128 /* ngx_accept_mutex */ + + 128 /* ngx_accept_mutex_last_owner */ + 128; /* ngx_connection_counter */ #if (NGX_STAT_STUB) @@ -489,16 +491,17 @@ ngx_event_module_init(ngx_cycle_t *cycle) } ngx_accept_mutex_ptr = (ngx_atomic_t *) shared; - ngx_connection_counter = (ngx_atomic_t *) (shared + 128); + ngx_accept_mutex_last_owner = (ngx_atomic_t *) (shared + 1 * 128); + ngx_connection_counter = (ngx_atomic_t *) (shared + 2 * 128); #if (NGX_STAT_STUB) - ngx_stat_accepted = (ngx_atomic_t *) (shared + 2 * 128); - ngx_stat_handled = (ngx_atomic_t *) (shared + 3 * 128); - ngx_stat_requests = (ngx_atomic_t *) (shared + 4 * 128); - ngx_stat_active = (ngx_atomic_t *) (shared + 5 * 128); - ngx_stat_reading = (ngx_atomic_t *) (shared + 6 * 128); - ngx_stat_writing = (ngx_atomic_t *) (shared + 7 * 128); + ngx_stat_accepted = (ngx_atomic_t *) (shared + 3 * 128); + ngx_stat_handled = (ngx_atomic_t *) (shared + 4 * 128); + ngx_stat_requests = (ngx_atomic_t *) (shared + 5 * 128); + ngx_stat_active = (ngx_atomic_t *) (shared + 6 * 128); + ngx_stat_reading = (ngx_atomic_t *) (shared + 7 * 128); + ngx_stat_writing = (ngx_atomic_t *) (shared + 8 * 128); #endif @@ -1082,10 +1085,10 @@ ngx_event_init_conf(ngx_cycle_t *cycle, void *conf) #endif #if (NGX_HAVE_RTSIG) ngx_uint_t rtsig; + ngx_core_conf_t *ccf; #endif ngx_int_t i, connections; ngx_module_t *module; - ngx_core_conf_t *ccf; ngx_event_module_t *event_module; connections = NGX_CONF_UNSET_UINT; @@ -1189,8 +1192,6 @@ ngx_event_init_conf(ngx_cycle_t *cycle, void *conf) return NGX_CONF_OK; } -#endif - if (ecf->accept_mutex) { return NGX_CONF_OK; } @@ -1205,6 +1206,12 @@ ngx_event_init_conf(ngx_cycle_t *cycle, void *conf) "the \"rtsig\" method requires \"accept_mutex\" to be on"); return NGX_CONF_ERROR; + +#else + + return NGX_CONF_OK; + +#endif } diff --git a/src/event/ngx_event.h b/src/event/ngx_event.h index af3e4a458..215463578 100644 --- a/src/event/ngx_event.h +++ b/src/event/ngx_event.h @@ -438,6 +438,7 @@ typedef struct { extern ngx_atomic_t *ngx_connection_counter; extern ngx_atomic_t *ngx_accept_mutex_ptr; +extern ngx_atomic_t *ngx_accept_mutex_last_owner; extern ngx_atomic_t *ngx_accept_mutex; extern ngx_uint_t ngx_accept_mutex_held; extern ngx_msec_t ngx_accept_mutex_delay; @@ -474,8 +475,6 @@ extern ngx_module_t ngx_event_core_module; void ngx_event_accept(ngx_event_t *ev); ngx_int_t ngx_trylock_accept_mutex(ngx_cycle_t *cycle); -ngx_int_t ngx_disable_accept_events(ngx_cycle_t *cycle); -ngx_int_t ngx_enable_accept_events(ngx_cycle_t *cycle); u_char *ngx_accept_log_error(ngx_log_t *log, u_char *buf, size_t len); diff --git a/src/event/ngx_event_accept.c b/src/event/ngx_event_accept.c index 238a49415..f1745c15a 100644 --- a/src/event/ngx_event_accept.c +++ b/src/event/ngx_event_accept.c @@ -13,6 +13,8 @@ #define NGX_SOCKLEN 512 +static ngx_int_t ngx_enable_accept_events(ngx_cycle_t *cycle); +static ngx_int_t ngx_disable_accept_events(ngx_cycle_t *cycle); static void ngx_close_accepted_connection(ngx_connection_t *c); @@ -262,15 +264,20 @@ ngx_trylock_accept_mutex(ngx_cycle_t *cycle) ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "accept mutex locked"); - if (!ngx_accept_mutex_held) { - if (ngx_enable_accept_events(cycle) == NGX_ERROR) { - *ngx_accept_mutex = 0; - return NGX_ERROR; - } + if (ngx_accept_mutex_held + && (!(ngx_event_flags & NGX_USE_RTSIG_EVENT) + || *ngx_accept_mutex_last_owner == (ngx_atomic_t) ngx_pid)) + { + return NGX_OK; + } - ngx_accept_mutex_held = 1; + if (ngx_enable_accept_events(cycle) == NGX_ERROR) { + *ngx_accept_mutex = 0; + return NGX_ERROR; } + ngx_accept_mutex_held = 1; + return NGX_OK; } @@ -286,7 +293,7 @@ ngx_trylock_accept_mutex(ngx_cycle_t *cycle) } -ngx_int_t +static ngx_int_t ngx_enable_accept_events(ngx_cycle_t *cycle) { ngx_uint_t i; @@ -299,10 +306,17 @@ ngx_enable_accept_events(ngx_cycle_t *cycle) c = ls[i].connection; if (ngx_event_flags & NGX_USE_RTSIG_EVENT) { + + if (ngx_accept_mutex_held) { + c->read->disabled = 1; + } + if (ngx_add_conn(c) == NGX_ERROR) { return NGX_ERROR; } + *ngx_accept_mutex_last_owner = ngx_pid; + } else { if (ngx_add_event(c->read, NGX_READ_EVENT, 0) == NGX_ERROR) { return NGX_ERROR; @@ -314,7 +328,7 @@ ngx_enable_accept_events(ngx_cycle_t *cycle) } -ngx_int_t +static ngx_int_t ngx_disable_accept_events(ngx_cycle_t *cycle) { ngx_uint_t i; diff --git a/src/http/modules/ngx_http_access_module.c b/src/http/modules/ngx_http_access_module.c index b02e8cfd1..0e3430385 100644 --- a/src/http/modules/ngx_http_access_module.c +++ b/src/http/modules/ngx_http_access_module.c @@ -14,7 +14,7 @@ typedef struct { in_addr_t mask; in_addr_t addr; - unsigned deny; + ngx_uint_t deny; /* unsigned deny:1; */ } ngx_http_access_rule_t; @@ -106,7 +106,7 @@ ngx_http_access_handler(ngx_http_request_t *r) for (i = 0; i < alcf->rules->nelts; i++) { ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "%08XD %08XD %08XD", + "access: %08XD %08XD %08XD", sin->sin_addr.s_addr, rule[i].mask, rule[i].addr); if ((sin->sin_addr.s_addr & rule[i].mask) == rule[i].addr) { diff --git a/src/http/modules/ngx_http_fastcgi_module.c b/src/http/modules/ngx_http_fastcgi_module.c index d58c7c664..160aacbc3 100644 --- a/src/http/modules/ngx_http_fastcgi_module.c +++ b/src/http/modules/ngx_http_fastcgi_module.c @@ -17,6 +17,7 @@ typedef struct { ngx_str_t index; + ngx_array_t *flushes; ngx_array_t *params_len; ngx_array_t *params; ngx_array_t *params_source; @@ -111,9 +112,8 @@ static ngx_int_t ngx_http_fastcgi_add_variables(ngx_conf_t *cf); static void *ngx_http_fastcgi_create_loc_conf(ngx_conf_t *cf); static char *ngx_http_fastcgi_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child); -static ngx_http_variable_value_t * - ngx_http_fastcgi_script_name_variable(ngx_http_request_t *r, - uintptr_t data); +static ngx_int_t ngx_http_fastcgi_script_name_variable(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); static char *ngx_http_fastcgi_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); @@ -410,6 +410,9 @@ ngx_http_fastcgi_create_request(ngx_http_request_t *r) if (flcf->params_len) { ngx_memzero(&le, sizeof(ngx_http_script_engine_t)); + ngx_http_script_flush_no_cachable_variables(r, flcf->flushes); + le.flushed = 1; + le.ip = flcf->params_len->elts; le.request = r; @@ -507,6 +510,7 @@ ngx_http_fastcgi_create_request(ngx_http_request_t *r) e.ip = flcf->params->elts; e.pos = b->last; e.request = r; + e.flushed = 1; le.ip = flcf->params_len->elts; @@ -597,8 +601,8 @@ ngx_http_fastcgi_create_request(ngx_http_request_t *r) *b->last++ = ch; } - b->last = ngx_cpymem(b->last, header[i].value.data, - header[i].value.len); + b->last = ngx_copy(b->last, header[i].value.data, + header[i].value.len); } } @@ -1634,9 +1638,10 @@ ngx_http_fastcgi_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) } if (conf->params_source == NULL) { - conf->params_source = prev->params_source; + conf->flushes = prev->flushes; conf->params_len = prev->params_len; conf->params = prev->params; + conf->params_source = prev->params_source; if (conf->params_source == NULL) { return NGX_CONF_OK; @@ -1647,7 +1652,7 @@ ngx_http_fastcgi_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) if (conf->params_len == NULL) { return NGX_CONF_ERROR; } - + conf->params = ngx_array_create(cf->pool, 512, 1); if (conf->params == NULL) { return NGX_CONF_ERROR; @@ -1729,6 +1734,7 @@ ngx_http_fastcgi_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) sc.cf = cf; sc.source = &src[i].value; + sc.flushes = &conf->flushes; sc.lengths = &conf->params_len; sc.values = &conf->params; @@ -1764,38 +1770,36 @@ ngx_http_fastcgi_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) } -static ngx_http_variable_value_t * -ngx_http_fastcgi_script_name_variable(ngx_http_request_t *r, uintptr_t data) +static ngx_int_t +ngx_http_fastcgi_script_name_variable(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) { u_char *p; - ngx_http_variable_value_t *vv; ngx_http_fastcgi_loc_conf_t *flcf; - vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t)); - if (vv == NULL) { - return NULL; - } - - vv->value = 0; + v->valid = 1; + v->no_cachable = 0; + v->not_found = 0; flcf = ngx_http_get_module_loc_conf(r, ngx_http_fastcgi_module); if (r->uri.data[r->uri.len - 1] != '/') { - vv->text = r->uri; - return vv; + v->len = r->uri.len; + v->data = r->uri.data; + return NGX_OK; } - vv->text.len = r->uri.len + flcf->index.len; + v->len = r->uri.len + flcf->index.len; - vv->text.data = ngx_palloc(r->pool, vv->text.len); - if (vv->text.data == NULL) { - return NULL; + v->data = ngx_palloc(r->pool, v->len); + if (v->data == NULL) { + return NGX_ERROR; } - p = ngx_cpymem(vv->text.data, r->uri.data, r->uri.len); + p = ngx_copy(v->data, r->uri.data, r->uri.len); ngx_memcpy(p, flcf->index.data, flcf->index.len); - return vv; + return NGX_OK; } @@ -1860,7 +1864,7 @@ ngx_http_fastcgi_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) clcf->handler = ngx_http_fastcgi_handler; - lcf->upstream.location = &clcf->name; + lcf->upstream.location = clcf->name; if (clcf->name.data[clcf->name.len - 1] == '/') { clcf->auto_redirect = 1; diff --git a/src/http/modules/ngx_http_geo_module.c b/src/http/modules/ngx_http_geo_module.c index 6d94a069e..a3638e4bf 100644 --- a/src/http/modules/ngx_http_geo_module.c +++ b/src/http/modules/ngx_http_geo_module.c @@ -65,31 +65,34 @@ ngx_module_t ngx_http_geo_module = { static ngx_http_variable_value_t ngx_http_geo_null_value = - { 0, ngx_string("0") }; + ngx_http_variable(""); /* AF_INET only */ -static ngx_http_variable_value_t * -ngx_http_geo_variable(ngx_http_request_t *r, uintptr_t data) +static ngx_int_t +ngx_http_geo_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v, + uintptr_t data) { ngx_radix_tree_t *tree = (ngx_radix_tree_t *) data; struct sockaddr_in *sin; - ngx_http_variable_value_t *var; + ngx_http_variable_value_t *vv; sin = (struct sockaddr_in *) r->connection->sockaddr; ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http geo started"); - var = (ngx_http_variable_value_t *) + vv = (ngx_http_variable_value_t *) ngx_radix32tree_find(tree, ntohl(sin->sin_addr.s_addr)); + *v = *vv; + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "http geo: %V %V", &r->connection->addr_text, &var->text); + "http geo: %V %V", &r->connection->addr_text, v); - return var; + return NGX_OK; } @@ -182,7 +185,7 @@ ngx_http_geo_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) static char * ngx_http_geo(ngx_conf_t *cf, ngx_command_t *dummy, void *conf) { - ngx_int_t rc, n; + ngx_int_t rc; ngx_str_t *value, file; ngx_uint_t i; ngx_inet_cidr_t cidrin; @@ -226,30 +229,18 @@ ngx_http_geo(ngx_conf_t *cf, ngx_command_t *dummy, void *conf) cidrin.mask = ntohl(cidrin.mask); } - n = ngx_atoi(value[1].data, value[1].len); - var = NULL; v = geo->values.elts; - if (n == NGX_ERROR) { - for (i = 0; i < geo->values.nelts; i++) { - if (v[i]->text.len != value[1].len) { - continue; - } - - if (ngx_strncmp(value[1].data, v[i]->text.data, value[1].len) == 0) - { - var = v[i]; - break; - } + for (i = 0; i < geo->values.nelts; i++) { + if ((size_t) v[i]->len != value[1].len) { + continue; } - } else { - for (i = 0; i < geo->values.nelts; i++) { - if (v[i]->value == (ngx_uint_t) n) { - var = v[i]; - break; - } + if (ngx_strncmp(value[1].data, v[i]->data, value[1].len) == 0) + { + var = v[i]; + break; } } @@ -259,13 +250,15 @@ ngx_http_geo(ngx_conf_t *cf, ngx_command_t *dummy, void *conf) return NGX_CONF_ERROR; } - var->text.len = value[1].len; - var->text.data = ngx_pstrdup(geo->pool, &value[1]); - if (var->text.data == NULL) { + var->len = value[1].len; + var->data = ngx_pstrdup(geo->pool, &value[1]); + if (var->data == NULL) { return NGX_CONF_ERROR; } - var->value = (n == NGX_ERROR) ? 0 : n; + var->valid = 1; + var->no_cachable = 0; + var->not_found = 0; v = ngx_array_push(&geo->values); if (v == NULL) { @@ -294,7 +287,7 @@ ngx_http_geo(ngx_conf_t *cf, ngx_command_t *dummy, void *conf) ngx_conf_log_error(NGX_LOG_WARN, cf, 0, "duplicate parameter \"%V\", value: \"%V\", " "old value: \"%V\"", - &value[0], &var->text, &old->text); + &value[0], var, old); rc = ngx_radix32tree_delete(geo->tree, cidrin.addr, cidrin.mask); diff --git a/src/http/modules/ngx_http_gzip_filter_module.c b/src/http/modules/ngx_http_gzip_filter_module.c index 923dd1724..adf7005c2 100644 --- a/src/http/modules/ngx_http_gzip_filter_module.c +++ b/src/http/modules/ngx_http_gzip_filter_module.c @@ -79,7 +79,9 @@ static void ngx_http_gzip_error(ngx_http_gzip_ctx_t *ctx); static u_char *ngx_http_gzip_log_ratio(ngx_http_request_t *r, u_char *buf, ngx_http_log_op_t *op); -static ngx_int_t ngx_http_gzip_add_log_formats(ngx_conf_t *cf); +static ngx_int_t ngx_http_gzip_add_variables(ngx_conf_t *cf); +static ngx_int_t ngx_http_gzip_ratio_variable(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); static ngx_int_t ngx_http_gzip_filter_init(ngx_cycle_t *cycle); static void *ngx_http_gzip_create_conf(ngx_conf_t *cf); @@ -199,7 +201,7 @@ static ngx_command_t ngx_http_gzip_filter_commands[] = { static ngx_http_module_t ngx_http_gzip_filter_module_ctx = { - ngx_http_gzip_add_log_formats, /* preconfiguration */ + ngx_http_gzip_add_variables, /* preconfiguration */ NULL, /* postconfiguration */ NULL, /* create main configuration */ @@ -256,6 +258,7 @@ struct gztrailer { #endif +static ngx_str_t ngx_http_gzip_ratio = ngx_string("gzip_ratio"); static ngx_str_t ngx_http_gzip_no_cache = ngx_string("no-cache"); static ngx_str_t ngx_http_gzip_no_store = ngx_string("no-store"); static ngx_str_t ngx_http_gzip_private = ngx_string("private"); @@ -956,10 +959,18 @@ ngx_http_gzip_error(ngx_http_gzip_ctx_t *ctx) static ngx_int_t -ngx_http_gzip_add_log_formats(ngx_conf_t *cf) +ngx_http_gzip_add_variables(ngx_conf_t *cf) { + ngx_http_variable_t *var; ngx_http_log_op_name_t *op; + var = ngx_http_add_variable(cf, &ngx_http_gzip_ratio, 0); + if (var == NULL) { + return NGX_ERROR; + } + + var->handler = ngx_http_gzip_ratio_variable; + for (op = ngx_http_gzip_log_fmt_ops; op->name.len; op++) { /* void */ } op->run = NULL; @@ -976,6 +987,50 @@ ngx_http_gzip_add_log_formats(ngx_conf_t *cf) static ngx_int_t +ngx_http_gzip_ratio_variable(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ + ngx_uint_t zint, zfrac; + ngx_http_gzip_ctx_t *ctx; + + v->valid = 1; + v->no_cachable = 0; + v->not_found = 0; + + ctx = ngx_http_get_module_ctx(r, ngx_http_gzip_filter_module); + + if (ctx == NULL || ctx->zout == 0) { + v->not_found = 1; + return NGX_OK; + } + + v->data = ngx_palloc(r->pool, NGX_INT32_LEN + 3); + if (v->data == NULL) { + return NGX_ERROR; + } + + zint = (ngx_uint_t) (ctx->zin / ctx->zout); + zfrac = (ngx_uint_t) ((ctx->zin * 100 / ctx->zout) % 100); + + if ((ctx->zin * 1000 / ctx->zout) % 10 > 4) { + + /* the rounding, e.g., 2.125 to 2.13 */ + + zfrac++; + + if (zfrac > 99) { + zint++; + zfrac = 0; + } + } + + v->len = ngx_sprintf(v->data, "%ui.%02ui", zint, zfrac) - v->data; + + return NGX_OK; +} + + +static ngx_int_t ngx_http_gzip_filter_init(ngx_cycle_t *cycle) { ngx_http_next_header_filter = ngx_http_top_header_filter; diff --git a/src/http/modules/ngx_http_headers_filter_module.c b/src/http/modules/ngx_http_headers_filter_module.c index 0855990a5..da9061be8 100644 --- a/src/http/modules/ngx_http_headers_filter_module.c +++ b/src/http/modules/ngx_http_headers_filter_module.c @@ -10,7 +10,9 @@ typedef struct { - time_t expires; + time_t expires; + ngx_str_t cache_control; + ngx_array_t *headers; } ngx_http_headers_conf_t; @@ -22,20 +24,31 @@ typedef struct { static ngx_int_t ngx_http_headers_filter_init(ngx_cycle_t *cycle); static void *ngx_http_headers_create_conf(ngx_conf_t *cf); static char *ngx_http_headers_merge_conf(ngx_conf_t *cf, - void *parent, void *child); + void *parent, void *child); static char *ngx_http_headers_expires(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); +static char *ngx_http_headers_add(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf); static ngx_command_t ngx_http_headers_filter_commands[] = { { ngx_string("expires"), - NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF + |NGX_CONF_TAKE1, ngx_http_headers_expires, NGX_HTTP_LOC_CONF_OFFSET, 0, NULL}, + { ngx_string("add_header"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF + |NGX_CONF_TAKE2, + ngx_http_headers_add, + NGX_HTTP_LOC_CONF_OFFSET, + 0, + NULL}, + ngx_null_command }; @@ -79,7 +92,7 @@ ngx_http_headers_filter(ngx_http_request_t *r) { size_t len; ngx_uint_t i; - ngx_table_elt_t *expires, *cc, **ccp; + ngx_table_elt_t *expires, *cc, **ccp, *h, *out; ngx_http_headers_conf_t *conf; if ((r->headers_out.status != NGX_HTTP_OK @@ -117,7 +130,8 @@ ngx_http_headers_filter(ngx_http_request_t *r) if (ccp == NULL) { if (ngx_array_init(&r->headers_out.cache_control, r->pool, - 1, sizeof(ngx_table_elt_t *)) != NGX_OK) + 1, sizeof(ngx_table_elt_t *)) + != NGX_OK) { return NGX_ERROR; } @@ -188,6 +202,50 @@ ngx_http_headers_filter(ngx_http_request_t *r) } } + if (conf->cache_control.len) { + + ccp = r->headers_out.cache_control.elts; + + if (ccp == NULL) { + + if (ngx_array_init(&r->headers_out.cache_control, r->pool, + 1, sizeof(ngx_table_elt_t *)) + != NGX_OK) + { + return NGX_ERROR; + } + } + + ccp = ngx_array_push(&r->headers_out.cache_control); + if (ccp == NULL) { + return NGX_ERROR; + } + + cc = ngx_list_push(&r->headers_out.headers); + if (cc == NULL) { + return NGX_ERROR; + } + + cc->hash = 1; + cc->key.len = sizeof("Cache-Control") - 1; + cc->key.data = (u_char *) "Cache-Control"; + cc->value = conf->cache_control; + + *ccp = cc; + } + + if (conf->headers) { + h = conf->headers->elts; + for (i = 0; i < conf->headers->nelts; i++) { + out = ngx_list_push(&r->headers_out.headers); + if (out == NULL) { + return NGX_ERROR; + } + + *out = h[i]; + } + } + return ngx_http_next_header_filter(r); } @@ -207,11 +265,19 @@ ngx_http_headers_create_conf(ngx_conf_t *cf) { ngx_http_headers_conf_t *conf; - conf = ngx_palloc(cf->pool, sizeof(ngx_http_headers_conf_t)); + conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_headers_conf_t)); if (conf == NULL) { return NGX_CONF_ERROR; } + /* + * set by ngx_pcalloc(): + * + * conf->cache_control.len = 0; + * conf->cache_control.data = NULL; + * conf->headers = NULL; + */ + conf->expires = NGX_HTTP_EXPIRES_UNSET; return conf; @@ -229,6 +295,14 @@ ngx_http_headers_merge_conf(ngx_conf_t *cf, void *parent, void *child) NGX_HTTP_EXPIRES_OFF : prev->expires; } + if (conf->cache_control.data == NULL) { + conf->cache_control = prev->cache_control; + } + + if (conf->headers == NULL) { + conf->headers = prev->headers; + } + return NGX_CONF_OK; } @@ -287,3 +361,38 @@ ngx_http_headers_expires(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) return NGX_CONF_OK; } + + +static char * +ngx_http_headers_add(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) +{ + ngx_http_headers_conf_t *hcf = conf; + + ngx_str_t *value; + ngx_table_elt_t *h; + + value = cf->args->elts; + + if (ngx_strcasecmp(value[1].data, "cache-control") == 0) { + hcf->cache_control = value[2]; + return NGX_CONF_OK; + } + + if (hcf->headers == NULL) { + hcf->headers = ngx_array_create(cf->pool, 1, sizeof(ngx_table_elt_t)); + if (hcf->headers == NULL) { + return NGX_CONF_ERROR; + } + } + + h = ngx_array_push(hcf->headers); + if (h == NULL) { + return NGX_CONF_ERROR; + } + + h->hash = 1; + h->key = value[1]; + h->value = value[2]; + + return NGX_CONF_OK; +} diff --git a/src/http/modules/ngx_http_index_module.c b/src/http/modules/ngx_http_index_module.c index b7daa6d41..4847cb700 100644 --- a/src/http/modules/ngx_http_index_module.c +++ b/src/http/modules/ngx_http_index_module.c @@ -180,6 +180,7 @@ ngx_http_index_handler(ngx_http_request_t *r) e.ip = index[i].lengths->elts; e.request = r; + e.flushed = 1; /* 1 byte for terminating '\0' */ @@ -298,7 +299,7 @@ ngx_http_index_handler(ngx_http_request_t *r) return NGX_HTTP_INTERNAL_SERVER_ERROR; } - last = ngx_cpymem(uri.data, r->uri.data, r->uri.len); + last = ngx_copy(uri.data, r->uri.data, r->uri.len); ngx_memcpy(last, ctx->index.data, ctx->index.len - 1); } @@ -476,7 +477,7 @@ ngx_http_index_set_index(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) ilcf->max_index_len = index->name.len; } - /* include the terminating '\0' to the length to use ngx_memcpy() */ + /* include the terminating '\0' to the length to use ngx_copy() */ index->name.len++; continue; diff --git a/src/http/modules/ngx_http_log_module.c b/src/http/modules/ngx_http_log_module.c index f4993b5a9..e83207042 100644 --- a/src/http/modules/ngx_http_log_module.c +++ b/src/http/modules/ngx_http_log_module.c @@ -10,6 +10,35 @@ #include <nginx.h> + +typedef struct { + ngx_str_t name; + ngx_array_t *ops; /* array of ngx_http_log_op_t */ +} ngx_http_log_fmt_t; + +typedef struct { + ngx_array_t formats; /* array of ngx_http_log_fmt_t */ + ngx_uint_t combined_used; /* unsigned combined_used:1 */ +} ngx_http_log_main_conf_t; + +typedef struct { + ngx_open_file_t *file; + ngx_array_t *ops; /* array of ngx_http_log_op_t */ +} ngx_http_log_t; + +typedef struct { + ngx_array_t *logs; /* array of ngx_http_log_t */ + ngx_uint_t off; /* unsigned off:1 */ +} ngx_http_log_loc_conf_t; + + +typedef struct { + ngx_str_t name; + size_t len; + ngx_http_log_op_run_pt run; +} ngx_http_log_var_t; + + static u_char *ngx_http_log_addr(ngx_http_request_t *r, u_char *buf, ngx_http_log_op_t *op); static u_char *ngx_http_log_connection(ngx_http_request_t *r, u_char *buf, @@ -24,10 +53,10 @@ static u_char *ngx_http_log_request_time(ngx_http_request_t *r, u_char *buf, ngx_http_log_op_t *op); static u_char *ngx_http_log_status(ngx_http_request_t *r, u_char *buf, ngx_http_log_op_t *op); -static u_char *ngx_http_log_length(ngx_http_request_t *r, u_char *buf, - ngx_http_log_op_t *op); -static u_char *ngx_http_log_apache_length(ngx_http_request_t *r, u_char *buf, +static u_char *ngx_http_log_bytes_sent(ngx_http_request_t *r, u_char *buf, ngx_http_log_op_t *op); +static u_char *ngx_http_log_apache_bytes_sent(ngx_http_request_t *r, + u_char *buf, ngx_http_log_op_t *op); static u_char *ngx_http_log_request_length(ngx_http_request_t *r, u_char *buf, ngx_http_log_op_t *op); @@ -83,7 +112,9 @@ static char *ngx_http_log_set_log(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); static char *ngx_http_log_set_format(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); -static ngx_int_t ngx_http_log_init(ngx_cycle_t *cycle); +static char *ngx_http_log_compile_format(ngx_conf_t *cf, + ngx_array_t *ops, ngx_array_t *args, ngx_uint_t s); +static ngx_int_t ngx_http_log_init(ngx_conf_t *cf); static ngx_command_t ngx_http_log_commands[] = { @@ -108,7 +139,7 @@ static ngx_command_t ngx_http_log_commands[] = { ngx_http_module_t ngx_http_log_module_ctx = { ngx_http_log_set_formats, /* preconfiguration */ - NULL, /* postconfiguration */ + ngx_http_log_init, /* postconfiguration */ ngx_http_log_create_main_conf, /* create main configuration */ NULL, /* init main configuration */ @@ -127,7 +158,7 @@ ngx_module_t ngx_http_log_module = { ngx_http_log_commands, /* module directives */ NGX_HTTP_MODULE, /* module type */ NULL, /* init master */ - ngx_http_log_init, /* init module */ + NULL, /* init module */ NULL, /* init process */ NULL, /* init thread */ NULL, /* exit thread */ @@ -137,21 +168,34 @@ ngx_module_t ngx_http_log_module = { }; -static ngx_str_t http_access_log = ngx_string(NGX_HTTP_LOG_PATH); +static ngx_str_t http_access_log = ngx_string(NGX_HTTP_LOG_PATH); -static ngx_str_t ngx_http_combined_fmt = -#if 0 - ngx_string("$remote_addr - $remote_user [%time] " - "\"$request\" %status %apache_length " +static ngx_str_t ngx_http_combined_fmt = + ngx_string("$remote_addr - $remote_user [$time_gmt] " + "\"$request\" $status $apache_bytes_sent " "\"$http_referer\" \"$http_user_agent\""); -#endif - ngx_string("%addr - - [%time] " - "\"%request\" %status %apache_length " - "\"%{referer}i\" \"%{user-agent}i\""); -ngx_http_log_op_name_t ngx_http_log_fmt_ops[] = { +static ngx_http_log_var_t ngx_http_log_vars[] = { + { ngx_string("connection"), NGX_ATOMIC_T_LEN, ngx_http_log_connection }, + { ngx_string("pipe"), 1, ngx_http_log_pipe }, + { ngx_string("time_gmt"), sizeof("28/Sep/1970:12:00:00 +0600") - 1, + ngx_http_log_time }, + { ngx_string("msec"), NGX_TIME_T_LEN + 4, ngx_http_log_msec }, + { ngx_string("request_time"), NGX_TIME_T_LEN, ngx_http_log_request_time }, + { ngx_string("status"), 3, ngx_http_log_status }, + { ngx_string("bytes_sent"), NGX_OFF_T_LEN, ngx_http_log_bytes_sent }, + { ngx_string("apache_bytes_sent"), NGX_OFF_T_LEN, + ngx_http_log_apache_bytes_sent }, + { ngx_string("request_length"), NGX_SIZE_T_LEN, + ngx_http_log_request_length }, + + { ngx_null_string, 0, NULL } +}; + + +ngx_http_log_op_name_t ngx_http_log_fmt_ops[] = { { ngx_string("addr"), INET_ADDRSTRLEN - 1, NULL, NULL, ngx_http_log_addr }, { ngx_string("conn"), NGX_ATOMIC_T_LEN, NULL, NULL, ngx_http_log_connection }, @@ -162,9 +206,10 @@ ngx_http_log_op_name_t ngx_http_log_fmt_ops[] = { { ngx_string("request_time"), NGX_TIME_T_LEN, NULL, NULL, ngx_http_log_request_time }, { ngx_string("status"), 3, NULL, NULL, ngx_http_log_status }, - { ngx_string("length"), NGX_OFF_T_LEN, NULL, NULL, ngx_http_log_length }, + { ngx_string("length"), NGX_OFF_T_LEN, + NULL, NULL, ngx_http_log_bytes_sent }, { ngx_string("apache_length"), NGX_OFF_T_LEN, - NULL, NULL, ngx_http_log_apache_length }, + NULL, NULL, ngx_http_log_apache_bytes_sent }, { ngx_string("request_length"), NGX_SIZE_T_LEN, NULL, NULL, ngx_http_log_request_length }, @@ -376,14 +421,15 @@ ngx_http_log_status(ngx_http_request_t *r, u_char *buf, ngx_http_log_op_t *op) static u_char * -ngx_http_log_length(ngx_http_request_t *r, u_char *buf, ngx_http_log_op_t *op) +ngx_http_log_bytes_sent(ngx_http_request_t *r, u_char *buf, + ngx_http_log_op_t *op) { return ngx_sprintf(buf, "%O", r->connection->sent); } static u_char * -ngx_http_log_apache_length(ngx_http_request_t *r, u_char *buf, +ngx_http_log_apache_bytes_sent(ngx_http_request_t *r, u_char *buf, ngx_http_log_op_t *op) { off_t length; @@ -792,14 +838,11 @@ ngx_http_log_variable_getlen(ngx_http_request_t *r, uintptr_t data) value = ngx_http_get_indexed_variable(r, data); - if (value == NULL - || value == NGX_HTTP_VAR_NOT_FOUND - || value->text.len == 0) - { + if (value == NULL || value->not_found) { return 1; } - return value->text.len; + return value->len; } @@ -810,15 +853,12 @@ ngx_http_log_variable(ngx_http_request_t *r, u_char *buf, ngx_http_log_op_t *op) value = ngx_http_get_indexed_variable(r, op->data); - if (value == NULL - || value == NGX_HTTP_VAR_NOT_FOUND - || value->text.len == 0) - { + if (value == NULL || value->not_found) { *buf = '-'; return buf + 1; } - return ngx_cpymem(buf, value->text.data, value->text.len); + return ngx_cpymem(buf, value->data, value->len); } @@ -839,8 +879,7 @@ ngx_http_log_create_main_conf(ngx_conf_t *cf) { ngx_http_log_main_conf_t *conf; - char *rc; - ngx_str_t *value; + ngx_http_log_fmt_t *fmt; conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_log_main_conf_t)); if (conf == NULL) { @@ -848,38 +887,21 @@ ngx_http_log_create_main_conf(ngx_conf_t *cf) } if (ngx_array_init(&conf->formats, cf->pool, 4, sizeof(ngx_http_log_fmt_t)) - == NGX_ERROR) + != NGX_OK) { return NGX_CONF_ERROR; } - cf->args->nelts = 0; - - value = ngx_array_push(cf->args); - if (value == NULL) { - return NGX_CONF_ERROR; - } - - value->len = 0; - value->data = NULL; - - value = ngx_array_push(cf->args); - if (value == NULL) { - return NGX_CONF_ERROR; - } - - value->len = sizeof("combined") - 1; - value->data = (u_char *) "combined"; - - value = ngx_array_push(cf->args); - if (value == NULL) { + fmt = ngx_array_push(&conf->formats); + if (fmt == NULL) { return NGX_CONF_ERROR; } - *value = ngx_http_combined_fmt; + fmt->name.len = sizeof("combined") - 1; + fmt->name.data = (u_char *) "combined"; - rc = ngx_http_log_set_format(cf, NULL, conf); - if (rc != NGX_CONF_OK) { + fmt->ops = ngx_array_create(cf->pool, 16, sizeof(ngx_http_log_op_t)); + if (fmt->ops == NULL) { return NGX_CONF_ERROR; } @@ -947,6 +969,7 @@ ngx_http_log_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) /* the default "combined" format */ log->ops = fmt[0].ops; + lmcf->combined_used = 1; } } @@ -997,6 +1020,7 @@ ngx_http_log_set_log(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) } else { name.len = sizeof("combined") - 1; name.data = (u_char *) "combined"; + lmcf->combined_used = 1; } fmt = lmcf->formats.elts; @@ -1058,20 +1082,16 @@ ngx_http_log_set_format(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { ngx_http_log_main_conf_t *lmcf = conf; - u_char *data, *p, *fname, ch; - size_t i, len, fname_len; - ngx_str_t *value, var, arg, *a; - ngx_uint_t s, f, bracket; - ngx_http_log_op_t *op; - ngx_http_log_fmt_t *fmt; - ngx_http_log_op_name_t *name; + ngx_str_t *value; + ngx_uint_t i; + ngx_http_log_fmt_t *fmt; value = cf->args->elts; fmt = lmcf->formats.elts; - for (f = 0; f < lmcf->formats.nelts; f++) { - if (fmt[f].name.len == value[1].len - && ngx_strcmp(fmt->name.data, value[1].data) == 0) + for (i = 0; i < lmcf->formats.nelts; i++) { + if (fmt[i].name.len == value[1].len + && ngx_strcmp(fmt[i].name.data, value[1].data) == 0) { return "duplicate \"log_format\" name"; } @@ -1084,20 +1104,38 @@ ngx_http_log_set_format(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) fmt->name = value[1]; - fmt->ops = ngx_array_create(cf->pool, 20, sizeof(ngx_http_log_op_t)); + fmt->ops = ngx_array_create(cf->pool, 16, sizeof(ngx_http_log_op_t)); if (fmt->ops == NULL) { return NGX_CONF_ERROR; } - arg.data = NULL; + return ngx_http_log_compile_format(cf, fmt->ops, cf->args, 2); +} + + +static char * +ngx_http_log_compile_format(ngx_conf_t *cf, ngx_array_t *ops, + ngx_array_t *args, ngx_uint_t s) +{ + u_char *data, *p, *fname, *arg_data, ch; + size_t i, len, fname_len, arg_len; + ngx_str_t *value, var, *a; + ngx_uint_t bracket; + ngx_http_log_op_t *op; + ngx_http_log_var_t *v; + ngx_http_log_op_name_t *name; + static ngx_uint_t warn; - for (s = 2; s < cf->args->nelts; s++) { + value = args->elts; + arg_data = NULL; + + for ( /* void */ ; s < args->nelts; s++) { i = 0; while (i < value[s].len) { - op = ngx_array_push(fmt->ops); + op = ngx_array_push(ops); if (op == NULL) { return NGX_CONF_ERROR; } @@ -1114,22 +1152,29 @@ ngx_http_log_set_format(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) if (value[s].data[i] == '{') { i++; - arg.data = &value[s].data[i]; + arg_data = &value[s].data[i]; while (i < value[s].len && value[s].data[i] != '}') { i++; } - arg.len = &value[s].data[i] - arg.data; + arg_len = &value[s].data[i] - arg_data; - if (i == value[s].len || arg.len == 0) { + if (i == value[s].len || arg_len == 0) { goto invalid; } i++; } else { - arg.len = 0; + arg_len = 0; + } + + if (warn == 0) { + ngx_conf_log_error(NGX_LOG_WARN, cf, 0, + "the parameters in the \"%%name\" form are deprecated, " + "use the \"$variable\" instead"); + warn = 1; } fname = &value[s].data[i]; @@ -1156,7 +1201,7 @@ ngx_http_log_set_format(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) && ngx_strncmp(name->name.data, fname, fname_len) == 0) { if (name->compile == NULL) { - if (arg.len) { + if (arg_len) { fname[fname_len] = '\0'; ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "\"%s\" must not have argument", @@ -1172,7 +1217,7 @@ ngx_http_log_set_format(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) break; } - if (arg.len == 0) { + if (arg_len == 0) { fname[fname_len] = '\0'; ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "\"%s\" requires argument", @@ -1185,7 +1230,9 @@ ngx_http_log_set_format(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) return NGX_CONF_ERROR; } - *a = arg; + a->len = arg_len; + a->data = arg_data; + if (name->compile(cf, op, a) == NGX_ERROR) { return NGX_CONF_ERROR; } @@ -1198,6 +1245,8 @@ ngx_http_log_set_format(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) goto invalid; } + continue; + } else if (value[s].data[i] == '$') { if (++i == value[s].len) { @@ -1249,47 +1298,64 @@ ngx_http_log_set_format(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) goto invalid; } + for (v = ngx_http_log_vars; v->name.len; v++) { + + if (v->name.len == var.len + && ngx_strncmp(v->name.data, var.data, var.len) == 0) + { + op->len = v->len; + op->getlen = NULL; + op->run = v->run; + op->data = 0; + + goto found; + } + } + if (ngx_http_log_variable_compile(cf, op, &var) != NGX_OK) { return NGX_CONF_ERROR; } - } else { - i++; + found: - while (i < value[s].len - && value[s].data[i] != '$' - && value[s].data[i] != '%') - { - i++; - } + continue; + } - len = &value[s].data[i] - data; + i++; - if (len) { + while (i < value[s].len + && value[s].data[i] != '$' + && value[s].data[i] != '%') + { + i++; + } - op->len = len; - op->getlen = NULL; + len = &value[s].data[i] - data; - if (len <= sizeof(uintptr_t)) { - op->run = ngx_http_log_copy_short; - op->data = 0; + if (len) { - while (len--) { - op->data <<= 8; - op->data |= data[len]; - } + op->len = len; + op->getlen = NULL; - } else { - op->run = ngx_http_log_copy_long; + if (len <= sizeof(uintptr_t)) { + op->run = ngx_http_log_copy_short; + op->data = 0; - p = ngx_palloc(cf->pool, len); - if (p == NULL) { - return NGX_CONF_ERROR; - } + while (len--) { + op->data <<= 8; + op->data |= data[len]; + } - ngx_memcpy(p, data, len); - op->data = (uintptr_t) p; + } else { + op->run = ngx_http_log_copy_long; + + p = ngx_palloc(cf->pool, len); + if (p == NULL) { + return NGX_CONF_ERROR; } + + ngx_memcpy(p, data, len); + op->data = (uintptr_t) p; } } } @@ -1306,11 +1372,37 @@ invalid: static ngx_int_t -ngx_http_log_init(ngx_cycle_t *cycle) +ngx_http_log_init(ngx_conf_t *cf) { + ngx_str_t *value; + ngx_array_t a; + ngx_http_log_fmt_t *fmt; + ngx_http_log_main_conf_t *lmcf; ngx_http_core_main_conf_t *cmcf; - cmcf = ngx_http_cycle_get_module_main_conf(cycle, ngx_http_core_module); + lmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_log_module); + + if (lmcf->combined_used) { + if (ngx_array_init(&a, cf->pool, 1, sizeof(ngx_str_t)) != NGX_OK) { + return NGX_ERROR; + } + + value = ngx_array_push(&a); + if (value == NULL) { + return NGX_ERROR; + } + + *value = ngx_http_combined_fmt; + fmt = lmcf->formats.elts; + + if (ngx_http_log_compile_format(cf, fmt->ops, &a, 0) + != NGX_CONF_OK) + { + return NGX_ERROR; + } + } + + cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module); cmcf->log_handler = ngx_http_log_handler; diff --git a/src/http/modules/ngx_http_log_module.h b/src/http/modules/ngx_http_log_module.h index c414bc4ac..01cfb5418 100644 --- a/src/http/modules/ngx_http_log_module.h +++ b/src/http/modules/ngx_http_log_module.h @@ -35,12 +35,6 @@ struct ngx_http_log_op_s { typedef struct { ngx_str_t name; - ngx_array_t *ops; /* array of ngx_http_log_op_t */ -} ngx_http_log_fmt_t; - - -typedef struct { - ngx_str_t name; size_t len; ngx_http_log_op_compile_pt compile; ngx_http_log_op_getlen_pt getlen; @@ -48,23 +42,6 @@ typedef struct { } ngx_http_log_op_name_t; -typedef struct { - ngx_array_t formats; /* array of ngx_http_log_fmt_t */ -} ngx_http_log_main_conf_t; - - -typedef struct { - ngx_open_file_t *file; - ngx_array_t *ops; /* array of ngx_http_log_op_t */ -} ngx_http_log_t; - - -typedef struct { - ngx_array_t *logs; /* array of ngx_http_log_t */ - ngx_uint_t off; /* unsigned off:1 */ -} ngx_http_log_loc_conf_t; - - extern ngx_http_log_op_name_t ngx_http_log_fmt_ops[]; diff --git a/src/http/modules/ngx_http_proxy_module.c b/src/http/modules/ngx_http_proxy_module.c index 8c4231a53..26f08315e 100644 --- a/src/http/modules/ngx_http_proxy_module.c +++ b/src/http/modules/ngx_http_proxy_module.c @@ -37,6 +37,7 @@ typedef struct { ngx_peers_t *peers; + ngx_array_t *flushes; ngx_array_t *headers_set_len; ngx_array_t *headers_set; ngx_hash_t *headers_set_hash; @@ -75,13 +76,13 @@ static void ngx_http_proxy_abort_request(ngx_http_request_t *r); static void ngx_http_proxy_finalize_request(ngx_http_request_t *r, ngx_int_t rc); -static ngx_http_variable_value_t * - ngx_http_proxy_host_variable(ngx_http_request_t *r, uintptr_t data); -static ngx_http_variable_value_t * - ngx_http_proxy_port_variable(ngx_http_request_t *r, uintptr_t data); -static ngx_http_variable_value_t * +static ngx_int_t ngx_http_proxy_host_variable(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_http_proxy_port_variable(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_http_proxy_add_x_forwarded_for_variable(ngx_http_request_t *r, - uintptr_t data); + ngx_http_variable_value_t *v, uintptr_t data); static ngx_int_t ngx_http_proxy_rewrite_redirect(ngx_http_request_t *r, ngx_table_elt_t *h, size_t prefix); @@ -431,7 +432,7 @@ ngx_http_proxy_create_request(ngx_http_request_t *r) escape = 0; - loc_len = r->valid_location ? u->conf->location->len : 0; + loc_len = r->valid_location ? u->conf->location.len : 0; if (u->conf->uri.len == 0 && r->valid_unparsed_uri) { len += r->unparsed_uri.len; @@ -447,8 +448,11 @@ ngx_http_proxy_create_request(ngx_http_request_t *r) ngx_memzero(&e, sizeof(ngx_http_script_engine_t)); + ngx_http_script_flush_no_cachable_variables(r, plcf->flushes); + le.ip = plcf->headers_set_len->elts; le.request = r; + le.flushed = 1; while (*(uintptr_t *) le.ip) { while (*(uintptr_t *) le.ip) { @@ -506,16 +510,16 @@ ngx_http_proxy_create_request(ngx_http_request_t *r) /* the request line */ - b->last = ngx_cpymem(b->last, method.data, method.len); + b->last = ngx_copy(b->last, method.data, method.len); u->uri.data = b->last; if (u->conf->uri.len == 0 && r->valid_unparsed_uri) { - b->last = ngx_cpymem(b->last, r->unparsed_uri.data, - r->unparsed_uri.len); + b->last = ngx_copy(b->last, r->unparsed_uri.data, r->unparsed_uri.len); + } else { if (r->valid_location) { - b->last = ngx_cpymem(b->last, u->conf->uri.data, u->conf->uri.len); + b->last = ngx_copy(b->last, u->conf->uri.data, u->conf->uri.len); } if (escape) { @@ -524,13 +528,13 @@ ngx_http_proxy_create_request(ngx_http_request_t *r) b->last += r->uri.len - loc_len + escape; } else { - b->last = ngx_cpymem(b->last, r->uri.data + loc_len, - r->uri.len - loc_len); + b->last = ngx_copy(b->last, r->uri.data + loc_len, + r->uri.len - loc_len); } if (r->args.len > 0) { *b->last++ = '?'; - b->last = ngx_cpymem(b->last, r->args.data, r->args.len); + b->last = ngx_copy(b->last, r->args.data, r->args.len); } } @@ -543,6 +547,7 @@ ngx_http_proxy_create_request(ngx_http_request_t *r) e.ip = plcf->headers_set->elts; e.pos = b->last; e.request = r; + e.flushed = 1; le.ip = plcf->headers_set_len->elts; @@ -600,13 +605,12 @@ ngx_http_proxy_create_request(ngx_http_request_t *r) continue; } - b->last = ngx_cpymem(b->last, header[i].key.data, - header[i].key.len); + b->last = ngx_copy(b->last, header[i].key.data, header[i].key.len); *b->last++ = ':'; *b->last++ = ' '; - b->last = ngx_cpymem(b->last, header[i].value.data, - header[i].value.len); + b->last = ngx_copy(b->last, header[i].value.data, + header[i].value.len); *b->last++ = CR; *b->last++ = LF; @@ -735,6 +739,7 @@ ngx_http_proxy_process_status_line(ngx_http_request_t *r) if (u->headers_in.status_line.data == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } + ngx_memcpy(u->headers_in.status_line.data, p->status_start, u->headers_in.status_line.len); @@ -1054,83 +1059,77 @@ ngx_http_proxy_finalize_request(ngx_http_request_t *r, ngx_int_t rc) } -static ngx_http_variable_value_t * -ngx_http_proxy_host_variable(ngx_http_request_t *r, uintptr_t data) +static ngx_int_t +ngx_http_proxy_host_variable(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) { - ngx_http_variable_value_t *vv; ngx_http_proxy_loc_conf_t *plcf; - vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t)); - if (vv == NULL) { - return NULL; - } - plcf = ngx_http_get_module_loc_conf(r, ngx_http_proxy_module); - vv->value = 0; - vv->text = plcf->host_header; + v->len = plcf->host_header.len; + v->valid = 1; + v->no_cachable = 0; + v->not_found = 0; + v->data = plcf->host_header.data; - return vv; + return NGX_OK; } -static ngx_http_variable_value_t * -ngx_http_proxy_port_variable(ngx_http_request_t *r, uintptr_t data) +static ngx_int_t +ngx_http_proxy_port_variable(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) { - ngx_http_variable_value_t *vv; ngx_http_proxy_loc_conf_t *plcf; - vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t)); - if (vv == NULL) { - return NULL; - } - plcf = ngx_http_get_module_loc_conf(r, ngx_http_proxy_module); - vv->value = 0; - vv->text = plcf->port_text; + v->len = plcf->port_text.len; + v->valid = 1; + v->no_cachable = 0; + v->not_found = 0; + v->data = plcf->port_text.data; - return vv; + return NGX_OK; } -static ngx_http_variable_value_t * +static ngx_int_t ngx_http_proxy_add_x_forwarded_for_variable(ngx_http_request_t *r, - uintptr_t data) + + ngx_http_variable_value_t *v, uintptr_t data) { - u_char *p; - ngx_http_variable_value_t *vv; + u_char *p; - vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t)); - if (vv == NULL) { - return NULL; - } - - vv->value = 0; + v->valid = 1; + v->no_cachable = 0; + v->not_found = 0; if (r->headers_in.x_forwarded_for == NULL) { - vv->text = r->connection->addr_text; - return vv; + v->len = r->connection->addr_text.len; + v->data = r->connection->addr_text.data; + return NGX_OK; } - vv->text.len = r->headers_in.x_forwarded_for->value.len - + sizeof(", ") - 1 + r->connection->addr_text.len; + v->len = r->headers_in.x_forwarded_for->value.len + + sizeof(", ") - 1 + r->connection->addr_text.len; - p = ngx_palloc(r->pool, vv->text.len); + p = ngx_palloc(r->pool, v->len); if (p == NULL) { - return NULL; + return NGX_ERROR; } - vv->text.data = p; + v->data = p; - p = ngx_cpymem(p, r->headers_in.x_forwarded_for->value.data, - r->headers_in.x_forwarded_for->value.len); + p = ngx_copy(p, r->headers_in.x_forwarded_for->value.data, + r->headers_in.x_forwarded_for->value.len); *p++ = ','; *p++ = ' '; ngx_memcpy(p, r->connection->addr_text.data, r->connection->addr_text.len); - return vv; + return NGX_OK; } @@ -1186,11 +1185,9 @@ ngx_http_proxy_rewrite_redirect_text(ngx_http_request_t *r, ngx_table_elt_t *h, p = data; - if (prefix) { - p = ngx_cpymem(p, h->value.data, prefix); - } + p = ngx_copy(p, h->value.data, prefix); - p = ngx_cpymem(p, pr->replacement.text.data, pr->replacement.text.len); + p = ngx_copy(p, pr->replacement.text.data, pr->replacement.text.len); ngx_memcpy(p, h->value.data + prefix + pr->redirect.len, h->value.len - pr->redirect.len - prefix); @@ -1235,9 +1232,7 @@ ngx_http_proxy_rewrite_redirect_vars(ngx_http_request_t *r, ngx_table_elt_t *h, p = data; - if (prefix) { - p = ngx_cpymem(p, h->value.data, prefix); - } + p = ngx_copy(p, h->value.data, prefix); e.ip = pr->replacement.vars.values; e.pos = p; @@ -1530,7 +1525,7 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) pr->handler = ngx_http_proxy_rewrite_redirect_text; pr->redirect = conf->upstream.url; - pr->replacement.text = *conf->upstream.location; + pr->replacement.text = conf->upstream.location; } } @@ -1540,10 +1535,11 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) } if (conf->headers_source == NULL) { - conf->headers_source = prev->headers_source; + conf->flushes = prev->flushes; conf->headers_set_len = prev->headers_set_len; conf->headers_set = prev->headers_set; conf->headers_set_hash = prev->headers_set_hash; + conf->headers_source = prev->headers_source; } if (conf->headers_set_hash) { @@ -1680,6 +1676,7 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) sc.cf = cf; sc.source = &src[i].value; + sc.flushes = &conf->flushes; sc.lengths = &conf->headers_set_len; sc.values = &conf->headers_set; @@ -1843,15 +1840,19 @@ ngx_http_proxy_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) clcf->handler = ngx_http_proxy_handler; - plcf->upstream.location = &clcf->name; + plcf->upstream.location = clcf->name; #if (NGX_PCRE) - if (clcf->regex && plcf->upstream.uri.len) { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "\"proxy_pass\" may not have URI part in " - "location given by regular expression"); - return NGX_CONF_ERROR; + if (clcf->regex) { + if (plcf->upstream.uri.len) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "\"proxy_pass\" may not have URI part in " + "location given by regular expression"); + return NGX_CONF_ERROR; + } + + plcf->upstream.location.len = 0; } #endif @@ -1911,7 +1912,7 @@ ngx_http_proxy_redirect(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) pr->handler = ngx_http_proxy_rewrite_redirect_text; pr->redirect = plcf->upstream.url; - pr->replacement.text = *plcf->upstream.location; + pr->replacement.text = plcf->upstream.location; return NGX_CONF_OK; } diff --git a/src/http/modules/ngx_http_realip_module.c b/src/http/modules/ngx_http_realip_module.c new file mode 100644 index 000000000..8732423fd --- /dev/null +++ b/src/http/modules/ngx_http_realip_module.c @@ -0,0 +1,275 @@ + +/* + * Copyright (C) Igor Sysoev + */ + + +#include <ngx_config.h> +#include <ngx_core.h> +#include <ngx_http.h> + + +/* AF_INET only */ + +typedef struct { + in_addr_t mask; + in_addr_t addr; +} ngx_http_realip_from_t; + + +typedef struct { + ngx_array_t *from; /* array of ngx_http_realip_from_t */ + + ngx_uint_t xfwd; +} ngx_http_realip_loc_conf_t; + + +static ngx_int_t ngx_http_realip_handler(ngx_http_request_t *r); +static char *ngx_http_realip_from(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf); +static void *ngx_http_realip_create_loc_conf(ngx_conf_t *cf); +static char *ngx_http_realip_merge_loc_conf(ngx_conf_t *cf, + void *parent, void *child); +static ngx_int_t ngx_http_realip_init(ngx_cycle_t *cycle); + + +static ngx_conf_enum_t ngx_http_realip_header[] = { + { ngx_string("X-Forwarded-For"), 1 }, + { ngx_string("X-Real-IP"), 0 }, + { ngx_null_string, 0 } +}; + + +static ngx_command_t ngx_http_realip_commands[] = { + + { ngx_string("set_real_ip_from"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_http_realip_from, + NGX_HTTP_LOC_CONF_OFFSET, + 0, + NULL }, + + { ngx_string("real_ip_header"), + 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_realip_loc_conf_t, xfwd), + &ngx_http_realip_header }, + + ngx_null_command +}; + + + +ngx_http_module_t ngx_http_realip_module_ctx = { + NULL, /* preconfiguration */ + NULL, /* postconfiguration */ + + NULL, /* create main configuration */ + NULL, /* init main configuration */ + + NULL, /* create server configuration */ + NULL, /* merge server configuration */ + + ngx_http_realip_create_loc_conf, /* create location configuration */ + ngx_http_realip_merge_loc_conf /* merge location configuration */ +}; + + +ngx_module_t ngx_http_realip_module = { + NGX_MODULE_V1, + &ngx_http_realip_module_ctx, /* module context */ + ngx_http_realip_commands, /* module directives */ + NGX_HTTP_MODULE, /* module type */ + NULL, /* init master */ + ngx_http_realip_init, /* init module */ + NULL, /* init process */ + NULL, /* init thread */ + NULL, /* exit thread */ + NULL, /* exit process */ + NULL, /* exit master */ + NGX_MODULE_V1_PADDING +}; + + +static ngx_int_t +ngx_http_realip_handler(ngx_http_request_t *r) +{ + u_char *ip, *p; + size_t len; + ngx_uint_t i; + struct sockaddr_in *sin; + ngx_http_realip_from_t *from; + ngx_http_realip_loc_conf_t *rlcf; + + if (r->realip_set) { + return NGX_OK; + } + + rlcf = ngx_http_get_module_loc_conf(r, ngx_http_realip_module); + + if (rlcf->from == NULL) { + return NGX_OK; + } + + if (rlcf->xfwd == 0) { + if (r->headers_in.x_real_ip == NULL) { + return NGX_OK; + } + + len = r->headers_in.x_real_ip->value.len; + ip = r->headers_in.x_real_ip->value.data; + + } else { + if (r->headers_in.x_forwarded_for == NULL) { + return NGX_OK; + } + + len = r->headers_in.x_forwarded_for->value.len; + ip = r->headers_in.x_forwarded_for->value.data; + + for (p = ip + len; p > ip; p--) { + if (*p == ' ' || *p == ',') { + p++; + len -= p - ip; + ip = p; + break; + } + } + } + + /* AF_INET only */ + + sin = (struct sockaddr_in *) r->connection->sockaddr; + + from = rlcf->from->elts; + for (i = 0; i < rlcf->from->nelts; i++) { + + ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "realip: %08XD %08XD %08XD", + sin->sin_addr.s_addr, from[i].mask, from[i].addr); + + if ((sin->sin_addr.s_addr & from[i].mask) == from[i].addr) { + + r->connection->addr_text.len = len; + r->connection->addr_text.data = ip; + + sin->sin_addr.s_addr = inet_addr((char *) ip); + + r->realip_set = 1; + + return NGX_OK; + } + } + + return NGX_OK; +} + + +static char * +ngx_http_realip_from(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) +{ + ngx_http_realip_loc_conf_t *rlcf = conf; + + ngx_str_t *value; + ngx_inet_cidr_t in_cidr; + ngx_http_realip_from_t *from; + + if (rlcf->from == NULL) { + rlcf->from = ngx_array_create(cf->pool, 2, + sizeof(ngx_http_realip_from_t)); + if (rlcf->from == NULL) { + return NGX_CONF_ERROR; + } + } + + from = ngx_array_push(rlcf->from); + if (from == NULL) { + return NGX_CONF_ERROR; + } + + value = cf->args->elts; + + from->addr = inet_addr((char *) value[1].data); + + if (from->addr != INADDR_NONE) { + from->mask = 0xffffffff; + + return NGX_CONF_OK; + } + + if (ngx_ptocidr(&value[1], &in_cidr) == NGX_ERROR) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid parameter \"%V\"", + &value[1]); + return NGX_CONF_ERROR; + } + + from->mask = in_cidr.mask; + from->addr = in_cidr.addr; + + return NGX_CONF_OK; +} + + +static void * +ngx_http_realip_create_loc_conf(ngx_conf_t *cf) +{ + ngx_http_realip_loc_conf_t *conf; + + conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_realip_loc_conf_t)); + if (conf == NULL) { + return NGX_CONF_ERROR; + } + + /* + * set by ngx_pcalloc(): + * + * conf->from = NULL; + */ + + conf->xfwd = NGX_CONF_UNSET_UINT; + + return conf; +} + + +static char * +ngx_http_realip_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) +{ + ngx_http_realip_loc_conf_t *prev = parent; + ngx_http_realip_loc_conf_t *conf = child; + + if (conf->from == NULL) { + conf->from = prev->from; + } + + ngx_conf_merge_unsigned_value(conf->xfwd, prev->xfwd, 0); + + return NGX_CONF_OK; +} + + +static ngx_int_t +ngx_http_realip_init(ngx_cycle_t *cycle) +{ + ngx_http_handler_pt *h; + ngx_http_core_main_conf_t *cmcf; + + cmcf = ngx_http_cycle_get_module_main_conf(cycle, ngx_http_core_module); + + h = ngx_array_push(&cmcf->phases[NGX_HTTP_POST_READ_PHASE].handlers); + if (h == NULL) { + return NGX_ERROR; + } + + *h = ngx_http_realip_handler; + + h = ngx_array_push(&cmcf->phases[NGX_HTTP_ACCESS_PHASE].handlers); + if (h == NULL) { + return NGX_ERROR; + } + + *h = ngx_http_realip_handler; + + return NGX_OK; +} diff --git a/src/http/modules/ngx_http_rewrite_module.c b/src/http/modules/ngx_http_rewrite_module.c index c575d4343..6e64f6a99 100644 --- a/src/http/modules/ngx_http_rewrite_module.c +++ b/src/http/modules/ngx_http_rewrite_module.c @@ -142,7 +142,7 @@ ngx_module_t ngx_http_rewrite_module = { static ngx_http_variable_value_t ngx_http_rewrite_null_value = - { 0, ngx_string("") }; + ngx_http_variable(""); static ngx_int_t @@ -214,9 +214,8 @@ ngx_http_rewrite_invalid_referer_code(ngx_http_script_engine_t *e) e->ip += sizeof(uintptr_t); if (cf->referers == NULL) { - e->sp->value = 0; - e->sp->text.len = 0; - e->sp->text.data = (u_char *) ""; + e->sp->data = (u_char *) ""; + e->sp->len = 0; e->sp++; return; @@ -224,17 +223,15 @@ ngx_http_rewrite_invalid_referer_code(ngx_http_script_engine_t *e) if (r->headers_in.referer == NULL) { if (cf->no_referer) { - e->sp->value = 0; - e->sp->text.len = 0; - e->sp->text.data = (u_char *) ""; + e->sp->data = (u_char *) ""; + e->sp->len = 0; e->sp++; return; } else { - e->sp->value = 1; - e->sp->text.len = 1; - e->sp->text.data = (u_char *) "1"; + e->sp->data = (u_char *) "1"; + e->sp->len = 1; e->sp++; return; @@ -248,17 +245,15 @@ ngx_http_rewrite_invalid_referer_code(ngx_http_script_engine_t *e) || (ngx_strncasecmp(ref, "http://", 7) != 0)) { if (cf->blocked_referer) { - e->sp->value = 0; - e->sp->text.len = 0; - e->sp->text.data = (u_char *) "0"; + e->sp->data = (u_char *) ""; + e->sp->len = 0; e->sp++; return; } else { - e->sp->value = 1; - e->sp->text.len = 1; - e->sp->text.data = (u_char *) "1"; + e->sp->data = (u_char *) "1"; + e->sp->len = 1; e->sp++; return; @@ -288,9 +283,8 @@ ngx_http_rewrite_invalid_referer_code(ngx_http_script_engine_t *e) if (ngx_strncmp(&ref[n], refs[i].name.data, refs[i].name.len) == 0) { - e->sp->value = 0; - e->sp->text.len = 0; - e->sp->text.data = (u_char *) ""; + e->sp->data = (u_char *) ""; + e->sp->len = 0; e->sp++; return; @@ -300,9 +294,8 @@ ngx_http_rewrite_invalid_referer_code(ngx_http_script_engine_t *e) } else { if (ngx_strncasecmp(refs[i].name.data, ref, refs[i].name.len) == 0) { - e->sp->value = 0; - e->sp->text.len = 0; - e->sp->text.data = (u_char *) ""; + e->sp->data = (u_char *) ""; + e->sp->len = 0; e->sp++; return; @@ -310,15 +303,15 @@ ngx_http_rewrite_invalid_referer_code(ngx_http_script_engine_t *e) } } - e->sp->value = 1; - e->sp->text.len = 1; - e->sp->text.data = (u_char *) "1"; + e->sp->data = (u_char *) "1"; + e->sp->len = 1; e->sp++; } -static ngx_http_variable_value_t * -ngx_http_rewrite_var(ngx_http_request_t *r, uintptr_t data) +static ngx_int_t +ngx_http_rewrite_var(ngx_http_request_t *r, ngx_http_variable_value_t *v, + uintptr_t data) { ngx_http_variable_t *var; ngx_http_core_main_conf_t *cmcf; @@ -336,7 +329,9 @@ ngx_http_rewrite_var(ngx_http_request_t *r, uintptr_t data) ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, "using uninitialized \"%V\" variable", &var[data].name); - return &ngx_http_rewrite_null_value; + *v = ngx_http_rewrite_null_value; + + return NGX_OK; } @@ -411,6 +406,13 @@ ngx_http_rewrite_init(ngx_cycle_t *cycle) cmcf = ngx_http_cycle_get_module_main_conf(cycle, ngx_http_core_module); + h = ngx_array_push(&cmcf->phases[NGX_HTTP_SERVER_REWRITE_PHASE].handlers); + if (h == NULL) { + return NGX_ERROR; + } + + *h = ngx_http_rewrite_handler; + h = ngx_array_push(&cmcf->phases[NGX_HTTP_REWRITE_PHASE].handlers); if (h == NULL) { return NGX_ERROR; diff --git a/src/http/modules/ngx_http_ssi_filter_module.c b/src/http/modules/ngx_http_ssi_filter_module.c index 80de6910c..86700ecf3 100644 --- a/src/http/modules/ngx_http_ssi_filter_module.c +++ b/src/http/modules/ngx_http_ssi_filter_module.c @@ -144,8 +144,8 @@ static ngx_int_t ngx_http_ssi_else(ngx_http_request_t *r, static ngx_int_t ngx_http_ssi_endif(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx, ngx_str_t **params); -static ngx_http_variable_value_t * - ngx_http_ssi_date_gmt_local_variable(ngx_http_request_t *r, uintptr_t gmt); +static ngx_int_t ngx_http_ssi_date_gmt_local_variable(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t gmt); static char *ngx_http_ssi_types(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); @@ -562,6 +562,8 @@ ngx_http_ssi_body_filter(ngx_http_request_t *r, ngx_chain_t *in) } + b = NULL; + if (rc == NGX_OK) { for (cmd = ngx_http_ssi_commands; cmd->handler; cmd++) { @@ -1200,10 +1202,12 @@ ngx_http_ssi_parse(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx) } if (ch == '"' && state == ssi_double_quoted_value_state) { + ctx->param->value.data[ctx->param->value.len - 1] = ch; break; } if (ch == '\'' && state == ssi_quoted_value_state) { + ctx->param->value.data[ctx->param->value.len - 1] = ch; break; } @@ -1378,9 +1382,9 @@ static ngx_int_t ngx_http_ssi_evaluate_string(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx, ngx_str_t *text, ngx_uint_t flags) { - u_char ch, *p, **value, *data; - size_t *size, len, prefix; - ngx_str_t var, part, *val; + u_char ch, *p, **value, *data, *part_data; + size_t *size, len, prefix, part_len; + ngx_str_t var, *val; ngx_uint_t i, j, n, bracket; ngx_array_t lengths, values; ngx_http_variable_value_t *vv; @@ -1408,7 +1412,7 @@ ngx_http_ssi_evaluate_string(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx, return NGX_ERROR; } - p = ngx_cpymem(data, r->uri.data, prefix); + p = ngx_copy(data, r->uri.data, prefix); ngx_memcpy(p, text->data, text->len); text->len = len; @@ -1498,20 +1502,22 @@ ngx_http_ssi_evaluate_string(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx, return NGX_ERROR; } - if (vv == NGX_HTTP_VAR_NOT_FOUND) { + if (vv->not_found) { continue; } - part = vv->text; + part_data = vv->data; + part_len = vv->len; } else { - part = *val; + part_data = val->data; + part_len = val->len; } } else { - part.data = &text->data[i]; + part_data = &text->data[i]; - for (p = part.data; i < text->len; i++) { + for (p = part_data; i < text->len; i++) { ch = text->data[i]; if (ch == '$') { @@ -1527,24 +1533,24 @@ ngx_http_ssi_evaluate_string(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx, *p++ = ch; } - part.len = p - part.data; + part_len = p - part_data; } - len += part.len; + len += part_len; size = ngx_array_push(&lengths); if (size == NULL) { return NGX_ERROR; } - *size = part.len; + *size = part_len; value = ngx_array_push(&values); if (value == NULL) { return NGX_ERROR; } - *value = part.data; + *value = part_data; } prefix = 0; @@ -1577,12 +1583,10 @@ ngx_http_ssi_evaluate_string(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx, text->len = len; text->data = p; - if (prefix) { - p = ngx_cpymem(p, r->uri.data, prefix); - } + p = ngx_copy(p, r->uri.data, prefix); for (i = 0; i < values.nelts; i++) { - p = ngx_cpymem(p, value[i], size[i]); + p = ngx_copy(p, value[i], size[i]); } return NGX_OK; @@ -1601,7 +1605,7 @@ ngx_http_ssi_include(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx, ngx_str_t **params) { ngx_str_t *uri, *file, args; - ngx_uint_t i; + ngx_uint_t flags; uri = params[NGX_HTTP_SSI_INCLUDE_VIRTUAL]; file = params[NGX_HTTP_SSI_INCLUDE_FILE]; @@ -1631,20 +1635,16 @@ ngx_http_ssi_include(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx, args.len = 0; args.data = NULL; + flags = 0; - if (params[NGX_HTTP_SSI_INCLUDE_VIRTUAL]) { - for (i = 0; i < uri->len; i++) { - if (uri->data[i] == '?') { - args.len = uri->len - i - 1; - args.data = &uri->data[i + 1]; - uri->len -= args.len + 1; + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "ssi include: \"%V\"", uri); - break; - } - } + if (ngx_http_parse_unsafe_uri(r, uri, &args, &flags) != NGX_OK) { + return NGX_HTTP_SSI_ERROR; } - if (ngx_http_subrequest(r, uri, &args) != NGX_OK) { + if (ngx_http_subrequest(r, uri, &args, flags) != NGX_OK) { return NGX_HTTP_SSI_ERROR; } @@ -1658,7 +1658,7 @@ ngx_http_ssi_echo(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx, { ngx_uint_t i; ngx_buf_t *b; - ngx_str_t *var, *value; + ngx_str_t *var, *value, text; ngx_chain_t *cl; ngx_http_variable_value_t *vv; @@ -1677,8 +1677,10 @@ ngx_http_ssi_echo(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx, return NGX_HTTP_SSI_ERROR; } - if (vv != NGX_HTTP_VAR_NOT_FOUND) { - value = &vv->text; + if (!vv->not_found) { + text.data = vv->data; + text.len = vv->len; + value = &text; } } @@ -1817,7 +1819,8 @@ ngx_http_ssi_if(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx, if ((*p >= 'a' && *p <= 'z') || (*p >= '0' && *p <= '9') - || *p == '$' || *p == '{' || *p == '}' || *p == '_') + || *p == '$' || *p == '{' || *p == '}' || *p == '_' + || *p == '"' || *p == '\'') { continue; } @@ -1971,19 +1974,18 @@ ngx_http_ssi_endif(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx, } -static ngx_http_variable_value_t * -ngx_http_ssi_date_gmt_local_variable(ngx_http_request_t *r, uintptr_t gmt) +static ngx_int_t +ngx_http_ssi_date_gmt_local_variable(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t gmt) { - ngx_http_ssi_ctx_t *ctx; - ngx_http_variable_value_t *vv; - ngx_time_t *tp; - struct tm tm; - char buf[NGX_HTTP_SSI_DATE_LEN]; + ngx_http_ssi_ctx_t *ctx; + ngx_time_t *tp; + struct tm tm; + char buf[NGX_HTTP_SSI_DATE_LEN]; - vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t)); - if (vv == NULL) { - return NULL; - } + v->valid = 1; + v->no_cachable = 0; + v->not_found = 0; tp = ngx_timeofday(); @@ -1992,16 +1994,14 @@ ngx_http_ssi_date_gmt_local_variable(ngx_http_request_t *r, uintptr_t gmt) if (ctx->timefmt.len == sizeof("%s") - 1 && ctx->timefmt.data[0] == '%' && ctx->timefmt.data[1] == 's') { - vv->value = tp->sec + (gmt ? 0 : tp->gmtoff); - - vv->text.data = ngx_palloc(r->pool, NGX_TIME_T_LEN); - if (vv->text.data == NULL) { - return NULL; + v->data = ngx_palloc(r->pool, NGX_TIME_T_LEN); + if (v->data == NULL) { + return NGX_ERROR; } - vv->text.len = ngx_sprintf(vv->text.data, "%T", vv->value) - - vv->text.data; - return vv; + v->len = ngx_sprintf(v->data, "%T", tp->sec + (gmt ? 0 : tp->gmtoff)) + - v->data; + return NGX_OK; } if (gmt) { @@ -2010,22 +2010,20 @@ ngx_http_ssi_date_gmt_local_variable(ngx_http_request_t *r, uintptr_t gmt) ngx_libc_localtime(tp->sec, &tm); } - vv->value = tp->sec + (gmt ? 0 : tp->gmtoff); - - vv->text.len = strftime(buf, NGX_HTTP_SSI_DATE_LEN, - (char *) ctx->timefmt.data, &tm); - if (vv->text.len == 0) { - return NULL; + v->len = strftime(buf, NGX_HTTP_SSI_DATE_LEN, + (char *) ctx->timefmt.data, &tm); + if (v->len == 0) { + return NGX_ERROR; } - vv->text.data = ngx_palloc(r->pool, vv->text.len); - if (vv->text.data == NULL) { - return NULL; + v->data = ngx_palloc(r->pool, v->len); + if (v->data == NULL) { + return NGX_ERROR; } - ngx_memcpy(vv->text.data, buf, vv->text.len); + ngx_memcpy(v->data, buf, v->len); - return vv; + return NGX_OK; } diff --git a/src/http/modules/ngx_http_ssl_module.c b/src/http/modules/ngx_http_ssl_module.c index 09bf63dcf..d75b9e60d 100644 --- a/src/http/modules/ngx_http_ssl_module.c +++ b/src/http/modules/ngx_http_ssl_module.c @@ -8,6 +8,7 @@ #include <ngx_core.h> #include <ngx_http.h> + #define NGX_DEFLAUT_CERTIFICATE "cert.pem" #define NGX_DEFLAUT_CERTIFICATE_KEY "cert.pem" #define NGX_DEFLAUT_CIPHERS "ALL:!ADH:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP" @@ -84,6 +85,13 @@ static ngx_command_t ngx_http_ssl_commands[] = { ngx_http_ssl_nosupported, 0, 0, ngx_http_ssl_openssl097 }, #endif + { ngx_string("ssl_session_timeout"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, + ngx_conf_set_sec_slot, + NGX_HTTP_SRV_CONF_OFFSET, + offsetof(ngx_http_ssl_srv_conf_t, session_timeout), + NULL }, + ngx_null_command }; @@ -146,6 +154,7 @@ ngx_http_ssl_create_srv_conf(ngx_conf_t *cf) */ scf->enable = NGX_CONF_UNSET; + scf->session_timeout = NGX_CONF_UNSET; scf->prefer_server_ciphers = NGX_CONF_UNSET; return scf; @@ -166,6 +175,9 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) return NGX_CONF_OK; } + ngx_conf_merge_value(conf->session_timeout, + prev->session_timeout, 300); + ngx_conf_merge_value(conf->prefer_server_ciphers, prev->prefer_server_ciphers, 0); @@ -229,6 +241,8 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) SSL_CTX_set_session_id_context(conf->ssl.ctx, ngx_http_session_id_ctx, sizeof(ngx_http_session_id_ctx) - 1); + SSL_CTX_set_timeout(conf->ssl.ctx, conf->session_timeout); + return NGX_CONF_OK; } diff --git a/src/http/modules/ngx_http_ssl_module.h b/src/http/modules/ngx_http_ssl_module.h index a705635ff..4207cdfdb 100644 --- a/src/http/modules/ngx_http_ssl_module.h +++ b/src/http/modules/ngx_http_ssl_module.h @@ -22,6 +22,8 @@ typedef struct { ngx_uint_t protocols; + time_t session_timeout; + ngx_str_t certificate; ngx_str_t certificate_key; @@ -29,14 +31,6 @@ typedef struct { } ngx_http_ssl_srv_conf_t; -ngx_int_t ngx_http_ssl_read(ngx_http_request_t *r, u_char *buf, size_t size); -ngx_int_t ngx_http_ssl_shutdown(ngx_http_request_t *r); -ngx_chain_t *ngx_http_ssl_write(ngx_connection_t *c, ngx_chain_t *in, - off_t limit); - -void ngx_http_ssl_close_connection(SSL *ssl, ngx_log_t *log); - - extern ngx_module_t ngx_http_ssl_module; diff --git a/src/http/modules/ngx_http_static_module.c b/src/http/modules/ngx_http_static_module.c index 0e995f526..ab7ac9c6f 100644 --- a/src/http/modules/ngx_http_static_module.c +++ b/src/http/modules/ngx_http_static_module.c @@ -195,7 +195,7 @@ ngx_http_static_handler(ngx_http_request_t *r) return NGX_HTTP_INTERNAL_SERVER_ERROR; } - last = ngx_cpymem(location, r->uri.data, r->uri.len); + last = ngx_copy(location, r->uri.data, r->uri.len); } *last = '/'; diff --git a/src/http/modules/ngx_http_userid_filter_module.c b/src/http/modules/ngx_http_userid_filter_module.c index 221d33bf3..94a709b60 100644 --- a/src/http/modules/ngx_http_userid_filter_module.c +++ b/src/http/modules/ngx_http_userid_filter_module.c @@ -55,7 +55,10 @@ static size_t ngx_http_userid_log_uid_set_getlen(ngx_http_request_t *r, static u_char *ngx_http_userid_log_uid_set(ngx_http_request_t *r, u_char *buf, ngx_http_log_op_t *op); -static ngx_int_t ngx_http_userid_add_log_formats(ngx_conf_t *cf); +static ngx_int_t ngx_http_userid_add_variables(ngx_conf_t *cf); +static ngx_int_t ngx_http_userid_variable(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); + static ngx_int_t ngx_http_userid_init(ngx_cycle_t *cycle); static void *ngx_http_userid_create_conf(ngx_conf_t *cf); static char *ngx_http_userid_merge_conf(ngx_conf_t *cf, void *parent, @@ -158,7 +161,7 @@ static ngx_command_t ngx_http_userid_commands[] = { ngx_http_module_t ngx_http_userid_filter_module_ctx = { - ngx_http_userid_add_log_formats, /* preconfiguration */ + ngx_http_userid_add_variables, /* preconfiguration */ NULL, /* postconfiguration */ NULL, /* create main configuration */ @@ -199,6 +202,10 @@ static ngx_http_log_op_name_t ngx_http_userid_log_fmt_ops[] = { }; +static ngx_str_t ngx_http_userid_got = ngx_string("uid_got"); +static ngx_str_t ngx_http_userid_set = ngx_string("uid_set"); + + static ngx_int_t ngx_http_userid_filter(ngx_http_request_t *r) { @@ -387,7 +394,7 @@ ngx_http_userid_set_uid(ngx_http_request_t *r, ngx_http_userid_ctx_t *ctx, return NGX_ERROR; } - p = ngx_cpymem(cookie, conf->name.data, conf->name.len); + p = ngx_copy(cookie, conf->name.data, conf->name.len); *p++ = '='; if (ctx->uid_got[3] == 0) { @@ -417,11 +424,9 @@ ngx_http_userid_set_uid(ngx_http_request_t *r, ngx_http_userid_ctx_t *ctx, p = ngx_http_cookie_time(p, ngx_time() + conf->expires); } - if (conf->domain.len) { - p = ngx_cpymem(p, conf->domain.data, conf->domain.len); - } + p = ngx_copy(p, conf->domain.data, conf->domain.len); - p = ngx_cpymem(p, conf->path.data, conf->path.len); + p = ngx_copy(p, conf->path.data, conf->path.len); set_cookie = ngx_list_push(&r->headers_out.headers); if (set_cookie == NULL) { @@ -489,7 +494,7 @@ ngx_http_userid_log_uid_got(ngx_http_request_t *r, u_char *buf, conf = ngx_http_get_module_loc_conf(r, ngx_http_userid_filter_module); - buf = ngx_cpymem(buf, conf->name.data, conf->name.len); + buf = ngx_copy(buf, conf->name.data, conf->name.len); *buf++ = '='; @@ -533,7 +538,7 @@ ngx_http_userid_log_uid_set(ngx_http_request_t *r, u_char *buf, conf = ngx_http_get_module_loc_conf(r, ngx_http_userid_filter_module); - buf = ngx_cpymem(buf, conf->name.data, conf->name.len); + buf = ngx_copy(buf, conf->name.data, conf->name.len); *buf++ = '='; @@ -544,10 +549,28 @@ ngx_http_userid_log_uid_set(ngx_http_request_t *r, u_char *buf, static ngx_int_t -ngx_http_userid_add_log_formats(ngx_conf_t *cf) +ngx_http_userid_add_variables(ngx_conf_t *cf) { + ngx_http_variable_t *var; ngx_http_log_op_name_t *op; + var = ngx_http_add_variable(cf, &ngx_http_userid_got, 0); + if (var == NULL) { + return NGX_ERROR; + } + + var->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, 0); + if (var == NULL) { + return NGX_ERROR; + } + + var->handler = ngx_http_userid_variable; + var->data = offsetof(ngx_http_userid_ctx_t, uid_set); + + for (op = ngx_http_userid_log_fmt_ops; op->name.len; op++) { /* void */ } op->run = NULL; @@ -564,6 +587,42 @@ ngx_http_userid_add_log_formats(ngx_conf_t *cf) static ngx_int_t +ngx_http_userid_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v, + uintptr_t data) +{ + uint32_t *uid; + ngx_http_userid_ctx_t *ctx; + ngx_http_userid_conf_t *conf; + + v->valid = 1; + v->no_cachable = 0; + v->not_found = 0; + + ctx = ngx_http_get_module_ctx(r, ngx_http_userid_filter_module); + + uid = (uint32_t *) ((char *) ctx + data); + + if (ctx == NULL || uid[3] == 0) { + v->not_found = 1; + return NGX_OK; + } + + conf = ngx_http_get_module_loc_conf(r, ngx_http_userid_filter_module); + + v->len = conf->name.len + sizeof("=00001111222233334444555566667777") - 1; + v->data = ngx_palloc(r->pool, v->len); + if (v->data == NULL) { + return NGX_ERROR; + } + + ngx_sprintf(v->data, "%V=%08XD%08XD%08XD%08XD", + &conf->name, uid[0], uid[1], uid[2], uid[3]); + + return NGX_OK; +} + + +static ngx_int_t ngx_http_userid_init(ngx_cycle_t *cycle) { ngx_http_next_header_filter = ngx_http_top_header_filter; diff --git a/src/http/ngx_http.c b/src/http/ngx_http.c index 867bf3118..7e4fab7f6 100644 --- a/src/http/ngx_http.c +++ b/src/http/ngx_http.c @@ -277,19 +277,31 @@ ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) /* init lists of the handlers */ - if (ngx_array_init(&cmcf->phases[NGX_HTTP_REWRITE_PHASE].handlers, - cf->pool, 1, sizeof(ngx_http_handler_pt)) != NGX_OK) + if (ngx_array_init(&cmcf->phases[NGX_HTTP_POST_READ_PHASE].handlers, + cf->pool, 1, sizeof(ngx_http_handler_pt)) + != NGX_OK) { return NGX_CONF_ERROR; } - cmcf->phases[NGX_HTTP_REWRITE_PHASE].type = NGX_OK; + cmcf->phases[NGX_HTTP_POST_READ_PHASE].type = NGX_OK; + + + if (ngx_array_init(&cmcf->phases[NGX_HTTP_SERVER_REWRITE_PHASE].handlers, + cf->pool, 1, sizeof(ngx_http_handler_pt)) + != NGX_OK) + { + return NGX_CONF_ERROR; + } + + cmcf->phases[NGX_HTTP_SERVER_REWRITE_PHASE].type = NGX_OK; /* the special find config phase for a single handler */ if (ngx_array_init(&cmcf->phases[NGX_HTTP_FIND_CONFIG_PHASE].handlers, - cf->pool, 1, sizeof(ngx_http_handler_pt)) != NGX_OK) + cf->pool, 1, sizeof(ngx_http_handler_pt)) + != NGX_OK) { return NGX_CONF_ERROR; } @@ -304,8 +316,19 @@ ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) *h = ngx_http_find_location_config; + if (ngx_array_init(&cmcf->phases[NGX_HTTP_REWRITE_PHASE].handlers, + cf->pool, 1, sizeof(ngx_http_handler_pt)) + != NGX_OK) + { + return NGX_CONF_ERROR; + } + + cmcf->phases[NGX_HTTP_REWRITE_PHASE].type = NGX_OK; + + if (ngx_array_init(&cmcf->phases[NGX_HTTP_ACCESS_PHASE].handlers, - cf->pool, 1, sizeof(ngx_http_handler_pt)) != NGX_OK) + cf->pool, 4, sizeof(ngx_http_handler_pt)) + != NGX_OK) { return NGX_CONF_ERROR; } @@ -314,7 +337,8 @@ ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) if (ngx_array_init(&cmcf->phases[NGX_HTTP_CONTENT_PHASE].handlers, - cf->pool, 4, sizeof(ngx_http_handler_pt)) != NGX_OK) + cf->pool, 4, sizeof(ngx_http_handler_pt)) + != NGX_OK) { return NGX_CONF_ERROR; } @@ -353,6 +377,9 @@ ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) } } + if (ngx_http_variables_init_vars(cf) != NGX_OK) { + return NGX_CONF_ERROR; + } /* * http{}'s cf->ctx was needed while the configuration merging diff --git a/src/http/ngx_http.h b/src/http/ngx_http.h index 5be39363b..8e5ae5740 100644 --- a/src/http/ngx_http.h +++ b/src/http/ngx_http.h @@ -62,6 +62,8 @@ void ngx_http_init_connection(ngx_connection_t *c); ngx_int_t ngx_http_parse_request_line(ngx_http_request_t *r, ngx_buf_t *b); ngx_int_t ngx_http_parse_complex_uri(ngx_http_request_t *r); +ngx_int_t ngx_http_parse_unsafe_uri(ngx_http_request_t *r, ngx_str_t *uri, + ngx_str_t *args, ngx_uint_t *flags); ngx_int_t ngx_http_parse_header_line(ngx_http_request_t *r, ngx_buf_t *b); ngx_int_t ngx_http_parse_multi_header_lines(ngx_array_t *headers, ngx_str_t *name, ngx_str_t *value); diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c index a12a1344d..c230860bb 100644 --- a/src/http/ngx_http_core_module.c +++ b/src/http/ngx_http_core_module.c @@ -22,7 +22,6 @@ static ngx_int_t ngx_http_core_find_location(ngx_http_request_t *r, ngx_array_t *locations, size_t len); static ngx_int_t ngx_http_core_preconfiguration(ngx_conf_t *cf); -static ngx_int_t ngx_http_core_postconfiguration(ngx_conf_t *cf); static void *ngx_http_core_create_main_conf(ngx_conf_t *cf); static char *ngx_http_core_init_main_conf(ngx_conf_t *cf, void *conf); static void *ngx_http_core_create_srv_conf(ngx_conf_t *cf); @@ -368,7 +367,7 @@ static ngx_command_t ngx_http_core_commands[] = { ngx_http_module_t ngx_http_core_module_ctx = { ngx_http_core_preconfiguration, /* preconfiguration */ - ngx_http_core_postconfiguration, /* postconfiguration */ + NULL, /* postconfiguration */ ngx_http_core_create_main_conf, /* create main configuration */ ngx_http_core_init_main_conf, /* init main configuration */ @@ -448,7 +447,8 @@ ngx_http_handler(ngx_http_request_t *r) r->uri_changed = 1; r->uri_changes = NGX_HTTP_MAX_REWRITE_CYCLES + 1; - r->phase = NGX_HTTP_REWRITE_PHASE; + r->phase = (r->main == r) ? NGX_HTTP_POST_READ_PHASE: + NGX_HTTP_SERVER_REWRITE_PHASE; r->phase_handler = 0; ngx_http_core_run_phases(r); @@ -991,7 +991,7 @@ ngx_http_map_uri_to_path(ngx_http_request_t *r, ngx_str_t *path, return NULL; } - last = ngx_cpymem(path->data, clcf->root.data, clcf->root.len); + last = ngx_copy(path->data, clcf->root.data, clcf->root.len); last = ngx_cpystrn(last, r->uri.data + alias, r->uri.len - alias + 1); return last; @@ -1054,7 +1054,7 @@ ngx_http_auth_basic_user(ngx_http_request_t *r) } } - if (len == auth.len) { + if (len == 0 || len == auth.len) { r->headers_in.user.data = (u_char *) ""; return NGX_DECLINED; } @@ -1070,7 +1070,7 @@ ngx_http_auth_basic_user(ngx_http_request_t *r) ngx_int_t ngx_http_subrequest(ngx_http_request_t *r, - ngx_str_t *uri, ngx_str_t *args) + ngx_str_t *uri, ngx_str_t *args, ngx_uint_t flags) { ngx_http_request_t *sr; ngx_http_core_srv_conf_t *cscf; @@ -1116,9 +1116,21 @@ ngx_http_subrequest(ngx_http_request_t *r, sr->request_line = r->request_line; sr->uri = *uri; + + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "http subrequest \"%V\"", uri); + if (args) { sr->args = *args; + + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "http subrequest args \"%V\"", args); } + + if (flags & NGX_HTTP_ZERO_IN_URI) { + sr->zero_in_uri = 1; + } + sr->unparsed_uri = r->unparsed_uri; sr->method_name = r->method_name; sr->http_protocol = r->http_protocol; @@ -1167,9 +1179,6 @@ ngx_http_subrequest(ngx_http_request_t *r, sr->discard_body = r->discard_body; sr->main_filter_need_in_memory = r->main_filter_need_in_memory; - ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "http subrequest \"%V\"", uri); - ngx_http_handler(sr); /* the request pool may be already destroyed */ @@ -1192,6 +1201,9 @@ ngx_http_internal_redirect(ngx_http_request_t *r, if (args) { r->args = *args; + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "internal redirect args: \"%V\"", args); + } else { r->args.len = 0; r->args.data = NULL; @@ -1657,13 +1669,6 @@ ngx_http_core_preconfiguration(ngx_conf_t *cf) } -static ngx_int_t -ngx_http_core_postconfiguration(ngx_conf_t *cf) -{ - return ngx_http_variables_init_vars(cf); -} - - static void * ngx_http_core_create_main_conf(ngx_conf_t *cf) { diff --git a/src/http/ngx_http_core_module.h b/src/http/ngx_http_core_module.h index 598965521..b2c25cf0b 100644 --- a/src/http/ngx_http_core_module.h +++ b/src/http/ngx_http_core_module.h @@ -44,8 +44,10 @@ typedef struct { typedef enum { - NGX_HTTP_FIND_CONFIG_PHASE = 0, + NGX_HTTP_POST_READ_PHASE = 0, + NGX_HTTP_SERVER_REWRITE_PHASE, + NGX_HTTP_FIND_CONFIG_PHASE, NGX_HTTP_REWRITE_PHASE, NGX_HTTP_ACCESS_PHASE, @@ -260,7 +262,7 @@ u_char *ngx_http_map_uri_to_path(ngx_http_request_t *r, ngx_str_t *name, ngx_int_t ngx_http_auth_basic_user(ngx_http_request_t *r); ngx_int_t ngx_http_subrequest(ngx_http_request_t *r, - ngx_str_t *uri, ngx_str_t *args); + ngx_str_t *uri, ngx_str_t *args, ngx_uint_t flags); ngx_int_t ngx_http_internal_redirect(ngx_http_request_t *r, ngx_str_t *uri, ngx_str_t *args); diff --git a/src/http/ngx_http_header_filter_module.c b/src/http/ngx_http_header_filter_module.c index 253fc0674..b14b3cfc2 100644 --- a/src/http/ngx_http_header_filter_module.c +++ b/src/http/ngx_http_header_filter_module.c @@ -351,12 +351,12 @@ ngx_http_header_filter(ngx_http_request_t *r) /* status line */ if (r->headers_out.status_line.len) { - b->last = ngx_cpymem(b->last, r->headers_out.status_line.data, - r->headers_out.status_line.len); + b->last = ngx_copy(b->last, r->headers_out.status_line.data, + r->headers_out.status_line.len); } else { - b->last = ngx_cpymem(b->last, ngx_http_status_lines[status].data, - ngx_http_status_lines[status].len); + b->last = ngx_copy(b->last, ngx_http_status_lines[status].data, + ngx_http_status_lines[status].len); } *b->last++ = CR; *b->last++ = LF; @@ -377,14 +377,14 @@ ngx_http_header_filter(ngx_http_request_t *r) b->last = ngx_cpymem(b->last, "Content-Type: ", sizeof("Content-Type: ") - 1); p = b->last; - b->last = ngx_cpymem(b->last, r->headers_out.content_type.data, - r->headers_out.content_type.len); + b->last = ngx_copy(b->last, r->headers_out.content_type.data, + r->headers_out.content_type.len); if (r->headers_out.charset.len) { b->last = ngx_cpymem(b->last, "; charset=", sizeof("; charset=") - 1); - b->last = ngx_cpymem(b->last, r->headers_out.charset.data, - r->headers_out.charset.len); + b->last = ngx_copy(b->last, r->headers_out.charset.data, + r->headers_out.charset.len); /* update r->headers_out.content_type for possible logging */ @@ -428,28 +428,27 @@ ngx_http_header_filter(ngx_http_request_t *r) #endif *b->last++ = ':'; *b->last++ = '/'; *b->last++ = '/'; - b->last = ngx_cpymem(b->last, r->server_name.data, - r->server_name.len); + b->last = ngx_copy(b->last, r->server_name.data, r->server_name.len); if (clcf->port_in_redirect) { #if (NGX_HTTP_SSL) if (r->connection->ssl) { if (r->port != 443) { - b->last = ngx_cpymem(b->last, r->port_text->data, - r->port_text->len); + b->last = ngx_copy(b->last, r->port_text->data, + r->port_text->len); } } else #endif { if (r->port != 80) { - b->last = ngx_cpymem(b->last, r->port_text->data, - r->port_text->len); + b->last = ngx_copy(b->last, r->port_text->data, + r->port_text->len); } } } - b->last = ngx_cpymem(b->last, r->headers_out.location->value.data, - r->headers_out.location->value.len); + b->last = ngx_copy(b->last, r->headers_out.location->value.data, + r->headers_out.location->value.len); /* update r->headers_out.location->value for possible logging */ @@ -497,11 +496,10 @@ ngx_http_header_filter(ngx_http_request_t *r) continue; } - b->last = ngx_cpymem(b->last, header[i].key.data, header[i].key.len); + b->last = ngx_copy(b->last, header[i].key.data, header[i].key.len); *b->last++ = ':' ; *b->last++ = ' ' ; - b->last = ngx_cpymem(b->last, header[i].value.data, - header[i].value.len); + b->last = ngx_copy(b->last, header[i].value.data, header[i].value.len); *b->last++ = CR; *b->last++ = LF; } diff --git a/src/http/ngx_http_parse.c b/src/http/ngx_http_parse.c index 302cd819a..0001286c6 100644 --- a/src/http/ngx_http_parse.c +++ b/src/http/ngx_http_parse.c @@ -763,6 +763,7 @@ ngx_http_parse_complex_uri(ngx_http_request_t *r) "s:%d in:'%Xd:%c', out:'%c'", state, ch, ch, *u); switch (state) { + case sw_usual: switch(ch) { #if (NGX_WIN32) @@ -810,7 +811,6 @@ ngx_http_parse_complex_uri(ngx_http_request_t *r) switch(ch) { #if (NGX_WIN32) case '\\': - break; #endif case '/': break; @@ -837,7 +837,6 @@ ngx_http_parse_complex_uri(ngx_http_request_t *r) switch(ch) { #if (NGX_WIN32) case '\\': - /* fall through */ #endif case '/': state = sw_slash; @@ -866,7 +865,6 @@ ngx_http_parse_complex_uri(ngx_http_request_t *r) switch(ch) { #if (NGX_WIN32) case '\\': - /* fall through */ #endif case '/': state = sw_slash; @@ -923,6 +921,9 @@ ngx_http_parse_complex_uri(ngx_http_request_t *r) quoted_state = state; state = sw_quoted; break; + case '?': + r->args_start = p; + goto done; default: state = sw_usual; *u++ = ch; @@ -1003,6 +1004,92 @@ done: ngx_int_t +ngx_http_parse_unsafe_uri(ngx_http_request_t *r, ngx_str_t *uri, + ngx_str_t *args, ngx_uint_t *flags) +{ + u_char ch, *p; + size_t len; + + len = uri->len; + p = uri->data; + + if (len == 0 || p[0] == '?') { + goto unsafe; + } + + if (p[0] == '.' && len == 3 && p[1] == '.' && (p[2] == '/' +#if (NGX_WIN32) + || p[2] == '\\' +#endif + )) + { + goto unsafe; + } + + for ( /* void */ ; len; len--) { + + ch = *p++; + + if (ch == '?') { + args->len = len - 1; + args->data = p; + uri->len -= len; + + return NGX_OK; + } + + if (ch == '\0') { + *flags |= NGX_HTTP_ZERO_IN_URI; + continue; + } + + if (ch != '/' +#if (NGX_WIN32) + && ch != '\\' +#endif + ) + { + continue; + } + + if (len > 2) { + + /* detect "/../" */ + + if (p[2] == '/') { + goto unsafe; + } + +#if (NGX_WIN32) + + if (p[2] == '\\') { + goto unsafe; + } + + if (len > 3) { + + /* detect "/.../" */ + + if (p[3] == '/' || p[3] == '\\') { + goto unsafe; + } + } +#endif + } + } + + return NGX_OK; + +unsafe: + + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "unsafe URI \"%V\" was detected", uri); + + return NGX_ERROR; +} + + +ngx_int_t ngx_http_parse_multi_header_lines(ngx_array_t *headers, ngx_str_t *name, ngx_str_t *value) { @@ -1059,6 +1146,7 @@ ngx_http_parse_multi_header_lines(ngx_array_t *headers, ngx_str_t *name, return i; skip: + while (start < end) { ch = *start++; if (ch == ';' || ch == ',') { diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c index 82f69c8d0..ef5a45f56 100644 --- a/src/http/ngx_http_request.c +++ b/src/http/ngx_http_request.c @@ -112,12 +112,18 @@ ngx_http_header_t ngx_http_headers_in[] = { { ngx_string("Keep-Alive"), offsetof(ngx_http_headers_in_t, keep_alive), ngx_http_process_header_line }, -#if (NGX_HTTP_PROXY) +#if (NGX_HTTP_PROXY || NGX_HTTP_REALIP) { ngx_string("X-Forwarded-For"), offsetof(ngx_http_headers_in_t, x_forwarded_for), ngx_http_process_header_line }, #endif +#if (NGX_HTTP_REALIP) + { ngx_string("X-Real-IP"), + offsetof(ngx_http_headers_in_t, x_real_ip), + ngx_http_process_header_line }, +#endif + #if (NGX_HTTP_HEADERS) { ngx_string("Accept"), offsetof(ngx_http_headers_in_t, accept), ngx_http_process_header_line }, @@ -190,20 +196,21 @@ ngx_http_init_connection(ngx_connection_t *c) static void ngx_http_init_request(ngx_event_t *rev) { - ngx_uint_t i; - socklen_t len; - struct sockaddr_in sin; - ngx_connection_t *c; - ngx_http_request_t *r; - ngx_http_in_port_t *in_port; - ngx_http_in_addr_t *in_addr; - ngx_http_log_ctx_t *ctx; - ngx_http_connection_t *hc; - ngx_http_server_name_t *server_name; - ngx_http_core_srv_conf_t *cscf; - ngx_http_core_loc_conf_t *clcf; + ngx_uint_t i; + socklen_t len; + struct sockaddr_in sin; + ngx_connection_t *c; + ngx_http_request_t *r; + ngx_http_in_port_t *in_port; + ngx_http_in_addr_t *in_addr; + ngx_http_log_ctx_t *ctx; + ngx_http_connection_t *hc; + ngx_http_server_name_t *server_name; + ngx_http_core_srv_conf_t *cscf; + ngx_http_core_loc_conf_t *clcf; + ngx_http_core_main_conf_t *cmcf; #if (NGX_HTTP_SSL) - ngx_http_ssl_srv_conf_t *sscf; + ngx_http_ssl_srv_conf_t *sscf; #endif #if (NGX_STAT_STUB) @@ -377,13 +384,21 @@ void ngx_http_init_request(ngx_event_t *rev) return; } - r->ctx = ngx_pcalloc(r->pool, sizeof(void *) * ngx_http_max_module); if (r->ctx == NULL) { ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); return; } + cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module); + + r->variables = ngx_pcalloc(r->pool, cmcf->variables.nelts + * sizeof(ngx_http_variable_value_t)); + if (r->variables == NULL) { + ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); + return; + } + c->single_connection = 1; r->connection = c; diff --git a/src/http/ngx_http_request.h b/src/http/ngx_http_request.h index 40a328c32..b0bb5d00f 100644 --- a/src/http/ngx_http_request.h +++ b/src/http/ngx_http_request.h @@ -40,6 +40,8 @@ #define NGX_HTTP_PARSE_HEADER_ERROR 13 #define NGX_HTTP_PARSE_INVALID_HEADER 13 +#define NGX_HTTP_ZERO_IN_URI 1 + #define NGX_HTTP_OK 200 #define NGX_HTTP_NO_CONTENT 204 @@ -150,10 +152,14 @@ typedef struct { ngx_table_elt_t *keep_alive; -#if (NGX_HTTP_PROXY) +#if (NGX_HTTP_PROXY || NGX_HTTP_REALIP) ngx_table_elt_t *x_forwarded_for; #endif +#if (NGX_HTTP_REALIP) + ngx_table_elt_t *x_real_ip; +#endif + #if (NGX_HTTP_HEADERS) ngx_table_elt_t *accept; ngx_table_elt_t *accept_language; @@ -320,7 +326,7 @@ struct ngx_http_request_s { ngx_http_handler_pt content_handler; ngx_uint_t access_code; - ngx_http_variable_value_t **variables; + ngx_http_variable_value_t *variables; size_t limit_rate; @@ -366,6 +372,16 @@ struct ngx_http_request_s { unsigned bypass_cache:1; unsigned no_cache:1; +#if (NGX_HTTP_REALIP) + + /* + * instead of using the request context data in ngx_http_realip_module + * we use the single bit in the request structure + */ + unsigned realip_set:1; + +#endif + #if 0 unsigned cachable:1; #endif diff --git a/src/http/ngx_http_request_body.c b/src/http/ngx_http_request_body.c index 66c7c6722..6f02f0d4b 100644 --- a/src/http/ngx_http_request_body.c +++ b/src/http/ngx_http_request_body.c @@ -220,14 +220,7 @@ ngx_http_do_read_client_request_body(ngx_http_request_t *r) "http client request body recv %z", n); if (n == NGX_AGAIN) { - clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); - ngx_add_timer(c->read, clcf->client_body_timeout); - - if (ngx_handle_read_event(c->read, 0) == NGX_ERROR) { - return NGX_HTTP_INTERNAL_SERVER_ERROR; - } - - return NGX_AGAIN; + break; } if (n == 0) { @@ -257,9 +250,20 @@ ngx_http_do_read_client_request_body(ngx_http_request_t *r) "http client request body rest %uz", rb->rest); if (rb->rest) { + clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); + ngx_add_timer(c->read, clcf->client_body_timeout); + + if (ngx_handle_read_event(c->read, 0) == NGX_ERROR) { + return NGX_HTTP_INTERNAL_SERVER_ERROR; + } + return NGX_AGAIN; } + if (c->read->timer_set) { + ngx_del_timer(c->read); + } + if (rb->temp_file) { /* save the last part */ diff --git a/src/http/ngx_http_script.c b/src/http/ngx_http_script.c index a8272ec67..90620cd59 100644 --- a/src/http/ngx_http_script.c +++ b/src/http/ngx_http_script.c @@ -34,7 +34,7 @@ ngx_http_script_compile(ngx_http_script_compile_t *sc) { u_char ch; size_t size; - ngx_int_t index; + ngx_int_t index, *p; ngx_str_t name; uintptr_t *code; ngx_uint_t i, n, bracket; @@ -42,6 +42,15 @@ ngx_http_script_compile(ngx_http_script_compile_t *sc) ngx_http_script_copy_code_t *copy; ngx_http_script_copy_capture_code_t *copy_capture; + if (sc->flushes && *sc->flushes == NULL) { + n = sc->variables ? sc->variables : 1; + *sc->flushes = ngx_array_create(sc->cf->pool, n, sizeof(ngx_uint_t)); + if (*sc->flushes == NULL) { + return NGX_ERROR; + } + } + + if (*sc->lengths == NULL) { n = sc->variables * (2 * sizeof(ngx_http_script_copy_code_t) + sizeof(ngx_http_script_var_code_t)) @@ -167,6 +176,15 @@ ngx_http_script_compile(ngx_http_script_compile_t *sc) return NGX_ERROR; } + if (sc->flushes) { + p = ngx_array_push(*sc->flushes); + if (p == NULL) { + return NGX_ERROR; + } + + *p = index; + } + var_code = ngx_http_script_add_code(*sc->lengths, sizeof(ngx_http_script_var_code_t), NULL); @@ -276,6 +294,24 @@ invalid_variable: } +void +ngx_http_script_flush_no_cachable_variables(ngx_http_request_t *r, + ngx_array_t *indices) +{ + ngx_uint_t n, *index; + + if (indices) { + index = indices->elts; + for (n = 0; n < indices->nelts; n++) { + if (r->variables[index[n]].no_cachable) { + r->variables[index[n]].valid = 0; + r->variables[index[n]].not_found = 0; + } + } + } +} + + void * ngx_http_script_start_code(ngx_pool_t *pool, ngx_array_t **codes, size_t size) { @@ -335,8 +371,8 @@ ngx_http_script_copy_code(ngx_http_script_engine_t *e) code = (ngx_http_script_copy_code_t *) e->ip; if (!e->skip) { - e->pos = ngx_cpymem(e->pos, e->ip + sizeof(ngx_http_script_copy_code_t), - code->len); + e->pos = ngx_copy(e->pos, e->ip + sizeof(ngx_http_script_copy_code_t), + code->len); } e->ip += sizeof(ngx_http_script_copy_code_t) @@ -359,10 +395,15 @@ ngx_http_script_copy_var_len_code(ngx_http_script_engine_t *e) e->ip += sizeof(ngx_http_script_var_code_t); - value = ngx_http_get_indexed_variable(e->request, code->index); + if (e->flushed) { + value = ngx_http_get_indexed_variable(e->request, code->index); + + } else { + value = ngx_http_get_flushed_variable(e->request, code->index); + } - if (value && value != NGX_HTTP_VAR_NOT_FOUND) { - return value->text.len; + if (value && !value->not_found) { + return value->len; } return 0; @@ -380,10 +421,16 @@ ngx_http_script_copy_var_code(ngx_http_script_engine_t *e) e->ip += sizeof(ngx_http_script_var_code_t); if (!e->skip) { - value = ngx_http_get_indexed_variable(e->request, code->index); - if (value && value != NGX_HTTP_VAR_NOT_FOUND) { - e->pos = ngx_cpymem(e->pos, value->text.data, value->text.len); + if (e->flushed) { + value = ngx_http_get_indexed_variable(e->request, code->index); + + } else { + value = ngx_http_get_flushed_variable(e->request, code->index); + } + + if (value && !value->not_found) { + e->pos = ngx_copy(e->pos, value->data, value->len); if (e->log) { ngx_log_debug1(NGX_LOG_DEBUG_HTTP, @@ -440,9 +487,9 @@ ngx_http_script_copy_capture_code(ngx_http_script_engine_t *e) e->captures[code->n + 1] - e->captures[code->n], NGX_ESCAPE_ARGS); } else { - e->pos = ngx_cpymem(e->pos, - &e->line.data[e->captures[code->n]], - e->captures[code->n + 1] - e->captures[code->n]); + e->pos = ngx_copy(e->pos, + &e->line.data[e->captures[code->n]], + e->captures[code->n + 1] - e->captures[code->n]); } } @@ -487,7 +534,8 @@ ngx_http_script_regex_start_code(ngx_http_script_engine_t *e) e->line = r->uri; } else { e->sp--; - e->line = e->sp->text; + e->line.len = e->sp->len; + e->line.data = e->sp->data; } rc = ngx_regex_exec(code->regex, &e->line, e->captures, code->ncaptures); @@ -502,9 +550,8 @@ ngx_http_script_regex_start_code(ngx_http_script_engine_t *e) e->ncaptures = 0; if (code->test) { - e->sp->value = 0; - e->sp->text.len = 0; - e->sp->text.data = (u_char *) ""; + e->sp->len = 0; + e->sp->data = (u_char *) ""; e->sp++; e->ip += sizeof(ngx_http_script_regex_code_t); @@ -533,9 +580,8 @@ ngx_http_script_regex_start_code(ngx_http_script_engine_t *e) e->ncaptures = code->ncaptures; if (code->test) { - e->sp->value = 1; - e->sp->text.len = 1; - e->sp->text.data = (u_char *) "1"; + e->sp->len = 1; + e->sp->data = (u_char *) "1"; e->sp++; e->ip += sizeof(ngx_http_script_regex_code_t); @@ -634,7 +680,7 @@ ngx_http_script_regex_end_code(ngx_http_script_engine_t *e) if (code->add_args && r->args.len) { *e->pos++ = (u_char) (code->args ? '&' : '?'); - e->pos = ngx_cpymem(e->pos, r->args.data, r->args.len); + e->pos = ngx_copy(e->pos, r->args.data, r->args.len); } e->buf.len = e->pos - e->buf.data; @@ -665,7 +711,7 @@ ngx_http_script_regex_end_code(ngx_http_script_engine_t *e) if (code->add_args && r->args.len) { *e->pos++ = '&'; - e->pos = ngx_cpymem(e->pos, r->args.data, r->args.len); + e->pos = ngx_copy(e->pos, r->args.data, r->args.len); } r->args.len = e->pos - e->args; @@ -741,7 +787,7 @@ ngx_http_script_if_code(ngx_http_script_engine_t *e) e->sp--; - if (e->sp->value) { + if (e->sp->len && e->sp->data[0] != '0') { if (code->loc_conf) { e->request->loc_conf = code->loc_conf; ngx_http_update_location_config(e->request); @@ -794,8 +840,8 @@ ngx_http_script_complex_value_code(ngx_http_script_engine_t *e) e->pos = e->buf.data; - e->sp->value = 0; - e->sp->text = e->buf; + e->sp->data = e->buf.data; + e->sp->len = e->buf.len; e->sp++; } @@ -812,9 +858,8 @@ ngx_http_script_value_code(ngx_http_script_engine_t *e) ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0, "http script value"); - e->sp->value = (ngx_uint_t) code->value; - e->sp->text.len = (size_t) code->text_len; - e->sp->text.data = (u_char *) code->text_data; + e->sp->len = code->text_len; + e->sp->data = (u_char *) code->text_data; e->sp++; } @@ -823,8 +868,6 @@ void ngx_http_script_set_var_code(ngx_http_script_engine_t *e) { ngx_http_request_t *r; - ngx_http_variable_value_t *value; - ngx_http_core_main_conf_t *cmcf; ngx_http_script_var_code_t *code; ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0, @@ -836,30 +879,13 @@ ngx_http_script_set_var_code(ngx_http_script_engine_t *e) r = e->request; - if (r->variables == NULL) { - cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module); - - r->variables = ngx_pcalloc(r->pool, cmcf->variables.nelts - * sizeof(ngx_http_variable_value_t *)); - if (r->variables == NULL) { - e->ip = ngx_http_script_exit; - e->status = NGX_HTTP_INTERNAL_SERVER_ERROR; - return; - } - } - - value = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t)); - if (value == NULL) { - e->ip = ngx_http_script_exit; - e->status = NGX_HTTP_INTERNAL_SERVER_ERROR; - return; - } - e->sp--; - *value = *e->sp; - - r->variables[code->index] = value; + r->variables[code->index].len = e->sp->len; + r->variables[code->index].valid = 1; + r->variables[code->index].no_cachable = 0; + r->variables[code->index].not_found = 0; + r->variables[code->index].data = e->sp->data; } @@ -876,20 +902,20 @@ ngx_http_script_var_code(ngx_http_script_engine_t *e) e->ip += sizeof(ngx_http_script_var_code_t); - value = ngx_http_get_indexed_variable(e->request, code->index); + value = ngx_http_get_flushed_variable(e->request, code->index); + + if (value && !value->not_found) { + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0, + "http script var: \"%V\"", value); - if (value && value != NGX_HTTP_VAR_NOT_FOUND) { - ngx_log_debug2(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0, - "http script var: %ui, \"%V\"", value->value, &value->text); *e->sp = *value; e->sp++; return; } - e->sp->value = 0; - e->sp->text.len = 0; - e->sp->text.data = (u_char *) ""; + e->sp->data = (u_char *) ""; + e->sp->len = 0; e->sp++; } diff --git a/src/http/ngx_http_script.h b/src/http/ngx_http_script.h index 21625427f..f67b5bee8 100644 --- a/src/http/ngx_http_script.h +++ b/src/http/ngx_http_script.h @@ -14,46 +14,49 @@ typedef struct { - u_char *ip; - u_char *pos; - ngx_http_variable_value_t *sp; + u_char *ip; + u_char *pos; + ngx_http_variable_value_t *sp; - ngx_str_t buf; - ngx_str_t line; + ngx_str_t buf; + ngx_str_t line; /* the start of the rewritten arguments */ - u_char *args; + u_char *args; - unsigned skip:1; - unsigned quote:1; - unsigned log:1; + unsigned flushed:1; + unsigned skip:1; + unsigned quote:1; + unsigned log:1; - int *captures; - ngx_uint_t ncaptures; + int *captures; + ngx_uint_t ncaptures; - ngx_int_t status; - ngx_http_request_t *request; + ngx_int_t status; + ngx_http_request_t *request; } ngx_http_script_engine_t; typedef struct { - ngx_conf_t *cf; - ngx_str_t *source; - ngx_array_t **lengths; - ngx_array_t **values; + ngx_conf_t *cf; + ngx_str_t *source; - ngx_uint_t variables; - ngx_uint_t ncaptures; - ngx_uint_t size; + ngx_array_t **flushes; + ngx_array_t **lengths; + ngx_array_t **values; - void *main; + ngx_uint_t variables; + ngx_uint_t ncaptures; + ngx_uint_t size; - unsigned compile_args:1; - unsigned compile_null:1; - unsigned complete_lengths:1; - unsigned complete_values:1; + void *main; - unsigned args:1; + unsigned compile_args:1; + unsigned compile_null:1; + unsigned complete_lengths:1; + unsigned complete_values:1; + + unsigned args:1; } ngx_http_script_compile_t; @@ -149,6 +152,8 @@ typedef struct { ngx_uint_t ngx_http_script_variables_count(ngx_str_t *value); ngx_int_t ngx_http_script_compile(ngx_http_script_compile_t *sc); +void ngx_http_script_flush_no_cachable_variables(ngx_http_request_t *r, + ngx_array_t *indices); void *ngx_http_script_start_code(ngx_pool_t *pool, ngx_array_t **codes, size_t size); diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c index 6ec9933da..48af6fe4c 100644 --- a/src/http/ngx_http_upstream.c +++ b/src/http/ngx_http_upstream.c @@ -67,12 +67,20 @@ static size_t ngx_http_upstream_log_status_getlen(ngx_http_request_t *r, uintptr_t data); static u_char *ngx_http_upstream_log_status(ngx_http_request_t *r, u_char *buf, ngx_http_log_op_t *op); +static size_t ngx_http_upstream_log_response_time_getlen(ngx_http_request_t *r, + uintptr_t data); static u_char *ngx_http_upstream_log_response_time(ngx_http_request_t *r, u_char *buf, ngx_http_log_op_t *op); static u_char *ngx_http_upstream_log_error(ngx_http_request_t *r, u_char *buf, size_t len); -static ngx_int_t ngx_http_upstream_add_log_formats(ngx_conf_t *cf); + +static ngx_int_t ngx_http_upstream_add_variables(ngx_conf_t *cf); +static ngx_int_t ngx_http_upstream_status_variable(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_http_upstream_response_time_variable(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); + static void *ngx_http_upstream_create_main_conf(ngx_conf_t *cf); static char *ngx_http_core_init_main_conf(ngx_conf_t *cf, void *conf); @@ -133,6 +141,12 @@ ngx_http_upstream_header_t ngx_http_upstream_headers_in[] = { ngx_http_upstream_copy_multi_header_lines, offsetof(ngx_http_headers_out_t, cache_control), 1 }, + { ngx_string("Expires"), + ngx_http_upstream_process_header_line, + offsetof(ngx_http_upstream_headers_in_t, expires), + ngx_http_upstream_copy_header_line, + offsetof(ngx_http_headers_out_t, expires), 1 }, + { ngx_string("Connection"), ngx_http_upstream_ignore_header_line, 0, ngx_http_upstream_ignore_header_line, 0, 0 }, @@ -173,7 +187,7 @@ ngx_http_upstream_header_t ngx_http_upstream_headers_in[] = { ngx_http_module_t ngx_http_upstream_module_ctx = { - ngx_http_upstream_add_log_formats, /* preconfiguration */ + ngx_http_upstream_add_variables, /* preconfiguration */ NULL, /* postconfiguration */ ngx_http_upstream_create_main_conf, /* create main configuration */ @@ -205,14 +219,27 @@ ngx_module_t ngx_http_upstream_module = { static ngx_http_log_op_name_t ngx_http_upstream_log_fmt_ops[] = { { ngx_string("upstream_status"), 0, NULL, - ngx_http_upstream_log_status_getlen, - ngx_http_upstream_log_status }, - { ngx_string("upstream_response_time"), NGX_TIME_T_LEN + 4, NULL, NULL, - ngx_http_upstream_log_response_time }, + ngx_http_upstream_log_status_getlen, + ngx_http_upstream_log_status }, + { ngx_string("upstream_response_time"), 0, NULL, + ngx_http_upstream_log_response_time_getlen, + ngx_http_upstream_log_response_time }, { ngx_null_string, 0, NULL, NULL, NULL } }; +static ngx_http_variable_t ngx_http_upstream_vars[] = { + + { ngx_string("upstream_status"), + ngx_http_upstream_status_variable, 0, 0, 0 }, + + { ngx_string("upstream_response_time"), + ngx_http_upstream_response_time_variable, 0, 0, 0 }, + + { ngx_null_string, NULL, 0, 0, 0 } +}; + + char *ngx_http_upstream_header_errors[] = { "upstream sent invalid header", "upstream sent too long header line" @@ -509,29 +536,27 @@ ngx_http_upstream_connect(ngx_http_request_t *r, ngx_http_upstream_t *u) } } - if (r->request_body) { - if (r->request_body->temp_file && r->main == r) { + if (r->request_body && r->request_body->temp_file && r->main == r) { - /* - * the r->request_body->buf can be reused for one request only, - * the subrequests should allocate their own temporay bufs - */ + /* + * the r->request_body->buf can be reused for one request only, + * the subrequests should allocate their own temporay bufs + */ - u->output.free = ngx_alloc_chain_link(r->pool); - if (u->output.free == NULL) { - ngx_http_upstream_finalize_request(r, u, - NGX_HTTP_INTERNAL_SERVER_ERROR); - return; - } + u->output.free = ngx_alloc_chain_link(r->pool); + if (u->output.free == NULL) { + ngx_http_upstream_finalize_request(r, u, + NGX_HTTP_INTERNAL_SERVER_ERROR); + return; + } - u->output.free->buf = r->request_body->buf; - u->output.free->next = NULL; - u->output.allocated = 1; + u->output.free->buf = r->request_body->buf; + u->output.free->next = NULL; + u->output.allocated = 1; - r->request_body->buf->pos = r->request_body->buf->start; - r->request_body->buf->last = r->request_body->buf->start; - r->request_body->buf->tag = u->output.tag; - } + r->request_body->buf->pos = r->request_body->buf->start; + r->request_body->buf->last = r->request_body->buf->start; + r->request_body->buf->tag = u->output.tag; } u->request_sent = 0; @@ -574,20 +599,19 @@ ngx_http_upstream_reinit(ngx_http_request_t *r, ngx_http_upstream_t *u) /* reinit the subrequest's ngx_output_chain() context */ - if (r->request_body) { - if (r->request_body->temp_file && r->main != r && u->output.buf) { - - u->output.free = ngx_alloc_chain_link(r->pool); - if (u->output.free == NULL) { - return NGX_ERROR; - } + if (r->request_body && r->request_body->temp_file + && r->main != r && u->output.buf) + { + u->output.free = ngx_alloc_chain_link(r->pool); + if (u->output.free == NULL) { + return NGX_ERROR; + } - u->output.free->buf = u->output.buf; - u->output.free->next = NULL; + u->output.free->buf = u->output.buf; + u->output.free->next = NULL; - u->output.buf->pos = u->output.buf->start; - u->output.buf->last = u->output.buf->start; - } + u->output.buf->pos = u->output.buf->start; + u->output.buf->last = u->output.buf->start; } u->output.buf = NULL; @@ -690,7 +714,6 @@ ngx_http_upstream_send_request(ngx_http_request_t *r, ngx_http_upstream_t *u) } c->tcp_nopush = NGX_TCP_NOPUSH_UNSET; - return; } ngx_add_timer(c->read, u->conf->read_timeout); @@ -751,7 +774,8 @@ ngx_http_upstream_process_header(ngx_event_t *rev) { ssize_t n; ngx_int_t rc; - ngx_uint_t i, key; + ngx_str_t *uri, args; + ngx_uint_t i, key, flags; ngx_list_part_t *part; ngx_table_elt_t *h; ngx_connection_t *c; @@ -982,9 +1006,21 @@ ngx_http_upstream_process_header(ngx_event_t *rev) } } - ngx_http_internal_redirect(r, - &r->upstream->headers_in.x_accel_redirect->value, - NULL); + uri = &r->upstream->headers_in.x_accel_redirect->value; + args.len = 0; + args.data = NULL; + flags = 0; + + if (ngx_http_parse_unsafe_uri(r, uri, &args, &flags) != NGX_OK) { + ngx_http_upstream_finalize_request(r, u, NGX_HTTP_NOT_FOUND); + return; + } + + if (flags & NGX_HTTP_ZERO_IN_URI) { + r->zero_in_uri = 1; + } + + ngx_http_internal_redirect(r, uri, &args); return; } @@ -1057,7 +1093,7 @@ ngx_http_upstream_send_response(ngx_http_request_t *r, ngx_http_upstream_t *u) u->header_sent = 1; - if (r->request_body->temp_file) { + if (r->request_body && r->request_body->temp_file) { for (cl = r->pool->cleanup; cl; cl = cl->next) { if (cl->handler == ngx_pool_cleanup_file) { clf = cl->data; @@ -1586,7 +1622,7 @@ static ngx_int_t ngx_http_upstream_copy_header_line(ngx_http_request_t *r, ngx_table_elt_t *h, ngx_uint_t offset) { - ngx_table_elt_t *ho; + ngx_table_elt_t *ho, **ph; ho = ngx_list_push(&r->headers_out.headers); if (ho == NULL) { @@ -1595,6 +1631,11 @@ ngx_http_upstream_copy_header_line(ngx_http_request_t *r, ngx_table_elt_t *h, *ho = *h; + if (offset) { + ph = (ngx_table_elt_t **) ((char *) &r->headers_out + offset); + *ph = ho; + } + return NGX_OK; } @@ -1814,7 +1855,7 @@ ngx_http_upstream_log_status(ngx_http_request_t *r, u_char *buf, u = r->upstream; - if (u == NULL) { + if (u == NULL || u->states.nelts == 0) { *buf = '-'; return buf + 1; } @@ -1840,6 +1881,18 @@ ngx_http_upstream_log_status(ngx_http_request_t *r, u_char *buf, } +static size_t +ngx_http_upstream_log_response_time_getlen(ngx_http_request_t *r, + uintptr_t data) +{ + if (r->upstream) { + return r->upstream->states.nelts * (NGX_TIME_T_LEN + 4 + 2); + } + + return 1; +} + + static u_char * ngx_http_upstream_log_response_time(ngx_http_request_t *r, u_char *buf, ngx_http_log_op_t *op) @@ -1850,7 +1903,7 @@ ngx_http_upstream_log_response_time(ngx_http_request_t *r, u_char *buf, u = r->upstream; - if (u == NULL) { + if (u == NULL || u->states.nelts == 0) { *buf = '-'; return buf + 1; } @@ -1905,10 +1958,21 @@ ngx_http_upstream_log_error(ngx_http_request_t *r, u_char *buf, size_t len) static ngx_int_t -ngx_http_upstream_add_log_formats(ngx_conf_t *cf) +ngx_http_upstream_add_variables(ngx_conf_t *cf) { + ngx_http_variable_t *var, *v; ngx_http_log_op_name_t *op; + for (v = ngx_http_upstream_vars; v->name.len; v++) { + var = ngx_http_add_variable(cf, &v->name, v->flags); + if (var == NULL) { + return NGX_ERROR; + } + + var->handler = v->handler; + var->data = v->data; + } + for (op = ngx_http_upstream_log_fmt_ops; op->name.len; op++) { /* void */ } op->run = NULL; @@ -1924,6 +1988,118 @@ ngx_http_upstream_add_log_formats(ngx_conf_t *cf) } +static ngx_int_t +ngx_http_upstream_status_variable(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ + u_char *p; + size_t len; + ngx_uint_t i; + ngx_http_upstream_t *u; + ngx_http_upstream_state_t *state; + + v->valid = 1; + v->no_cachable = 0; + v->not_found = 0; + + u = r->upstream; + + if (u == NULL || u->states.nelts == 0) { + v->not_found = 1; + return NGX_OK; + } + + len = u->states.nelts * (3 + 2); + + p = ngx_palloc(r->pool, len); + if (p == NULL) { + return NGX_ERROR; + } + + v->data = p; + + i = 0; + state = u->states.elts; + + for ( ;; ) { + if (state[i].status == 0) { + *p++ = '-'; + + } else { + p = ngx_sprintf(p, "%ui", state[i].status); + } + + if (++i == u->states.nelts) { + break; + } + + *p++ = ','; + *p++ = ' '; + } + + v->len = p - v->data; + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_upstream_response_time_variable(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ + u_char *p; + size_t len; + ngx_uint_t i; + ngx_http_upstream_t *u; + ngx_http_upstream_state_t *state; + + v->valid = 1; + v->no_cachable = 0; + v->not_found = 0; + + u = r->upstream; + + if (u == NULL || u->states.nelts == 0) { + v->not_found = 1; + return NGX_OK; + } + + len = u->states.nelts * (NGX_TIME_T_LEN + 4 + 2); + + p = ngx_palloc(r->pool, len); + if (p == NULL) { + return NGX_ERROR; + } + + v->data = p; + + i = 0; + state = u->states.elts; + + for ( ;; ) { + if (state[i].status == 0) { + *p++ = '-'; + + } else { + p = ngx_sprintf(p, "%d.%03d", + state[i].response_time / 1000, + state[i].response_time % 1000); + } + + if (++i == u->states.nelts) { + break; + } + + *p++ = ','; + *p++ = ' '; + } + + v->len = p - v->data; + + return NGX_OK; +} + + static void * ngx_http_upstream_create_main_conf(ngx_conf_t *cf) { diff --git a/src/http/ngx_http_upstream.h b/src/http/ngx_http_upstream.h index d6b4a62cc..027dd45f9 100644 --- a/src/http/ngx_http_upstream.h +++ b/src/http/ngx_http_upstream.h @@ -83,7 +83,7 @@ typedef struct { ngx_str_t schema; ngx_str_t uri; - ngx_str_t *location; + ngx_str_t location; ngx_str_t url; /* used in proxy_rewrite_location */ } ngx_http_upstream_conf_t; diff --git a/src/http/ngx_http_variables.c b/src/http/ngx_http_variables.c index e3954009b..2fc2e50ae 100644 --- a/src/http/ngx_http_variables.c +++ b/src/http/ngx_http_variables.c @@ -10,34 +10,32 @@ #include <ngx_http.h> -static ngx_http_variable_value_t * - ngx_http_variable_request(ngx_http_request_t *r, uintptr_t data); -static ngx_http_variable_value_t * - ngx_http_variable_header(ngx_http_request_t *r, uintptr_t data); -static ngx_http_variable_value_t * - ngx_http_variable_headers(ngx_http_request_t *r, uintptr_t data); -static ngx_http_variable_value_t * - ngx_http_variable_unknown_header(ngx_http_request_t *r, uintptr_t data); -static ngx_http_variable_value_t * - ngx_http_variable_host(ngx_http_request_t *r, uintptr_t data); -static ngx_http_variable_value_t * - ngx_http_variable_remote_addr(ngx_http_request_t *r, uintptr_t data); -static ngx_http_variable_value_t * - ngx_http_variable_remote_port(ngx_http_request_t *r, uintptr_t data); -static ngx_http_variable_value_t * - ngx_http_variable_server_addr(ngx_http_request_t *r, uintptr_t data); -static ngx_http_variable_value_t * - ngx_http_variable_server_port(ngx_http_request_t *r, uintptr_t data); -static ngx_http_variable_value_t * - ngx_http_variable_document_root(ngx_http_request_t *r, uintptr_t data); -static ngx_http_variable_value_t * - ngx_http_variable_request_filename(ngx_http_request_t *r, uintptr_t data); -static ngx_http_variable_value_t * - ngx_http_variable_request_method(ngx_http_request_t *r, uintptr_t data); -static ngx_http_variable_value_t * - ngx_http_variable_remote_user(ngx_http_request_t *r, uintptr_t data); -static ngx_http_variable_value_t * - ngx_http_variable_sent(ngx_http_request_t *r, uintptr_t data); +static ngx_int_t ngx_http_variable_request(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, + ngx_http_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_http_variable_unknown_header(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_http_variable_host(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_http_variable_remote_addr(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_http_variable_remote_port(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_http_variable_server_addr(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_http_variable_server_port(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_http_variable_document_root(ngx_http_request_t *r, + 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_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, + ngx_http_variable_value_t *v, uintptr_t data); /* @@ -95,8 +93,13 @@ static ngx_http_variable_t ngx_http_core_variables[] = { { ngx_string("request_uri"), ngx_http_variable_request, offsetof(ngx_http_request_t, unparsed_uri), 0, 0 }, + { ngx_string("uri"), 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), 0, 0 }, + offsetof(ngx_http_request_t, uri), + NGX_HTTP_VAR_NOCACHABLE, 0 }, { ngx_string("request"), ngx_http_variable_request, offsetof(ngx_http_request_t, request_line), 0, 0 }, @@ -117,10 +120,6 @@ static ngx_http_variable_t ngx_http_core_variables[] = { { ngx_string("remote_user"), ngx_http_variable_remote_user, 0, 0, 0 }, - { ngx_string("sent"), ngx_http_variable_sent, 0, 0, 0 }, - - { ngx_string("apache_sent"), ngx_http_variable_sent, 1, 0, 0 }, - { ngx_null_string, NULL, 0, 0, 0 } }; @@ -233,7 +232,6 @@ ngx_http_variable_value_t * ngx_http_get_indexed_variable(ngx_http_request_t *r, ngx_uint_t index) { ngx_http_variable_t *v; - ngx_http_variable_value_t *vv; ngx_http_core_main_conf_t *cmcf; cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module); @@ -244,27 +242,42 @@ ngx_http_get_indexed_variable(ngx_http_request_t *r, ngx_uint_t index) return NULL; } - if (r->variables && r->variables[index]) { - return r->variables[index]; + if (r->variables[index].not_found || r->variables[index].valid) { + return &r->variables[index]; } v = cmcf->variables.elts; - vv = v[index].handler(r, v[index].data); + if (v[index].handler(r, &r->variables[index], v[index].data) == NGX_OK) { - if (r->variables == NULL) { - r->variables = ngx_pcalloc(r->pool, cmcf->variables.nelts - * sizeof(ngx_http_variable_value_t *)); - if (r->variables == NULL) { - return NULL; + if (v[index].flags & NGX_HTTP_VAR_NOCACHABLE) { + r->variables[index].no_cachable = 1; } + + return &r->variables[index]; } - if (!(v[index].flags & NGX_HTTP_VAR_NOCACHABLE)) { - r->variables[index] = vv; + return NULL; +} + + +ngx_http_variable_value_t * +ngx_http_get_flushed_variable(ngx_http_request_t *r, ngx_uint_t index) +{ + ngx_http_variable_value_t *v; + + v = &r->variables[index]; + + if (v->valid) { + if (!v->no_cachable) { + return v; + } + + v->valid = 0; + v->not_found = 0; } - return vv; + return ngx_http_get_indexed_variable(r, index); } @@ -273,6 +286,7 @@ ngx_http_get_variable(ngx_http_request_t *r, ngx_str_t *name) { ngx_uint_t i, key; ngx_http_variable_t *v; + ngx_http_variable_value_t *vv; ngx_http_core_main_conf_t *cmcf; cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module); @@ -292,113 +306,133 @@ ngx_http_get_variable(ngx_http_request_t *r, ngx_str_t *name) return ngx_http_get_indexed_variable(r, v[key].index); } else { - return v[key].handler(r, v[key].data); + + vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t)); + + if (vv && v[key].handler(r, vv, v[key].data) == NGX_OK) { + return vv; + } + + return NULL; } } + vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t)); + if (vv == NULL) { + return NULL; + } + if (ngx_strncmp(name->data, "http_", 5) == 0) { - return ngx_http_variable_unknown_header(r, (uintptr_t) name); + + if (ngx_http_variable_unknown_header(r, vv, (uintptr_t) name) == NGX_OK) + { + return vv; + } + + return NULL; } ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "unknown \"%V\" variable", name); - return NGX_HTTP_VAR_NOT_FOUND; + vv->not_found = 1; + + return vv; } -static ngx_http_variable_value_t * -ngx_http_variable_request(ngx_http_request_t *r, uintptr_t data) +static ngx_int_t +ngx_http_variable_request(ngx_http_request_t *r, ngx_http_variable_value_t *v, + uintptr_t data) { - ngx_str_t *s; - ngx_http_variable_value_t *vv; + ngx_str_t *s; s = (ngx_str_t *) ((char *) r + data); - if (s->data == NULL) { - return NGX_HTTP_VAR_NOT_FOUND; - } + if (s->data) { + v->len = s->len; + v->valid = 1; + v->no_cachable = 0; + v->not_found = 0; + v->data = s->data; - vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t)); - if (vv == NULL) { - return NULL; + } else { + v->not_found = 1; } - vv->value = 0; - vv->text = *s; - - return vv; + return NGX_OK; } -static ngx_http_variable_value_t * -ngx_http_variable_header(ngx_http_request_t *r, 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) { - ngx_table_elt_t *h; - ngx_http_variable_value_t *vv; + ngx_table_elt_t *h; h = *(ngx_table_elt_t **) ((char *) r + data); - if (h == NULL) { - return NGX_HTTP_VAR_NOT_FOUND; - } + if (h) { + v->len = h->value.len; + v->valid = 1; + v->no_cachable = 0; + v->not_found = 0; + v->data = h->value.data; - vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t)); - if (vv == NULL) { - return NULL; + } else { + v->not_found = 1; } - vv->value = 0; - vv->text = h->value; - - return vv; + return NGX_OK; } -static ngx_http_variable_value_t * -ngx_http_variable_headers(ngx_http_request_t *r, uintptr_t data) +static ngx_int_t +ngx_http_variable_headers(ngx_http_request_t *r, ngx_http_variable_value_t *v, + uintptr_t data) { - u_char *p; - ngx_uint_t i; - ngx_array_t *a; - ngx_table_elt_t **h; - ngx_http_variable_value_t *vv; + size_t len; + u_char *p; + ngx_uint_t i; + ngx_array_t *a; + ngx_table_elt_t **h; a = (ngx_array_t *) ((char *) r + data); if (a->nelts == 0) { - return NGX_HTTP_VAR_NOT_FOUND; - } - - vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t)); - if (vv == NULL) { - return NULL; + v->not_found = 1; + return NGX_OK; } - vv->value = 0; + v->valid = 1; + v->no_cachable = 0; + v->not_found = 0; h = a->elts; if (a->nelts == 1) { - vv->text = (*h)->value; - return vv; + v->len = (*h)->value.len; + v->data = (*h)->value.data; + + return NGX_OK; } - vv->text.len = (size_t) - (ssize_t) (sizeof("; ") - 1); + len = (size_t) - (ssize_t) (sizeof("; ") - 1); for (i = 0; i < a->nelts; i++) { - vv->text.len += h[i]->value.len + sizeof("; ") - 1; + len += h[i]->value.len + sizeof("; ") - 1; } - vv->text.data = ngx_palloc(r->pool, vv->text.len); - if (vv->text.data == NULL) { - return NULL; + p = ngx_palloc(r->pool, len); + if (p == NULL) { + return NGX_ERROR; } - p = vv->text.data; + v->len = len; + v->data = p; for (i = 0; /* void */ ; i++) { - p = ngx_cpymem(p, h[i]->value.data, h[i]->value.len); + p = ngx_copy(p, h[i]->value.data, h[i]->value.len); if (i == a->nelts - 1) { break; @@ -407,20 +441,20 @@ ngx_http_variable_headers(ngx_http_request_t *r, uintptr_t data) *p++ = ';'; *p++ = ' '; } - return vv; + return NGX_OK; } -static ngx_http_variable_value_t * -ngx_http_variable_unknown_header(ngx_http_request_t *r, uintptr_t data) +static ngx_int_t +ngx_http_variable_unknown_header(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) { ngx_str_t *var = (ngx_str_t *) data; - u_char ch; - ngx_uint_t i, n; - ngx_list_part_t *part; - ngx_table_elt_t *header; - ngx_http_variable_value_t *vv; + u_char ch; + ngx_uint_t i, n; + ngx_list_part_t *part; + ngx_table_elt_t *header; part = &r->headers_in.headers.part; header = part->elts; @@ -453,80 +487,72 @@ ngx_http_variable_unknown_header(ngx_http_request_t *r, uintptr_t data) } if (n + 5 == var->len) { - vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t)); - if (vv == NULL) { - return NULL; - } + v->len = header[i].value.len; + v->valid = 1; + v->no_cachable = 0; + v->not_found = 0; + v->data = header[i].value.data; - vv->value = 0; - vv->text = header[i].value; - return vv; + return NGX_OK; } } - return NGX_HTTP_VAR_NOT_FOUND; + v->not_found = 1; + + return NGX_OK; } -static ngx_http_variable_value_t * -ngx_http_variable_host(ngx_http_request_t *r, uintptr_t data) +static ngx_int_t +ngx_http_variable_host(ngx_http_request_t *r, ngx_http_variable_value_t *v, + uintptr_t data) { - ngx_http_variable_value_t *vv; - - vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t)); - if (vv == NULL) { - return NULL; - } - - vv->value = 0; - if (r->headers_in.host) { - vv->text.len = r->headers_in.host_name_len; - vv->text.data = r->headers_in.host->value.data; + v->len = r->headers_in.host_name_len; + v->data = r->headers_in.host->value.data; } else { - vv->text = r->server_name; + v->len = r->server_name.len; + v->data = r->server_name.data; } - return vv; + v->valid = 1; + v->no_cachable = 0; + v->not_found = 0; + + return NGX_OK; } -static ngx_http_variable_value_t * -ngx_http_variable_remote_addr(ngx_http_request_t *r, uintptr_t data) +static ngx_int_t +ngx_http_variable_remote_addr(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) { - ngx_http_variable_value_t *vv; + v->len = r->connection->addr_text.len; + v->valid = 1; + v->no_cachable = 0; + v->not_found = 0; + v->data = r->connection->addr_text.data; - vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t)); - if (vv == NULL) { - return NULL; - } - - vv->value = 0; - vv->text = r->connection->addr_text; - - return vv; + return NGX_OK; } -static ngx_http_variable_value_t * -ngx_http_variable_remote_port(ngx_http_request_t *r, uintptr_t data) +static ngx_int_t +ngx_http_variable_remote_port(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) { - ngx_uint_t port; - struct sockaddr_in *sin; - ngx_http_variable_value_t *vv; + ngx_uint_t port; + struct sockaddr_in *sin; - vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t)); - if (vv == NULL) { - return NULL; - } - - vv->value = 0; - vv->text.len = 0; + v->len = 0; + v->valid = 1; + v->no_cachable = 0; + v->not_found = 0; - vv->text.data = ngx_palloc(r->pool, sizeof("65535") - 1); - if (vv->text.data == NULL) { - return NULL; + v->data = ngx_palloc(r->pool, sizeof("65535") - 1); + if (v->data == NULL) { + return NGX_ERROR; } /* AF_INET only */ @@ -537,34 +563,25 @@ ngx_http_variable_remote_port(ngx_http_request_t *r, uintptr_t data) port = ntohs(sin->sin_port); if (port > 0 && port < 65536) { - vv->value = port; - vv->text.len = ngx_sprintf(vv->text.data, "%ui", port) - - vv->text.data; + v->len = ngx_sprintf(v->data, "%ui", port) - v->data; } } - return vv; + return NGX_OK; } -static ngx_http_variable_value_t * -ngx_http_variable_server_addr(ngx_http_request_t *r, uintptr_t data) +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_http_variable_value_t *vv; - - vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t)); - if (vv == NULL) { - return NULL; - } + socklen_t len; + ngx_connection_t *c; + struct sockaddr_in sin; - vv->value = 0; - - vv->text.data = ngx_palloc(r->pool, INET_ADDRSTRLEN); - if (vv->text.data == NULL) { - return NULL; + v->data = ngx_palloc(r->pool, INET_ADDRSTRLEN); + if (v->data == NULL) { + return NGX_ERROR; } c = r->connection; @@ -574,168 +591,126 @@ ngx_http_variable_server_addr(ngx_http_request_t *r, uintptr_t data) if (getsockname(c->fd, (struct sockaddr *) &sin, &len) == -1) { ngx_log_error(NGX_LOG_CRIT, c->log, ngx_socket_errno, "getsockname() failed"); - return NULL; + return NGX_ERROR; } r->in_addr = sin.sin_addr.s_addr; } - vv->text.len = ngx_inet_ntop(c->listening->family, &r->in_addr, - vv->text.data, INET_ADDRSTRLEN); + v->len = ngx_inet_ntop(c->listening->family, &r->in_addr, + v->data, INET_ADDRSTRLEN); + v->valid = 1; + v->no_cachable = 0; + v->not_found = 0; - return vv; + return NGX_OK; } -static ngx_http_variable_value_t * -ngx_http_variable_server_port(ngx_http_request_t *r, uintptr_t data) +static ngx_int_t +ngx_http_variable_server_port(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) { - ngx_http_variable_value_t *vv; + v->len = r->port_text->len - 1; + v->valid = 1; + v->no_cachable = 0; + v->not_found = 0; + v->data = r->port_text->data + 1; - vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t)); - if (vv == NULL) { - return NULL; - } - - vv->value = r->port; - vv->text.len = r->port_text->len - 1; - vv->text.data = r->port_text->data + 1; - - return vv; + return NGX_OK; } -static ngx_http_variable_value_t * -ngx_http_variable_document_root(ngx_http_request_t *r, uintptr_t data) +static ngx_int_t +ngx_http_variable_document_root(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) { - ngx_http_core_loc_conf_t *clcf; - ngx_http_variable_value_t *vv; - - vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t)); - if (vv == NULL) { - return NULL; - } + ngx_http_core_loc_conf_t *clcf; clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); - vv->value = 0; - vv->text = clcf->root; + v->len = clcf->root.len; + v->valid = 1; + v->no_cachable = 0; + v->not_found = 0; + v->data = clcf->root.data; - return vv; + return NGX_OK; } -static ngx_http_variable_value_t * -ngx_http_variable_request_filename(ngx_http_request_t *r, 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) { - ngx_http_variable_value_t *vv; + ngx_str_t path; - vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t)); - if (vv == NULL) { - return NULL; - } - - vv->value = 0; - - if (ngx_http_map_uri_to_path(r, &vv->text, 0) == NULL) { - return NULL; + if (ngx_http_map_uri_to_path(r, &path, 0) == NULL) { + return NGX_ERROR; } /* ngx_http_map_uri_to_path() allocates memory for terminating '\0' */ - vv->text.len--; + v->len = path.len - 1; + v->valid = 1; + v->no_cachable = 0; + v->not_found = 0; + v->data = path.data; - return vv; + return NGX_OK; } -static ngx_http_variable_value_t * -ngx_http_variable_request_method(ngx_http_request_t *r, 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) { - ngx_http_variable_value_t *vv; - - if (r->method_name.data == NULL) { - return NGX_HTTP_VAR_NOT_FOUND; - } + if (r->method_name.data) { + if (r->upstream && r->upstream->method.len) { + v->len = r->upstream->method.len; + v->data = r->upstream->method.data; - vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t)); - if (vv == NULL) { - return NULL; - } - - vv->value = 0; + } else { + v->len = r->method_name.len; + v->data = r->method_name.data; + } - if (r->upstream && r->upstream->method.len) { - vv->text = r->upstream->method; + v->valid = 1; + v->no_cachable = 0; + v->not_found = 0; } else { - vv->text = r->method_name; + v->not_found = 1; } - return vv; + return NGX_OK; } -static ngx_http_variable_value_t * -ngx_http_variable_remote_user(ngx_http_request_t *r, uintptr_t data) +static ngx_int_t +ngx_http_variable_remote_user(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) { - ngx_int_t rc; - ngx_http_variable_value_t *vv; + ngx_int_t rc; rc = ngx_http_auth_basic_user(r); if (rc == NGX_DECLINED) { - return NGX_HTTP_VAR_NOT_FOUND; + v->not_found = 1; + return NGX_OK; } if (rc == NGX_ERROR) { - return NULL; - } - - vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t)); - if (vv == NULL) { - return NULL; - } - - vv->value = 0; - vv->text = r->headers_in.user; - - return vv; -} - - -static ngx_http_variable_value_t * -ngx_http_variable_sent(ngx_http_request_t *r, uintptr_t data) -{ - off_t sent; - u_char *p; - ngx_http_variable_value_t *vv; - - vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t)); - if (vv == NULL) { - return NULL; - } - - sent = r->connection->sent; - - if (data) { - sent -= r->header_size; - - if (sent < 0) { - sent = 0; - } - } - - p = ngx_palloc(r->pool, NGX_OFF_T_LEN); - if (p == NULL) { - return NULL; + return NGX_ERROR; } - vv->value = 0; - vv->text.len = ngx_sprintf(p, "%O", sent) - p; - vv->text.data = p; + v->len = r->headers_in.user.len; + v->valid = 1; + v->no_cachable = 0; + v->not_found = 0; + v->data = r->headers_in.user.data; - return vv; + return NGX_OK; } diff --git a/src/http/ngx_http_variables.h b/src/http/ngx_http_variables.h index df0fc9efa..67b781e6d 100644 --- a/src/http/ngx_http_variables.h +++ b/src/http/ngx_http_variables.h @@ -14,18 +14,22 @@ #include <ngx_http.h> -#define NGX_HTTP_VAR_NOT_FOUND (ngx_http_variable_value_t *) -1 +typedef struct { + unsigned len:29; + unsigned valid:1; + unsigned no_cachable:1; + unsigned not_found:1; -typedef struct { - ngx_uint_t value; - ngx_str_t text; + u_char *data; } ngx_http_variable_value_t; +#define ngx_http_variable(v) { sizeof(v) - 1, 1, 0, 0, (u_char *) v } + typedef struct ngx_http_variable_s ngx_http_variable_t; -typedef ngx_http_variable_value_t * - (*ngx_http_get_variable_pt) (ngx_http_request_t *r, 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); #define NGX_HTTP_VAR_CHANGABLE 1 @@ -34,11 +38,11 @@ typedef ngx_http_variable_value_t * struct ngx_http_variable_s { - ngx_str_t name; /* must be first to build the hash */ - ngx_http_get_variable_pt handler; - uintptr_t data; - ngx_uint_t flags; - ngx_uint_t index; + ngx_str_t name; /* must be first to build the hash */ + ngx_http_get_variable_pt handler; + uintptr_t data; + ngx_uint_t flags; + ngx_uint_t index; }; @@ -47,9 +51,15 @@ ngx_http_variable_t *ngx_http_add_variable(ngx_conf_t *cf, ngx_str_t *name, ngx_int_t ngx_http_get_variable_index(ngx_conf_t *cf, ngx_str_t *name); ngx_http_variable_value_t *ngx_http_get_indexed_variable(ngx_http_request_t *r, ngx_uint_t index); +ngx_http_variable_value_t *ngx_http_get_flushed_variable(ngx_http_request_t *r, + ngx_uint_t index); + ngx_http_variable_value_t *ngx_http_get_variable(ngx_http_request_t *r, ngx_str_t *name); +#define ngx_http_clear_variable(r, index) r->variables0[index].text.data = NULL; + + ngx_int_t ngx_http_variables_add_core_vars(ngx_conf_t *cf); ngx_int_t ngx_http_variables_init_vars(ngx_conf_t *cf); diff --git a/src/imap/ngx_imap_auth_http_module.c b/src/imap/ngx_imap_auth_http_module.c index 4b8584de1..dfe0c2043 100644 --- a/src/imap/ngx_imap_auth_http_module.c +++ b/src/imap/ngx_imap_auth_http_module.c @@ -18,6 +18,9 @@ typedef struct { ngx_str_t host_header; ngx_str_t uri; + ngx_str_t header; + + ngx_array_t *headers; } ngx_imap_auth_http_conf_t; @@ -70,6 +73,8 @@ static void *ngx_imap_auth_http_create_conf(ngx_conf_t *cf); static char *ngx_imap_auth_http_merge_conf(ngx_conf_t *cf, void *parent, void *child); static char *ngx_imap_auth_http(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); +static char *ngx_imap_auth_http_header(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf); static ngx_command_t ngx_imap_auth_http_commands[] = { @@ -88,6 +93,13 @@ static ngx_command_t ngx_imap_auth_http_commands[] = { offsetof(ngx_imap_auth_http_conf_t, timeout), NULL }, + { ngx_string("auth_http_header"), + NGX_IMAP_MAIN_CONF|NGX_IMAP_SRV_CONF|NGX_CONF_TAKE2, + ngx_imap_auth_http_header, + NGX_IMAP_SRV_CONF_OFFSET, + 0, + NULL }, + ngx_null_command }; @@ -991,12 +1003,12 @@ ngx_imap_auth_http_create_request(ngx_imap_session_t *s, ngx_pool_t *pool, } b->last = ngx_cpymem(b->last, "GET ", sizeof("GET ") - 1); - b->last = ngx_cpymem(b->last, ahcf->uri.data, ahcf->uri.len); + b->last = ngx_copy(b->last, ahcf->uri.data, ahcf->uri.len); b->last = ngx_cpymem(b->last, " HTTP/1.0" CRLF, sizeof(" HTTP/1.0" CRLF) - 1); b->last = ngx_cpymem(b->last, "Host: ", sizeof("Host: ") - 1); - b->last = ngx_cpymem(b->last, ahcf->host_header.data, + b->last = ngx_copy(b->last, ahcf->host_header.data, ahcf->host_header.len); *b->last++ = CR; *b->last++ = LF; @@ -1004,11 +1016,11 @@ ngx_imap_auth_http_create_request(ngx_imap_session_t *s, ngx_pool_t *pool, sizeof("Auth-Method: plain" CRLF) - 1); b->last = ngx_cpymem(b->last, "Auth-User: ", sizeof("Auth-User: ") - 1); - b->last = ngx_cpymem(b->last, s->login.data, s->login.len); + b->last = ngx_copy(b->last, s->login.data, s->login.len); *b->last++ = CR; *b->last++ = LF; b->last = ngx_cpymem(b->last, "Auth-Pass: ", sizeof("Auth-Pass: ") - 1); - b->last = ngx_cpymem(b->last, s->passwd.data, s->passwd.len); + b->last = ngx_copy(b->last, s->passwd.data, s->passwd.len); *b->last++ = CR; *b->last++ = LF; b->last = ngx_cpymem(b->last, "Auth-Protocol: ", @@ -1021,10 +1033,14 @@ ngx_imap_auth_http_create_request(ngx_imap_session_t *s, ngx_pool_t *pool, s->login_attempt); b->last = ngx_cpymem(b->last, "Client-IP: ", sizeof("Client-IP: ") - 1); - b->last = ngx_cpymem(b->last, s->connection->addr_text.data, + b->last = ngx_copy(b->last, s->connection->addr_text.data, s->connection->addr_text.len); *b->last++ = CR; *b->last++ = LF; + if (ahcf->header.len) { + b->last = ngx_copy(b->last, ahcf->header.data, ahcf->header.len); + } + /* add "\r\n" at the header end */ *b->last++ = CR; *b->last++ = LF; @@ -1065,6 +1081,11 @@ ngx_imap_auth_http_merge_conf(ngx_conf_t *cf, void *parent, void *child) ngx_imap_auth_http_conf_t *prev = parent; ngx_imap_auth_http_conf_t *conf = child; + u_char *p; + size_t len; + ngx_uint_t i; + ngx_table_elt_t *header; + if (conf->peers == NULL) { conf->peers = prev->peers; conf->host_header = prev->host_header; @@ -1073,6 +1094,34 @@ ngx_imap_auth_http_merge_conf(ngx_conf_t *cf, void *parent, void *child) ngx_conf_merge_msec_value(conf->timeout, prev->timeout, 60000); + if (conf->headers == NULL) { + conf->headers = prev->headers; + conf->header = prev->header; + } + + if (conf->headers && conf->header.len == 0) { + len = 0; + header = conf->headers->elts; + for (i = 0; i < conf->headers->nelts; i++) { + len += header[i].key.len + 2 + header[i].value.len + 2; + } + + p = ngx_palloc(cf->pool, len); + if (p == NULL) { + return NGX_CONF_ERROR; + } + + conf->header.len = len; + conf->header.data = p; + + for (i = 0; i < conf->headers->nelts; i++) { + p = ngx_cpymem(p, header[i].key.data, header[i].key.len); + *p++ = ':'; *p++ = ' '; + p = ngx_cpymem(p, header[i].value.data, header[i].value.len); + *p++ = CR; *p++ = LF; + } + } + return NGX_CONF_OK; } @@ -1087,7 +1136,7 @@ ngx_imap_auth_http(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) #if (NGX_HAVE_UNIX_DOMAIN) ngx_unix_domain_upstream_t unix_upstream; #endif - + value = cf->args->elts; url = &value[1]; @@ -1143,3 +1192,32 @@ ngx_imap_auth_http(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) return NGX_CONF_OK; } + + +static char * +ngx_imap_auth_http_header(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) +{ + ngx_imap_auth_http_conf_t *ahcf = conf; + + ngx_str_t *value; + ngx_table_elt_t *header; + + if (ahcf->headers == NULL) { + ahcf->headers = ngx_array_create(cf->pool, 1, sizeof(ngx_table_elt_t)); + if (ahcf->headers == NULL) { + return NGX_CONF_ERROR; + } + } + + header = ngx_array_push(ahcf->headers); + if (header == NULL) { + return NGX_CONF_ERROR; + } + + value = cf->args->elts; + + header->key = value[1]; + header->value = value[2]; + + return NGX_CONF_OK; +} diff --git a/src/imap/ngx_imap_ssl_module.c b/src/imap/ngx_imap_ssl_module.c index d663e8850..f92dba60b 100644 --- a/src/imap/ngx_imap_ssl_module.c +++ b/src/imap/ngx_imap_ssl_module.c @@ -83,6 +83,12 @@ static ngx_command_t ngx_imap_ssl_commands[] = { ngx_imap_ssl_nosupported, 0, 0, ngx_imap_ssl_openssl097 }, #endif + { ngx_string("ssl_session_timeout"), + NGX_IMAP_MAIN_CONF|NGX_IMAP_SRV_CONF|NGX_CONF_TAKE1, + ngx_conf_set_sec_slot, + NGX_IMAP_SRV_CONF_OFFSET, + offsetof(ngx_imap_ssl_conf_t, session_timeout), + NULL }, ngx_null_command }; @@ -140,6 +146,7 @@ ngx_imap_ssl_create_conf(ngx_conf_t *cf) */ scf->enable = NGX_CONF_UNSET; + scf->session_timeout = NGX_CONF_UNSET; scf->prefer_server_ciphers = NGX_CONF_UNSET; return scf; @@ -160,6 +167,9 @@ ngx_imap_ssl_merge_conf(ngx_conf_t *cf, void *parent, void *child) return NGX_CONF_OK; } + ngx_conf_merge_value(conf->session_timeout, + prev->session_timeout, 300); + ngx_conf_merge_value(conf->prefer_server_ciphers, prev->prefer_server_ciphers, 0); @@ -225,6 +235,8 @@ ngx_imap_ssl_merge_conf(ngx_conf_t *cf, void *parent, void *child) SSL_CTX_set_session_id_context(conf->ssl.ctx, ngx_imap_session_id_ctx, sizeof(ngx_imap_session_id_ctx) - 1); + SSL_CTX_set_timeout(conf->ssl.ctx, conf->session_timeout); + return NGX_CONF_OK; } diff --git a/src/imap/ngx_imap_ssl_module.h b/src/imap/ngx_imap_ssl_module.h index fd0ccada4..2ac9f119e 100644 --- a/src/imap/ngx_imap_ssl_module.h +++ b/src/imap/ngx_imap_ssl_module.h @@ -22,6 +22,8 @@ typedef struct { ngx_uint_t protocols; + time_t session_timeout; + ngx_str_t certificate; ngx_str_t certificate_key; diff --git a/src/os/unix/ngx_process_cycle.c b/src/os/unix/ngx_process_cycle.c index e0f967fc0..ddc10c8a5 100644 --- a/src/os/unix/ngx_process_cycle.c +++ b/src/os/unix/ngx_process_cycle.c @@ -15,9 +15,10 @@ static void ngx_start_worker_processes(ngx_cycle_t *cycle, ngx_int_t n, static void ngx_start_garbage_collector(ngx_cycle_t *cycle, ngx_int_t type); static void ngx_signal_worker_processes(ngx_cycle_t *cycle, int signo); static ngx_uint_t ngx_reap_childs(ngx_cycle_t *cycle); -static void ngx_master_exit(ngx_cycle_t *cycle); +static void ngx_master_process_exit(ngx_cycle_t *cycle); static void ngx_worker_process_cycle(ngx_cycle_t *cycle, void *data); static void ngx_worker_process_init(ngx_cycle_t *cycle, ngx_uint_t priority); +static void ngx_worker_process_exit(ngx_cycle_t *cycle); static void ngx_channel_handler(ngx_event_t *ev); #if (NGX_THREADS) static void ngx_wakeup_worker_threads(ngx_cycle_t *cycle); @@ -156,7 +157,7 @@ ngx_master_process_cycle(ngx_cycle_t *cycle) } if (!live && (ngx_terminate || ngx_quit)) { - ngx_master_exit(cycle); + ngx_master_process_exit(cycle); } if (ngx_terminate) { @@ -283,7 +284,7 @@ ngx_single_process_cycle(ngx_cycle_t *cycle) } } - ngx_master_exit(cycle); + ngx_master_process_exit(cycle); } if (ngx_reconfigure) { @@ -628,7 +629,7 @@ ngx_reap_childs(ngx_cycle_t *cycle) static void -ngx_master_exit(ngx_cycle_t *cycle) +ngx_master_process_exit(ngx_cycle_t *cycle) { ngx_uint_t i; @@ -658,8 +659,6 @@ ngx_master_exit(ngx_cycle_t *cycle) static void ngx_worker_process_cycle(ngx_cycle_t *cycle, void *data) { - ngx_uint_t i; - ngx_connection_t *c; #if (NGX_THREADS) ngx_int_t n; ngx_err_t err; @@ -717,26 +716,7 @@ ngx_worker_process_cycle(ngx_cycle_t *cycle, void *data) { ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "exiting"); - -#if (NGX_THREADS) - ngx_terminate = 1; - - ngx_wakeup_worker_threads(cycle); -#endif - - if (ngx_debug_quit) { - ngx_debug_point(); - } - - /* - * we do not destroy cycle->pool here because a signal handler - * that uses cycle->log can be called at this point - */ - -#if 0 - ngx_destroy_pool(cycle->pool); -#endif - exit(0); + ngx_worker_process_exit(cycle); } ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "worker cycle"); @@ -746,41 +726,7 @@ ngx_worker_process_cycle(ngx_cycle_t *cycle, void *data) if (ngx_terminate) { ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "exiting"); -#if (NGX_THREADS) - ngx_wakeup_worker_threads(cycle); -#endif - - for (i = 0; ngx_modules[i]; i++) { - if (ngx_modules[i]->exit_process) { - ngx_modules[i]->exit_process(cycle); - } - } - - c = cycle->connections; - for (i = 0; i < cycle->connection_n; i++) { - if (c[i].fd != -1 - && c[i].read - && !c[i].read->accept - && !c[i].read->channel) - { - ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, - "open socket #%d left in %ui connection, " - "aborting", - c[i].fd, i); - ngx_abort(); - } - } - - /* - * we do not destroy cycle->pool here because a signal handler - * that uses cycle->log can be called at this point - */ - -#if 0 - ngx_destroy_pool(cycle->pool); -#endif - - exit(0); + ngx_worker_process_exit(cycle); } if (ngx_quit) { @@ -957,6 +903,56 @@ ngx_worker_process_init(ngx_cycle_t *cycle, ngx_uint_t priority) static void +ngx_worker_process_exit(ngx_cycle_t *cycle) +{ + ngx_uint_t i; + ngx_connection_t *c; + +#if (NGX_THREADS) + ngx_terminate = 1; + + ngx_wakeup_worker_threads(cycle); +#endif + + for (i = 0; ngx_modules[i]; i++) { + if (ngx_modules[i]->exit_process) { + ngx_modules[i]->exit_process(cycle); + } + } + + c = cycle->connections; + for (i = 0; i < cycle->connection_n; i++) { + if (c[i].fd != -1 + && c[i].read + && !c[i].read->accept + && !c[i].read->channel) + { + ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, + "open socket #%d left in %ui connection, " + "aborting", + c[i].fd, i); + ngx_abort(); + } + } + + if (ngx_debug_quit) { + ngx_debug_point(); + } + + /* + * we do not destroy cycle->pool here because a signal handler + * that uses cycle->log can be called at this point + */ + +#if 0 + ngx_destroy_pool(cycle->pool); +#endif + + exit(0); +} + + +static void ngx_channel_handler(ngx_event_t *ev) { ngx_int_t n; |