# HG changeset patch # User Igor Sysoev # Date 1116446400 -14400 # Node ID 5db440287648a24019a0e8d8c88ee10dbe5cd134 # Parent e428671357816c23beb021446ca922ed4c38264f nginx 0.1.32 *) Bugfix: the arguments were omitted in the redirects, issued by the "rewrite" directive; bug appeared in 0.1.29. *) Feature: the "if" directive supports the captures in regular expressions. *) Feature: the "set" directive supports the variables and the captures of regular expressions. *) Feature: the "X-Accel-Redirect" response header line is supported in proxy and FastCGI mode. diff --git a/CHANGES b/CHANGES --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,18 @@ + +Changes with nginx 0.1.32 19 May 2005 + + *) Bugfix: the arguments were omitted in the redirects, issued by the + "rewrite" directive; bug appeared in 0.1.29. + + *) Feature: the "if" directive supports the captures in regular + expressions. + + *) Feature: the "set" directive supports the variables and the captures + of regular expressions. + + *) Feature: the "X-Accel-Redirect" response header line is supported in + proxy and FastCGI mode. + Changes with nginx 0.1.31 16 May 2005 diff --git a/CHANGES.ru b/CHANGES.ru --- a/CHANGES.ru +++ b/CHANGES.ru @@ -1,3 +1,18 @@ + +Изменения в nginx 0.1.32 19.05.2005 + + *) Исправление: в редиректах, выдаваемых с помощью директивы rewrite, + не передавались аргументы; ошибка появилась в 0.1.29. + + *) Добавление: директива if поддерживает выделения в регулярных + выражениях. + + *) Добавление: директива set поддерживает переменные и выделения из + регулярных выражений. + + *) Добавление: в режиме прокси и FastCGI поддерживается строка + заголовка X-Accel-Redirect в ответе бэкенда. + Изменения в nginx 0.1.31 16.05.2005 diff --git a/auto/cc/acc b/auto/cc/acc new file mode 100644 --- /dev/null +++ b/auto/cc/acc @@ -0,0 +1,14 @@ + +# Copyright (C) Igor Sysoev + + +# aCC: HP ANSI C++ B3910B A.03.55.02 + +# C89 mode + +CFLAGS="$CFLAGS -Ae" +CC_TEST_FLAGS="-Ae" + +PCRE_OPT="$PCRE_OPT -Ae" +ZLIB_OPT="$ZLIB_OPT -Ae" +MD5_OPT="$MD5_OPT -Ae" diff --git a/auto/cc/ccc b/auto/cc/ccc new file mode 100644 --- /dev/null +++ b/auto/cc/ccc @@ -0,0 +1,41 @@ + +# Copyright (C) Igor Sysoev + + +# Compaq C V6.5-207 + +ngx_include_opt="-I" + +# warnings + +CFLAGS="$CFLAGS -msg_enable level6 -msg_fatal level6" + +CFLAGS="$CFLAGS -msg_disable unnecincl" +CFLAGS="$CFLAGS -msg_disable nestincl" +CFLAGS="$CFLAGS -msg_disable unusedincl" +CFLAGS="$CFLAGS -msg_disable unknownmacro" +CFLAGS="$CFLAGS -msg_disable strctpadding" +CFLAGS="$CFLAGS -msg_disable ansialiascast" +CFLAGS="$CFLAGS -msg_disable inlinestoclsmod" +CFLAGS="$CFLAGS -msg_disable cxxkeyword" +CFLAGS="$CFLAGS -msg_disable longlongsufx" + +# STUB +CFLAGS="$CFLAGS -msg_disable truncintcast" +CFLAGS="$CFLAGS -msg_disable trunclongcast" +CFLAGS="$CFLAGS -msg_disable truncintasn" +CFLAGS="$CFLAGS -msg_disable trunclongint" +CFLAGS="$CFLAGS -msg_disable intconcastsgn" +CFLAGS="$CFLAGS -msg_disable intconstsign" +CFLAGS="$CFLAGS -msg_disable hexoctunsign" +CFLAGS="$CFLAGS -msg_disable switchlong" +CFLAGS="$CFLAGS -msg_disable valuepres" +CFLAGS="$CFLAGS -msg_disable subscrbounds2" +CFLAGS="$CFLAGS -msg_disable ignorecallval" +CFLAGS="$CFLAGS -msg_disable nonstandcast" +CFLAGS="$CFLAGS -msg_disable embedcomment" +CFLAGS="$CFLAGS -msg_disable unreachcode" +CFLAGS="$CFLAGS -msg_disable questcompare2" +CFLAGS="$CFLAGS -msg_disable unusedtop" +CFLAGS="$CFLAGS -msg_disable unrefdecl" +CFLAGS="$CFLAGS -msg_disable bitnotint" diff --git a/auto/cc/conf b/auto/cc/conf --- a/auto/cc/conf +++ b/auto/cc/conf @@ -42,30 +42,30 @@ else case $NGX_CC_NAME in gcc) - # gcc 2.7.2.3, 2.8.1, 2.95.4, - # 3.0.4, 3.1.1, 3.2.3, 3.3.2, 3.3.3, 3.3.4, 3.4 + # gcc 2.7.2.3, 2.8.1, 2.95.4, egcs-1.1.2 + # 3.0.4, 3.1.1, 3.2.3, 3.3.2, 3.3.3, 3.3.4, 3.4.0, 3.4.2 + # 4.0.0 . auto/cc/gcc ;; icc) - # Intel C++ compiler 7.1, 8.0 + # Intel C++ compiler 7.1, 8.0, 8.1 . auto/cc/icc ;; ccc) -# # Compaq C V6.5-207 -# -# . auto/cc/ccc - ngx_include_opt="-I" + # Compaq C V6.5-207 + + . auto/cc/ccc ;; -# acc) -# # aCC: HP ANSI C++ B3910B A.03.55.02 -# -# . auto/cc/acc -# ;; + acc) + # aCC: HP ANSI C++ B3910B A.03.55.02 + + . auto/cc/acc + ;; msvc*) # MSVC++ 6.0 SP2, MSVC++ Toolkit 2003 @@ -87,7 +87,7 @@ else esac - CC_TEST_FLAGS=$NGX_CC_OPT + CC_TEST_FLAGS="$CC_TEST_FLAGS $NGX_CC_OPT" fi @@ -124,16 +124,20 @@ if [ "$NGX_PLATFORM" != win32 ]; then . auto/feature - ngx_feature="C99 variadic macros" - ngx_feature_name="NGX_HAVE_C99_VARIADIC_MACROS" - ngx_feature_run=yes - ngx_feature_incs="#include -#define var(dummy, ...) sprintf(__VA_ARGS__)" - ngx_feature_libs= - ngx_feature_test="char buf[30]; buf[0] = '0'; - var(0, buf, \"%d\", 1); - if (buf[0] != '1') return 1" - . auto/feature + if [ $NGX_CC_NAME = 'ccc' ]; then + echo "checking for C99 variadic macros ... disabled" + else + ngx_feature="C99 variadic macros" + ngx_feature_name="NGX_HAVE_C99_VARIADIC_MACROS" + ngx_feature_run=yes + ngx_feature_incs="#include +#define var(dummy, ...) sprintf(__VA_ARGS__)" + ngx_feature_libs= + ngx_feature_test="char buf[30]; buf[0] = '0'; + var(0, buf, \"%d\", 1); + if (buf[0] != '1') return 1" + . auto/feature + fi # ngx_feature="inline" diff --git a/auto/os/conf b/auto/os/conf --- a/auto/os/conf +++ b/auto/os/conf @@ -23,15 +23,6 @@ case "$NGX_PLATFORM" in . auto/os/freebsd ;; - Darwin:*) - have=NGX_DARWIN . auto/have_headers - have=NGX_HAVE_INHERITED_NONBLOCK . auto/have - CORE_INCS="$UNIX_INCS" - CORE_DEPS="$UNIX_DEPS $POSIX_DEPS" - CORE_SRCS="$UNIX_SRCS" - CRYPT_LIB= - ;; - Linux:*) . auto/os/linux ;; @@ -44,11 +35,35 @@ case "$NGX_PLATFORM" in . auto/os/win32 ;; + Darwin:*) + have=NGX_DARWIN . auto/have_headers + have=NGX_HAVE_INHERITED_NONBLOCK . auto/have + CORE_INCS="$UNIX_INCS" + CORE_DEPS="$UNIX_DEPS $POSIX_DEPS" + CORE_SRCS="$UNIX_SRCS" + ;; + + HP-UX:*) + # HP/UX + have=NGX_HPUX . auto/have_headers + CORE_INCS="$UNIX_INCS" + CORE_DEPS="$UNIX_DEPS $POSIX_DEPS" + CORE_SRCS="$UNIX_SRCS" + CC_AUX_FLAGS="$CC_AUX_FLAGS -D_XOPEN_SOURCE -D_XOPEN_SOURCE_EXTENDED=1" + ;; + + OSF1:*) + # HP Tru64 + have=NGX_TRU64 . auto/have_headers + CORE_INCS="$UNIX_INCS" + CORE_DEPS="$UNIX_DEPS $POSIX_DEPS" + CORE_SRCS="$UNIX_SRCS" + ;; + *) CORE_INCS="$UNIX_INCS" CORE_DEPS="$UNIX_DEPS $POSIX_DEPS" CORE_SRCS="$UNIX_SRCS" - CRYPT_LIB="-lcrypt" ;; esac @@ -56,119 +71,8 @@ esac case "$NGX_MACHINE" in - i386|i686|i86pc|amd64) + i386 | i686 | i86pc | amd64) have=NGX_HAVE_NONALIGNED . auto/have ;; esac - - -if [ "$NGX_PLATFORM" != win32 ]; then - - NGX_USER=${NGX_USER:-nobody} - - if [ -z "$NGX_GROUP" -a $NGX_USER = nobody ] ; then - if grep nobody /etc/group 2>&1 >/dev/null; then - echo "checking for nobody group ... found" - NGX_GROUP=nobody - else - echo "checking for nobody group ... not found" - - if grep nogroup /etc/group 2>&1 >/dev/null; then - echo "checking for nogroup group ... found" - NGX_GROUP=nogroup - else - echo "checking for nogroup group ... not found" - NGX_GROUP=nobody - fi - fi - - else - NGX_GROUP=$NGX_USER - fi - - - ngx_feature="poll()" - ngx_feature_name= - ngx_feature_run=no - ngx_feature_incs="#include " - ngx_feature_libs= - ngx_feature_test="int n, dp; struct pollfd pl; - dp = 0; - pl.fd = 0; - pl.events = 0; - pl.revents = 0; - n = poll(&pl, 1, 0)" - . auto/feature - - if [ $ngx_found = no ]; then - EVENT_POLL=NONE - fi - - - ngx_feature="/dev/poll" - ngx_feature_name="NGX_HAVE_DEVPOLL" - ngx_feature_run=no - ngx_feature_incs="#include " - ngx_feature_libs= - ngx_feature_test="int n, dp; struct dvpoll dvp; - dp = 0; - dvp.dp_fds = NULL; - dvp.dp_nfds = 0; - dvp.dp_timeout = 0; - n = ioctl(dp, DP_POLL, &dvp)" - . auto/feature - - if [ $ngx_found = yes ]; then - CORE_SRCS="$CORE_SRCS $DEVPOLL_SRCS" - EVENT_MODULES="$EVENT_MODULES $DEVPOLL_MODULE" - EVENT_FOUND=YES - fi - - - if test -z "$NGX_KQUEUE_CHECKED"; then - ngx_feature="kqueue" - ngx_feature_name="NGX_HAVE_KQUEUE" - ngx_feature_run=no - ngx_feature_incs="#include " - ngx_feature_libs= - ngx_feature_test="int kq; kq = kqueue()" - . auto/feature - - if [ $ngx_found = yes ]; then - - have=NGX_HAVE_CLEAR_EVENT . auto/have - EVENT_MODULES="$EVENT_MODULES $KQUEUE_MODULE" - CORE_SRCS="$CORE_SRCS $KQUEUE_SRCS" - EVENT_FOUND=YES - - ngx_feature="kqueue's NOTE_LOWAT" - ngx_feature_name="NGX_HAVE_LOWAT_EVENT" - ngx_feature_run=no - ngx_feature_incs="#include " - ngx_feature_libs= - ngx_feature_test="struct kevent kev; - kev.fflags = NOTE_LOWAT;" - . auto/feature - fi - fi - - if [ "$NGX_SYSTEM" = "NetBSD" ]; then - - # NetBSD 2.0 incompatibly defines kevent.udata as "intptr_t" - - cat << END >> $NGX_AUTO_CONFIG_H - -#define NGX_KQUEUE_UDATA_T - -END - - else - cat << END >> $NGX_AUTO_CONFIG_H - -#define NGX_KQUEUE_UDATA_T (void *) - -END - - fi -fi diff --git a/auto/os/features b/auto/os/features new file mode 100644 --- /dev/null +++ b/auto/os/features @@ -0,0 +1,131 @@ + +# Copyright (C) Igor Sysoev + + +NGX_USER=${NGX_USER:-nobody} + +if [ -z "$NGX_GROUP" -a $NGX_USER = nobody ] ; then + if grep nobody /etc/group 2>&1 >/dev/null; then + echo "checking for nobody group ... found" + NGX_GROUP=nobody + else + echo "checking for nobody group ... not found" + + if grep nogroup /etc/group 2>&1 >/dev/null; then + echo "checking for nogroup group ... found" + NGX_GROUP=nogroup + else + echo "checking for nogroup group ... not found" + NGX_GROUP=nobody + fi + fi + +else + NGX_GROUP=$NGX_USER +fi + + +ngx_feature="poll()" +ngx_feature_name= +ngx_feature_run=no +ngx_feature_incs="#include " +ngx_feature_libs= +ngx_feature_test="int n, dp; struct pollfd pl; + dp = 0; + pl.fd = 0; + pl.events = 0; + pl.revents = 0; + n = poll(&pl, 1, 0)" +. auto/feature + +if [ $ngx_found = no ]; then + EVENT_POLL=NONE +fi + + +ngx_feature="/dev/poll" +ngx_feature_name="NGX_HAVE_DEVPOLL" +ngx_feature_run=no +ngx_feature_incs="#include " +ngx_feature_libs= +ngx_feature_test="int n, dp; struct dvpoll dvp; + dp = 0; + dvp.dp_fds = NULL; + dvp.dp_nfds = 0; + dvp.dp_timeout = 0; + n = ioctl(dp, DP_POLL, &dvp)" +. auto/feature + +if [ $ngx_found = yes ]; then + CORE_SRCS="$CORE_SRCS $DEVPOLL_SRCS" + EVENT_MODULES="$EVENT_MODULES $DEVPOLL_MODULE" + EVENT_FOUND=YES +fi + + +if test -z "$NGX_KQUEUE_CHECKED"; then + ngx_feature="kqueue" + ngx_feature_name="NGX_HAVE_KQUEUE" + ngx_feature_run=no + ngx_feature_incs="#include " + ngx_feature_libs= + ngx_feature_test="int kq; kq = kqueue()" + . auto/feature + + if [ $ngx_found = yes ]; then + + have=NGX_HAVE_CLEAR_EVENT . auto/have + EVENT_MODULES="$EVENT_MODULES $KQUEUE_MODULE" + CORE_SRCS="$CORE_SRCS $KQUEUE_SRCS" + EVENT_FOUND=YES + + ngx_feature="kqueue's NOTE_LOWAT" + ngx_feature_name="NGX_HAVE_LOWAT_EVENT" + ngx_feature_run=no + ngx_feature_incs="#include " + ngx_feature_libs= + ngx_feature_test="struct kevent kev; + kev.fflags = NOTE_LOWAT;" + . auto/feature + fi +fi + +if [ "$NGX_SYSTEM" = "NetBSD" ]; then + + # NetBSD 2.0 incompatibly defines kevent.udata as "intptr_t" + + cat << END >> $NGX_AUTO_CONFIG_H + +#define NGX_KQUEUE_UDATA_T + +END + +else + cat << END >> $NGX_AUTO_CONFIG_H + +#define NGX_KQUEUE_UDATA_T (void *) + +END + +fi + + +ngx_feature="crypt()" +ngx_feature_name= +ngx_feature_run=no +ngx_feature_incs= +ngx_feature_libs= +ngx_feature_test="crypt(\"test\", \"salt\");" +. auto/feature + + +if [ $ngx_found = no ]; then + + ngx_feature="crypt() in libcrypt" + ngx_feature_libs=-lcrypt + . auto/feature + + if [ $ngx_found = yes ]; then + CRYPT_LIB="-lcrypt" + fi +fi diff --git a/auto/os/freebsd b/auto/os/freebsd --- a/auto/os/freebsd +++ b/auto/os/freebsd @@ -7,7 +7,6 @@ have=NGX_FREEBSD . auto/have_headers CORE_INCS="$UNIX_INCS" CORE_DEPS="$UNIX_DEPS $FREEBSD_DEPS" CORE_SRCS="$UNIX_SRCS $FREEBSD_SRCS" -CRYPT_LIB="-lcrypt" ngx_spacer=' ' diff --git a/auto/os/linux b/auto/os/linux --- a/auto/os/linux +++ b/auto/os/linux @@ -7,7 +7,6 @@ have=NGX_LINUX . auto/have_headers CORE_INCS="$UNIX_INCS" CORE_DEPS="$UNIX_DEPS $LINUX_DEPS" CORE_SRCS="$UNIX_SRCS $LINUX_SRCS" -CRYPT_LIB="-lcrypt" ngx_spacer=' ' diff --git a/auto/unix b/auto/unix --- a/auto/unix +++ b/auto/unix @@ -32,7 +32,7 @@ ngx_type="sig_atomic_t"; ngx_types="int" . auto/types/sizeof ngx_param=NGX_SIG_ATOMIC_T_SIZE; ngx_value=$ngx_size; . auto/types/value -ngx_type="socklen_t"; ngx_types="uint32_t"; . auto/types/typedef +ngx_type="socklen_t"; ngx_types="int"; . auto/types/typedef ngx_type="in_addr_t"; ngx_types="uint32_t"; . auto/types/typedef diff --git a/configure b/configure --- a/configure +++ b/configure @@ -27,6 +27,7 @@ fi . auto/os/conf if [ "$NGX_PLATFORM" != win32 ]; then + . auto/os/features . auto/threads fi diff --git a/src/core/nginx.h b/src/core/nginx.h --- a/src/core/nginx.h +++ b/src/core/nginx.h @@ -8,7 +8,7 @@ #define _NGINX_H_INCLUDED_ -#define NGINX_VER "nginx/0.1.31" +#define NGINX_VER "nginx/0.1.32" #define NGINX_VAR "NGINX" #define NGX_NEWPID_EXT ".newbin" diff --git a/src/core/ngx_inet.c b/src/core/ngx_inet.c --- a/src/core/ngx_inet.c +++ b/src/core/ngx_inet.c @@ -419,7 +419,7 @@ ngx_inet_parse_host_port(ngx_inet_upstre u->host.data = url->data; u->host_header = *url; - for (/* void */; i < url->len; i++) { + for ( /* void */ ; i < url->len; i++) { if (url->data[i] == ':') { u->port_text.data = &url->data[i] + 1; diff --git a/src/core/ngx_log.h b/src/core/ngx_log.h --- a/src/core/ngx_log.h +++ b/src/core/ngx_log.h @@ -130,6 +130,7 @@ void ngx_cdecl ngx_log_debug_core(ngx_lo #define ngx_log_debug7 ngx_log_debug #define ngx_log_debug8 ngx_log_debug + #else /* NO VARIADIC MACROS */ #define ngx_log_debug0(level, log, err, fmt) \ diff --git a/src/core/ngx_string.h b/src/core/ngx_string.h --- a/src/core/ngx_string.h +++ b/src/core/ngx_string.h @@ -59,12 +59,12 @@ typedef struct { * while ZeroMemory() and bzero() are the calls. * icc may also inline several mov's of a zeroed register for small blocks. */ -#define ngx_memzero(buf, n) memset(buf, 0, n) -#define ngx_memset(buf, c, n) memset(buf, c, n) +#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" */ -#define ngx_memcpy(dst, src, n) memcpy(dst, src, n) +#define ngx_memcpy(dst, src, n) (void) memcpy(dst, src, n) #define ngx_cpymem(dst, src, n) ((u_char *) memcpy(dst, src, n)) + (n) diff --git a/src/event/ngx_event_timer.c b/src/event/ngx_event_timer.c --- a/src/event/ngx_event_timer.c +++ b/src/event/ngx_event_timer.c @@ -121,7 +121,7 @@ ngx_event_expire_timers(ngx_msec_t timer ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0, "event timer del: %d: %i", - ngx_event_ident(ev->data), ev->rbtree_key); + ngx_event_ident(ev->data), ev->rbtree_key); ngx_rbtree_delete((ngx_rbtree_t **) &ngx_event_timer_rbtree, &ngx_event_timer_sentinel, diff --git a/src/http/modules/ngx_http_fastcgi_module.c b/src/http/modules/ngx_http_fastcgi_module.c --- a/src/http/modules/ngx_http_fastcgi_module.c +++ b/src/http/modules/ngx_http_fastcgi_module.c @@ -33,7 +33,7 @@ typedef enum { ngx_http_fastcgi_st_padding_length, ngx_http_fastcgi_st_reserved, ngx_http_fastcgi_st_data, - ngx_http_fastcgi_st_padding, + ngx_http_fastcgi_st_padding } ngx_http_fastcgi_state_e; diff --git a/src/http/modules/ngx_http_proxy_module.c b/src/http/modules/ngx_http_proxy_module.c --- a/src/http/modules/ngx_http_proxy_module.c +++ b/src/http/modules/ngx_http_proxy_module.c @@ -542,7 +542,9 @@ ngx_http_proxy_create_request(ngx_http_r while (*(uintptr_t *) le.ip) { lcode = *(ngx_http_script_len_code_pt *) le.ip; - lcode(&le); + + /* skip the header line name length */ + (void) lcode(&le); if (*(ngx_http_script_len_code_pt *) le.ip) { diff --git a/src/http/modules/ngx_http_rewrite_module.c b/src/http/modules/ngx_http_rewrite_module.c --- a/src/http/modules/ngx_http_rewrite_module.c +++ b/src/http/modules/ngx_http_rewrite_module.c @@ -16,16 +16,10 @@ typedef struct { typedef struct { - ngx_str_t *name; - ngx_http_variable_value_t *value; -} ngx_http_rewrite_variable_t; - - -typedef struct { ngx_array_t *codes; /* uintptr_t */ ngx_array_t *referers; /* ngx_http_rewrite_referer_t */ - ngx_uint_t max_captures; + ngx_uint_t captures; ngx_uint_t stack_size; ngx_flag_t log; @@ -159,8 +153,8 @@ ngx_http_rewrite_handler(ngx_http_reques return NGX_HTTP_INTERNAL_SERVER_ERROR; } - if (cf->max_captures) { - e->captures = ngx_palloc(r->pool, cf->max_captures * sizeof(int)); + if (cf->captures) { + e->captures = ngx_palloc(r->pool, cf->captures * sizeof(int)); if (e->captures == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } @@ -542,10 +536,10 @@ ngx_http_rewrite(ngx_conf_t *cf, ngx_com if (regex->ncaptures) { regex->ncaptures = (regex->ncaptures + 1) * 3; - } - if (lcf->max_captures < regex->ncaptures) { - lcf->max_captures = regex->ncaptures; + if (lcf->captures < regex->ncaptures) { + lcf->captures = regex->ncaptures; + } } regex_end = ngx_http_script_add_code(lcf->codes, @@ -735,7 +729,7 @@ static char * ngx_http_rewrite_if_condition(ngx_conf_t *cf, ngx_http_rewrite_loc_conf_t *lcf) { ngx_str_t *value, err; - ngx_uint_t cur, last; + ngx_uint_t cur, last, n; ngx_http_script_regex_code_t *regex; u_char errstr[NGX_MAX_CONF_ERRSTR]; @@ -823,6 +817,16 @@ ngx_http_rewrite_if_condition(ngx_conf_t regex->test = 1; regex->name = value[last]; + n = ngx_regex_capture_count(regex->regex); + + if (n) { + regex->ncaptures = (n + 1) * 3; + + if (lcf->captures < regex->ncaptures) { + lcf->captures = regex->ncaptures; + } + } + return NGX_CONF_OK; } @@ -977,11 +981,13 @@ ngx_http_rewrite_set(ngx_conf_t *cf, ngx { ngx_http_rewrite_loc_conf_t *lcf = conf; - ngx_int_t n, index; - ngx_str_t *value; - ngx_http_variable_t *v; - ngx_http_script_var_code_t *var; - ngx_http_script_value_code_t *val; + ngx_int_t n, index; + ngx_str_t *value; + ngx_http_variable_t *v; + ngx_http_script_compile_t sc; + ngx_http_script_var_code_t *var; + ngx_http_script_value_code_t *val; + ngx_http_script_complex_value_code_t *complex; value = cf->args->elts; @@ -1007,22 +1013,49 @@ ngx_http_rewrite_set(ngx_conf_t *cf, ngx v->handler = ngx_http_rewrite_var; v->data = index; - val = ngx_http_script_start_code(cf->pool, &lcf->codes, - sizeof(ngx_http_script_value_code_t)); - if (val == NULL) { - return NGX_CONF_ERROR; - } + n = ngx_http_script_variables_count(&value[2]); + + if (n == 0) { + val = ngx_http_script_start_code(cf->pool, &lcf->codes, + sizeof(ngx_http_script_value_code_t)); + if (val == NULL) { + return NGX_CONF_ERROR; + } - n = ngx_atoi(value[2].data, value[2].len); + n = ngx_atoi(value[2].data, value[2].len); + + if (n == NGX_ERROR) { + n = 0; + } + + val->code = ngx_http_script_value_code; + val->value = (uintptr_t) n; + val->text_len = (uintptr_t) value[2].len; + val->text_data = (uintptr_t) value[2].data; - if (n == NGX_ERROR) { - n = 0; - } + } else { + complex = ngx_http_script_start_code(cf->pool, &lcf->codes, + sizeof(ngx_http_script_complex_value_code_t)); + if (complex == NULL) { + return NGX_CONF_ERROR; + } + + complex->code = ngx_http_script_complex_value_code; + complex->lengths = NULL; + + ngx_memzero(&sc, sizeof(ngx_http_script_compile_t)); - val->code = ngx_http_script_value_code; - val->value = (uintptr_t) n; - val->text_len = (uintptr_t) value[2].len; - val->text_data = (uintptr_t) value[2].data; + sc.cf = cf; + sc.source = &value[2]; + sc.lengths = &complex->lengths; + sc.values = &lcf->codes; + sc.variables = n; + sc.complete_lengths = 1; + + if (ngx_http_script_compile(&sc) != NGX_OK) { + return NGX_CONF_ERROR; + } + } var = ngx_http_script_start_code(cf->pool, &lcf->codes, sizeof(ngx_http_script_var_code_t)); diff --git a/src/http/ngx_http_script.c b/src/http/ngx_http_script.c --- a/src/http/ngx_http_script.c +++ b/src/http/ngx_http_script.c @@ -405,17 +405,21 @@ ngx_http_script_copy_capture_len_code(ng e->ip += sizeof(ngx_http_script_copy_capture_code_t); - if ((e->args || e->quote) - && (e->request->quoted_uri || e->request->plus_in_uri)) - { - return e->captures[code->n + 1] - e->captures[code->n] - + ngx_escape_uri(NULL, - &e->line->data[e->captures[code->n]], + if (code->n < e->ncaptures) { + if ((e->args || e->quote) + && (e->request->quoted_uri || e->request->plus_in_uri)) + { + return e->captures[code->n + 1] - e->captures[code->n] + + ngx_escape_uri(NULL, + &e->line.data[e->captures[code->n]], e->captures[code->n + 1] - e->captures[code->n], NGX_ESCAPE_ARGS); - } else { - return e->captures[code->n + 1] - e->captures[code->n]; + } else { + return e->captures[code->n + 1] - e->captures[code->n]; + } } + + return 0; } @@ -428,17 +432,19 @@ ngx_http_script_copy_capture_code(ngx_ht e->ip += sizeof(ngx_http_script_copy_capture_code_t); - if ((e->args || e->quote) - && (e->request->quoted_uri || e->request->plus_in_uri)) - { - e->pos = (u_char *) ngx_escape_uri(e->pos, - &e->line->data[e->captures[code->n]], + if (code->n < e->ncaptures) { + if ((e->args || e->quote) + && (e->request->quoted_uri || e->request->plus_in_uri)) + { + e->pos = (u_char *) ngx_escape_uri(e->pos, + &e->line.data[e->captures[code->n]], 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]); + } else { + e->pos = ngx_cpymem(e->pos, + &e->line.data[e->captures[code->n]], + e->captures[code->n + 1] - e->captures[code->n]); + } } ngx_log_debug1(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0, @@ -476,20 +482,23 @@ ngx_http_script_regex_start_code(ngx_htt "http script regex: \"%V\"", &code->name); if (code->uri) { - e->line = &r->uri; + e->line = r->uri; } else { e->sp--; - e->line = &e->sp->text; + e->line = e->sp->text; } - rc = ngx_regex_exec(code->regex, e->line, e->captures, code->ncaptures); + rc = ngx_regex_exec(code->regex, &e->line, e->captures, code->ncaptures); if (rc == NGX_REGEX_NO_MATCHED) { if (e->log) { ngx_log_error(NGX_LOG_NOTICE, r->connection->log, 0, - "\"%V\" does not match \"%V\"", &code->name, e->line); + "\"%V\" does not match \"%V\"", + &code->name, &e->line); } + e->ncaptures = 0; + if (code->test) { e->sp->value = 0; e->sp->text.len = 0; @@ -507,7 +516,7 @@ ngx_http_script_regex_start_code(ngx_htt if (rc < 0) { ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, ngx_regex_exec_n " failed: %d on \"%V\" using \"%V\"", - rc, e->line, &code->name); + rc, &e->line, &code->name); e->ip = ngx_http_script_exit; e->status = NGX_HTTP_INTERNAL_SERVER_ERROR; @@ -516,9 +525,11 @@ ngx_http_script_regex_start_code(ngx_htt if (e->log) { ngx_log_error(NGX_LOG_NOTICE, r->connection->log, 0, - "\"%V\" matches \"%V\"", &code->name, e->line); + "\"%V\" matches \"%V\"", &code->name, &e->line); } + e->ncaptures = code->ncaptures; + if (code->test) { e->sp->value = 1; e->sp->text.len = 1; @@ -570,6 +581,7 @@ ngx_http_script_regex_start_code(ngx_htt le.ip = code->lengths->elts; le.request = r; le.captures = e->captures; + le.ncaptures = e->ncaptures; len = 1; /* reserve 1 byte for possible "?" */ @@ -581,7 +593,7 @@ ngx_http_script_regex_start_code(ngx_htt e->buf.len = len; } - if (code->args && code->add_args && r->args.len) { + if (code->add_args && r->args.len) { e->buf.len += r->args.len + 1; } @@ -724,6 +736,48 @@ ngx_http_script_if_code(ngx_http_script_ void +ngx_http_script_complex_value_code(ngx_http_script_engine_t *e) +{ + size_t len; + ngx_http_script_engine_t le; + ngx_http_script_len_code_pt lcode; + ngx_http_script_complex_value_code_t *code; + + code = (ngx_http_script_complex_value_code_t *) e->ip; + + e->ip += sizeof(ngx_http_script_complex_value_code_t); + + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0, + "http script complex value"); + + ngx_memzero(&le, sizeof(ngx_http_script_engine_t)); + + le.ip = code->lengths->elts; + le.request = e->request; + le.captures = e->captures; + le.ncaptures = e->ncaptures; + + for (len = 0; *(uintptr_t *) le.ip; len += lcode(&le)) { + lcode = *(ngx_http_script_len_code_pt *) le.ip; + } + + e->buf.len = len; + e->buf.data = ngx_palloc(e->request->pool, len); + if (e->buf.data == NULL) { + e->ip = ngx_http_script_exit; + e->status = NGX_HTTP_INTERNAL_SERVER_ERROR; + return; + } + + e->pos = e->buf.data; + + e->sp->value = 0; + e->sp->text = e->buf; + e->sp++; +} + + +void ngx_http_script_value_code(ngx_http_script_engine_t *e) { ngx_http_script_value_code_t *code; diff --git a/src/http/ngx_http_script.h b/src/http/ngx_http_script.h --- a/src/http/ngx_http_script.h +++ b/src/http/ngx_http_script.h @@ -19,7 +19,7 @@ typedef struct { ngx_http_variable_value_t *sp; ngx_str_t buf; - ngx_str_t *line; + ngx_str_t line; /* the start of the rewritten arguments */ u_char *args; @@ -29,6 +29,7 @@ typedef struct { unsigned log:1; int *captures; + ngx_uint_t ncaptures; ngx_int_t status; ngx_http_request_t *request; @@ -130,6 +131,12 @@ typedef struct { typedef struct { ngx_http_script_code_pt code; + ngx_array_t *lengths; +} ngx_http_script_complex_value_code_t; + + +typedef struct { + ngx_http_script_code_pt code; uintptr_t value; uintptr_t text_len; uintptr_t text_data; @@ -155,6 +162,7 @@ void ngx_http_script_copy_capture_code(n void ngx_http_script_start_args_code(ngx_http_script_engine_t *e); void ngx_http_script_return_code(ngx_http_script_engine_t *e); void ngx_http_script_if_code(ngx_http_script_engine_t *e); +void ngx_http_script_complex_value_code(ngx_http_script_engine_t *e); void ngx_http_script_value_code(ngx_http_script_engine_t *e); void ngx_http_script_set_var_code(ngx_http_script_engine_t *e); void ngx_http_script_var_code(ngx_http_script_engine_t *e); diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c --- a/src/http/ngx_http_upstream.c +++ b/src/http/ngx_http_upstream.c @@ -77,71 +77,80 @@ ngx_http_upstream_header_t ngx_http_ups { ngx_string("Status"), ngx_http_upstream_process_header_line, offsetof(ngx_http_upstream_headers_in_t, status), - /* STUB */ ngx_http_upstream_ignore_header_line, 0 }, + /* STUB */ ngx_http_upstream_ignore_header_line, 0, 0 }, { ngx_string("Content-Type"), ngx_http_upstream_process_header_line, offsetof(ngx_http_upstream_headers_in_t, content_type), - ngx_http_upstream_copy_content_type, 0 }, + ngx_http_upstream_copy_content_type, 0, 0 }, { ngx_string("Content-Length"), ngx_http_upstream_process_header_line, offsetof(ngx_http_upstream_headers_in_t, content_length), - ngx_http_upstream_copy_content_length, 0 }, + ngx_http_upstream_copy_content_length, 0, 0 }, { ngx_string("Date"), ngx_http_upstream_process_header_line, offsetof(ngx_http_upstream_headers_in_t, date), ngx_http_upstream_conditional_copy_header_line, - offsetof(ngx_http_upstream_conf_t, pass_date) }, + offsetof(ngx_http_upstream_conf_t, pass_date), 0 }, { ngx_string("Server"), ngx_http_upstream_process_header_line, offsetof(ngx_http_upstream_headers_in_t, server), ngx_http_upstream_conditional_copy_header_line, - offsetof(ngx_http_upstream_conf_t, pass_server) }, + offsetof(ngx_http_upstream_conf_t, pass_server), 0 }, { ngx_string("Location"), ngx_http_upstream_ignore_header_line, 0, - ngx_http_upstream_rewrite_location, 0 }, + ngx_http_upstream_rewrite_location, 0, 0 }, { ngx_string("Refresh"), ngx_http_upstream_ignore_header_line, 0, - ngx_http_upstream_rewrite_refresh, 0 }, + ngx_http_upstream_rewrite_refresh, 0, 0 }, + + { ngx_string("Set-Cookie"), + ngx_http_upstream_ignore_header_line, 0, + ngx_http_upstream_copy_header_line, 0, 1 }, { ngx_string("Cache-Control"), ngx_http_upstream_process_multi_header_lines, offsetof(ngx_http_upstream_headers_in_t, cache_control), ngx_http_upstream_copy_multi_header_lines, - offsetof(ngx_http_headers_out_t, cache_control) }, + offsetof(ngx_http_headers_out_t, cache_control), 1 }, { ngx_string("Connection"), ngx_http_upstream_ignore_header_line, 0, - ngx_http_upstream_ignore_header_line, 0 }, + ngx_http_upstream_ignore_header_line, 0, 0 }, { ngx_string("X-Pad"), ngx_http_upstream_ignore_header_line, 0, - ngx_http_upstream_ignore_header_line, 0 }, + ngx_http_upstream_ignore_header_line, 0, 0 }, { ngx_string("X-Powered-By"), ngx_http_upstream_ignore_header_line, 0, ngx_http_upstream_conditional_copy_header_line, - offsetof(ngx_http_upstream_conf_t, pass_x_powered_by) }, + offsetof(ngx_http_upstream_conf_t, pass_x_powered_by), 0 }, { ngx_string("X-Accel-Expires"), ngx_http_upstream_process_header_line, offsetof(ngx_http_upstream_headers_in_t, x_accel_expires), ngx_http_upstream_conditional_copy_header_line, - offsetof(ngx_http_upstream_conf_t, pass_x_accel_expires) }, + offsetof(ngx_http_upstream_conf_t, pass_x_accel_expires), 0 }, + + { ngx_string("X-Accel-Redirect"), + ngx_http_upstream_process_header_line, + offsetof(ngx_http_upstream_headers_in_t, x_accel_redirect), + ngx_http_upstream_ignore_header_line, 0, 0 }, #if (NGX_HTTP_GZIP) { ngx_string("Content-Encoding"), ngx_http_upstream_process_header_line, offsetof(ngx_http_upstream_headers_in_t, content_encoding), - ngx_http_upstream_copy_content_encoding, 0 }, + ngx_http_upstream_copy_content_encoding, 0, 0 }, #endif - { ngx_null_string, NULL, 0, NULL, 0 } + { ngx_null_string, NULL, 0, NULL, 0, 0 } }; @@ -698,14 +707,18 @@ ngx_http_upstream_send_request_handler(n static void ngx_http_upstream_process_header(ngx_event_t *rev) { - ssize_t n; - ngx_int_t rc; - ngx_uint_t i; - ngx_connection_t *c; - ngx_http_request_t *r; - ngx_http_upstream_t *u; - ngx_http_err_page_t *err_page; - ngx_http_core_loc_conf_t *clcf; + ssize_t n; + ngx_int_t rc; + ngx_uint_t i, key; + ngx_list_part_t *part; + ngx_table_elt_t *h; + ngx_connection_t *c; + ngx_http_request_t *r; + ngx_http_upstream_t *u; + ngx_http_err_page_t *err_page; + ngx_http_core_loc_conf_t *clcf; + ngx_http_upstream_header_t *hh; + ngx_http_upstream_main_conf_t *umcf; c = rev->data; r = c->data; @@ -875,6 +888,48 @@ ngx_http_upstream_process_header(ngx_eve } } + if (r->upstream->headers_in.x_accel_redirect) { + ngx_http_upstream_finalize_request(r, u, NGX_DECLINED); + + umcf = ngx_http_get_module_main_conf(r, ngx_http_upstream_module); + hh = (ngx_http_upstream_header_t *) umcf->headers_in_hash.buckets; + + part = &r->upstream->headers_in.headers.part; + h = part->elts; + + for (i = 0; /* void */; i++) { + + if (i >= part->nelts) { + if (part->next == NULL) { + break; + } + + part = part->next; + h = part->elts; + i = 0; + } + + key = h[i].hash % umcf->headers_in_hash.hash_size; + + if (hh[key].redirect + && hh[key].name.len == h[i].key.len + && ngx_strcasecmp(hh[key].name.data, h[i].key.data) == 0) + { + if (hh[key].copy_handler(r, &h[i], hh[key].conf) != NGX_OK) { + ngx_http_upstream_finalize_request(r, u, + NGX_HTTP_INTERNAL_SERVER_ERROR); + return; + } + + } + } + + ngx_http_internal_redirect(r, + &r->upstream->headers_in.x_accel_redirect->value, + NULL); + return; + } + ngx_http_upstream_send_response(r, u); } @@ -1307,6 +1362,11 @@ ngx_http_upstream_finalize_request(ngx_h #endif r->log_handler = u->saved_log_handler; + + if (rc == NGX_DECLINED) { + return; + } + r->connection->log->action = "sending to client"; if (rc == 0 && r->main == NULL) { diff --git a/src/http/ngx_http_upstream.h b/src/http/ngx_http_upstream.h --- a/src/http/ngx_http_upstream.h +++ b/src/http/ngx_http_upstream.h @@ -87,6 +87,7 @@ typedef struct { ngx_uint_t offset; ngx_http_header_handler_pt copy_handler; ngx_uint_t conf; + ngx_uint_t redirect; /* unsigned redirect:1; */ } ngx_http_upstream_header_t; @@ -101,6 +102,7 @@ typedef struct { ngx_table_elt_t *expires; ngx_table_elt_t *etag; ngx_table_elt_t *x_accel_expires; + ngx_table_elt_t *x_accel_redirect; ngx_table_elt_t *content_type; ngx_table_elt_t *content_length; diff --git a/src/http/ngx_http_variables.c b/src/http/ngx_http_variables.c --- a/src/http/ngx_http_variables.c +++ b/src/http/ngx_http_variables.c @@ -15,6 +15,8 @@ static ngx_http_variable_value_t * 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); @@ -63,6 +65,9 @@ static ngx_http_variable_t ngx_http_cor offsetof(ngx_http_request_t, headers_in.x_forwarded_for), 0 }, #endif + { ngx_string("http_cookie"), ngx_http_variable_headers, + offsetof(ngx_http_request_t, headers_in.cookies), 0 }, + { ngx_string("content_length"), ngx_http_variable_header, offsetof(ngx_http_request_t, headers_in.content_length), 0 }, @@ -334,6 +339,62 @@ ngx_http_variable_header(ngx_http_reques static ngx_http_variable_value_t * +ngx_http_variable_headers(ngx_http_request_t *r, 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; + + 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; + } + + vv->value = 0; + + h = a->elts; + + if (a->nelts == 1) { + vv->text = (*h)->value; + return vv; + } + + vv->text.len = (size_t) - (ssize_t) (sizeof("; ") - 1); + + for (i = 0; i < a->nelts; i++) { + vv->text.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 = vv->text.data; + + for (i = 0; /* void */ ; i++) { + p = ngx_cpymem(p, h[i]->value.data, h[i]->value.len); + + if (i == a->nelts - 1) { + break; + } + + *p++ = ';'; *p++ = ' '; + } + + return vv; +} + + +static ngx_http_variable_value_t * ngx_http_variable_unknown_header(ngx_http_request_t *r, uintptr_t data) { ngx_str_t *var = (ngx_str_t *) data; diff --git a/src/os/unix/ngx_os.h b/src/os/unix/ngx_os.h --- a/src/os/unix/ngx_os.h +++ b/src/os/unix/ngx_os.h @@ -31,7 +31,7 @@ typedef struct { } ngx_os_io_t; -void ngx_debug_init(); +void ngx_debug_init(void); ngx_int_t ngx_os_init(ngx_log_t *log); void ngx_os_status(ngx_log_t *log); ngx_int_t ngx_daemon(ngx_log_t *log); diff --git a/src/os/unix/ngx_posix_config.h b/src/os/unix/ngx_posix_config.h --- a/src/os/unix/ngx_posix_config.h +++ b/src/os/unix/ngx_posix_config.h @@ -8,13 +8,13 @@ #define _NGX_POSIX_CONFIG_H_INCLUDED_ -#if 0 +#if (NGX_HPUX) #define _XOPEN_SOURCE #define _XOPEN_SOURCE_EXTENDED 1 #endif -#if 0 +#if (NGX_TRU64) #define _REENTRANT #endif diff --git a/src/os/unix/ngx_process.c b/src/os/unix/ngx_process.c --- a/src/os/unix/ngx_process.c +++ b/src/os/unix/ngx_process.c @@ -23,9 +23,9 @@ ngx_int_t ngx_last_process; ngx_process_t ngx_processes[NGX_MAX_PROCESSES]; -ngx_pid_t ngx_spawn_process(ngx_cycle_t *cycle, - ngx_spawn_proc_pt proc, void *data, - char *name, ngx_int_t respawn) +ngx_pid_t +ngx_spawn_process(ngx_cycle_t *cycle, ngx_spawn_proc_pt proc, void *data, + char *name, ngx_int_t respawn) { u_long on; ngx_pid_t pid; @@ -185,14 +185,16 @@ ngx_pid_t ngx_spawn_process(ngx_cycle_t } -ngx_pid_t ngx_execute(ngx_cycle_t *cycle, ngx_exec_ctx_t *ctx) +ngx_pid_t +ngx_execute(ngx_cycle_t *cycle, ngx_exec_ctx_t *ctx) { return ngx_spawn_process(cycle, ngx_execute_proc, ctx, ctx->name, NGX_PROCESS_DETACHED); } -static void ngx_execute_proc(ngx_cycle_t *cycle, void *data) +static void +ngx_execute_proc(ngx_cycle_t *cycle, void *data) { ngx_exec_ctx_t *ctx = data; @@ -206,7 +208,8 @@ static void ngx_execute_proc(ngx_cycle_t } -void ngx_process_get_status() +void +ngx_process_get_status(void) { int status; char *process; @@ -301,7 +304,8 @@ void ngx_process_get_status() } -void ngx_debug_point() +void +ngx_debug_point(void) { ngx_core_conf_t *ccf; diff --git a/src/os/unix/ngx_setproctitle.h b/src/os/unix/ngx_setproctitle.h --- a/src/os/unix/ngx_setproctitle.h +++ b/src/os/unix/ngx_setproctitle.h @@ -16,30 +16,36 @@ #define ngx_setproctitle setproctitle -#elif !defined NGX_SETPROCTITLE_USES_ENV +#else /* !NGX_HAVE_SETPROCTITLE */ -#define NGX_SETPROCTITLE_USES_ENV 1 +#if !defined NGX_SETPROCTITLE_USES_ENV #if (NGX_SOLARIS) +#define NGX_SETPROCTITLE_USES_ENV 1 #define NGX_SETPROCTITLE_PAD ' ' -#elif (NGX_LINUX) || (NGX_DARWIN) - -#define NGX_SETPROCTITLE_PAD '\0' - -#endif - ngx_int_t ngx_init_setproctitle(ngx_log_t *log); void ngx_setproctitle(char *title); +#elif (NGX_LINUX) || (NGX_DARWIN) -#else /* !NGX_SETPROCTITLE_USES_ENV */ +#define NGX_SETPROCTITLE_USES_ENV 1 +#define NGX_SETPROCTITLE_PAD '\0' + +ngx_int_t ngx_init_setproctitle(ngx_log_t *log); +void ngx_setproctitle(char *title); + +#else #define ngx_init_setproctitle(log) #define ngx_setproctitle(title) -#endif +#endif /* OSes */ + +#endif /* NGX_SETPROCTITLE_USES_ENV */ + +#endif /* NGX_HAVE_SETPROCTITLE */ #endif /* _NGX_SETPROCTITLE_H_INCLUDED_ */