diff --git a/.hgtags b/.hgtags index 6bd05126781..2fb896b61a9 100644 --- a/.hgtags +++ b/.hgtags @@ -404,3 +404,18 @@ cb783d9cc19761e14e1285d91c38f4b84d0b8756 release-1.11.1 b83a067949a3384a49fd3d943eb8d0997b31f87b release-1.11.3 953512ca02c6f63b4fcbbc3e10d0d9835896bf99 release-1.11.4 5253015a339aaca0a3111473d3e931b6d4752393 release-1.11.5 +5e371426b3bcba4312ce08606194b89b758927d1 release-1.11.6 +5c8f60faf33ca8926473d2da27b4c3c417bd4630 release-1.11.7 +4591da489a30f790def29bc5987f43409b503cae release-1.11.8 +20a45c768e5ed26b740679d0e22045c98727c3cc release-1.11.9 +1ad0999a7ded3d4fb01c7acf8ff57c80b643da7e release-1.11.10 +d8b321a876d6254e9e98795e3b194ef053290354 release-1.11.11 +7f394e433f0003222aa6531931ecc0b24740d5e4 release-1.11.12 +3d0e8655f897959e48cc74e87670bb5492a58871 release-1.11.13 +3671096a45bce570a2afa20b9faf42c7fb0f7e66 release-1.13.0 +539f7893ecb96bee60965528c8958d7eb2f1ce6b release-1.13.1 +5be2b25bdc65775a85f18f68a4be4f58c7384415 release-1.13.2 +8457ce87640f9bfe6221c4ac4466ced20e03bebe release-1.13.3 +bbc642c813c829963ce8197c0ca237ab7601f3d4 release-1.13.4 +0d45b4cf7c2e4e626a5a16e1fe604402ace1cea5 release-1.13.5 +f87da7d9ca02b8ced4caa6c5eb9013ccd47b0117 release-1.13.6 diff --git a/auto/cc/bcc b/auto/cc/bcc index ec82e60fb13..e990a9f73a7 100644 --- a/auto/cc/bcc +++ b/auto/cc/bcc @@ -62,7 +62,6 @@ ngx_include_opt="-I" ngx_objout="-o" ngx_binout="-e" ngx_objext="obj" -ngx_binext=".exe" ngx_long_start='@&&| ' diff --git a/auto/cc/conf b/auto/cc/conf index b3b9f92eb00..afbca62bcef 100644 --- a/auto/cc/conf +++ b/auto/cc/conf @@ -178,21 +178,25 @@ if [ "$NGX_PLATFORM" != win32 ]; then fi - ngx_feature="gcc builtin atomic operations" - ngx_feature_name=NGX_HAVE_GCC_ATOMIC - ngx_feature_run=yes - ngx_feature_incs= - ngx_feature_path= - ngx_feature_libs= - ngx_feature_test="long n = 0; - if (!__sync_bool_compare_and_swap(&n, 0, 1)) - return 1; - if (__sync_fetch_and_add(&n, 1) != 1) - return 1; - if (n != 2) - return 1; - __sync_synchronize();" - . auto/feature + if [ "$NGX_CC_NAME" = "sunc" ]; then + echo "checking for gcc builtin atomic operations ... disabled" + else + ngx_feature="gcc builtin atomic operations" + ngx_feature_name=NGX_HAVE_GCC_ATOMIC + ngx_feature_run=yes + ngx_feature_incs= + ngx_feature_path= + ngx_feature_libs= + ngx_feature_test="long n = 0; + if (!__sync_bool_compare_and_swap(&n, 0, 1)) + return 1; + if (__sync_fetch_and_add(&n, 1) != 1) + return 1; + if (n != 2) + return 1; + __sync_synchronize();" + . auto/feature + fi if [ "$NGX_CC_NAME" = "ccc" ]; then @@ -209,7 +213,7 @@ if [ "$NGX_PLATFORM" != win32 ]; then var(0, buf, \"%d\", 1); if (buf[0] != '1') return 1" . auto/feature - fi + fi ngx_feature="gcc variadic macros" diff --git a/auto/cc/msvc b/auto/cc/msvc index 4eef1010593..8257252997d 100644 --- a/auto/cc/msvc +++ b/auto/cc/msvc @@ -142,7 +142,6 @@ ngx_pic_opt= ngx_objout="-Fo" ngx_binout="-Fe" ngx_objext="obj" -ngx_binext=".exe" ngx_long_start='@<< ' diff --git a/auto/cc/owc b/auto/cc/owc index a063aa34121..f7fd88c9aaf 100644 --- a/auto/cc/owc +++ b/auto/cc/owc @@ -84,7 +84,6 @@ ngx_include_opt="-i=" ngx_objout="-fo" ngx_binout="-fe=" ngx_objext="obj" -ngx_binext=".exe" ngx_regex_dirsep='\\' ngx_dirsep="\\" diff --git a/auto/cc/sunc b/auto/cc/sunc index 806ccc43956..552c2d3e124 100644 --- a/auto/cc/sunc +++ b/auto/cc/sunc @@ -8,7 +8,10 @@ # Sun C 5.9 SunOS_i386 2007/05/03 Sun Studio 12 # Sun C 5.9 SunOS_sparc 2007/05/03 # Sun C 5.10 SunOS_i386 2009/06/03 Sun Studio 12.1 -# Sun C 5.11 SunOS_i386 2010/08/13 Sun Studio 12.2 +# Sun C 5.11 SunOS_i386 2010/08/13 Oracle Solaris Studio 12.2 +# Sun C 5.12 SunOS_i386 2011/11/16 Oracle Solaris Studio 12.3 +# Sun C 5.13 SunOS_i386 2014/10/20 Oracle Solaris Studio 12.4 +# Sun C 5.14 SunOS_i386 2016/05/31 Oracle Developer Studio 12.5 NGX_SUNC_VER=`$CC -V 2>&1 | grep 'Sun C' 2>&1 \ | sed -e 's/^.* Sun C \(.*\)/\1/'` diff --git a/auto/configure b/auto/configure index ceff15e4999..7e6e33a7c86 100755 --- a/auto/configure +++ b/auto/configure @@ -36,7 +36,7 @@ if test -z "$NGX_PLATFORM"; then NGX_PLATFORM="$NGX_SYSTEM:$NGX_RELEASE:$NGX_MACHINE"; case "$NGX_SYSTEM" in - MINGW32_*) + MINGW32_* | MINGW64_* | MSYS_*) NGX_PLATFORM=win32 ;; esac diff --git a/auto/lib/conf b/auto/lib/conf index 0b8545a3752..2c7af104008 100644 --- a/auto/lib/conf +++ b/auto/lib/conf @@ -7,7 +7,7 @@ if [ $USE_PCRE = YES -o $PCRE != NONE ]; then . auto/lib/pcre/conf else - if [ $USE_PCRE = DISABLED -a $HTTP_REWRITE = YES ]; then + if [ $USE_PCRE = DISABLED -a $HTTP = YES -a $HTTP_REWRITE = YES ]; then cat << END diff --git a/auto/lib/openssl/conf b/auto/lib/openssl/conf index 39d96023732..e7d3795b2a8 100644 --- a/auto/lib/openssl/conf +++ b/auto/lib/openssl/conf @@ -15,8 +15,16 @@ if [ $OPENSSL != NONE ]; then CORE_INCS="$CORE_INCS $OPENSSL/openssl/include" CORE_DEPS="$CORE_DEPS $OPENSSL/openssl/include/openssl/ssl.h" - CORE_LIBS="$CORE_LIBS $OPENSSL/openssl/lib/ssleay32.lib" - CORE_LIBS="$CORE_LIBS $OPENSSL/openssl/lib/libeay32.lib" + + if [ -f $OPENSSL/ms/do_ms.bat ]; then + # before OpenSSL 1.1.0 + CORE_LIBS="$CORE_LIBS $OPENSSL/openssl/lib/ssleay32.lib" + CORE_LIBS="$CORE_LIBS $OPENSSL/openssl/lib/libeay32.lib" + else + # OpenSSL 1.1.0+ + CORE_LIBS="$CORE_LIBS $OPENSSL/openssl/lib/libssl.lib" + CORE_LIBS="$CORE_LIBS $OPENSSL/openssl/lib/libcrypto.lib" + fi # libeay32.lib requires gdi32.lib CORE_LIBS="$CORE_LIBS gdi32.lib" diff --git a/auto/lib/openssl/makefile.msvc b/auto/lib/openssl/makefile.msvc index fc9e57864ae..5b90dcb2588 100644 --- a/auto/lib/openssl/makefile.msvc +++ b/auto/lib/openssl/makefile.msvc @@ -6,9 +6,16 @@ all: cd $(OPENSSL) - perl Configure VC-WIN32 no-shared --prefix=openssl $(OPENSSL_OPT) + perl Configure VC-WIN32 no-shared \ + --prefix="%cd%/openssl" \ + --openssldir="%cd%/openssl/ssl" \ + $(OPENSSL_OPT) - ms\do_ms - - $(MAKE) -f ms\nt.mak - $(MAKE) -f ms\nt.mak install + if exist ms\do_ms.bat ( \ + ms\do_ms \ + && $(MAKE) -f ms\nt.mak \ + && $(MAKE) -f ms\nt.mak install \ + ) else ( \ + $(MAKE) \ + && $(MAKE) install_sw \ + ) diff --git a/auto/lib/perl/conf b/auto/lib/perl/conf index d891d821acd..e16a1bc85a1 100644 --- a/auto/lib/perl/conf +++ b/auto/lib/perl/conf @@ -12,9 +12,9 @@ NGX_PERL_VER=`$NGX_PERL -v 2>&1 | grep '^This is perl' 2>&1 \ if test -n "$NGX_PERL_VER"; then echo " + perl version: $NGX_PERL_VER" - if [ "`$NGX_PERL -e 'use 5.006001; print "OK"'`" != "OK" ]; then + if [ "`$NGX_PERL -e 'use 5.008006; print "OK"'`" != "OK" ]; then echo - echo "$0: error: perl 5.6.1 or higher is required" + echo "$0: error: perl 5.8.6 or higher is required" echo exit 1; @@ -76,7 +76,7 @@ if test -n "$NGX_PERL_VER"; then else echo - echo "$0: error: perl 5.6.1 or higher is required" + echo "$0: error: perl 5.8.6 or higher is required" echo exit 1; diff --git a/auto/lib/perl/make b/auto/lib/perl/make index 350090c7623..74e0f3ad610 100644 --- a/auto/lib/perl/make +++ b/auto/lib/perl/make @@ -3,9 +3,6 @@ # Copyright (C) Nginx, Inc. -v=`grep 'define NGINX_VERSION' src/core/nginx.h | sed -e 's/^.*"\(.*\)".*/\1/'` - - cat << END >> $NGX_MAKEFILE $NGX_OBJS/src/http/modules/perl/ngx_http_perl_module.o: \\ @@ -27,7 +24,11 @@ $NGX_OBJS/src/http/modules/perl/Makefile: \\ src/http/modules/perl/nginx.pm \\ src/http/modules/perl/nginx.xs \\ src/http/modules/perl/typemap - sed "s/%%VERSION%%/$v/" src/http/modules/perl/nginx.pm > \\ + grep 'define NGINX_VERSION' src/core/nginx.h \\ + | sed -e 's/^.*"\(.*\)".*/\1/' > \\ + $NGX_OBJS/src/http/modules/perl/version + sed "s/%%VERSION%%/\`cat $NGX_OBJS/src/http/modules/perl/version\`/" \\ + src/http/modules/perl/nginx.pm > \\ $NGX_OBJS/src/http/modules/perl/nginx.pm cp -p src/http/modules/perl/nginx.xs $NGX_OBJS/src/http/modules/perl/ cp -p src/http/modules/perl/typemap $NGX_OBJS/src/http/modules/perl/ diff --git a/auto/make b/auto/make index 84d266819b6..7ddd1007b63 100644 --- a/auto/make +++ b/auto/make @@ -156,7 +156,7 @@ fi ngx_all_srcs="$ngx_all_srcs $MISC_SRCS" -if test -n "$NGX_ADDON_SRCS"; then +if test -n "$NGX_ADDON_SRCS$DYNAMIC_MODULES"; then cat << END >> $NGX_MAKEFILE @@ -499,17 +499,6 @@ else ngx_perl_cc="$ngx_perl_cc \$(ALL_INCS)" fi -ngx_obj_deps="\$(CORE_DEPS)" -if [ $HTTP != NO ]; then - ngx_obj_deps="$ngx_obj_deps \$(HTTP_DEPS)" -fi -if [ $MAIL != NO ]; then - ngx_obj_deps="$ngx_obj_deps \$(MAIL_DEPS)" -fi -if [ $STREAM != NO ]; then - ngx_obj_deps="$ngx_obj_deps \$(STREAM_DEPS)" -fi - for ngx_module in $DYNAMIC_MODULES do eval ngx_module_srcs="\$${ngx_module}_SRCS" @@ -665,7 +654,7 @@ END cat << END >> $NGX_MAKEFILE -$ngx_obj: $ngx_obj_deps$ngx_cont$ngx_src +$ngx_obj: \$(ADDON_DEPS)$ngx_cont$ngx_src $ngx_perl_cc$ngx_tab$ngx_objout$ngx_obj$ngx_tab$ngx_src$NGX_AUX END @@ -673,7 +662,7 @@ END cat << END >> $NGX_MAKEFILE -$ngx_obj: $ngx_obj_deps$ngx_cont$ngx_src +$ngx_obj: \$(ADDON_DEPS)$ngx_cont$ngx_src $ngx_cc$ngx_tab$ngx_objout$ngx_obj$ngx_tab$ngx_src$NGX_AUX END diff --git a/auto/module b/auto/module index 3b00a07f8d1..a2b578db2c6 100644 --- a/auto/module +++ b/auto/module @@ -35,6 +35,10 @@ if [ "$ngx_module_link" = DYNAMIC ]; then CORE_INCS="$CORE_INCS $ngx_module_incs" fi + if test -n "$ngx_module_deps"; then + NGX_ADDON_DEPS="$NGX_ADDON_DEPS $ngx_module_deps" + fi + libs= for lib in $ngx_module_libs do diff --git a/auto/modules b/auto/modules index 89377bf0d0f..26b05bd8b42 100644 --- a/auto/modules +++ b/auto/modules @@ -56,832 +56,851 @@ if [ $NGX_TEST_BUILD_SOLARIS_SENDFILEV = YES ]; then fi -HTTP_MODULES= -HTTP_DEPS= -HTTP_INCS= - -ngx_module_type=HTTP - -if :; then - ngx_module_name="ngx_http_module \ - ngx_http_core_module \ - ngx_http_log_module \ - ngx_http_upstream_module" - ngx_module_incs="src/http src/http/modules" - ngx_module_deps="src/http/ngx_http.h \ - src/http/ngx_http_request.h \ - src/http/ngx_http_config.h \ - src/http/ngx_http_core_module.h \ - src/http/ngx_http_cache.h \ - src/http/ngx_http_variables.h \ - src/http/ngx_http_script.h \ - src/http/ngx_http_upstream.h \ - src/http/ngx_http_upstream_round_robin.h" - ngx_module_srcs="src/http/ngx_http.c \ - src/http/ngx_http_core_module.c \ - src/http/ngx_http_special_response.c \ - src/http/ngx_http_request.c \ - src/http/ngx_http_parse.c \ - src/http/modules/ngx_http_log_module.c \ - src/http/ngx_http_request_body.c \ - src/http/ngx_http_variables.c \ - src/http/ngx_http_script.c \ - src/http/ngx_http_upstream.c \ - src/http/ngx_http_upstream_round_robin.c" - ngx_module_libs= - ngx_module_link=YES +if [ $HTTP = YES ]; then + HTTP_MODULES= + HTTP_DEPS= + HTTP_INCS= + + ngx_module_type=HTTP + + if :; then + ngx_module_name="ngx_http_module \ + ngx_http_core_module \ + ngx_http_log_module \ + ngx_http_upstream_module" + ngx_module_incs="src/http src/http/modules" + ngx_module_deps="src/http/ngx_http.h \ + src/http/ngx_http_request.h \ + src/http/ngx_http_config.h \ + src/http/ngx_http_core_module.h \ + src/http/ngx_http_cache.h \ + src/http/ngx_http_variables.h \ + src/http/ngx_http_script.h \ + src/http/ngx_http_upstream.h \ + src/http/ngx_http_upstream_round_robin.h" + ngx_module_srcs="src/http/ngx_http.c \ + src/http/ngx_http_core_module.c \ + src/http/ngx_http_special_response.c \ + src/http/ngx_http_request.c \ + src/http/ngx_http_parse.c \ + src/http/modules/ngx_http_log_module.c \ + src/http/ngx_http_request_body.c \ + src/http/ngx_http_variables.c \ + src/http/ngx_http_script.c \ + src/http/ngx_http_upstream.c \ + src/http/ngx_http_upstream_round_robin.c" + ngx_module_libs= + ngx_module_link=YES - . auto/module -fi + . auto/module + fi -if [ $HTTP != YES ]; then - have=NGX_CRYPT . auto/nohave - CRYPT_LIB= -fi + if [ $HTTP_CACHE = YES ]; then + have=NGX_HTTP_CACHE . auto/have + HTTP_SRCS="$HTTP_SRCS $HTTP_FILE_CACHE_SRCS" + fi -if [ $HTTP_CACHE = YES ]; then - have=NGX_HTTP_CACHE . auto/have - HTTP_SRCS="$HTTP_SRCS $HTTP_FILE_CACHE_SRCS" -fi + if [ $HTTP_SSI = YES ]; then + HTTP_POSTPONE=YES + fi -if [ $HTTP_SSI = YES ]; then - HTTP_POSTPONE=YES -fi + if [ $HTTP_SLICE = YES ]; then + HTTP_POSTPONE=YES + fi -if [ $HTTP_SLICE = YES ]; then - HTTP_POSTPONE=YES -fi + if [ $HTTP_ADDITION = YES ]; then + HTTP_POSTPONE=YES + fi -if [ $HTTP_ADDITION = YES ]; then - HTTP_POSTPONE=YES -fi + # the module order is important + # ngx_http_static_module + # ngx_http_gzip_static_module + # ngx_http_dav_module + # ngx_http_autoindex_module + # ngx_http_index_module + # ngx_http_random_index_module + # + # ngx_http_access_module + # ngx_http_realip_module + # + # + # the filter order is important + # ngx_http_write_filter + # ngx_http_header_filter + # ngx_http_chunked_filter + # ngx_http_v2_filter + # ngx_http_range_header_filter + # ngx_http_gzip_filter + # ngx_http_postpone_filter + # ngx_http_ssi_filter + # ngx_http_charset_filter + # ngx_http_xslt_filter + # ngx_http_image_filter + # ngx_http_sub_filter + # ngx_http_addition_filter + # ngx_http_gunzip_filter + # ngx_http_userid_filter + # ngx_http_headers_filter + # ngx_http_copy_filter + # ngx_http_range_body_filter + # ngx_http_not_modified_filter + # ngx_http_slice_filter + + ngx_module_type=HTTP_FILTER + HTTP_FILTER_MODULES= + + ngx_module_order="ngx_http_static_module \ + ngx_http_gzip_static_module \ + ngx_http_dav_module \ + ngx_http_autoindex_module \ + ngx_http_index_module \ + ngx_http_random_index_module \ + ngx_http_access_module \ + ngx_http_realip_module \ + ngx_http_write_filter_module \ + ngx_http_header_filter_module \ + ngx_http_chunked_filter_module \ + ngx_http_v2_filter_module \ + ngx_http_range_header_filter_module \ + ngx_http_gzip_filter_module \ + ngx_http_postpone_filter_module \ + ngx_http_ssi_filter_module \ + ngx_http_charset_filter_module \ + ngx_http_xslt_filter_module \ + ngx_http_image_filter_module \ + ngx_http_sub_filter_module \ + ngx_http_addition_filter_module \ + ngx_http_gunzip_filter_module \ + ngx_http_userid_filter_module \ + ngx_http_headers_filter_module \ + ngx_http_copy_filter_module \ + ngx_http_range_body_filter_module \ + ngx_http_not_modified_filter_module \ + ngx_http_slice_filter_module" + + if :; then + ngx_module_name=ngx_http_write_filter_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/ngx_http_write_filter_module.c + ngx_module_libs= + ngx_module_link=YES + . auto/module + fi -# the module order is important -# ngx_http_static_module -# ngx_http_gzip_static_module -# ngx_http_dav_module -# ngx_http_autoindex_module -# ngx_http_index_module -# ngx_http_random_index_module -# -# ngx_http_access_module -# ngx_http_realip_module -# -# -# the filter order is important -# ngx_http_write_filter -# ngx_http_header_filter -# ngx_http_chunked_filter -# ngx_http_v2_filter -# ngx_http_range_header_filter -# ngx_http_gzip_filter -# ngx_http_postpone_filter -# ngx_http_ssi_filter -# ngx_http_charset_filter -# ngx_http_xslt_filter -# ngx_http_image_filter -# ngx_http_sub_filter -# ngx_http_addition_filter -# ngx_http_gunzip_filter -# ngx_http_userid_filter -# ngx_http_headers_filter -# ngx_http_copy_filter -# ngx_http_range_body_filter -# ngx_http_not_modified_filter -# ngx_http_slice_filter - -ngx_module_type=HTTP_FILTER -HTTP_FILTER_MODULES= - -ngx_module_order="ngx_http_static_module \ - ngx_http_gzip_static_module \ - ngx_http_dav_module \ - ngx_http_autoindex_module \ - ngx_http_index_module \ - ngx_http_random_index_module \ - ngx_http_access_module \ - ngx_http_realip_module \ - ngx_http_write_filter_module \ - ngx_http_header_filter_module \ - ngx_http_chunked_filter_module \ - ngx_http_v2_filter_module \ - ngx_http_range_header_filter_module \ - ngx_http_gzip_filter_module \ - ngx_http_postpone_filter_module \ - ngx_http_ssi_filter_module \ - ngx_http_charset_filter_module \ - ngx_http_xslt_filter_module \ - ngx_http_image_filter_module \ - ngx_http_sub_filter_module \ - ngx_http_addition_filter_module \ - ngx_http_gunzip_filter_module \ - ngx_http_userid_filter_module \ - ngx_http_headers_filter_module \ - ngx_http_copy_filter_module \ - ngx_http_range_body_filter_module \ - ngx_http_not_modified_filter_module \ - ngx_http_slice_filter_module" - -if :; then - ngx_module_name=ngx_http_write_filter_module - ngx_module_incs= - ngx_module_deps= - ngx_module_srcs=src/http/ngx_http_write_filter_module.c - ngx_module_libs= - ngx_module_link=YES + if :; then + ngx_module_name=ngx_http_header_filter_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/ngx_http_header_filter_module.c + ngx_module_libs= + ngx_module_link=YES - . auto/module -fi + . auto/module + fi -if :; then - ngx_module_name=ngx_http_header_filter_module - ngx_module_incs= - ngx_module_deps= - ngx_module_srcs=src/http/ngx_http_header_filter_module.c - ngx_module_libs= - ngx_module_link=YES + if :; then + ngx_module_name=ngx_http_chunked_filter_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/modules/ngx_http_chunked_filter_module.c + ngx_module_libs= + ngx_module_link=YES - . auto/module -fi + . auto/module + fi -if :; then - ngx_module_name=ngx_http_chunked_filter_module - ngx_module_incs= - ngx_module_deps= - ngx_module_srcs=src/http/modules/ngx_http_chunked_filter_module.c - ngx_module_libs= - ngx_module_link=YES + if [ $HTTP_V2 = YES ]; then + ngx_module_name=ngx_http_v2_filter_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/v2/ngx_http_v2_filter_module.c + ngx_module_libs= + ngx_module_link=$HTTP_V2 - . auto/module -fi + . auto/module + fi -if [ $HTTP_V2 = YES ]; then - ngx_module_name=ngx_http_v2_filter_module - ngx_module_incs= - ngx_module_deps= - ngx_module_srcs=src/http/v2/ngx_http_v2_filter_module.c - ngx_module_libs= - ngx_module_link=$HTTP_V2 + if :; then + ngx_module_name=ngx_http_range_header_filter_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/modules/ngx_http_range_filter_module.c + ngx_module_libs= + ngx_module_link=YES - . auto/module -fi + . auto/module + fi -if :; then - ngx_module_name=ngx_http_range_header_filter_module - ngx_module_incs= - ngx_module_deps= - ngx_module_srcs=src/http/modules/ngx_http_range_filter_module.c - ngx_module_libs= - ngx_module_link=YES + if [ $HTTP_GZIP = YES ]; then + have=NGX_HTTP_GZIP . auto/have + USE_ZLIB=YES - . auto/module -fi + ngx_module_name=ngx_http_gzip_filter_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/modules/ngx_http_gzip_filter_module.c + ngx_module_libs= + ngx_module_link=$HTTP_GZIP -if [ $HTTP_GZIP = YES ]; then - have=NGX_HTTP_GZIP . auto/have - USE_ZLIB=YES + . auto/module + fi - ngx_module_name=ngx_http_gzip_filter_module - ngx_module_incs= - ngx_module_deps= - ngx_module_srcs=src/http/modules/ngx_http_gzip_filter_module.c - ngx_module_libs= - ngx_module_link=$HTTP_GZIP + if [ $HTTP_POSTPONE = YES ]; then + ngx_module_name=ngx_http_postpone_filter_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/ngx_http_postpone_filter_module.c + ngx_module_libs= + ngx_module_link=$HTTP_POSTPONE - . auto/module -fi + . auto/module + fi -if [ $HTTP_POSTPONE = YES ]; then - ngx_module_name=ngx_http_postpone_filter_module - ngx_module_incs= - ngx_module_deps= - ngx_module_srcs=src/http/ngx_http_postpone_filter_module.c - ngx_module_libs= - ngx_module_link=$HTTP_POSTPONE + if [ $HTTP_SSI = YES ]; then + have=NGX_HTTP_SSI . auto/have - . auto/module -fi + ngx_module_name=ngx_http_ssi_filter_module + ngx_module_incs= + ngx_module_deps=src/http/modules/ngx_http_ssi_filter_module.h + ngx_module_srcs=src/http/modules/ngx_http_ssi_filter_module.c + ngx_module_libs= + ngx_module_link=$HTTP_SSI -if [ $HTTP_SSI = YES ]; then - have=NGX_HTTP_SSI . auto/have + . auto/module + fi - ngx_module_name=ngx_http_ssi_filter_module - ngx_module_incs= - ngx_module_deps=src/http/modules/ngx_http_ssi_filter_module.h - ngx_module_srcs=src/http/modules/ngx_http_ssi_filter_module.c - ngx_module_libs= - ngx_module_link=$HTTP_SSI + if [ $HTTP_CHARSET = YES ]; then + ngx_module_name=ngx_http_charset_filter_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/modules/ngx_http_charset_filter_module.c + ngx_module_libs= + ngx_module_link=$HTTP_CHARSET - . auto/module -fi + . auto/module + fi -if [ $HTTP_CHARSET = YES ]; then - ngx_module_name=ngx_http_charset_filter_module - ngx_module_incs= - ngx_module_deps= - ngx_module_srcs=src/http/modules/ngx_http_charset_filter_module.c - ngx_module_libs= - ngx_module_link=$HTTP_CHARSET + if [ $HTTP_XSLT != NO ]; then + ngx_module_name=ngx_http_xslt_filter_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/modules/ngx_http_xslt_filter_module.c + ngx_module_libs=LIBXSLT + ngx_module_link=$HTTP_XSLT - . auto/module -fi + . auto/module + fi -if [ $HTTP_XSLT != NO ]; then - ngx_module_name=ngx_http_xslt_filter_module - ngx_module_incs= - ngx_module_deps= - ngx_module_srcs=src/http/modules/ngx_http_xslt_filter_module.c - ngx_module_libs=LIBXSLT - ngx_module_link=$HTTP_XSLT + if [ $HTTP_IMAGE_FILTER != NO ]; then + ngx_module_name=ngx_http_image_filter_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/modules/ngx_http_image_filter_module.c + ngx_module_libs=LIBGD + ngx_module_link=$HTTP_IMAGE_FILTER - . auto/module -fi + . auto/module + fi -if [ $HTTP_IMAGE_FILTER != NO ]; then - ngx_module_name=ngx_http_image_filter_module - ngx_module_incs= - ngx_module_deps= - ngx_module_srcs=src/http/modules/ngx_http_image_filter_module.c - ngx_module_libs=LIBGD - ngx_module_link=$HTTP_IMAGE_FILTER + if [ $HTTP_SUB = YES ]; then + ngx_module_name=ngx_http_sub_filter_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/modules/ngx_http_sub_filter_module.c + ngx_module_libs= + ngx_module_link=$HTTP_SUB - . auto/module -fi + . auto/module + fi -if [ $HTTP_SUB = YES ]; then - ngx_module_name=ngx_http_sub_filter_module - ngx_module_incs= - ngx_module_deps= - ngx_module_srcs=src/http/modules/ngx_http_sub_filter_module.c - ngx_module_libs= - ngx_module_link=$HTTP_SUB + if [ $HTTP_ADDITION = YES ]; then + ngx_module_name=ngx_http_addition_filter_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/modules/ngx_http_addition_filter_module.c + ngx_module_libs= + ngx_module_link=$HTTP_ADDITION - . auto/module -fi + . auto/module + fi -if [ $HTTP_ADDITION = YES ]; then - ngx_module_name=ngx_http_addition_filter_module - ngx_module_incs= - ngx_module_deps= - ngx_module_srcs=src/http/modules/ngx_http_addition_filter_module.c - ngx_module_libs= - ngx_module_link=$HTTP_ADDITION + if [ $HTTP_GUNZIP = YES ]; then + have=NGX_HTTP_GZIP . auto/have + USE_ZLIB=YES - . auto/module -fi + ngx_module_name=ngx_http_gunzip_filter_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/modules/ngx_http_gunzip_filter_module.c + ngx_module_libs= + ngx_module_link=$HTTP_GUNZIP -if [ $HTTP_GUNZIP = YES ]; then - have=NGX_HTTP_GZIP . auto/have - USE_ZLIB=YES + . auto/module + fi - ngx_module_name=ngx_http_gunzip_filter_module - ngx_module_incs= - ngx_module_deps= - ngx_module_srcs=src/http/modules/ngx_http_gunzip_filter_module.c - ngx_module_libs= - ngx_module_link=$HTTP_GUNZIP + if [ $HTTP_USERID = YES ]; then + ngx_module_name=ngx_http_userid_filter_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/modules/ngx_http_userid_filter_module.c + ngx_module_libs= + ngx_module_link=$HTTP_USERID - . auto/module -fi + . auto/module + fi -if [ $HTTP_USERID = YES ]; then - ngx_module_name=ngx_http_userid_filter_module - ngx_module_incs= - ngx_module_deps= - ngx_module_srcs=src/http/modules/ngx_http_userid_filter_module.c - ngx_module_libs= - ngx_module_link=$HTTP_USERID + if :; then + ngx_module_name=ngx_http_headers_filter_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/modules/ngx_http_headers_filter_module.c + ngx_module_libs= + ngx_module_link=YES - . auto/module -fi + . auto/module + fi -if :; then - ngx_module_name=ngx_http_headers_filter_module - ngx_module_incs= - ngx_module_deps= - ngx_module_srcs=src/http/modules/ngx_http_headers_filter_module.c - ngx_module_libs= - ngx_module_link=YES - . auto/module -fi + ngx_module_type=HTTP_INIT_FILTER + HTTP_INIT_FILTER_MODULES= + if :; then + ngx_module_name=ngx_http_copy_filter_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/ngx_http_copy_filter_module.c + ngx_module_libs= + ngx_module_link=YES -ngx_module_type=HTTP_INIT_FILTER -HTTP_INIT_FILTER_MODULES= + . auto/module + fi -if :; then - ngx_module_name=ngx_http_copy_filter_module - ngx_module_incs= - ngx_module_deps= - ngx_module_srcs=src/http/ngx_http_copy_filter_module.c - ngx_module_libs= - ngx_module_link=YES + if :; then + ngx_module_name=ngx_http_range_body_filter_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs= + ngx_module_libs= + ngx_module_link=YES - . auto/module -fi + . auto/module + fi -if :; then - ngx_module_name=ngx_http_range_body_filter_module - ngx_module_incs= - ngx_module_deps= - ngx_module_srcs= - ngx_module_libs= - ngx_module_link=YES + if :; then + ngx_module_name=ngx_http_not_modified_filter_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/modules/ngx_http_not_modified_filter_module.c + ngx_module_libs= + ngx_module_link=YES - . auto/module -fi + . auto/module + fi -if :; then - ngx_module_name=ngx_http_not_modified_filter_module - ngx_module_incs= - ngx_module_deps= - ngx_module_srcs=src/http/modules/ngx_http_not_modified_filter_module.c - ngx_module_libs= - ngx_module_link=YES + if [ $HTTP_SLICE = YES ]; then + ngx_module_name=ngx_http_slice_filter_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/modules/ngx_http_slice_filter_module.c + ngx_module_libs= + ngx_module_link=$HTTP_SLICE - . auto/module -fi + . auto/module + fi -if [ $HTTP_SLICE = YES ]; then - ngx_module_name=ngx_http_slice_filter_module - ngx_module_incs= - ngx_module_deps= - ngx_module_srcs=src/http/modules/ngx_http_slice_filter_module.c - ngx_module_libs= - ngx_module_link=$HTTP_SLICE - . auto/module -fi + ngx_module_type=HTTP + if [ $HTTP_V2 = YES ]; then + have=NGX_HTTP_V2 . auto/have -ngx_module_type=HTTP + ngx_module_name=ngx_http_v2_module + ngx_module_incs=src/http/v2 + ngx_module_deps="src/http/v2/ngx_http_v2.h \ + src/http/v2/ngx_http_v2_module.h" + ngx_module_srcs="src/http/v2/ngx_http_v2.c \ + src/http/v2/ngx_http_v2_table.c \ + src/http/v2/ngx_http_v2_huff_decode.c \ + src/http/v2/ngx_http_v2_huff_encode.c \ + src/http/v2/ngx_http_v2_module.c" + ngx_module_libs= + ngx_module_link=$HTTP_V2 -if [ $HTTP_V2 = YES ]; then - have=NGX_HTTP_V2 . auto/have + . auto/module + fi - ngx_module_name=ngx_http_v2_module - ngx_module_incs=src/http/v2 - ngx_module_deps="src/http/v2/ngx_http_v2.h src/http/v2/ngx_http_v2_module.h" - ngx_module_srcs="src/http/v2/ngx_http_v2.c \ - src/http/v2/ngx_http_v2_table.c \ - src/http/v2/ngx_http_v2_huff_decode.c \ - src/http/v2/ngx_http_v2_huff_encode.c \ - src/http/v2/ngx_http_v2_module.c" - ngx_module_libs= - ngx_module_link=$HTTP_V2 + if :; then + ngx_module_name=ngx_http_static_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/modules/ngx_http_static_module.c + ngx_module_libs= + ngx_module_link=YES - . auto/module -fi + . auto/module + fi -if :; then - ngx_module_name=ngx_http_static_module - ngx_module_incs= - ngx_module_deps= - ngx_module_srcs=src/http/modules/ngx_http_static_module.c - ngx_module_libs= - ngx_module_link=YES + if [ $HTTP_GZIP_STATIC = YES ]; then + have=NGX_HTTP_GZIP . auto/have - . auto/module -fi + ngx_module_name=ngx_http_gzip_static_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/modules/ngx_http_gzip_static_module.c + ngx_module_libs= + ngx_module_link=$HTTP_GZIP_STATIC -if [ $HTTP_GZIP_STATIC = YES ]; then - have=NGX_HTTP_GZIP . auto/have + . auto/module + fi - ngx_module_name=ngx_http_gzip_static_module - ngx_module_incs= - ngx_module_deps= - ngx_module_srcs=src/http/modules/ngx_http_gzip_static_module.c - ngx_module_libs= - ngx_module_link=$HTTP_GZIP_STATIC + if [ $HTTP_DAV = YES ]; then + have=NGX_HTTP_DAV . auto/have - . auto/module -fi + ngx_module_name=ngx_http_dav_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/modules/ngx_http_dav_module.c + ngx_module_libs= + ngx_module_link=$HTTP_DAV -if [ $HTTP_DAV = YES ]; then - have=NGX_HTTP_DAV . auto/have + . auto/module + fi - ngx_module_name=ngx_http_dav_module - ngx_module_incs= - ngx_module_deps= - ngx_module_srcs=src/http/modules/ngx_http_dav_module.c - ngx_module_libs= - ngx_module_link=$HTTP_DAV + if [ $HTTP_AUTOINDEX = YES ]; then + ngx_module_name=ngx_http_autoindex_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/modules/ngx_http_autoindex_module.c + ngx_module_libs= + ngx_module_link=$HTTP_AUTOINDEX - . auto/module -fi + . auto/module + fi -if [ $HTTP_AUTOINDEX = YES ]; then - ngx_module_name=ngx_http_autoindex_module - ngx_module_incs= - ngx_module_deps= - ngx_module_srcs=src/http/modules/ngx_http_autoindex_module.c - ngx_module_libs= - ngx_module_link=$HTTP_AUTOINDEX + if :; then + ngx_module_name=ngx_http_index_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/modules/ngx_http_index_module.c + ngx_module_libs= + ngx_module_link=YES - . auto/module -fi + . auto/module + fi -if :; then - ngx_module_name=ngx_http_index_module - ngx_module_incs= - ngx_module_deps= - ngx_module_srcs=src/http/modules/ngx_http_index_module.c - ngx_module_libs= - ngx_module_link=YES + if [ $HTTP_RANDOM_INDEX = YES ]; then + ngx_module_name=ngx_http_random_index_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/modules/ngx_http_random_index_module.c + ngx_module_libs= + ngx_module_link=$HTTP_RANDOM_INDEX - . auto/module -fi + . auto/module + fi -if [ $HTTP_RANDOM_INDEX = YES ]; then - ngx_module_name=ngx_http_random_index_module - ngx_module_incs= - ngx_module_deps= - ngx_module_srcs=src/http/modules/ngx_http_random_index_module.c - ngx_module_libs= - ngx_module_link=$HTTP_RANDOM_INDEX + if [ $HTTP_MIRROR = YES ]; then + ngx_module_name=ngx_http_mirror_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/modules/ngx_http_mirror_module.c + ngx_module_libs= + ngx_module_link=$HTTP_MIRROR - . auto/module -fi + . auto/module + fi -if [ $HTTP_AUTH_REQUEST = YES ]; then - ngx_module_name=ngx_http_auth_request_module - ngx_module_incs= - ngx_module_deps= - ngx_module_srcs=src/http/modules/ngx_http_auth_request_module.c - ngx_module_libs= - ngx_module_link=$HTTP_AUTH_REQUEST + if :; then + ngx_module_name=ngx_http_try_files_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/modules/ngx_http_try_files_module.c + ngx_module_libs= + ngx_module_link=YES - . auto/module -fi + . auto/module + fi -if [ $HTTP_AUTH_BASIC = YES ]; then - have=NGX_CRYPT . auto/have + if [ $HTTP_AUTH_REQUEST = YES ]; then + ngx_module_name=ngx_http_auth_request_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/modules/ngx_http_auth_request_module.c + ngx_module_libs= + ngx_module_link=$HTTP_AUTH_REQUEST - ngx_module_name=ngx_http_auth_basic_module - ngx_module_incs= - ngx_module_deps= - ngx_module_srcs=src/http/modules/ngx_http_auth_basic_module.c - ngx_module_libs=$CRYPT_LIB - ngx_module_link=$HTTP_AUTH_BASIC + . auto/module + fi - . auto/module -fi + if [ $HTTP_AUTH_BASIC = YES ]; then + have=NGX_CRYPT . auto/have -if [ $HTTP_ACCESS = YES ]; then - ngx_module_name=ngx_http_access_module - ngx_module_incs= - ngx_module_deps= - ngx_module_srcs=src/http/modules/ngx_http_access_module.c - ngx_module_libs= - ngx_module_link=$HTTP_ACCESS + ngx_module_name=ngx_http_auth_basic_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/modules/ngx_http_auth_basic_module.c + ngx_module_libs=$CRYPT_LIB + ngx_module_link=$HTTP_AUTH_BASIC - . auto/module -fi + . auto/module + fi -if [ $HTTP_LIMIT_CONN = YES ]; then - ngx_module_name=ngx_http_limit_conn_module - ngx_module_incs= - ngx_module_deps= - ngx_module_srcs=src/http/modules/ngx_http_limit_conn_module.c - ngx_module_libs= - ngx_module_link=$HTTP_LIMIT_CONN + if [ $HTTP_ACCESS = YES ]; then + ngx_module_name=ngx_http_access_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/modules/ngx_http_access_module.c + ngx_module_libs= + ngx_module_link=$HTTP_ACCESS - . auto/module -fi + . auto/module + fi -if [ $HTTP_LIMIT_REQ = YES ]; then - ngx_module_name=ngx_http_limit_req_module - ngx_module_incs= - ngx_module_deps= - ngx_module_srcs=src/http/modules/ngx_http_limit_req_module.c - ngx_module_libs= - ngx_module_link=$HTTP_LIMIT_REQ + if [ $HTTP_LIMIT_CONN = YES ]; then + ngx_module_name=ngx_http_limit_conn_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/modules/ngx_http_limit_conn_module.c + ngx_module_libs= + ngx_module_link=$HTTP_LIMIT_CONN - . auto/module -fi + . auto/module + fi -if [ $HTTP_REALIP = YES ]; then - have=NGX_HTTP_REALIP . auto/have - have=NGX_HTTP_X_FORWARDED_FOR . auto/have + if [ $HTTP_LIMIT_REQ = YES ]; then + ngx_module_name=ngx_http_limit_req_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/modules/ngx_http_limit_req_module.c + ngx_module_libs= + ngx_module_link=$HTTP_LIMIT_REQ - ngx_module_name=ngx_http_realip_module - ngx_module_incs= - ngx_module_deps= - ngx_module_srcs=src/http/modules/ngx_http_realip_module.c - ngx_module_libs= - ngx_module_link=$HTTP_REALIP + . auto/module + fi - . auto/module -fi + if [ $HTTP_REALIP = YES ]; then + have=NGX_HTTP_REALIP . auto/have + have=NGX_HTTP_X_FORWARDED_FOR . auto/have -if [ $HTTP_STATUS = YES ]; then - ngx_module_name=ngx_http_status_module - ngx_module_incs= - ngx_module_deps= - ngx_module_srcs=src/http/modules/ngx_http_status_module.c - ngx_module_libs= - ngx_module_link=$HTTP_STATUS + ngx_module_name=ngx_http_realip_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/modules/ngx_http_realip_module.c + ngx_module_libs= + ngx_module_link=$HTTP_REALIP + + . auto/module + fi + + if [ $HTTP_STATUS = YES ]; then + ngx_module_name=ngx_http_status_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/modules/ngx_http_status_module.c + ngx_module_libs= + ngx_module_link=$HTTP_STATUS - . auto/module -fi + . auto/module + fi -if [ $HTTP_GEO = YES ]; then - have=NGX_HTTP_X_FORWARDED_FOR . auto/have + if [ $HTTP_GEO = YES ]; then + have=NGX_HTTP_X_FORWARDED_FOR . auto/have - ngx_module_name=ngx_http_geo_module - ngx_module_incs= - ngx_module_deps= - ngx_module_srcs=src/http/modules/ngx_http_geo_module.c - ngx_module_libs= - ngx_module_link=$HTTP_GEO + ngx_module_name=ngx_http_geo_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/modules/ngx_http_geo_module.c + ngx_module_libs= + ngx_module_link=$HTTP_GEO - . auto/module -fi + . auto/module + fi -if [ $HTTP_GEOIP != NO ]; then - have=NGX_HTTP_X_FORWARDED_FOR . auto/have + if [ $HTTP_GEOIP != NO ]; then + have=NGX_HTTP_X_FORWARDED_FOR . auto/have - ngx_module_name=ngx_http_geoip_module - ngx_module_incs= - ngx_module_deps= - ngx_module_srcs=src/http/modules/ngx_http_geoip_module.c - ngx_module_libs=GEOIP - ngx_module_link=$HTTP_GEOIP + ngx_module_name=ngx_http_geoip_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/modules/ngx_http_geoip_module.c + ngx_module_libs=GEOIP + ngx_module_link=$HTTP_GEOIP - . auto/module -fi + . auto/module + fi -if [ $HTTP_MAP = YES ]; then - ngx_module_name=ngx_http_map_module - ngx_module_incs= - ngx_module_deps= - ngx_module_srcs=src/http/modules/ngx_http_map_module.c - ngx_module_libs= - ngx_module_link=$HTTP_MAP + if [ $HTTP_MAP = YES ]; then + ngx_module_name=ngx_http_map_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/modules/ngx_http_map_module.c + ngx_module_libs= + ngx_module_link=$HTTP_MAP - . auto/module -fi + . auto/module + fi -if [ $HTTP_SPLIT_CLIENTS = YES ]; then - ngx_module_name=ngx_http_split_clients_module - ngx_module_incs= - ngx_module_deps= - ngx_module_srcs=src/http/modules/ngx_http_split_clients_module.c - ngx_module_libs= - ngx_module_link=$HTTP_SPLIT_CLIENTS + if [ $HTTP_SPLIT_CLIENTS = YES ]; then + ngx_module_name=ngx_http_split_clients_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/modules/ngx_http_split_clients_module.c + ngx_module_libs= + ngx_module_link=$HTTP_SPLIT_CLIENTS - . auto/module -fi + . auto/module + fi -if [ $HTTP_REFERER = YES ]; then - ngx_module_name=ngx_http_referer_module - ngx_module_incs= - ngx_module_deps= - ngx_module_srcs=src/http/modules/ngx_http_referer_module.c - ngx_module_libs= - ngx_module_link=$HTTP_REFERER + if [ $HTTP_REFERER = YES ]; then + ngx_module_name=ngx_http_referer_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/modules/ngx_http_referer_module.c + ngx_module_libs= + ngx_module_link=$HTTP_REFERER - . auto/module -fi + . auto/module + fi -if [ $HTTP_REWRITE = YES -a $USE_PCRE != DISABLED ]; then - USE_PCRE=YES + if [ $HTTP_REWRITE = YES -a $USE_PCRE != DISABLED ]; then + USE_PCRE=YES - ngx_module_name=ngx_http_rewrite_module - ngx_module_incs= - ngx_module_deps= - ngx_module_srcs=src/http/modules/ngx_http_rewrite_module.c - ngx_module_libs= - ngx_module_link=$HTTP_REWRITE + ngx_module_name=ngx_http_rewrite_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/modules/ngx_http_rewrite_module.c + ngx_module_libs= + ngx_module_link=$HTTP_REWRITE - . auto/module -fi + . auto/module + fi -if [ $HTTP_SSL = YES ]; then - USE_OPENSSL=YES - have=NGX_HTTP_SSL . auto/have + if [ $HTTP_SSL = YES ]; then + USE_OPENSSL=YES + have=NGX_HTTP_SSL . auto/have - ngx_module_name=ngx_http_ssl_module - ngx_module_incs= - ngx_module_deps=src/http/modules/ngx_http_ssl_module.h - ngx_module_srcs=src/http/modules/ngx_http_ssl_module.c - ngx_module_libs= - ngx_module_link=$HTTP_SSL + ngx_module_name=ngx_http_ssl_module + ngx_module_incs= + ngx_module_deps=src/http/modules/ngx_http_ssl_module.h + ngx_module_srcs=src/http/modules/ngx_http_ssl_module.c + ngx_module_libs= + ngx_module_link=$HTTP_SSL - . auto/module -fi + . auto/module + fi -if [ $HTTP_PROXY = YES ]; then - have=NGX_HTTP_X_FORWARDED_FOR . auto/have + if [ $HTTP_PROXY = YES ]; then + have=NGX_HTTP_X_FORWARDED_FOR . auto/have - ngx_module_name=ngx_http_proxy_module - ngx_module_incs= - ngx_module_deps= - ngx_module_srcs=src/http/modules/ngx_http_proxy_module.c - ngx_module_libs= - ngx_module_link=$HTTP_PROXY + ngx_module_name=ngx_http_proxy_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/modules/ngx_http_proxy_module.c + ngx_module_libs= + ngx_module_link=$HTTP_PROXY - . auto/module -fi + . auto/module + fi -if [ $HTTP_FASTCGI = YES ]; then - ngx_module_name=ngx_http_fastcgi_module - ngx_module_incs= - ngx_module_deps= - ngx_module_srcs=src/http/modules/ngx_http_fastcgi_module.c - ngx_module_libs= - ngx_module_link=$HTTP_FASTCGI + if [ $HTTP_FASTCGI = YES ]; then + ngx_module_name=ngx_http_fastcgi_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/modules/ngx_http_fastcgi_module.c + ngx_module_libs= + ngx_module_link=$HTTP_FASTCGI - . auto/module -fi + . auto/module + fi -if [ $HTTP_UWSGI = YES ]; then - ngx_module_name=ngx_http_uwsgi_module - ngx_module_incs= - ngx_module_deps= - ngx_module_srcs=src/http/modules/ngx_http_uwsgi_module.c - ngx_module_libs= - ngx_module_link=$HTTP_UWSGI + if [ $HTTP_UWSGI = YES ]; then + ngx_module_name=ngx_http_uwsgi_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/modules/ngx_http_uwsgi_module.c + ngx_module_libs= + ngx_module_link=$HTTP_UWSGI - . auto/module -fi + . auto/module + fi -if [ $HTTP_SCGI = YES ]; then - ngx_module_name=ngx_http_scgi_module - ngx_module_incs= - ngx_module_deps= - ngx_module_srcs=src/http/modules/ngx_http_scgi_module.c - ngx_module_libs= - ngx_module_link=$HTTP_SCGI + if [ $HTTP_SCGI = YES ]; then + ngx_module_name=ngx_http_scgi_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/modules/ngx_http_scgi_module.c + ngx_module_libs= + ngx_module_link=$HTTP_SCGI - . auto/module -fi + . auto/module + fi -if [ $HTTP_PERL != NO ]; then - ngx_module_name=ngx_http_perl_module - ngx_module_incs=src/http/modules/perl - ngx_module_deps=src/http/modules/perl/ngx_http_perl_module.h - ngx_module_srcs=src/http/modules/perl/ngx_http_perl_module.c - ngx_module_libs=PERL - ngx_module_link=$HTTP_PERL + if [ $HTTP_PERL != NO ]; then + ngx_module_name=ngx_http_perl_module + ngx_module_incs=src/http/modules/perl + ngx_module_deps=src/http/modules/perl/ngx_http_perl_module.h + ngx_module_srcs=src/http/modules/perl/ngx_http_perl_module.c + ngx_module_libs=PERL + ngx_module_link=$HTTP_PERL - . auto/module -fi + . auto/module + fi -if [ $HTTP_MEMCACHED = YES ]; then - ngx_module_name=ngx_http_memcached_module - ngx_module_incs= - ngx_module_deps= - ngx_module_srcs=src/http/modules/ngx_http_memcached_module.c - ngx_module_libs= - ngx_module_link=$HTTP_MEMCACHED + if [ $HTTP_MEMCACHED = YES ]; then + ngx_module_name=ngx_http_memcached_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/modules/ngx_http_memcached_module.c + ngx_module_libs= + ngx_module_link=$HTTP_MEMCACHED - . auto/module -fi + . auto/module + fi -if [ $HTTP_EMPTY_GIF = YES ]; then - ngx_module_name=ngx_http_empty_gif_module - ngx_module_incs= - ngx_module_deps= - ngx_module_srcs=src/http/modules/ngx_http_empty_gif_module.c - ngx_module_libs= - ngx_module_link=$HTTP_EMPTY_GIF + if [ $HTTP_EMPTY_GIF = YES ]; then + ngx_module_name=ngx_http_empty_gif_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/modules/ngx_http_empty_gif_module.c + ngx_module_libs= + ngx_module_link=$HTTP_EMPTY_GIF - . auto/module -fi + . auto/module + fi -if [ $HTTP_BROWSER = YES ]; then - ngx_module_name=ngx_http_browser_module - ngx_module_incs= - ngx_module_deps= - ngx_module_srcs=src/http/modules/ngx_http_browser_module.c - ngx_module_libs= - ngx_module_link=$HTTP_BROWSER + if [ $HTTP_BROWSER = YES ]; then + ngx_module_name=ngx_http_browser_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/modules/ngx_http_browser_module.c + ngx_module_libs= + ngx_module_link=$HTTP_BROWSER - . auto/module -fi + . auto/module + fi -if [ $HTTP_SECURE_LINK = YES ]; then - ngx_module_name=ngx_http_secure_link_module - ngx_module_incs= - ngx_module_deps= - ngx_module_srcs=src/http/modules/ngx_http_secure_link_module.c - ngx_module_libs= - ngx_module_link=$HTTP_SECURE_LINK + if [ $HTTP_SECURE_LINK = YES ]; then + ngx_module_name=ngx_http_secure_link_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/modules/ngx_http_secure_link_module.c + ngx_module_libs= + ngx_module_link=$HTTP_SECURE_LINK - . auto/module -fi + . auto/module + fi -if [ $HTTP_DEGRADATION = YES ]; then - have=NGX_HTTP_DEGRADATION . auto/have + if [ $HTTP_DEGRADATION = YES ]; then + have=NGX_HTTP_DEGRADATION . auto/have - ngx_module_name=ngx_http_degradation_module - ngx_module_incs= - ngx_module_deps= - ngx_module_srcs=src/http/modules/ngx_http_degradation_module.c - ngx_module_libs= - ngx_module_link=$HTTP_DEGRADATION + ngx_module_name=ngx_http_degradation_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/modules/ngx_http_degradation_module.c + ngx_module_libs= + ngx_module_link=$HTTP_DEGRADATION - . auto/module -fi + . auto/module + fi -if [ $HTTP_FLV = YES ]; then - ngx_module_name=ngx_http_flv_module - ngx_module_incs= - ngx_module_deps= - ngx_module_srcs=src/http/modules/ngx_http_flv_module.c - ngx_module_libs= - ngx_module_link=$HTTP_FLV + if [ $HTTP_FLV = YES ]; then + ngx_module_name=ngx_http_flv_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/modules/ngx_http_flv_module.c + ngx_module_libs= + ngx_module_link=$HTTP_FLV - . auto/module -fi + . auto/module + fi -if [ $HTTP_MP4 = YES ]; then - ngx_module_name=ngx_http_mp4_module - ngx_module_incs= - ngx_module_deps= - ngx_module_srcs=src/http/modules/ngx_http_mp4_module.c - ngx_module_libs= - ngx_module_link=$HTTP_MP4 + if [ $HTTP_MP4 = YES ]; then + ngx_module_name=ngx_http_mp4_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/modules/ngx_http_mp4_module.c + ngx_module_libs= + ngx_module_link=$HTTP_MP4 - . auto/module -fi + . auto/module + fi -if [ $HTTP_UPSTREAM_HASH = YES ]; then - ngx_module_name=ngx_http_upstream_hash_module - ngx_module_incs= - ngx_module_deps= - ngx_module_srcs=src/http/modules/ngx_http_upstream_hash_module.c - ngx_module_libs= - ngx_module_link=$HTTP_UPSTREAM_HASH + if [ $HTTP_UPSTREAM_HASH = YES ]; then + ngx_module_name=ngx_http_upstream_hash_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/modules/ngx_http_upstream_hash_module.c + ngx_module_libs= + ngx_module_link=$HTTP_UPSTREAM_HASH - . auto/module -fi + . auto/module + fi -if [ $HTTP_UPSTREAM_IP_HASH = YES ]; then - ngx_module_name=ngx_http_upstream_ip_hash_module - ngx_module_incs= - ngx_module_deps= - ngx_module_srcs=src/http/modules/ngx_http_upstream_ip_hash_module.c - ngx_module_libs= - ngx_module_link=$HTTP_UPSTREAM_IP_HASH + if [ $HTTP_UPSTREAM_IP_HASH = YES ]; then + ngx_module_name=ngx_http_upstream_ip_hash_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/modules/ngx_http_upstream_ip_hash_module.c + ngx_module_libs= + ngx_module_link=$HTTP_UPSTREAM_IP_HASH - . auto/module -fi + . auto/module + fi -if [ $HTTP_UPSTREAM_LEAST_CONN = YES ]; then - ngx_module_name=ngx_http_upstream_least_conn_module - ngx_module_incs= - ngx_module_deps= - ngx_module_srcs=src/http/modules/ngx_http_upstream_least_conn_module.c - ngx_module_libs= - ngx_module_link=$HTTP_UPSTREAM_LEAST_CONN + if [ $HTTP_UPSTREAM_LEAST_CONN = YES ]; then + ngx_module_name=ngx_http_upstream_least_conn_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/modules/ngx_http_upstream_least_conn_module.c + ngx_module_libs= + ngx_module_link=$HTTP_UPSTREAM_LEAST_CONN - . auto/module -fi + . auto/module + fi -if [ $HTTP_UPSTREAM_KEEPALIVE = YES ]; then - ngx_module_name=ngx_http_upstream_keepalive_module - ngx_module_incs= - ngx_module_deps= - ngx_module_srcs=src/http/modules/ngx_http_upstream_keepalive_module.c - ngx_module_libs= - ngx_module_link=$HTTP_UPSTREAM_KEEPALIVE + if [ $HTTP_UPSTREAM_KEEPALIVE = YES ]; then + ngx_module_name=ngx_http_upstream_keepalive_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/modules/ngx_http_upstream_keepalive_module.c + ngx_module_libs= + ngx_module_link=$HTTP_UPSTREAM_KEEPALIVE - . auto/module -fi + . auto/module + fi -if [ $HTTP_UPSTREAM_ZONE = YES ]; then - have=NGX_HTTP_UPSTREAM_ZONE . auto/have + if [ $HTTP_UPSTREAM_ZONE = YES ]; then + have=NGX_HTTP_UPSTREAM_ZONE . auto/have - ngx_module_name=ngx_http_upstream_zone_module - ngx_module_incs= - ngx_module_deps= - ngx_module_srcs=src/http/modules/ngx_http_upstream_zone_module.c - ngx_module_libs= - ngx_module_link=$HTTP_UPSTREAM_ZONE + ngx_module_name=ngx_http_upstream_zone_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/modules/ngx_http_upstream_zone_module.c + ngx_module_libs= + ngx_module_link=$HTTP_UPSTREAM_ZONE - . auto/module -fi + . auto/module + fi -if [ $HTTP_STUB_STATUS = YES ]; then - have=NGX_STAT_STUB . auto/have + if [ $HTTP_STUB_STATUS = YES ]; then + have=NGX_STAT_STUB . auto/have - ngx_module_name=ngx_http_stub_status_module - ngx_module_incs= - ngx_module_deps= - ngx_module_srcs=src/http/modules/ngx_http_stub_status_module.c - ngx_module_libs= - ngx_module_link=$HTTP_STUB_STATUS + ngx_module_name=ngx_http_stub_status_module + ngx_module_incs= + ngx_module_deps= + ngx_module_srcs=src/http/modules/ngx_http_stub_status_module.c + ngx_module_libs= + ngx_module_link=$HTTP_STUB_STATUS - . auto/module + . auto/module + fi fi @@ -966,6 +985,8 @@ if [ $STREAM != NO ]; then STREAM_INCS= ngx_module_type=STREAM + ngx_module_libs= + ngx_module_link=YES ngx_module_order= @@ -1252,7 +1273,7 @@ if [ $MAIL != NO ]; then elif [ $MAIL = DYNAMIC ]; then ngx_module_name=$MAIL_MODULES ngx_module_incs= - ngx_module_deps=$MAIL_DEPS + ngx_module_deps= ngx_module_srcs=$MAIL_SRCS ngx_module_libs= ngx_module_link=DYNAMIC @@ -1272,7 +1293,7 @@ if [ $STREAM != NO ]; then elif [ $STREAM = DYNAMIC ]; then ngx_module_name=$STREAM_MODULES ngx_module_incs= - ngx_module_deps=$STREAM_DEPS + ngx_module_deps= ngx_module_srcs=$STREAM_SRCS ngx_module_libs= ngx_module_link=DYNAMIC diff --git a/auto/options b/auto/options index 43724b1e62e..24c2618b29c 100644 --- a/auto/options +++ b/auto/options @@ -70,6 +70,7 @@ HTTP_DAV=NO HTTP_ACCESS=YES HTTP_AUTH_BASIC=YES HTTP_AUTH_REQUEST=NO +HTTP_MIRROR=YES HTTP_USERID=YES HTTP_SLICE=NO HTTP_AUTOINDEX=YES @@ -249,6 +250,7 @@ $0: warning: the \"--with-ipv6\" option is deprecated" --without-http_userid_module) HTTP_USERID=NO ;; --without-http_access_module) HTTP_ACCESS=NO ;; --without-http_auth_basic_module) HTTP_AUTH_BASIC=NO ;; + --without-http_mirror_module) HTTP_MIRROR=NO ;; --without-http_autoindex_module) HTTP_AUTOINDEX=NO ;; --without-http_status_module) HTTP_STATUS=NO ;; --without-http_geo_module) HTTP_GEO=NO ;; @@ -458,6 +460,7 @@ cat << END --without-http_userid_module disable ngx_http_userid_module --without-http_access_module disable ngx_http_access_module --without-http_auth_basic_module disable ngx_http_auth_basic_module + --without-http_mirror_module disable ngx_http_mirror_module --without-http_autoindex_module disable ngx_http_autoindex_module --without-http_geo_module disable ngx_http_geo_module --without-http_map_module disable ngx_http_map_module @@ -574,19 +577,6 @@ END fi -if [ $HTTP = NO ]; then - HTTP_CHARSET=NO - HTTP_GZIP=NO - HTTP_SSI=NO - HTTP_USERID=NO - HTTP_ACCESS=NO - HTTP_STATUS=NO - HTTP_REWRITE=NO - HTTP_PROXY=NO - HTTP_FASTCGI=NO -fi - - if [ ".$NGX_PLATFORM" = ".win32" ]; then NGX_WINE=$WINE fi diff --git a/auto/os/conf b/auto/os/conf index 6ad0e74e0d4..6096af5d5ff 100644 --- a/auto/os/conf +++ b/auto/os/conf @@ -41,6 +41,14 @@ case "$NGX_PLATFORM" in ' ;; + NetBSD:*) + CORE_INCS="$UNIX_INCS" + CORE_DEPS="$UNIX_DEPS $POSIX_DEPS" + CORE_SRCS="$UNIX_SRCS" + + NGX_RPATH=YES + ;; + HP-UX:*) # HP/UX have=NGX_HPUX . auto/have_headers diff --git a/auto/os/darwin b/auto/os/darwin index b4b3ad30630..429468f7fd4 100644 --- a/auto/os/darwin +++ b/auto/os/darwin @@ -17,6 +17,9 @@ ngx_spacer=' MAIN_LINK= MODULE_LINK="-shared -Wl,-undefined,dynamic_lookup" +CC_AUX_FLAGS="$CC_AUX_FLAGS -D__APPLE_USE_RFC_3542" + + # kqueue echo " + kqueue found" @@ -86,7 +89,6 @@ ngx_feature_test="int kq; # sendfile() -CC_AUX_FLAGS="$CC_AUX_FLAGS" ngx_feature="sendfile()" ngx_feature_name="NGX_HAVE_SENDFILE" ngx_feature_run=yes diff --git a/auto/os/linux b/auto/os/linux index fae8842c645..a0c8795bbba 100644 --- a/auto/os/linux +++ b/auto/os/linux @@ -157,20 +157,6 @@ ngx_feature_test="if (prctl(PR_SET_DUMPABLE, 1, 0, 0, 0) == -1) return 1" . auto/feature -# sched_setaffinity() - -ngx_feature="sched_setaffinity()" -ngx_feature_name="NGX_HAVE_SCHED_SETAFFINITY" -ngx_feature_run=no -ngx_feature_incs="#include " -ngx_feature_path= -ngx_feature_libs= -ngx_feature_test="cpu_set_t mask; - CPU_ZERO(&mask); - sched_setaffinity(0, sizeof(cpu_set_t), &mask)" -. auto/feature - - # crypt_r() ngx_feature="crypt_r()" diff --git a/auto/os/win32 b/auto/os/win32 index 650cf495a94..7a82774960b 100644 --- a/auto/os/win32 +++ b/auto/os/win32 @@ -13,6 +13,7 @@ NGX_ICONS="$NGX_WIN32_ICONS" SELECT_SRCS=$WIN32_SELECT_SRCS ngx_pic_opt= +ngx_binext=".exe" case "$NGX_CC_NAME" in diff --git a/auto/unix b/auto/unix old mode 100755 new mode 100644 index 5ef74d4a899..10835f6cc4e --- a/auto/unix +++ b/auto/unix @@ -300,6 +300,18 @@ if [ $ngx_found = no ]; then fi +ngx_feature="sched_setaffinity()" +ngx_feature_name="NGX_HAVE_SCHED_SETAFFINITY" +ngx_feature_run=no +ngx_feature_incs="#include " +ngx_feature_path= +ngx_feature_libs= +ngx_feature_test="cpu_set_t mask; + CPU_ZERO(&mask); + sched_setaffinity(0, sizeof(cpu_set_t), &mask)" +. auto/feature + + ngx_feature="SO_SETFIB" ngx_feature_name="NGX_HAVE_SETFIB" ngx_feature_run=no @@ -394,6 +406,19 @@ ngx_feature_test="setsockopt(0, IPPROTO_IP, IP_RECVDSTADDR, NULL, 0)" . auto/feature +# BSD way to set IPv4 datagram source address + +ngx_feature="IP_SENDSRCADDR" +ngx_feature_name="NGX_HAVE_IP_SENDSRCADDR" +ngx_feature_run=no +ngx_feature_incs="#include + #include " +ngx_feature_path= +ngx_feature_libs= +ngx_feature_test="setsockopt(0, IPPROTO_IP, IP_SENDSRCADDR, NULL, 0)" +. auto/feature + + # Linux way to get IPv4 datagram destination address ngx_feature="IP_PKTINFO" @@ -403,7 +428,10 @@ ngx_feature_incs="#include #include " ngx_feature_path= ngx_feature_libs= -ngx_feature_test="setsockopt(0, IPPROTO_IP, IP_PKTINFO, NULL, 0)" +ngx_feature_test="struct in_pktinfo pkt; + pkt.ipi_spec_dst.s_addr = INADDR_ANY; + (void) pkt; + setsockopt(0, IPPROTO_IP, IP_PKTINFO, NULL, 0)" . auto/feature diff --git a/conf/mime.types b/conf/mime.types index 89be9a4cd63..8a2348ab04a 100644 --- a/conf/mime.types +++ b/conf/mime.types @@ -1,89 +1,95 @@ types { - text/html html htm shtml; - text/css css; - text/xml xml; - image/gif gif; - image/jpeg jpeg jpg; - application/javascript js; - application/atom+xml atom; - application/rss+xml rss; + text/html html htm shtml; + text/css css; + text/xml xml; + image/gif gif; + image/jpeg jpeg jpg; + application/javascript js; + application/atom+xml atom; + application/rss+xml rss; - text/mathml mml; - text/plain txt; - text/vnd.sun.j2me.app-descriptor jad; - text/vnd.wap.wml wml; - text/x-component htc; + text/mathml mml; + text/plain txt; + text/vnd.sun.j2me.app-descriptor jad; + text/vnd.wap.wml wml; + text/x-component htc; - image/png png; - image/tiff tif tiff; - image/vnd.wap.wbmp wbmp; - image/x-icon ico; - image/x-jng jng; - image/x-ms-bmp bmp; - image/svg+xml svg svgz; - image/webp webp; + image/png png; + image/svg+xml svg svgz; + image/tiff tif tiff; + image/vnd.wap.wbmp wbmp; + image/webp webp; + image/x-icon ico; + image/x-jng jng; + image/x-ms-bmp bmp; - application/font-woff woff; - application/java-archive jar war ear; - application/json json; - application/mac-binhex40 hqx; - application/msword doc; - application/pdf pdf; - application/postscript ps eps ai; - application/rtf rtf; - application/vnd.apple.mpegurl m3u8; - application/vnd.ms-excel xls; - application/vnd.ms-fontobject eot; - application/vnd.ms-powerpoint ppt; - application/vnd.wap.wmlc wmlc; - application/vnd.google-earth.kml+xml kml; - application/vnd.google-earth.kmz kmz; - application/x-7z-compressed 7z; - application/x-cocoa cco; - application/x-java-archive-diff jardiff; - application/x-java-jnlp-file jnlp; - application/x-makeself run; - application/x-perl pl pm; - application/x-pilot prc pdb; - application/x-rar-compressed rar; - application/x-redhat-package-manager rpm; - application/x-sea sea; - application/x-shockwave-flash swf; - application/x-stuffit sit; - application/x-tcl tcl tk; - application/x-x509-ca-cert der pem crt; - application/x-xpinstall xpi; - application/xhtml+xml xhtml; - application/xspf+xml xspf; - application/zip zip; + application/font-woff woff; + application/java-archive jar war ear; + application/json json; + application/mac-binhex40 hqx; + application/msword doc; + application/pdf pdf; + application/postscript ps eps ai; + application/rtf rtf; + application/vnd.apple.mpegurl m3u8; + application/vnd.google-earth.kml+xml kml; + application/vnd.google-earth.kmz kmz; + application/vnd.ms-excel xls; + application/vnd.ms-fontobject eot; + application/vnd.ms-powerpoint ppt; + application/vnd.oasis.opendocument.graphics odg; + application/vnd.oasis.opendocument.presentation odp; + application/vnd.oasis.opendocument.spreadsheet ods; + application/vnd.oasis.opendocument.text odt; + application/vnd.openxmlformats-officedocument.presentationml.presentation + pptx; + application/vnd.openxmlformats-officedocument.spreadsheetml.sheet + xlsx; + application/vnd.openxmlformats-officedocument.wordprocessingml.document + docx; + application/vnd.wap.wmlc wmlc; + application/x-7z-compressed 7z; + application/x-cocoa cco; + application/x-java-archive-diff jardiff; + application/x-java-jnlp-file jnlp; + application/x-makeself run; + application/x-perl pl pm; + application/x-pilot prc pdb; + application/x-rar-compressed rar; + application/x-redhat-package-manager rpm; + application/x-sea sea; + application/x-shockwave-flash swf; + application/x-stuffit sit; + application/x-tcl tcl tk; + application/x-x509-ca-cert der pem crt; + application/x-xpinstall xpi; + application/xhtml+xml xhtml; + application/xspf+xml xspf; + application/zip zip; - application/octet-stream bin exe dll; - application/octet-stream deb; - application/octet-stream dmg; - application/octet-stream iso img; - application/octet-stream msi msp msm; + application/octet-stream bin exe dll; + application/octet-stream deb; + application/octet-stream dmg; + application/octet-stream iso img; + application/octet-stream msi msp msm; - application/vnd.openxmlformats-officedocument.wordprocessingml.document docx; - application/vnd.openxmlformats-officedocument.spreadsheetml.sheet xlsx; - application/vnd.openxmlformats-officedocument.presentationml.presentation pptx; + audio/midi mid midi kar; + audio/mpeg mp3; + audio/ogg ogg; + audio/x-m4a m4a; + audio/x-realaudio ra; - audio/midi mid midi kar; - audio/mpeg mp3; - audio/ogg ogg; - audio/x-m4a m4a; - audio/x-realaudio ra; - - video/3gpp 3gpp 3gp; - video/mp2t ts; - video/mp4 mp4; - video/mpeg mpeg mpg; - video/quicktime mov; - video/webm webm; - video/x-flv flv; - video/x-m4v m4v; - video/x-mng mng; - video/x-ms-asf asx asf; - video/x-ms-wmv wmv; - video/x-msvideo avi; + video/3gpp 3gpp 3gp; + video/mp2t ts; + video/mp4 mp4; + video/mpeg mpeg mpg; + video/quicktime mov; + video/webm webm; + video/x-flv flv; + video/x-m4v m4v; + video/x-mng mng; + video/x-ms-asf asx asf; + video/x-ms-wmv wmv; + video/x-msvideo avi; } diff --git a/contrib/vim/ftplugin/nginx.vim b/contrib/vim/ftplugin/nginx.vim new file mode 100644 index 00000000000..463eea98962 --- /dev/null +++ b/contrib/vim/ftplugin/nginx.vim @@ -0,0 +1 @@ +setlocal commentstring=#\ %s diff --git a/contrib/vim/syntax/nginx.vim b/contrib/vim/syntax/nginx.vim index f1fd48a0eca..dc8c0cb4dec 100644 --- a/contrib/vim/syntax/nginx.vim +++ b/contrib/vim/syntax/nginx.vim @@ -5,832 +5,2170 @@ if exists("b:current_syntax") finish end -setlocal iskeyword+=. -setlocal iskeyword+=/ -setlocal iskeyword+=: +" general syntax -syn match ngxVariable '\$\(\w\+\|{\w\+}\)' -syn match ngxVariableBlock '\$\(\w\+\|{\w\+}\)' contained +if has("patch-7.4.1142") + " except control characters, ";", "{", and "}" + syn iskeyword 33-58,60-122,124,126-255 +endif + +syn match ngxName '\([^;{} \t\\]\|\\.\)\+' + \ contains=@ngxDirectives + \ nextgroup=@ngxParams skipwhite skipempty +syn match ngxParam '\([^;{ \t\\]\|\\.\)\+' + \ contained + \ contains=ngxVariable + \ nextgroup=@ngxParams skipwhite skipempty +syn region ngxString start=+\z(["']\)+ end=+\z1+ skip=+\\\\\|\\\z1+ + \ contains=ngxVariableString + \ nextgroup=@ngxParams skipwhite skipempty +syn match ngxParamComment '#.*$' + \ nextgroup=@ngxParams skipwhite skipempty +syn match ngxSemicolon ';' contained +syn region ngxBlock start=+{+ end=+}+ contained + \ contains=@ngxTopLevel +syn match ngxComment '#.*$' + +syn match ngxVariable '\$\w\+' contained syn match ngxVariableString '\$\(\w\+\|{\w\+}\)' contained -syn region ngxBlock start=+^+ end=+{+ skip=+\${+ contains=ngxComment,ngxDirectiveBlock,ngxVariableBlock,ngxString oneline -syn region ngxString start=+\z(["']\)+ end=+\z1+ skip=+\\\\\|\\\z1+ contains=ngxVariableString -syn match ngxComment ' *#.*$' - -syn keyword ngxBoolean on -syn keyword ngxBoolean off - -syn keyword ngxDirectiveBlock http contained -syn keyword ngxDirectiveBlock mail contained -syn keyword ngxDirectiveBlock events contained -syn keyword ngxDirectiveBlock server contained -syn keyword ngxDirectiveBlock types contained -syn keyword ngxDirectiveBlock location contained -syn keyword ngxDirectiveBlock upstream contained -syn keyword ngxDirectiveBlock charset_map contained -syn keyword ngxDirectiveBlock limit_except contained -syn keyword ngxDirectiveBlock if contained -syn keyword ngxDirectiveBlock geo contained -syn keyword ngxDirectiveBlock map contained -syn keyword ngxDirectiveBlock split_clients contained - -syn keyword ngxDirectiveImportant include -syn keyword ngxDirectiveImportant root -syn keyword ngxDirectiveImportant server -syn keyword ngxDirectiveImportant server_name -syn keyword ngxDirectiveImportant listen -syn keyword ngxDirectiveImportant internal -syn keyword ngxDirectiveImportant proxy_pass -syn keyword ngxDirectiveImportant memcached_pass -syn keyword ngxDirectiveImportant fastcgi_pass -syn keyword ngxDirectiveImportant scgi_pass -syn keyword ngxDirectiveImportant uwsgi_pass -syn keyword ngxDirectiveImportant try_files - -syn keyword ngxDirectiveControl break -syn keyword ngxDirectiveControl return -syn keyword ngxDirectiveControl rewrite -syn keyword ngxDirectiveControl set - -syn keyword ngxDirectiveError error_page -syn keyword ngxDirectiveError post_action - -syn keyword ngxDirectiveDeprecated connections -syn keyword ngxDirectiveDeprecated imap -syn keyword ngxDirectiveDeprecated limit_zone -syn keyword ngxDirectiveDeprecated mysql_test -syn keyword ngxDirectiveDeprecated open_file_cache_retest -syn keyword ngxDirectiveDeprecated optimize_server_names -syn keyword ngxDirectiveDeprecated satisfy_any -syn keyword ngxDirectiveDeprecated so_keepalive - -syn keyword ngxDirective accept_mutex -syn keyword ngxDirective accept_mutex_delay -syn keyword ngxDirective acceptex_read -syn keyword ngxDirective access_log -syn keyword ngxDirective add_after_body -syn keyword ngxDirective add_before_body -syn keyword ngxDirective add_header -syn keyword ngxDirective addition_types -syn keyword ngxDirective aio -syn keyword ngxDirective alias -syn keyword ngxDirective allow -syn keyword ngxDirective ancient_browser -syn keyword ngxDirective ancient_browser_value -syn keyword ngxDirective auth_basic -syn keyword ngxDirective auth_basic_user_file -syn keyword ngxDirective auth_http -syn keyword ngxDirective auth_http_header -syn keyword ngxDirective auth_http_timeout -syn keyword ngxDirective auth_request -syn keyword ngxDirective auth_request_set -syn keyword ngxDirective autoindex -syn keyword ngxDirective autoindex_exact_size -syn keyword ngxDirective autoindex_localtime -syn keyword ngxDirective charset -syn keyword ngxDirective charset_types -syn keyword ngxDirective chunked_transfer_encoding -syn keyword ngxDirective client_body_buffer_size -syn keyword ngxDirective client_body_in_file_only -syn keyword ngxDirective client_body_in_single_buffer -syn keyword ngxDirective client_body_temp_path -syn keyword ngxDirective client_body_timeout -syn keyword ngxDirective client_header_buffer_size -syn keyword ngxDirective client_header_timeout -syn keyword ngxDirective client_max_body_size -syn keyword ngxDirective connection_pool_size -syn keyword ngxDirective create_full_put_path -syn keyword ngxDirective daemon -syn keyword ngxDirective dav_access -syn keyword ngxDirective dav_methods -syn keyword ngxDirective debug_connection -syn keyword ngxDirective debug_points -syn keyword ngxDirective default_type -syn keyword ngxDirective degradation -syn keyword ngxDirective degrade -syn keyword ngxDirective deny -syn keyword ngxDirective devpoll_changes -syn keyword ngxDirective devpoll_events -syn keyword ngxDirective directio -syn keyword ngxDirective directio_alignment -syn keyword ngxDirective disable_symlinks -syn keyword ngxDirective empty_gif -syn keyword ngxDirective env -syn keyword ngxDirective epoll_events -syn keyword ngxDirective error_log -syn keyword ngxDirective etag -syn keyword ngxDirective eventport_events -syn keyword ngxDirective expires -syn keyword ngxDirective fastcgi_bind -syn keyword ngxDirective fastcgi_buffer_size -syn keyword ngxDirective fastcgi_buffering -syn keyword ngxDirective fastcgi_buffers -syn keyword ngxDirective fastcgi_busy_buffers_size -syn keyword ngxDirective fastcgi_cache -syn keyword ngxDirective fastcgi_cache_bypass -syn keyword ngxDirective fastcgi_cache_key -syn keyword ngxDirective fastcgi_cache_lock -syn keyword ngxDirective fastcgi_cache_lock_timeout -syn keyword ngxDirective fastcgi_cache_methods -syn keyword ngxDirective fastcgi_cache_min_uses -syn keyword ngxDirective fastcgi_cache_path -syn keyword ngxDirective fastcgi_cache_revalidate -syn keyword ngxDirective fastcgi_cache_use_stale -syn keyword ngxDirective fastcgi_cache_valid -syn keyword ngxDirective fastcgi_catch_stderr -syn keyword ngxDirective fastcgi_connect_timeout -syn keyword ngxDirective fastcgi_force_ranges -syn keyword ngxDirective fastcgi_hide_header -syn keyword ngxDirective fastcgi_ignore_client_abort -syn keyword ngxDirective fastcgi_ignore_headers -syn keyword ngxDirective fastcgi_index -syn keyword ngxDirective fastcgi_intercept_errors -syn keyword ngxDirective fastcgi_keep_conn -syn keyword ngxDirective fastcgi_max_temp_file_size -syn keyword ngxDirective fastcgi_next_upstream -syn keyword ngxDirective fastcgi_next_upstream_timeout -syn keyword ngxDirective fastcgi_next_upstream_tries -syn keyword ngxDirective fastcgi_no_cache -syn keyword ngxDirective fastcgi_param -syn keyword ngxDirective fastcgi_pass_header -syn keyword ngxDirective fastcgi_pass_request_body -syn keyword ngxDirective fastcgi_pass_request_headers -syn keyword ngxDirective fastcgi_read_timeout -syn keyword ngxDirective fastcgi_send_lowat -syn keyword ngxDirective fastcgi_send_timeout -syn keyword ngxDirective fastcgi_split_path_info -syn keyword ngxDirective fastcgi_store -syn keyword ngxDirective fastcgi_store_access -syn keyword ngxDirective fastcgi_temp_file_write_size -syn keyword ngxDirective fastcgi_temp_path -syn keyword ngxDirective flv -syn keyword ngxDirective geoip_city -syn keyword ngxDirective geoip_country -syn keyword ngxDirective geoip_org -syn keyword ngxDirective geoip_proxy -syn keyword ngxDirective geoip_proxy_recursive -syn keyword ngxDirective google_perftools_profiles -syn keyword ngxDirective gunzip -syn keyword ngxDirective gunzip_buffers -syn keyword ngxDirective gzip -syn keyword ngxDirective gzip_buffers -syn keyword ngxDirective gzip_comp_level -syn keyword ngxDirective gzip_disable -syn keyword ngxDirective gzip_hash -syn keyword ngxDirective gzip_http_version -syn keyword ngxDirective gzip_min_length -syn keyword ngxDirective gzip_no_buffer -syn keyword ngxDirective gzip_proxied -syn keyword ngxDirective gzip_static -syn keyword ngxDirective gzip_types -syn keyword ngxDirective gzip_vary -syn keyword ngxDirective gzip_window -syn keyword ngxDirective hash -syn keyword ngxDirective if_modified_since -syn keyword ngxDirective ignore_invalid_headers -syn keyword ngxDirective image_filter -syn keyword ngxDirective image_filter_buffer -syn keyword ngxDirective image_filter_interlace -syn keyword ngxDirective image_filter_jpeg_quality -syn keyword ngxDirective image_filter_sharpen -syn keyword ngxDirective image_filter_transparency -syn keyword ngxDirective imap_auth -syn keyword ngxDirective imap_capabilities -syn keyword ngxDirective imap_client_buffer -syn keyword ngxDirective index -syn keyword ngxDirective iocp_threads -syn keyword ngxDirective ip_hash -syn keyword ngxDirective keepalive -syn keyword ngxDirective keepalive_disable -syn keyword ngxDirective keepalive_requests -syn keyword ngxDirective keepalive_timeout -syn keyword ngxDirective kqueue_changes -syn keyword ngxDirective kqueue_events -syn keyword ngxDirective large_client_header_buffers -syn keyword ngxDirective least_conn -syn keyword ngxDirective limit_conn -syn keyword ngxDirective limit_conn_log_level -syn keyword ngxDirective limit_conn_status -syn keyword ngxDirective limit_conn_zone -syn keyword ngxDirective limit_rate -syn keyword ngxDirective limit_rate_after -syn keyword ngxDirective limit_req -syn keyword ngxDirective limit_req_log_level -syn keyword ngxDirective limit_req_status -syn keyword ngxDirective limit_req_zone -syn keyword ngxDirective lingering_close -syn keyword ngxDirective lingering_time -syn keyword ngxDirective lingering_timeout -syn keyword ngxDirective lock_file -syn keyword ngxDirective log_format -syn keyword ngxDirective log_not_found -syn keyword ngxDirective log_subrequest -syn keyword ngxDirective map_hash_bucket_size -syn keyword ngxDirective map_hash_max_size -syn keyword ngxDirective master_process -syn keyword ngxDirective max_ranges -syn keyword ngxDirective memcached_bind -syn keyword ngxDirective memcached_buffer_size -syn keyword ngxDirective memcached_connect_timeout -syn keyword ngxDirective memcached_gzip_flag -syn keyword ngxDirective memcached_next_upstream -syn keyword ngxDirective memcached_next_upstream_timeout -syn keyword ngxDirective memcached_next_upstream_tries -syn keyword ngxDirective memcached_read_timeout -syn keyword ngxDirective memcached_send_timeout -syn keyword ngxDirective merge_slashes -syn keyword ngxDirective min_delete_depth -syn keyword ngxDirective modern_browser -syn keyword ngxDirective modern_browser_value -syn keyword ngxDirective mp4 -syn keyword ngxDirective mp4_buffer_size -syn keyword ngxDirective mp4_max_buffer_size -syn keyword ngxDirective msie_padding -syn keyword ngxDirective msie_refresh -syn keyword ngxDirective multi_accept -syn keyword ngxDirective open_file_cache -syn keyword ngxDirective open_file_cache_errors -syn keyword ngxDirective open_file_cache_events -syn keyword ngxDirective open_file_cache_min_uses -syn keyword ngxDirective open_file_cache_valid -syn keyword ngxDirective open_log_file_cache -syn keyword ngxDirective output_buffers -syn keyword ngxDirective override_charset -syn keyword ngxDirective pcre_jit -syn keyword ngxDirective perl -syn keyword ngxDirective perl_modules -syn keyword ngxDirective perl_require -syn keyword ngxDirective perl_set -syn keyword ngxDirective pid -syn keyword ngxDirective pop3_auth -syn keyword ngxDirective pop3_capabilities -syn keyword ngxDirective port_in_redirect -syn keyword ngxDirective post_acceptex -syn keyword ngxDirective postpone_gzipping -syn keyword ngxDirective postpone_output -syn keyword ngxDirective protocol -syn keyword ngxDirective proxy -syn keyword ngxDirective proxy_bind -syn keyword ngxDirective proxy_buffer -syn keyword ngxDirective proxy_buffer_size -syn keyword ngxDirective proxy_buffering -syn keyword ngxDirective proxy_buffers -syn keyword ngxDirective proxy_busy_buffers_size -syn keyword ngxDirective proxy_cache -syn keyword ngxDirective proxy_cache_bypass -syn keyword ngxDirective proxy_cache_key -syn keyword ngxDirective proxy_cache_lock -syn keyword ngxDirective proxy_cache_lock_timeout -syn keyword ngxDirective proxy_cache_methods -syn keyword ngxDirective proxy_cache_min_uses -syn keyword ngxDirective proxy_cache_path -syn keyword ngxDirective proxy_cache_revalidate -syn keyword ngxDirective proxy_cache_use_stale -syn keyword ngxDirective proxy_cache_valid -syn keyword ngxDirective proxy_connect_timeout -syn keyword ngxDirective proxy_cookie_domain -syn keyword ngxDirective proxy_cookie_path -syn keyword ngxDirective proxy_force_ranges -syn keyword ngxDirective proxy_headers_hash_bucket_size -syn keyword ngxDirective proxy_headers_hash_max_size -syn keyword ngxDirective proxy_hide_header -syn keyword ngxDirective proxy_http_version -syn keyword ngxDirective proxy_ignore_client_abort -syn keyword ngxDirective proxy_ignore_headers -syn keyword ngxDirective proxy_intercept_errors -syn keyword ngxDirective proxy_max_temp_file_size -syn keyword ngxDirective proxy_method -syn keyword ngxDirective proxy_next_upstream -syn keyword ngxDirective proxy_next_upstream_timeout -syn keyword ngxDirective proxy_next_upstream_tries -syn keyword ngxDirective proxy_no_cache -syn keyword ngxDirective proxy_pass_error_message -syn keyword ngxDirective proxy_pass_header -syn keyword ngxDirective proxy_pass_request_body -syn keyword ngxDirective proxy_pass_request_headers -syn keyword ngxDirective proxy_read_timeout -syn keyword ngxDirective proxy_redirect -syn keyword ngxDirective proxy_send_lowat -syn keyword ngxDirective proxy_send_timeout -syn keyword ngxDirective proxy_set_body -syn keyword ngxDirective proxy_set_header -syn keyword ngxDirective proxy_ssl_ciphers -syn keyword ngxDirective proxy_ssl_crl -syn keyword ngxDirective proxy_ssl_name -syn keyword ngxDirective proxy_ssl_protocols -syn keyword ngxDirective proxy_ssl_server_name -syn keyword ngxDirective proxy_ssl_session_reuse -syn keyword ngxDirective proxy_ssl_trusted_certificate -syn keyword ngxDirective proxy_ssl_verify -syn keyword ngxDirective proxy_ssl_verify_depth -syn keyword ngxDirective proxy_store -syn keyword ngxDirective proxy_store_access -syn keyword ngxDirective proxy_temp_file_write_size -syn keyword ngxDirective proxy_temp_path -syn keyword ngxDirective proxy_timeout -syn keyword ngxDirective random_index -syn keyword ngxDirective read_ahead -syn keyword ngxDirective real_ip_header -syn keyword ngxDirective real_ip_recursive -syn keyword ngxDirective recursive_error_pages -syn keyword ngxDirective referer_hash_bucket_size -syn keyword ngxDirective referer_hash_max_size -syn keyword ngxDirective request_pool_size -syn keyword ngxDirective reset_timedout_connection -syn keyword ngxDirective resolver -syn keyword ngxDirective resolver_timeout -syn keyword ngxDirective rewrite_log -syn keyword ngxDirective rtsig_overflow_events -syn keyword ngxDirective rtsig_overflow_test -syn keyword ngxDirective rtsig_overflow_threshold -syn keyword ngxDirective rtsig_signo -syn keyword ngxDirective satisfy -syn keyword ngxDirective scgi_bind -syn keyword ngxDirective scgi_buffer_size -syn keyword ngxDirective scgi_buffering -syn keyword ngxDirective scgi_buffers -syn keyword ngxDirective scgi_busy_buffers_size -syn keyword ngxDirective scgi_cache -syn keyword ngxDirective scgi_cache_bypass -syn keyword ngxDirective scgi_cache_key -syn keyword ngxDirective scgi_cache_lock -syn keyword ngxDirective scgi_cache_lock_timeout -syn keyword ngxDirective scgi_cache_methods -syn keyword ngxDirective scgi_cache_min_uses -syn keyword ngxDirective scgi_cache_path -syn keyword ngxDirective scgi_cache_revalidate -syn keyword ngxDirective scgi_cache_use_stale -syn keyword ngxDirective scgi_cache_valid -syn keyword ngxDirective scgi_connect_timeout -syn keyword ngxDirective scgi_force_ranges -syn keyword ngxDirective scgi_hide_header -syn keyword ngxDirective scgi_ignore_client_abort -syn keyword ngxDirective scgi_ignore_headers -syn keyword ngxDirective scgi_intercept_errors -syn keyword ngxDirective scgi_max_temp_file_size -syn keyword ngxDirective scgi_next_upstream -syn keyword ngxDirective scgi_next_upstream_timeout -syn keyword ngxDirective scgi_next_upstream_tries -syn keyword ngxDirective scgi_no_cache -syn keyword ngxDirective scgi_param -syn keyword ngxDirective scgi_pass_header -syn keyword ngxDirective scgi_pass_request_body -syn keyword ngxDirective scgi_pass_request_headers -syn keyword ngxDirective scgi_read_timeout -syn keyword ngxDirective scgi_send_timeout -syn keyword ngxDirective scgi_store -syn keyword ngxDirective scgi_store_access -syn keyword ngxDirective scgi_temp_file_write_size -syn keyword ngxDirective scgi_temp_path -syn keyword ngxDirective secure_link -syn keyword ngxDirective secure_link_md5 -syn keyword ngxDirective secure_link_secret -syn keyword ngxDirective send_lowat -syn keyword ngxDirective send_timeout -syn keyword ngxDirective sendfile -syn keyword ngxDirective sendfile_max_chunk -syn keyword ngxDirective server_name_in_redirect -syn keyword ngxDirective server_names_hash_bucket_size -syn keyword ngxDirective server_names_hash_max_size -syn keyword ngxDirective server_tokens -syn keyword ngxDirective set_real_ip_from -syn keyword ngxDirective smtp_auth -syn keyword ngxDirective smtp_capabilities -syn keyword ngxDirective smtp_client_buffer -syn keyword ngxDirective smtp_greeting_delay -syn keyword ngxDirective source_charset -syn keyword ngxDirective spdy_chunk_size -syn keyword ngxDirective spdy_headers_comp -syn keyword ngxDirective spdy_keepalive_timeout -syn keyword ngxDirective spdy_max_concurrent_streams -syn keyword ngxDirective spdy_pool_size -syn keyword ngxDirective spdy_recv_buffer_size -syn keyword ngxDirective spdy_recv_timeout -syn keyword ngxDirective spdy_streams_index_size -syn keyword ngxDirective ssi -syn keyword ngxDirective ssi_ignore_recycled_buffers -syn keyword ngxDirective ssi_last_modified -syn keyword ngxDirective ssi_min_file_chunk -syn keyword ngxDirective ssi_silent_errors -syn keyword ngxDirective ssi_types -syn keyword ngxDirective ssi_value_length -syn keyword ngxDirective ssl -syn keyword ngxDirective ssl_buffer_size -syn keyword ngxDirective ssl_certificate -syn keyword ngxDirective ssl_certificate_key -syn keyword ngxDirective ssl_ciphers -syn keyword ngxDirective ssl_client_certificate -syn keyword ngxDirective ssl_crl -syn keyword ngxDirective ssl_dhparam -syn keyword ngxDirective ssl_ecdh_curve -syn keyword ngxDirective ssl_engine -syn keyword ngxDirective ssl_password_file -syn keyword ngxDirective ssl_prefer_server_ciphers -syn keyword ngxDirective ssl_protocols -syn keyword ngxDirective ssl_session_cache -syn keyword ngxDirective ssl_session_ticket_key -syn keyword ngxDirective ssl_session_tickets -syn keyword ngxDirective ssl_session_timeout -syn keyword ngxDirective ssl_stapling -syn keyword ngxDirective ssl_stapling_file -syn keyword ngxDirective ssl_stapling_responder -syn keyword ngxDirective ssl_stapling_verify -syn keyword ngxDirective ssl_trusted_certificate -syn keyword ngxDirective ssl_verify_client -syn keyword ngxDirective ssl_verify_depth -syn keyword ngxDirective starttls -syn keyword ngxDirective stub_status -syn keyword ngxDirective sub_filter -syn keyword ngxDirective sub_filter_last_modified -syn keyword ngxDirective sub_filter_once -syn keyword ngxDirective sub_filter_types -syn keyword ngxDirective tcp_nodelay -syn keyword ngxDirective tcp_nopush -syn keyword ngxDirective thread_stack_size -syn keyword ngxDirective timeout -syn keyword ngxDirective timer_resolution -syn keyword ngxDirective types_hash_bucket_size -syn keyword ngxDirective types_hash_max_size -syn keyword ngxDirective underscores_in_headers -syn keyword ngxDirective uninitialized_variable_warn -syn keyword ngxDirective use -syn keyword ngxDirective user -syn keyword ngxDirective userid -syn keyword ngxDirective userid_domain -syn keyword ngxDirective userid_expires -syn keyword ngxDirective userid_mark -syn keyword ngxDirective userid_name -syn keyword ngxDirective userid_p3p -syn keyword ngxDirective userid_path -syn keyword ngxDirective userid_service -syn keyword ngxDirective uwsgi_bind -syn keyword ngxDirective uwsgi_buffer_size -syn keyword ngxDirective uwsgi_buffering -syn keyword ngxDirective uwsgi_buffers -syn keyword ngxDirective uwsgi_busy_buffers_size -syn keyword ngxDirective uwsgi_cache -syn keyword ngxDirective uwsgi_cache_bypass -syn keyword ngxDirective uwsgi_cache_key -syn keyword ngxDirective uwsgi_cache_lock -syn keyword ngxDirective uwsgi_cache_lock_timeout -syn keyword ngxDirective uwsgi_cache_methods -syn keyword ngxDirective uwsgi_cache_min_uses -syn keyword ngxDirective uwsgi_cache_path -syn keyword ngxDirective uwsgi_cache_revalidate -syn keyword ngxDirective uwsgi_cache_use_stale -syn keyword ngxDirective uwsgi_cache_valid -syn keyword ngxDirective uwsgi_connect_timeout -syn keyword ngxDirective uwsgi_force_ranges -syn keyword ngxDirective uwsgi_hide_header -syn keyword ngxDirective uwsgi_ignore_client_abort -syn keyword ngxDirective uwsgi_ignore_headers -syn keyword ngxDirective uwsgi_intercept_errors -syn keyword ngxDirective uwsgi_max_temp_file_size -syn keyword ngxDirective uwsgi_modifier1 -syn keyword ngxDirective uwsgi_modifier2 -syn keyword ngxDirective uwsgi_next_upstream -syn keyword ngxDirective uwsgi_next_upstream_timeout -syn keyword ngxDirective uwsgi_next_upstream_tries -syn keyword ngxDirective uwsgi_no_cache -syn keyword ngxDirective uwsgi_param -syn keyword ngxDirective uwsgi_pass_header -syn keyword ngxDirective uwsgi_pass_request_body -syn keyword ngxDirective uwsgi_pass_request_headers -syn keyword ngxDirective uwsgi_read_timeout -syn keyword ngxDirective uwsgi_send_timeout -syn keyword ngxDirective uwsgi_ssl_ciphers -syn keyword ngxDirective uwsgi_ssl_crl -syn keyword ngxDirective uwsgi_ssl_name -syn keyword ngxDirective uwsgi_ssl_protocols -syn keyword ngxDirective uwsgi_ssl_server_name -syn keyword ngxDirective uwsgi_ssl_session_reuse -syn keyword ngxDirective uwsgi_ssl_trusted_certificate -syn keyword ngxDirective uwsgi_ssl_verify -syn keyword ngxDirective uwsgi_ssl_verify_depth -syn keyword ngxDirective uwsgi_store -syn keyword ngxDirective uwsgi_store_access -syn keyword ngxDirective uwsgi_string -syn keyword ngxDirective uwsgi_temp_file_write_size -syn keyword ngxDirective uwsgi_temp_path -syn keyword ngxDirective valid_referers -syn keyword ngxDirective variables_hash_bucket_size -syn keyword ngxDirective variables_hash_max_size -syn keyword ngxDirective worker_aio_requests -syn keyword ngxDirective worker_connections -syn keyword ngxDirective worker_cpu_affinity -syn keyword ngxDirective worker_priority -syn keyword ngxDirective worker_processes -syn keyword ngxDirective worker_rlimit_core -syn keyword ngxDirective worker_rlimit_nofile -syn keyword ngxDirective worker_rlimit_sigpending -syn keyword ngxDirective worker_threads -syn keyword ngxDirective working_directory -syn keyword ngxDirective xclient -syn keyword ngxDirective xml_entities -syn keyword ngxDirective xslt_last_modified -syn keyword ngxDirective xslt_param -syn keyword ngxDirective xslt_string_param -syn keyword ngxDirective xslt_stylesheet -syn keyword ngxDirective xslt_types + +syn cluster ngxTopLevel + \ contains=ngxName,ngxString,ngxComment +syn cluster ngxDirectives + \ contains=ngxDirective,ngxDirectiveBlock,ngxDirectiveImportant + \ add=ngxDirectiveControl,ngxDirectiveError,ngxDirectiveDeprecated + \ add=ngxDirectiveThirdParty +syn cluster ngxParams + \ contains=ngxParam,ngxString,ngxParamComment,ngxSemicolon,ngxBlock + +" boolean parameters + +syn keyword ngxBoolean contained on off + \ nextgroup=@ngxParams skipwhite skipempty +syn cluster ngxParams add=ngxBoolean + +" listen directive + +syn cluster ngxTopLevel add=ngxDirectiveListen +syn keyword ngxDirectiveListen listen + \ nextgroup=@ngxListenParams skipwhite skipempty +syn match ngxListenParam '\([^;{ \t\\]\|\\.\)\+' + \ contained + \ nextgroup=@ngxListenParams skipwhite skipempty +syn region ngxListenString start=+\z(["']\)+ end=+\z1+ skip=+\\\\\|\\\z1+ + \ contained + \ nextgroup=@ngxListenParams skipwhite skipempty +syn match ngxListenComment '#.*$' + \ contained + \ nextgroup=@ngxListenParams skipwhite skipempty +syn keyword ngxListenOptions contained + \ default_server ssl http2 spdy proxy_protocol + \ setfib fastopen backlog rcvbuf sndbuf accept_filter deferred bind + \ ipv6only reuseport so_keepalive keepidle + \ nextgroup=@ngxListenParams skipwhite skipempty +syn cluster ngxListenParams + \ contains=ngxListenParam,ngxListenString,ngxListenComment + \ add=ngxListenOptions + +syn keyword ngxDirectiveBlock contained http +syn keyword ngxDirectiveBlock contained mail +syn keyword ngxDirectiveBlock contained events +syn keyword ngxDirectiveBlock contained server +syn keyword ngxDirectiveBlock contained types +syn keyword ngxDirectiveBlock contained location +syn keyword ngxDirectiveBlock contained upstream +syn keyword ngxDirectiveBlock contained charset_map +syn keyword ngxDirectiveBlock contained limit_except +syn keyword ngxDirectiveBlock contained if +syn keyword ngxDirectiveBlock contained geo +syn keyword ngxDirectiveBlock contained map +syn keyword ngxDirectiveBlock contained split_clients + +syn keyword ngxDirectiveImportant contained include +syn keyword ngxDirectiveImportant contained root +"syn keyword ngxDirectiveImportant contained server +syn keyword ngxDirectiveImportant contained server_name +"syn keyword ngxDirectiveImportant contained listen +syn keyword ngxDirectiveImportant contained internal +syn keyword ngxDirectiveImportant contained proxy_pass +syn keyword ngxDirectiveImportant contained memcached_pass +syn keyword ngxDirectiveImportant contained fastcgi_pass +syn keyword ngxDirectiveImportant contained scgi_pass +syn keyword ngxDirectiveImportant contained uwsgi_pass +syn keyword ngxDirectiveImportant contained try_files + +syn keyword ngxDirectiveControl contained break +syn keyword ngxDirectiveControl contained return +syn keyword ngxDirectiveControl contained rewrite +syn keyword ngxDirectiveControl contained set + +syn keyword ngxDirectiveError contained error_page +syn keyword ngxDirectiveError contained post_action + +syn keyword ngxDirectiveDeprecated contained connections +syn keyword ngxDirectiveDeprecated contained imap +syn keyword ngxDirectiveDeprecated contained limit_zone +syn keyword ngxDirectiveDeprecated contained mysql_test +syn keyword ngxDirectiveDeprecated contained open_file_cache_retest +syn keyword ngxDirectiveDeprecated contained optimize_server_names +syn keyword ngxDirectiveDeprecated contained satisfy_any +syn keyword ngxDirectiveDeprecated contained so_keepalive + +syn keyword ngxDirective contained absolute_redirect +syn keyword ngxDirective contained accept_mutex +syn keyword ngxDirective contained accept_mutex_delay +syn keyword ngxDirective contained acceptex_read +syn keyword ngxDirective contained access_log +syn keyword ngxDirective contained add_after_body +syn keyword ngxDirective contained add_before_body +syn keyword ngxDirective contained add_header +syn keyword ngxDirective contained addition_types +syn keyword ngxDirective contained aio +syn keyword ngxDirective contained aio_write +syn keyword ngxDirective contained alias +syn keyword ngxDirective contained allow +syn keyword ngxDirective contained ancient_browser +syn keyword ngxDirective contained ancient_browser_value +syn keyword ngxDirective contained auth_basic +syn keyword ngxDirective contained auth_basic_user_file +syn keyword ngxDirective contained auth_http +syn keyword ngxDirective contained auth_http_header +syn keyword ngxDirective contained auth_http_pass_client_cert +syn keyword ngxDirective contained auth_http_timeout +syn keyword ngxDirective contained auth_jwt +syn keyword ngxDirective contained auth_jwt_key_file +syn keyword ngxDirective contained auth_request +syn keyword ngxDirective contained auth_request_set +syn keyword ngxDirective contained autoindex +syn keyword ngxDirective contained autoindex_exact_size +syn keyword ngxDirective contained autoindex_format +syn keyword ngxDirective contained autoindex_localtime +syn keyword ngxDirective contained charset +syn keyword ngxDirective contained charset_map +syn keyword ngxDirective contained charset_types +syn keyword ngxDirective contained chunked_transfer_encoding +syn keyword ngxDirective contained client_body_buffer_size +syn keyword ngxDirective contained client_body_in_file_only +syn keyword ngxDirective contained client_body_in_single_buffer +syn keyword ngxDirective contained client_body_temp_path +syn keyword ngxDirective contained client_body_timeout +syn keyword ngxDirective contained client_header_buffer_size +syn keyword ngxDirective contained client_header_timeout +syn keyword ngxDirective contained client_max_body_size +syn keyword ngxDirective contained connection_pool_size +syn keyword ngxDirective contained create_full_put_path +syn keyword ngxDirective contained daemon +syn keyword ngxDirective contained dav_access +syn keyword ngxDirective contained dav_methods +syn keyword ngxDirective contained debug_connection +syn keyword ngxDirective contained debug_points +syn keyword ngxDirective contained default_type +syn keyword ngxDirective contained degradation +syn keyword ngxDirective contained degrade +syn keyword ngxDirective contained deny +syn keyword ngxDirective contained devpoll_changes +syn keyword ngxDirective contained devpoll_events +syn keyword ngxDirective contained directio +syn keyword ngxDirective contained directio_alignment +syn keyword ngxDirective contained disable_symlinks +syn keyword ngxDirective contained empty_gif +syn keyword ngxDirective contained env +syn keyword ngxDirective contained epoll_events +syn keyword ngxDirective contained error_log +syn keyword ngxDirective contained etag +syn keyword ngxDirective contained eventport_events +syn keyword ngxDirective contained expires +syn keyword ngxDirective contained f4f +syn keyword ngxDirective contained f4f_buffer_size +syn keyword ngxDirective contained fastcgi_bind +syn keyword ngxDirective contained fastcgi_buffer_size +syn keyword ngxDirective contained fastcgi_buffering +syn keyword ngxDirective contained fastcgi_buffers +syn keyword ngxDirective contained fastcgi_busy_buffers_size +syn keyword ngxDirective contained fastcgi_cache +syn keyword ngxDirective contained fastcgi_cache_bypass +syn keyword ngxDirective contained fastcgi_cache_key +syn keyword ngxDirective contained fastcgi_cache_lock +syn keyword ngxDirective contained fastcgi_cache_lock_age +syn keyword ngxDirective contained fastcgi_cache_lock_timeout +syn keyword ngxDirective contained fastcgi_cache_max_range_offset +syn keyword ngxDirective contained fastcgi_cache_methods +syn keyword ngxDirective contained fastcgi_cache_min_uses +syn keyword ngxDirective contained fastcgi_cache_path +syn keyword ngxDirective contained fastcgi_cache_purge +syn keyword ngxDirective contained fastcgi_cache_revalidate +syn keyword ngxDirective contained fastcgi_cache_use_stale +syn keyword ngxDirective contained fastcgi_cache_valid +syn keyword ngxDirective contained fastcgi_catch_stderr +syn keyword ngxDirective contained fastcgi_connect_timeout +syn keyword ngxDirective contained fastcgi_force_ranges +syn keyword ngxDirective contained fastcgi_hide_header +syn keyword ngxDirective contained fastcgi_ignore_client_abort +syn keyword ngxDirective contained fastcgi_ignore_headers +syn keyword ngxDirective contained fastcgi_index +syn keyword ngxDirective contained fastcgi_intercept_errors +syn keyword ngxDirective contained fastcgi_keep_conn +syn keyword ngxDirective contained fastcgi_limit_rate +syn keyword ngxDirective contained fastcgi_max_temp_file_size +syn keyword ngxDirective contained fastcgi_next_upstream +syn keyword ngxDirective contained fastcgi_next_upstream_timeout +syn keyword ngxDirective contained fastcgi_next_upstream_tries +syn keyword ngxDirective contained fastcgi_no_cache +syn keyword ngxDirective contained fastcgi_param +syn keyword ngxDirective contained fastcgi_pass_header +syn keyword ngxDirective contained fastcgi_pass_request_body +syn keyword ngxDirective contained fastcgi_pass_request_headers +syn keyword ngxDirective contained fastcgi_read_timeout +syn keyword ngxDirective contained fastcgi_request_buffering +syn keyword ngxDirective contained fastcgi_send_lowat +syn keyword ngxDirective contained fastcgi_send_timeout +syn keyword ngxDirective contained fastcgi_split_path_info +syn keyword ngxDirective contained fastcgi_store +syn keyword ngxDirective contained fastcgi_store_access +syn keyword ngxDirective contained fastcgi_temp_file_write_size +syn keyword ngxDirective contained fastcgi_temp_path +syn keyword ngxDirective contained flv +syn keyword ngxDirective contained geoip_city +syn keyword ngxDirective contained geoip_country +syn keyword ngxDirective contained geoip_org +syn keyword ngxDirective contained geoip_proxy +syn keyword ngxDirective contained geoip_proxy_recursive +syn keyword ngxDirective contained google_perftools_profiles +syn keyword ngxDirective contained gunzip +syn keyword ngxDirective contained gunzip_buffers +syn keyword ngxDirective contained gzip +syn keyword ngxDirective contained gzip_buffers +syn keyword ngxDirective contained gzip_comp_level +syn keyword ngxDirective contained gzip_disable +syn keyword ngxDirective contained gzip_hash +syn keyword ngxDirective contained gzip_http_version +syn keyword ngxDirective contained gzip_min_length +syn keyword ngxDirective contained gzip_no_buffer +syn keyword ngxDirective contained gzip_proxied +syn keyword ngxDirective contained gzip_static +syn keyword ngxDirective contained gzip_types +syn keyword ngxDirective contained gzip_vary +syn keyword ngxDirective contained gzip_window +syn keyword ngxDirective contained hash +syn keyword ngxDirective contained health_check +syn keyword ngxDirective contained health_check_timeout +syn keyword ngxDirective contained hls +syn keyword ngxDirective contained hls_buffers +syn keyword ngxDirective contained hls_forward_args +syn keyword ngxDirective contained hls_fragment +syn keyword ngxDirective contained hls_mp4_buffer_size +syn keyword ngxDirective contained hls_mp4_max_buffer_size +syn keyword ngxDirective contained http2_chunk_size +syn keyword ngxDirective contained http2_body_preread_size +syn keyword ngxDirective contained http2_idle_timeout +syn keyword ngxDirective contained http2_max_concurrent_streams +syn keyword ngxDirective contained http2_max_field_size +syn keyword ngxDirective contained http2_max_header_size +syn keyword ngxDirective contained http2_max_requests +syn keyword ngxDirective contained http2_recv_buffer_size +syn keyword ngxDirective contained http2_recv_timeout +syn keyword ngxDirective contained if_modified_since +syn keyword ngxDirective contained ignore_invalid_headers +syn keyword ngxDirective contained image_filter +syn keyword ngxDirective contained image_filter_buffer +syn keyword ngxDirective contained image_filter_interlace +syn keyword ngxDirective contained image_filter_jpeg_quality +syn keyword ngxDirective contained image_filter_sharpen +syn keyword ngxDirective contained image_filter_transparency +syn keyword ngxDirective contained image_filter_webp_quality +syn keyword ngxDirective contained imap_auth +syn keyword ngxDirective contained imap_capabilities +syn keyword ngxDirective contained imap_client_buffer +syn keyword ngxDirective contained index +syn keyword ngxDirective contained iocp_threads +syn keyword ngxDirective contained ip_hash +syn keyword ngxDirective contained js_access +syn keyword ngxDirective contained js_content +syn keyword ngxDirective contained js_filter +syn keyword ngxDirective contained js_include +syn keyword ngxDirective contained js_preread +syn keyword ngxDirective contained js_set +syn keyword ngxDirective contained keepalive +syn keyword ngxDirective contained keepalive_disable +syn keyword ngxDirective contained keepalive_requests +syn keyword ngxDirective contained keepalive_timeout +syn keyword ngxDirective contained kqueue_changes +syn keyword ngxDirective contained kqueue_events +syn keyword ngxDirective contained large_client_header_buffers +syn keyword ngxDirective contained least_conn +syn keyword ngxDirective contained least_time +syn keyword ngxDirective contained limit_conn +syn keyword ngxDirective contained limit_conn_log_level +syn keyword ngxDirective contained limit_conn_status +syn keyword ngxDirective contained limit_conn_zone +syn keyword ngxDirective contained limit_rate +syn keyword ngxDirective contained limit_rate_after +syn keyword ngxDirective contained limit_req +syn keyword ngxDirective contained limit_req_log_level +syn keyword ngxDirective contained limit_req_status +syn keyword ngxDirective contained limit_req_zone +syn keyword ngxDirective contained lingering_close +syn keyword ngxDirective contained lingering_time +syn keyword ngxDirective contained lingering_timeout +syn keyword ngxDirective contained load_module +syn keyword ngxDirective contained lock_file +syn keyword ngxDirective contained log_format +syn keyword ngxDirective contained log_not_found +syn keyword ngxDirective contained log_subrequest +syn keyword ngxDirective contained map_hash_bucket_size +syn keyword ngxDirective contained map_hash_max_size +syn keyword ngxDirective contained match +syn keyword ngxDirective contained master_process +syn keyword ngxDirective contained max_ranges +syn keyword ngxDirective contained memcached_bind +syn keyword ngxDirective contained memcached_buffer_size +syn keyword ngxDirective contained memcached_connect_timeout +syn keyword ngxDirective contained memcached_force_ranges +syn keyword ngxDirective contained memcached_gzip_flag +syn keyword ngxDirective contained memcached_next_upstream +syn keyword ngxDirective contained memcached_next_upstream_timeout +syn keyword ngxDirective contained memcached_next_upstream_tries +syn keyword ngxDirective contained memcached_read_timeout +syn keyword ngxDirective contained memcached_send_timeout +syn keyword ngxDirective contained merge_slashes +syn keyword ngxDirective contained min_delete_depth +syn keyword ngxDirective contained modern_browser +syn keyword ngxDirective contained modern_browser_value +syn keyword ngxDirective contained mp4 +syn keyword ngxDirective contained mp4_buffer_size +syn keyword ngxDirective contained mp4_max_buffer_size +syn keyword ngxDirective contained mp4_limit_rate +syn keyword ngxDirective contained mp4_limit_rate_after +syn keyword ngxDirective contained msie_padding +syn keyword ngxDirective contained msie_refresh +syn keyword ngxDirective contained multi_accept +syn keyword ngxDirective contained ntlm +syn keyword ngxDirective contained open_file_cache +syn keyword ngxDirective contained open_file_cache_errors +syn keyword ngxDirective contained open_file_cache_events +syn keyword ngxDirective contained open_file_cache_min_uses +syn keyword ngxDirective contained open_file_cache_valid +syn keyword ngxDirective contained open_log_file_cache +syn keyword ngxDirective contained output_buffers +syn keyword ngxDirective contained override_charset +syn keyword ngxDirective contained pcre_jit +syn keyword ngxDirective contained perl +syn keyword ngxDirective contained perl_modules +syn keyword ngxDirective contained perl_require +syn keyword ngxDirective contained perl_set +syn keyword ngxDirective contained pid +syn keyword ngxDirective contained pop3_auth +syn keyword ngxDirective contained pop3_capabilities +syn keyword ngxDirective contained port_in_redirect +syn keyword ngxDirective contained post_acceptex +syn keyword ngxDirective contained postpone_gzipping +syn keyword ngxDirective contained postpone_output +syn keyword ngxDirective contained preread_buffer_size +syn keyword ngxDirective contained preread_timeout +syn keyword ngxDirective contained protocol +syn keyword ngxDirective contained proxy +syn keyword ngxDirective contained proxy_bind +syn keyword ngxDirective contained proxy_buffer +syn keyword ngxDirective contained proxy_buffer_size +syn keyword ngxDirective contained proxy_buffering +syn keyword ngxDirective contained proxy_buffers +syn keyword ngxDirective contained proxy_busy_buffers_size +syn keyword ngxDirective contained proxy_cache +syn keyword ngxDirective contained proxy_cache_bypass +syn keyword ngxDirective contained proxy_cache_convert_head +syn keyword ngxDirective contained proxy_cache_key +syn keyword ngxDirective contained proxy_cache_lock +syn keyword ngxDirective contained proxy_cache_lock_age +syn keyword ngxDirective contained proxy_cache_lock_timeout +syn keyword ngxDirective contained proxy_cache_max_range_offset +syn keyword ngxDirective contained proxy_cache_methods +syn keyword ngxDirective contained proxy_cache_min_uses +syn keyword ngxDirective contained proxy_cache_path +syn keyword ngxDirective contained proxy_cache_purge +syn keyword ngxDirective contained proxy_cache_revalidate +syn keyword ngxDirective contained proxy_cache_use_stale +syn keyword ngxDirective contained proxy_cache_valid +syn keyword ngxDirective contained proxy_connect_timeout +syn keyword ngxDirective contained proxy_cookie_domain +syn keyword ngxDirective contained proxy_cookie_path +syn keyword ngxDirective contained proxy_download_rate +syn keyword ngxDirective contained proxy_force_ranges +syn keyword ngxDirective contained proxy_headers_hash_bucket_size +syn keyword ngxDirective contained proxy_headers_hash_max_size +syn keyword ngxDirective contained proxy_hide_header +syn keyword ngxDirective contained proxy_http_version +syn keyword ngxDirective contained proxy_ignore_client_abort +syn keyword ngxDirective contained proxy_ignore_headers +syn keyword ngxDirective contained proxy_intercept_errors +syn keyword ngxDirective contained proxy_limit_rate +syn keyword ngxDirective contained proxy_max_temp_file_size +syn keyword ngxDirective contained proxy_method +syn keyword ngxDirective contained proxy_next_upstream +syn keyword ngxDirective contained proxy_next_upstream_timeout +syn keyword ngxDirective contained proxy_next_upstream_tries +syn keyword ngxDirective contained proxy_no_cache +syn keyword ngxDirective contained proxy_pass_error_message +syn keyword ngxDirective contained proxy_pass_header +syn keyword ngxDirective contained proxy_pass_request_body +syn keyword ngxDirective contained proxy_pass_request_headers +syn keyword ngxDirective contained proxy_protocol +syn keyword ngxDirective contained proxy_protocol_timeout +syn keyword ngxDirective contained proxy_read_timeout +syn keyword ngxDirective contained proxy_redirect +syn keyword ngxDirective contained proxy_request_buffering +syn keyword ngxDirective contained proxy_responses +syn keyword ngxDirective contained proxy_send_lowat +syn keyword ngxDirective contained proxy_send_timeout +syn keyword ngxDirective contained proxy_set_body +syn keyword ngxDirective contained proxy_set_header +syn keyword ngxDirective contained proxy_ssl_certificate +syn keyword ngxDirective contained proxy_ssl_certificate_key +syn keyword ngxDirective contained proxy_ssl_ciphers +syn keyword ngxDirective contained proxy_ssl_crl +syn keyword ngxDirective contained proxy_ssl_name +syn keyword ngxDirective contained proxy_ssl_password_file +syn keyword ngxDirective contained proxy_ssl_protocols +syn keyword ngxDirective contained proxy_ssl_server_name +syn keyword ngxDirective contained proxy_ssl_session_reuse +syn keyword ngxDirective contained proxy_ssl_trusted_certificate +syn keyword ngxDirective contained proxy_ssl_verify +syn keyword ngxDirective contained proxy_ssl_verify_depth +syn keyword ngxDirective contained proxy_store +syn keyword ngxDirective contained proxy_store_access +syn keyword ngxDirective contained proxy_temp_file_write_size +syn keyword ngxDirective contained proxy_temp_path +syn keyword ngxDirective contained proxy_timeout +syn keyword ngxDirective contained proxy_upload_rate +syn keyword ngxDirective contained queue +syn keyword ngxDirective contained random_index +syn keyword ngxDirective contained read_ahead +syn keyword ngxDirective contained real_ip_header +syn keyword ngxDirective contained real_ip_recursive +syn keyword ngxDirective contained recursive_error_pages +syn keyword ngxDirective contained referer_hash_bucket_size +syn keyword ngxDirective contained referer_hash_max_size +syn keyword ngxDirective contained request_pool_size +syn keyword ngxDirective contained reset_timedout_connection +syn keyword ngxDirective contained resolver +syn keyword ngxDirective contained resolver_timeout +syn keyword ngxDirective contained rewrite_log +syn keyword ngxDirective contained rtsig_overflow_events +syn keyword ngxDirective contained rtsig_overflow_test +syn keyword ngxDirective contained rtsig_overflow_threshold +syn keyword ngxDirective contained rtsig_signo +syn keyword ngxDirective contained satisfy +syn keyword ngxDirective contained scgi_bind +syn keyword ngxDirective contained scgi_buffer_size +syn keyword ngxDirective contained scgi_buffering +syn keyword ngxDirective contained scgi_buffers +syn keyword ngxDirective contained scgi_busy_buffers_size +syn keyword ngxDirective contained scgi_cache +syn keyword ngxDirective contained scgi_cache_bypass +syn keyword ngxDirective contained scgi_cache_key +syn keyword ngxDirective contained scgi_cache_lock +syn keyword ngxDirective contained scgi_cache_lock_age +syn keyword ngxDirective contained scgi_cache_lock_timeout +syn keyword ngxDirective contained scgi_cache_max_range_offset +syn keyword ngxDirective contained scgi_cache_methods +syn keyword ngxDirective contained scgi_cache_min_uses +syn keyword ngxDirective contained scgi_cache_path +syn keyword ngxDirective contained scgi_cache_purge +syn keyword ngxDirective contained scgi_cache_revalidate +syn keyword ngxDirective contained scgi_cache_use_stale +syn keyword ngxDirective contained scgi_cache_valid +syn keyword ngxDirective contained scgi_connect_timeout +syn keyword ngxDirective contained scgi_force_ranges +syn keyword ngxDirective contained scgi_hide_header +syn keyword ngxDirective contained scgi_ignore_client_abort +syn keyword ngxDirective contained scgi_ignore_headers +syn keyword ngxDirective contained scgi_intercept_errors +syn keyword ngxDirective contained scgi_limit_rate +syn keyword ngxDirective contained scgi_max_temp_file_size +syn keyword ngxDirective contained scgi_next_upstream +syn keyword ngxDirective contained scgi_next_upstream_timeout +syn keyword ngxDirective contained scgi_next_upstream_tries +syn keyword ngxDirective contained scgi_no_cache +syn keyword ngxDirective contained scgi_param +syn keyword ngxDirective contained scgi_pass_header +syn keyword ngxDirective contained scgi_pass_request_body +syn keyword ngxDirective contained scgi_pass_request_headers +syn keyword ngxDirective contained scgi_read_timeout +syn keyword ngxDirective contained scgi_request_buffering +syn keyword ngxDirective contained scgi_send_timeout +syn keyword ngxDirective contained scgi_store +syn keyword ngxDirective contained scgi_store_access +syn keyword ngxDirective contained scgi_temp_file_write_size +syn keyword ngxDirective contained scgi_temp_path +syn keyword ngxDirective contained secure_link +syn keyword ngxDirective contained secure_link_md5 +syn keyword ngxDirective contained secure_link_secret +syn keyword ngxDirective contained send_lowat +syn keyword ngxDirective contained send_timeout +syn keyword ngxDirective contained sendfile +syn keyword ngxDirective contained sendfile_max_chunk +syn keyword ngxDirective contained server_name_in_redirect +syn keyword ngxDirective contained server_names_hash_bucket_size +syn keyword ngxDirective contained server_names_hash_max_size +syn keyword ngxDirective contained server_tokens +syn keyword ngxDirective contained session_log +syn keyword ngxDirective contained session_log_format +syn keyword ngxDirective contained session_log_zone +syn keyword ngxDirective contained set_real_ip_from +syn keyword ngxDirective contained slice +syn keyword ngxDirective contained smtp_auth +syn keyword ngxDirective contained smtp_capabilities +syn keyword ngxDirective contained smtp_client_buffer +syn keyword ngxDirective contained smtp_greeting_delay +syn keyword ngxDirective contained source_charset +syn keyword ngxDirective contained spdy_chunk_size +syn keyword ngxDirective contained spdy_headers_comp +syn keyword ngxDirective contained spdy_keepalive_timeout +syn keyword ngxDirective contained spdy_max_concurrent_streams +syn keyword ngxDirective contained spdy_pool_size +syn keyword ngxDirective contained spdy_recv_buffer_size +syn keyword ngxDirective contained spdy_recv_timeout +syn keyword ngxDirective contained spdy_streams_index_size +syn keyword ngxDirective contained ssi +syn keyword ngxDirective contained ssi_ignore_recycled_buffers +syn keyword ngxDirective contained ssi_last_modified +syn keyword ngxDirective contained ssi_min_file_chunk +syn keyword ngxDirective contained ssi_silent_errors +syn keyword ngxDirective contained ssi_types +syn keyword ngxDirective contained ssi_value_length +syn keyword ngxDirective contained ssl +syn keyword ngxDirective contained ssl_buffer_size +syn keyword ngxDirective contained ssl_certificate +syn keyword ngxDirective contained ssl_certificate_key +syn keyword ngxDirective contained ssl_ciphers +syn keyword ngxDirective contained ssl_client_certificate +syn keyword ngxDirective contained ssl_crl +syn keyword ngxDirective contained ssl_dhparam +syn keyword ngxDirective contained ssl_ecdh_curve +syn keyword ngxDirective contained ssl_engine +syn keyword ngxDirective contained ssl_handshake_timeout +syn keyword ngxDirective contained ssl_password_file +syn keyword ngxDirective contained ssl_prefer_server_ciphers +syn keyword ngxDirective contained ssl_preread +syn keyword ngxDirective contained ssl_protocols +syn keyword ngxDirective contained ssl_session_cache +syn keyword ngxDirective contained ssl_session_ticket_key +syn keyword ngxDirective contained ssl_session_tickets +syn keyword ngxDirective contained ssl_session_timeout +syn keyword ngxDirective contained ssl_stapling +syn keyword ngxDirective contained ssl_stapling_file +syn keyword ngxDirective contained ssl_stapling_responder +syn keyword ngxDirective contained ssl_stapling_verify +syn keyword ngxDirective contained ssl_trusted_certificate +syn keyword ngxDirective contained ssl_verify_client +syn keyword ngxDirective contained ssl_verify_depth +syn keyword ngxDirective contained starttls +syn keyword ngxDirective contained state +syn keyword ngxDirective contained status +syn keyword ngxDirective contained status_format +syn keyword ngxDirective contained status_zone +syn keyword ngxDirective contained sticky +syn keyword ngxDirective contained sticky_cookie_insert +syn keyword ngxDirective contained stub_status +syn keyword ngxDirective contained sub_filter +syn keyword ngxDirective contained sub_filter_last_modified +syn keyword ngxDirective contained sub_filter_once +syn keyword ngxDirective contained sub_filter_types +syn keyword ngxDirective contained tcp_nodelay +syn keyword ngxDirective contained tcp_nopush +syn keyword ngxDirective contained thread_pool +syn keyword ngxDirective contained thread_stack_size +syn keyword ngxDirective contained timeout +syn keyword ngxDirective contained timer_resolution +syn keyword ngxDirective contained types_hash_bucket_size +syn keyword ngxDirective contained types_hash_max_size +syn keyword ngxDirective contained underscores_in_headers +syn keyword ngxDirective contained uninitialized_variable_warn +syn keyword ngxDirective contained upstream_conf +syn keyword ngxDirective contained use +syn keyword ngxDirective contained user +syn keyword ngxDirective contained userid +syn keyword ngxDirective contained userid_domain +syn keyword ngxDirective contained userid_expires +syn keyword ngxDirective contained userid_mark +syn keyword ngxDirective contained userid_name +syn keyword ngxDirective contained userid_p3p +syn keyword ngxDirective contained userid_path +syn keyword ngxDirective contained userid_service +syn keyword ngxDirective contained uwsgi_bind +syn keyword ngxDirective contained uwsgi_buffer_size +syn keyword ngxDirective contained uwsgi_buffering +syn keyword ngxDirective contained uwsgi_buffers +syn keyword ngxDirective contained uwsgi_busy_buffers_size +syn keyword ngxDirective contained uwsgi_cache +syn keyword ngxDirective contained uwsgi_cache_bypass +syn keyword ngxDirective contained uwsgi_cache_key +syn keyword ngxDirective contained uwsgi_cache_lock +syn keyword ngxDirective contained uwsgi_cache_lock_age +syn keyword ngxDirective contained uwsgi_cache_lock_timeout +syn keyword ngxDirective contained uwsgi_cache_methods +syn keyword ngxDirective contained uwsgi_cache_min_uses +syn keyword ngxDirective contained uwsgi_cache_path +syn keyword ngxDirective contained uwsgi_cache_purge +syn keyword ngxDirective contained uwsgi_cache_revalidate +syn keyword ngxDirective contained uwsgi_cache_use_stale +syn keyword ngxDirective contained uwsgi_cache_valid +syn keyword ngxDirective contained uwsgi_connect_timeout +syn keyword ngxDirective contained uwsgi_force_ranges +syn keyword ngxDirective contained uwsgi_hide_header +syn keyword ngxDirective contained uwsgi_ignore_client_abort +syn keyword ngxDirective contained uwsgi_ignore_headers +syn keyword ngxDirective contained uwsgi_intercept_errors +syn keyword ngxDirective contained uwsgi_limit_rate +syn keyword ngxDirective contained uwsgi_max_temp_file_size +syn keyword ngxDirective contained uwsgi_modifier1 +syn keyword ngxDirective contained uwsgi_modifier2 +syn keyword ngxDirective contained uwsgi_next_upstream +syn keyword ngxDirective contained uwsgi_next_upstream_timeout +syn keyword ngxDirective contained uwsgi_next_upstream_tries +syn keyword ngxDirective contained uwsgi_no_cache +syn keyword ngxDirective contained uwsgi_param +syn keyword ngxDirective contained uwsgi_pass +syn keyword ngxDirective contained uwsgi_pass_header +syn keyword ngxDirective contained uwsgi_pass_request_body +syn keyword ngxDirective contained uwsgi_pass_request_headers +syn keyword ngxDirective contained uwsgi_read_timeout +syn keyword ngxDirective contained uwsgi_request_buffering +syn keyword ngxDirective contained uwsgi_send_timeout +syn keyword ngxDirective contained uwsgi_ssl_certificate +syn keyword ngxDirective contained uwsgi_ssl_certificate_key +syn keyword ngxDirective contained uwsgi_ssl_ciphers +syn keyword ngxDirective contained uwsgi_ssl_crl +syn keyword ngxDirective contained uwsgi_ssl_name +syn keyword ngxDirective contained uwsgi_ssl_password_file +syn keyword ngxDirective contained uwsgi_ssl_protocols +syn keyword ngxDirective contained uwsgi_ssl_server_name +syn keyword ngxDirective contained uwsgi_ssl_session_reuse +syn keyword ngxDirective contained uwsgi_ssl_trusted_certificate +syn keyword ngxDirective contained uwsgi_ssl_verify +syn keyword ngxDirective contained uwsgi_ssl_verify_depth +syn keyword ngxDirective contained uwsgi_store +syn keyword ngxDirective contained uwsgi_store_access +syn keyword ngxDirective contained uwsgi_string +syn keyword ngxDirective contained uwsgi_temp_file_write_size +syn keyword ngxDirective contained uwsgi_temp_path +syn keyword ngxDirective contained valid_referers +syn keyword ngxDirective contained variables_hash_bucket_size +syn keyword ngxDirective contained variables_hash_max_size +syn keyword ngxDirective contained worker_aio_requests +syn keyword ngxDirective contained worker_connections +syn keyword ngxDirective contained worker_cpu_affinity +syn keyword ngxDirective contained worker_priority +syn keyword ngxDirective contained worker_processes +syn keyword ngxDirective contained worker_rlimit_core +syn keyword ngxDirective contained worker_rlimit_nofile +syn keyword ngxDirective contained worker_rlimit_sigpending +syn keyword ngxDirective contained worker_threads +syn keyword ngxDirective contained working_directory +syn keyword ngxDirective contained xclient +syn keyword ngxDirective contained xml_entities +syn keyword ngxDirective contained xslt_last_modified +syn keyword ngxDirective contained xslt_param +syn keyword ngxDirective contained xslt_string_param +syn keyword ngxDirective contained xslt_stylesheet +syn keyword ngxDirective contained xslt_types +syn keyword ngxDirective contained zone " 3rd party module list: -" http://wiki.nginx.org/Nginx3rdPartyModules +" https://www.nginx.com/resources/wiki/modules/ -" Accept Language Module +" Accept Language Module " Parses the Accept-Language header and gives the most suitable locale from a list of supported locales. -syn keyword ngxDirectiveThirdParty set_from_accept_language +syn keyword ngxDirectiveThirdParty contained set_from_accept_language -" Access Key Module +" Access Key Module (DEPRECATED) " Denies access unless the request URL contains an access key. -syn keyword ngxDirectiveThirdParty accesskey -syn keyword ngxDirectiveThirdParty accesskey_arg -syn keyword ngxDirectiveThirdParty accesskey_hashmethod -syn keyword ngxDirectiveThirdParty accesskey_signature +syn keyword ngxDirectiveDeprecated contained accesskey +syn keyword ngxDirectiveDeprecated contained accesskey_arg +syn keyword ngxDirectiveDeprecated contained accesskey_hashmethod +syn keyword ngxDirectiveDeprecated contained accesskey_signature -" Auth PAM Module -" HTTP Basic Authentication using PAM. -syn keyword ngxDirectiveThirdParty auth_pam -syn keyword ngxDirectiveThirdParty auth_pam_service_name +" Asynchronous FastCGI Module +" Primarily a modified version of the Nginx FastCGI module which implements multiplexing of connections, allowing a single FastCGI server to handle many concurrent requests. +" syn keyword ngxDirectiveThirdParty contained fastcgi_bind +" syn keyword ngxDirectiveThirdParty contained fastcgi_buffer_size +" syn keyword ngxDirectiveThirdParty contained fastcgi_buffers +" syn keyword ngxDirectiveThirdParty contained fastcgi_busy_buffers_size +" syn keyword ngxDirectiveThirdParty contained fastcgi_cache +" syn keyword ngxDirectiveThirdParty contained fastcgi_cache_key +" syn keyword ngxDirectiveThirdParty contained fastcgi_cache_methods +" syn keyword ngxDirectiveThirdParty contained fastcgi_cache_min_uses +" syn keyword ngxDirectiveThirdParty contained fastcgi_cache_path +" syn keyword ngxDirectiveThirdParty contained fastcgi_cache_use_stale +" syn keyword ngxDirectiveThirdParty contained fastcgi_cache_valid +" syn keyword ngxDirectiveThirdParty contained fastcgi_catch_stderr +" syn keyword ngxDirectiveThirdParty contained fastcgi_connect_timeout +" syn keyword ngxDirectiveThirdParty contained fastcgi_hide_header +" syn keyword ngxDirectiveThirdParty contained fastcgi_ignore_client_abort +" syn keyword ngxDirectiveThirdParty contained fastcgi_ignore_headers +" syn keyword ngxDirectiveThirdParty contained fastcgi_index +" syn keyword ngxDirectiveThirdParty contained fastcgi_intercept_errors +" syn keyword ngxDirectiveThirdParty contained fastcgi_max_temp_file_size +" syn keyword ngxDirectiveThirdParty contained fastcgi_next_upstream +" syn keyword ngxDirectiveThirdParty contained fastcgi_param +" syn keyword ngxDirectiveThirdParty contained fastcgi_pass +" syn keyword ngxDirectiveThirdParty contained fastcgi_pass_header +" syn keyword ngxDirectiveThirdParty contained fastcgi_pass_request_body +" syn keyword ngxDirectiveThirdParty contained fastcgi_pass_request_headers +" syn keyword ngxDirectiveThirdParty contained fastcgi_read_timeout +" syn keyword ngxDirectiveThirdParty contained fastcgi_send_lowat +" syn keyword ngxDirectiveThirdParty contained fastcgi_send_timeout +" syn keyword ngxDirectiveThirdParty contained fastcgi_split_path_info +" syn keyword ngxDirectiveThirdParty contained fastcgi_store +" syn keyword ngxDirectiveThirdParty contained fastcgi_store_access +" syn keyword ngxDirectiveThirdParty contained fastcgi_temp_file_write_size +" syn keyword ngxDirectiveThirdParty contained fastcgi_temp_path +syn keyword ngxDirectiveDeprecated contained fastcgi_upstream_fail_timeout +syn keyword ngxDirectiveDeprecated contained fastcgi_upstream_max_fails + +" Akamai G2O Module +" Nginx Module for Authenticating Akamai G2O requests +syn keyword ngxDirectiveThirdParty contained g2o +syn keyword ngxDirectiveThirdParty contained g2o_nonce +syn keyword ngxDirectiveThirdParty contained g2o_key + +" Lua Module +" You can be very simple to execute lua code for nginx +syn keyword ngxDirectiveThirdParty contained lua_file + +" Array Variable Module +" Add support for array-typed variables to nginx config files +syn keyword ngxDirectiveThirdParty contained array_split +syn keyword ngxDirectiveThirdParty contained array_join +syn keyword ngxDirectiveThirdParty contained array_map +syn keyword ngxDirectiveThirdParty contained array_map_op -" Cache Purge Module -" Module adding ability to purge content from FastCGI and proxy caches. -syn keyword ngxDirectiveThirdParty fastcgi_cache_purge -syn keyword ngxDirectiveThirdParty proxy_cache_purge +" Nginx Audio Track for HTTP Live Streaming +" This nginx module generates audio track for hls streams on the fly. +syn keyword ngxDirectiveThirdParty contained ngx_hls_audio_track +syn keyword ngxDirectiveThirdParty contained ngx_hls_audio_track_rootpath +syn keyword ngxDirectiveThirdParty contained ngx_hls_audio_track_output_format +syn keyword ngxDirectiveThirdParty contained ngx_hls_audio_track_output_header -" Chunkin Module +" AWS Proxy Module +" Nginx module to proxy to authenticated AWS services +syn keyword ngxDirectiveThirdParty contained aws_access_key +syn keyword ngxDirectiveThirdParty contained aws_key_scope +syn keyword ngxDirectiveThirdParty contained aws_signing_key +syn keyword ngxDirectiveThirdParty contained aws_endpoint +syn keyword ngxDirectiveThirdParty contained aws_s3_bucket +syn keyword ngxDirectiveThirdParty contained aws_sign + +" Backtrace module +" A Nginx module to dump backtrace when a worker process exits abnormally +syn keyword ngxDirectiveThirdParty contained backtrace_log +syn keyword ngxDirectiveThirdParty contained backtrace_max_stack_size + +" Brotli Module +" Nginx module for Brotli compression +syn keyword ngxDirectiveThirdParty contained brotli_static +syn keyword ngxDirectiveThirdParty contained brotli +syn keyword ngxDirectiveThirdParty contained brotli_types +syn keyword ngxDirectiveThirdParty contained brotli_buffers +syn keyword ngxDirectiveThirdParty contained brotli_comp_level +syn keyword ngxDirectiveThirdParty contained brotli_window +syn keyword ngxDirectiveThirdParty contained brotli_min_length + +" Cache Purge Module +" Adds ability to purge content from FastCGI, proxy, SCGI and uWSGI caches. +syn keyword ngxDirectiveThirdParty contained fastcgi_cache_purge +syn keyword ngxDirectiveThirdParty contained proxy_cache_purge +" syn keyword ngxDirectiveThirdParty contained scgi_cache_purge +" syn keyword ngxDirectiveThirdParty contained uwsgi_cache_purge + +" Chunkin Module (DEPRECATED) " HTTP 1.1 chunked-encoding request body support for Nginx. -syn keyword ngxDirectiveThirdParty chunkin -syn keyword ngxDirectiveThirdParty chunkin_keepalive -syn keyword ngxDirectiveThirdParty chunkin_max_chunks_per_buf -syn keyword ngxDirectiveThirdParty chunkin_resume +syn keyword ngxDirectiveDeprecated contained chunkin +syn keyword ngxDirectiveDeprecated contained chunkin_keepalive +syn keyword ngxDirectiveDeprecated contained chunkin_max_chunks_per_buf +syn keyword ngxDirectiveDeprecated contained chunkin_resume -" Circle GIF Module +" Circle GIF Module " Generates simple circle images with the colors and size specified in the URL. -syn keyword ngxDirectiveThirdParty circle_gif -syn keyword ngxDirectiveThirdParty circle_gif_max_radius -syn keyword ngxDirectiveThirdParty circle_gif_min_radius -syn keyword ngxDirectiveThirdParty circle_gif_step_radius - -" Drizzle Module -" Make nginx talk directly to mysql, drizzle, and sqlite3 by libdrizzle. -syn keyword ngxDirectiveThirdParty drizzle_connect_timeout -syn keyword ngxDirectiveThirdParty drizzle_dbname -syn keyword ngxDirectiveThirdParty drizzle_keepalive -syn keyword ngxDirectiveThirdParty drizzle_module_header -syn keyword ngxDirectiveThirdParty drizzle_pass -syn keyword ngxDirectiveThirdParty drizzle_query -syn keyword ngxDirectiveThirdParty drizzle_recv_cols_timeout -syn keyword ngxDirectiveThirdParty drizzle_recv_rows_timeout -syn keyword ngxDirectiveThirdParty drizzle_send_query_timeout -syn keyword ngxDirectiveThirdParty drizzle_server - -" Echo Module -" Brings 'echo', 'sleep', 'time', 'exec' and more shell-style goodies to Nginx config file. -syn keyword ngxDirectiveThirdParty echo -syn keyword ngxDirectiveThirdParty echo_after_body -syn keyword ngxDirectiveThirdParty echo_before_body -syn keyword ngxDirectiveThirdParty echo_blocking_sleep -syn keyword ngxDirectiveThirdParty echo_duplicate -syn keyword ngxDirectiveThirdParty echo_end -syn keyword ngxDirectiveThirdParty echo_exec -syn keyword ngxDirectiveThirdParty echo_flush -syn keyword ngxDirectiveThirdParty echo_foreach_split -syn keyword ngxDirectiveThirdParty echo_location -syn keyword ngxDirectiveThirdParty echo_location_async -syn keyword ngxDirectiveThirdParty echo_read_request_body -syn keyword ngxDirectiveThirdParty echo_request_body -syn keyword ngxDirectiveThirdParty echo_reset_timer -syn keyword ngxDirectiveThirdParty echo_sleep -syn keyword ngxDirectiveThirdParty echo_subrequest -syn keyword ngxDirectiveThirdParty echo_subrequest_async - -" Events Module +syn keyword ngxDirectiveThirdParty contained circle_gif +syn keyword ngxDirectiveThirdParty contained circle_gif_max_radius +syn keyword ngxDirectiveThirdParty contained circle_gif_min_radius +syn keyword ngxDirectiveThirdParty contained circle_gif_step_radius + +" Nginx-Clojure Module +" Parses the Accept-Language header and gives the most suitable locale from a list of supported locales. +syn keyword ngxDirectiveThirdParty contained jvm_path +syn keyword ngxDirectiveThirdParty contained jvm_var +syn keyword ngxDirectiveThirdParty contained jvm_classpath +syn keyword ngxDirectiveThirdParty contained jvm_classpath_check +syn keyword ngxDirectiveThirdParty contained jvm_workers +syn keyword ngxDirectiveThirdParty contained jvm_options +syn keyword ngxDirectiveThirdParty contained jvm_handler_type +syn keyword ngxDirectiveThirdParty contained jvm_init_handler_name +syn keyword ngxDirectiveThirdParty contained jvm_init_handler_code +syn keyword ngxDirectiveThirdParty contained jvm_exit_handler_name +syn keyword ngxDirectiveThirdParty contained jvm_exit_handler_code +syn keyword ngxDirectiveThirdParty contained handlers_lazy_init +syn keyword ngxDirectiveThirdParty contained auto_upgrade_ws +syn keyword ngxDirectiveThirdParty contained content_handler_type +syn keyword ngxDirectiveThirdParty contained content_handler_name +syn keyword ngxDirectiveThirdParty contained content_handler_code +syn keyword ngxDirectiveThirdParty contained rewrite_handler_type +syn keyword ngxDirectiveThirdParty contained rewrite_handler_name +syn keyword ngxDirectiveThirdParty contained rewrite_handler_code +syn keyword ngxDirectiveThirdParty contained access_handler_type +syn keyword ngxDirectiveThirdParty contained access_handler_name +syn keyword ngxDirectiveThirdParty contained access_handler_code +syn keyword ngxDirectiveThirdParty contained header_filter_type +syn keyword ngxDirectiveThirdParty contained header_filter_name +syn keyword ngxDirectiveThirdParty contained header_filter_code +syn keyword ngxDirectiveThirdParty contained content_handler_property +syn keyword ngxDirectiveThirdParty contained rewrite_handler_property +syn keyword ngxDirectiveThirdParty contained access_handler_property +syn keyword ngxDirectiveThirdParty contained header_filter_property +syn keyword ngxDirectiveThirdParty contained always_read_body +syn keyword ngxDirectiveThirdParty contained shared_map +syn keyword ngxDirectiveThirdParty contained write_page_size + +" Upstream Consistent Hash +" A load balancer that uses an internal consistent hash ring to select the right backend node. +syn keyword ngxDirectiveThirdParty contained consistent_hash + +" Nginx Development Kit +" The NDK is an Nginx module that is designed to extend the core functionality of the excellent Nginx webserver in a way that can be used as a basis of other Nginx modules. +" NDK_UPSTREAM_LIST +" This submodule provides a directive that creates a list of upstreams, with optional weighting. This list can then be used by other modules to hash over the upstreams however they choose. +syn keyword ngxDirectiveThirdParty contained upstream_list + +" Drizzle Module +" Upstream module for talking to MySQL and Drizzle directly +syn keyword ngxDirectiveThirdParty contained drizzle_server +syn keyword ngxDirectiveThirdParty contained drizzle_keepalive +syn keyword ngxDirectiveThirdParty contained drizzle_query +syn keyword ngxDirectiveThirdParty contained drizzle_pass +syn keyword ngxDirectiveThirdParty contained drizzle_connect_timeout +syn keyword ngxDirectiveThirdParty contained drizzle_send_query_timeout +syn keyword ngxDirectiveThirdParty contained drizzle_recv_cols_timeout +syn keyword ngxDirectiveThirdParty contained drizzle_recv_rows_timeout +syn keyword ngxDirectiveThirdParty contained drizzle_buffer_size +syn keyword ngxDirectiveThirdParty contained drizzle_module_header +syn keyword ngxDirectiveThirdParty contained drizzle_status + +" Dynamic ETags Module +" Attempt at handling ETag / If-None-Match on proxied content. +syn keyword ngxDirectiveThirdParty contained dynamic_etags + +" Echo Module +" Bringing the power of "echo", "sleep", "time" and more to Nginx's config file +syn keyword ngxDirectiveThirdParty contained echo +syn keyword ngxDirectiveThirdParty contained echo_duplicate +syn keyword ngxDirectiveThirdParty contained echo_flush +syn keyword ngxDirectiveThirdParty contained echo_sleep +syn keyword ngxDirectiveThirdParty contained echo_blocking_sleep +syn keyword ngxDirectiveThirdParty contained echo_reset_timer +syn keyword ngxDirectiveThirdParty contained echo_read_request_body +syn keyword ngxDirectiveThirdParty contained echo_location_async +syn keyword ngxDirectiveThirdParty contained echo_location +syn keyword ngxDirectiveThirdParty contained echo_subrequest_async +syn keyword ngxDirectiveThirdParty contained echo_subrequest +syn keyword ngxDirectiveThirdParty contained echo_foreach_split +syn keyword ngxDirectiveThirdParty contained echo_end +syn keyword ngxDirectiveThirdParty contained echo_request_body +syn keyword ngxDirectiveThirdParty contained echo_exec +syn keyword ngxDirectiveThirdParty contained echo_status +syn keyword ngxDirectiveThirdParty contained echo_before_body +syn keyword ngxDirectiveThirdParty contained echo_after_body + +" Encrypted Session Module +" Encrypt and decrypt nginx variable values +syn keyword ngxDirectiveThirdParty contained encrypted_session_key +syn keyword ngxDirectiveThirdParty contained encrypted_session_iv +syn keyword ngxDirectiveThirdParty contained encrypted_session_expires +syn keyword ngxDirectiveThirdParty contained set_encrypt_session +syn keyword ngxDirectiveThirdParty contained set_decrypt_session + +" Enhanced Memcached Module +" This module is based on the standard Nginx Memcached module, with some additonal features +syn keyword ngxDirectiveThirdParty contained enhanced_memcached_pass +syn keyword ngxDirectiveThirdParty contained enhanced_memcached_hash_keys_with_md5 +syn keyword ngxDirectiveThirdParty contained enhanced_memcached_allow_put +syn keyword ngxDirectiveThirdParty contained enhanced_memcached_allow_delete +syn keyword ngxDirectiveThirdParty contained enhanced_memcached_stats +syn keyword ngxDirectiveThirdParty contained enhanced_memcached_flush +syn keyword ngxDirectiveThirdParty contained enhanced_memcached_flush_namespace +syn keyword ngxDirectiveThirdParty contained enhanced_memcached_bind +syn keyword ngxDirectiveThirdParty contained enhanced_memcached_connect_timeout +syn keyword ngxDirectiveThirdParty contained enhanced_memcached_send_timeout +syn keyword ngxDirectiveThirdParty contained enhanced_memcached_buffer_size +syn keyword ngxDirectiveThirdParty contained enhanced_memcached_read_timeout + +" Events Module (DEPRECATED) " Provides options for start/stop events. -syn keyword ngxDirectiveThirdParty on_start -syn keyword ngxDirectiveThirdParty on_stop +syn keyword ngxDirectiveDeprecated contained on_start +syn keyword ngxDirectiveDeprecated contained on_stop -" EY Balancer Module +" EY Balancer Module " Adds a request queue to Nginx that allows the limiting of concurrent requests passed to the upstream. -syn keyword ngxDirectiveThirdParty max_connections -syn keyword ngxDirectiveThirdParty max_connections_max_queue_length -syn keyword ngxDirectiveThirdParty max_connections_queue_timeout +syn keyword ngxDirectiveThirdParty contained max_connections +syn keyword ngxDirectiveThirdParty contained max_connections_max_queue_length +syn keyword ngxDirectiveThirdParty contained max_connections_queue_timeout + +" Upstream Fair Balancer +" Sends an incoming request to the least-busy backend server, rather than distributing requests round-robin. +syn keyword ngxDirectiveThirdParty contained fair +syn keyword ngxDirectiveThirdParty contained upstream_fair_shm_size -" Fancy Indexes Module +" Fancy Indexes Module " Like the built-in autoindex module, but fancier. -syn keyword ngxDirectiveThirdParty fancyindex -syn keyword ngxDirectiveThirdParty fancyindex_exact_size -syn keyword ngxDirectiveThirdParty fancyindex_footer -syn keyword ngxDirectiveThirdParty fancyindex_header -syn keyword ngxDirectiveThirdParty fancyindex_localtime -syn keyword ngxDirectiveThirdParty fancyindex_readme -syn keyword ngxDirectiveThirdParty fancyindex_readme_mode +syn keyword ngxDirectiveThirdParty contained fancyindex +syn keyword ngxDirectiveThirdParty contained fancyindex_default_sort +syn keyword ngxDirectiveThirdParty contained fancyindex_directories_first +syn keyword ngxDirectiveThirdParty contained fancyindex_css_href +syn keyword ngxDirectiveThirdParty contained fancyindex_exact_size +syn keyword ngxDirectiveThirdParty contained fancyindex_name_length +syn keyword ngxDirectiveThirdParty contained fancyindex_footer +syn keyword ngxDirectiveThirdParty contained fancyindex_header +syn keyword ngxDirectiveThirdParty contained fancyindex_show_path +syn keyword ngxDirectiveThirdParty contained fancyindex_ignore +syn keyword ngxDirectiveThirdParty contained fancyindex_hide_symlinks +syn keyword ngxDirectiveThirdParty contained fancyindex_localtime +syn keyword ngxDirectiveThirdParty contained fancyindex_time_format + +" Form Auth Module +" Provides authentication and authorization with credentials submitted via POST request +syn keyword ngxDirectiveThirdParty contained form_auth +syn keyword ngxDirectiveThirdParty contained form_auth_pam_service +syn keyword ngxDirectiveThirdParty contained form_auth_login +syn keyword ngxDirectiveThirdParty contained form_auth_password +syn keyword ngxDirectiveThirdParty contained form_auth_remote_user + +" Form Input Module +" Reads HTTP POST and PUT request body encoded in "application/x-www-form-urlencoded" and parses the arguments into nginx variables. +syn keyword ngxDirectiveThirdParty contained set_form_input +syn keyword ngxDirectiveThirdParty contained set_form_input_multi " GeoIP Module (DEPRECATED) " Country code lookups via the MaxMind GeoIP API. -syn keyword ngxDirectiveThirdParty geoip_country_file +syn keyword ngxDirectiveDeprecated contained geoip_country_file + +" GeoIP 2 Module +" Creates variables with values from the maxmind geoip2 databases based on the client IP +syn keyword ngxDirectiveThirdParty contained geoip2 + +" GridFS Module +" Nginx module for serving files from MongoDB's GridFS +syn keyword ngxDirectiveThirdParty contained gridfs -" Headers More Module +" Headers More Module " Set and clear input and output headers...more than "add"! -syn keyword ngxDirectiveThirdParty more_clear_headers -syn keyword ngxDirectiveThirdParty more_clear_input_headers -syn keyword ngxDirectiveThirdParty more_set_headers -syn keyword ngxDirectiveThirdParty more_set_input_headers +syn keyword ngxDirectiveThirdParty contained more_clear_headers +syn keyword ngxDirectiveThirdParty contained more_clear_input_headers +syn keyword ngxDirectiveThirdParty contained more_set_headers +syn keyword ngxDirectiveThirdParty contained more_set_input_headers -" HTTP Push Module -" Turn Nginx into an adept long-polling HTTP Push (Comet) server. -syn keyword ngxDirectiveThirdParty push_buffer_size -syn keyword ngxDirectiveThirdParty push_listener -syn keyword ngxDirectiveThirdParty push_message_timeout -syn keyword ngxDirectiveThirdParty push_queue_messages -syn keyword ngxDirectiveThirdParty push_sender - -" HTTP Redis Module > -" Redis support.> -syn keyword ngxDirectiveThirdParty redis_bind -syn keyword ngxDirectiveThirdParty redis_buffer_size -syn keyword ngxDirectiveThirdParty redis_connect_timeout -syn keyword ngxDirectiveThirdParty redis_next_upstream -syn keyword ngxDirectiveThirdParty redis_pass -syn keyword ngxDirectiveThirdParty redis_read_timeout -syn keyword ngxDirectiveThirdParty redis_send_timeout - -" HTTP JavaScript Module +" Health Checks Upstreams Module +" Polls backends and if they respond with HTTP 200 + an optional request body, they are marked good. Otherwise, they are marked bad. +syn keyword ngxDirectiveThirdParty contained healthcheck_enabled +syn keyword ngxDirectiveThirdParty contained healthcheck_delay +syn keyword ngxDirectiveThirdParty contained healthcheck_timeout +syn keyword ngxDirectiveThirdParty contained healthcheck_failcount +syn keyword ngxDirectiveThirdParty contained healthcheck_send +syn keyword ngxDirectiveThirdParty contained healthcheck_expected +syn keyword ngxDirectiveThirdParty contained healthcheck_buffer +syn keyword ngxDirectiveThirdParty contained healthcheck_status + +" HTTP Accounting Module +" Add traffic stat function to nginx. Useful for http accounting based on nginx configuration logic +syn keyword ngxDirectiveThirdParty contained http_accounting +syn keyword ngxDirectiveThirdParty contained http_accounting_log +syn keyword ngxDirectiveThirdParty contained http_accounting_id +syn keyword ngxDirectiveThirdParty contained http_accounting_interval +syn keyword ngxDirectiveThirdParty contained http_accounting_perturb + +" Nginx Digest Authentication module +" Digest Authentication for Nginx +syn keyword ngxDirectiveThirdParty contained auth_digest +syn keyword ngxDirectiveThirdParty contained auth_digest_user_file +syn keyword ngxDirectiveThirdParty contained auth_digest_timeout +syn keyword ngxDirectiveThirdParty contained auth_digest_expires +syn keyword ngxDirectiveThirdParty contained auth_digest_replays +syn keyword ngxDirectiveThirdParty contained auth_digest_shm_size + +" Auth PAM Module +" HTTP Basic Authentication using PAM. +syn keyword ngxDirectiveThirdParty contained auth_pam +syn keyword ngxDirectiveThirdParty contained auth_pam_service_name + +" HTTP Auth Request Module +" Implements client authorization based on the result of a subrequest +" syn keyword ngxDirectiveThirdParty contained auth_request +" syn keyword ngxDirectiveThirdParty contained auth_request_set + +" HTTP Concatenation module for Nginx +" A Nginx module for concatenating files in a given context: CSS and JS files usually +syn keyword ngxDirectiveThirdParty contained concat +syn keyword ngxDirectiveThirdParty contained concat_types +syn keyword ngxDirectiveThirdParty contained concat_unique +syn keyword ngxDirectiveThirdParty contained concat_max_files +syn keyword ngxDirectiveThirdParty contained concat_delimiter +syn keyword ngxDirectiveThirdParty contained concat_ignore_file_error + +" HTTP Dynamic Upstream Module +" Update upstreams' config by restful interface +syn keyword ngxDirectiveThirdParty contained dyups_interface +syn keyword ngxDirectiveThirdParty contained dyups_read_msg_timeout +syn keyword ngxDirectiveThirdParty contained dyups_shm_zone_size +syn keyword ngxDirectiveThirdParty contained dyups_upstream_conf +syn keyword ngxDirectiveThirdParty contained dyups_trylock + +" HTTP Footer If Filter Module +" The ngx_http_footer_if_filter_module is used to add given content to the end of the response according to the condition specified. +syn keyword ngxDirectiveThirdParty contained footer_if + +" HTTP Footer Filter Module +" This module implements a body filter that adds a given string to the page footer. +syn keyword ngxDirectiveThirdParty contained footer +syn keyword ngxDirectiveThirdParty contained footer_types + +" HTTP Internal Redirect Module +" Make an internal redirect to the uri specified according to the condition specified. +syn keyword ngxDirectiveThirdParty contained internal_redirect_if +syn keyword ngxDirectiveThirdParty contained internal_redirect_if_no_postponed + +" HTTP JavaScript Module " Embedding SpiderMonkey. Nearly full port on Perl module. -syn keyword ngxDirectiveThirdParty js -syn keyword ngxDirectiveThirdParty js_filter -syn keyword ngxDirectiveThirdParty js_filter_types -syn keyword ngxDirectiveThirdParty js_load -syn keyword ngxDirectiveThirdParty js_maxmem -syn keyword ngxDirectiveThirdParty js_require -syn keyword ngxDirectiveThirdParty js_set -syn keyword ngxDirectiveThirdParty js_utf8 - -" Log Request Speed +syn keyword ngxDirectiveThirdParty contained js +syn keyword ngxDirectiveThirdParty contained js_filter +syn keyword ngxDirectiveThirdParty contained js_filter_types +syn keyword ngxDirectiveThirdParty contained js_load +syn keyword ngxDirectiveThirdParty contained js_maxmem +syn keyword ngxDirectiveThirdParty contained js_require +syn keyword ngxDirectiveThirdParty contained js_set +syn keyword ngxDirectiveThirdParty contained js_utf8 + +" HTTP Push Module (DEPRECATED) +" Turn Nginx into an adept long-polling HTTP Push (Comet) server. +syn keyword ngxDirectiveDeprecated contained push_buffer_size +syn keyword ngxDirectiveDeprecated contained push_listener +syn keyword ngxDirectiveDeprecated contained push_message_timeout +syn keyword ngxDirectiveDeprecated contained push_queue_messages +syn keyword ngxDirectiveDeprecated contained push_sender + +" HTTP Redis Module +" Redis support. +syn keyword ngxDirectiveThirdParty contained redis_bind +syn keyword ngxDirectiveThirdParty contained redis_buffer_size +syn keyword ngxDirectiveThirdParty contained redis_connect_timeout +syn keyword ngxDirectiveThirdParty contained redis_next_upstream +syn keyword ngxDirectiveThirdParty contained redis_pass +syn keyword ngxDirectiveThirdParty contained redis_read_timeout +syn keyword ngxDirectiveThirdParty contained redis_send_timeout + +" Iconv Module +" A character conversion nginx module using libiconv +syn keyword ngxDirectiveThirdParty contained set_iconv +syn keyword ngxDirectiveThirdParty contained iconv_buffer_size +syn keyword ngxDirectiveThirdParty contained iconv_filter + +" IP Blocker Module +" An efficient shared memory IP blocking system for nginx. +syn keyword ngxDirectiveThirdParty contained ip_blocker + +" IP2Location Module +" Allows user to lookup for geolocation information using IP2Location database +syn keyword ngxDirectiveThirdParty contained ip2location_database + +" JS Module +" Reflect the nginx functionality in JS +syn keyword ngxDirectiveThirdParty contained js +syn keyword ngxDirectiveThirdParty contained js_access +syn keyword ngxDirectiveThirdParty contained js_load +syn keyword ngxDirectiveThirdParty contained js_set + +" Limit Upload Rate Module +" Limit client-upload rate when they are sending request bodies to you +syn keyword ngxDirectiveThirdParty contained limit_upload_rate +syn keyword ngxDirectiveThirdParty contained limit_upload_rate_after + +" Limit Upstream Module +" Limit the number of connections to upstream for NGINX +syn keyword ngxDirectiveThirdParty contained limit_upstream_zone +syn keyword ngxDirectiveThirdParty contained limit_upstream_conn +syn keyword ngxDirectiveThirdParty contained limit_upstream_log_level + +" Log If Module +" Conditional accesslog for nginx +syn keyword ngxDirectiveThirdParty contained access_log_bypass_if + +" Log Request Speed (DEPRECATED) " Log the time it took to process each request. -syn keyword ngxDirectiveThirdParty log_request_speed_filter -syn keyword ngxDirectiveThirdParty log_request_speed_filter_timeout +syn keyword ngxDirectiveDeprecated contained log_request_speed_filter +syn keyword ngxDirectiveDeprecated contained log_request_speed_filter_timeout -" Memc Module +" Log ZeroMQ Module +" ZeroMQ logger module for nginx +syn keyword ngxDirectiveThirdParty contained log_zmq_server +syn keyword ngxDirectiveThirdParty contained log_zmq_endpoint +syn keyword ngxDirectiveThirdParty contained log_zmq_format +syn keyword ngxDirectiveThirdParty contained log_zmq_off + +" Lower/UpperCase Module +" This module simply uppercases or lowercases a string and saves it into a new variable. +syn keyword ngxDirectiveThirdParty contained lower +syn keyword ngxDirectiveThirdParty contained upper + +" Lua Upstream Module +" Nginx C module to expose Lua API to ngx_lua for Nginx upstreams + +" Lua Module +" Embed the Power of Lua into NGINX HTTP servers +syn keyword ngxDirectiveThirdParty contained lua_use_default_type +syn keyword ngxDirectiveThirdParty contained lua_malloc_trim +syn keyword ngxDirectiveThirdParty contained lua_code_cache +syn keyword ngxDirectiveThirdParty contained lua_regex_cache_max_entries +syn keyword ngxDirectiveThirdParty contained lua_regex_match_limit +syn keyword ngxDirectiveThirdParty contained lua_package_path +syn keyword ngxDirectiveThirdParty contained lua_package_cpath +syn keyword ngxDirectiveThirdParty contained init_by_lua +syn keyword ngxDirectiveThirdParty contained init_by_lua_block +syn keyword ngxDirectiveThirdParty contained init_by_lua_file +syn keyword ngxDirectiveThirdParty contained init_worker_by_lua +syn keyword ngxDirectiveThirdParty contained init_worker_by_lua_block +syn keyword ngxDirectiveThirdParty contained init_worker_by_lua_file +syn keyword ngxDirectiveThirdParty contained set_by_lua +syn keyword ngxDirectiveThirdParty contained set_by_lua_block +syn keyword ngxDirectiveThirdParty contained set_by_lua_file +syn keyword ngxDirectiveThirdParty contained content_by_lua +syn keyword ngxDirectiveThirdParty contained content_by_lua_block +syn keyword ngxDirectiveThirdParty contained content_by_lua_file +syn keyword ngxDirectiveThirdParty contained rewrite_by_lua +syn keyword ngxDirectiveThirdParty contained rewrite_by_lua_block +syn keyword ngxDirectiveThirdParty contained rewrite_by_lua_file +syn keyword ngxDirectiveThirdParty contained access_by_lua +syn keyword ngxDirectiveThirdParty contained access_by_lua_block +syn keyword ngxDirectiveThirdParty contained access_by_lua_file +syn keyword ngxDirectiveThirdParty contained header_filter_by_lua +syn keyword ngxDirectiveThirdParty contained header_filter_by_lua_block +syn keyword ngxDirectiveThirdParty contained header_filter_by_lua_file +syn keyword ngxDirectiveThirdParty contained body_filter_by_lua +syn keyword ngxDirectiveThirdParty contained body_filter_by_lua_block +syn keyword ngxDirectiveThirdParty contained body_filter_by_lua_file +syn keyword ngxDirectiveThirdParty contained log_by_lua +syn keyword ngxDirectiveThirdParty contained log_by_lua_block +syn keyword ngxDirectiveThirdParty contained log_by_lua_file +syn keyword ngxDirectiveThirdParty contained balancer_by_lua_block +syn keyword ngxDirectiveThirdParty contained balancer_by_lua_file +syn keyword ngxDirectiveThirdParty contained lua_need_request_body +syn keyword ngxDirectiveThirdParty contained ssl_certificate_by_lua_block +syn keyword ngxDirectiveThirdParty contained ssl_certificate_by_lua_file +syn keyword ngxDirectiveThirdParty contained ssl_session_fetch_by_lua_block +syn keyword ngxDirectiveThirdParty contained ssl_session_fetch_by_lua_file +syn keyword ngxDirectiveThirdParty contained ssl_session_store_by_lua_block +syn keyword ngxDirectiveThirdParty contained ssl_session_store_by_lua_file +syn keyword ngxDirectiveThirdParty contained lua_shared_dict +syn keyword ngxDirectiveThirdParty contained lua_socket_connect_timeout +syn keyword ngxDirectiveThirdParty contained lua_socket_send_timeout +syn keyword ngxDirectiveThirdParty contained lua_socket_send_lowat +syn keyword ngxDirectiveThirdParty contained lua_socket_read_timeout +syn keyword ngxDirectiveThirdParty contained lua_socket_buffer_size +syn keyword ngxDirectiveThirdParty contained lua_socket_pool_size +syn keyword ngxDirectiveThirdParty contained lua_socket_keepalive_timeout +syn keyword ngxDirectiveThirdParty contained lua_socket_log_errors +syn keyword ngxDirectiveThirdParty contained lua_ssl_ciphers +syn keyword ngxDirectiveThirdParty contained lua_ssl_crl +syn keyword ngxDirectiveThirdParty contained lua_ssl_protocols +syn keyword ngxDirectiveThirdParty contained lua_ssl_trusted_certificate +syn keyword ngxDirectiveThirdParty contained lua_ssl_verify_depth +syn keyword ngxDirectiveThirdParty contained lua_http10_buffering +syn keyword ngxDirectiveThirdParty contained rewrite_by_lua_no_postpone +syn keyword ngxDirectiveThirdParty contained access_by_lua_no_postpone +syn keyword ngxDirectiveThirdParty contained lua_transform_underscores_in_response_headers +syn keyword ngxDirectiveThirdParty contained lua_check_client_abort +syn keyword ngxDirectiveThirdParty contained lua_max_pending_timers +syn keyword ngxDirectiveThirdParty contained lua_max_running_timers + +" MD5 Filter Module +" A content filter for nginx, which returns the md5 hash of the content otherwise returned. +syn keyword ngxDirectiveThirdParty contained md5_filter + +" Memc Module " An extended version of the standard memcached module that supports set, add, delete, and many more memcached commands. -syn keyword ngxDirectiveThirdParty memc_buffer_size -syn keyword ngxDirectiveThirdParty memc_cmds_allowed -syn keyword ngxDirectiveThirdParty memc_connect_timeout -syn keyword ngxDirectiveThirdParty memc_flags_to_last_modified -syn keyword ngxDirectiveThirdParty memc_next_upstream -syn keyword ngxDirectiveThirdParty memc_pass -syn keyword ngxDirectiveThirdParty memc_read_timeout -syn keyword ngxDirectiveThirdParty memc_send_timeout -syn keyword ngxDirectiveThirdParty memc_upstream_fail_timeout -syn keyword ngxDirectiveThirdParty memc_upstream_max_fails +syn keyword ngxDirectiveThirdParty contained memc_buffer_size +syn keyword ngxDirectiveThirdParty contained memc_cmds_allowed +syn keyword ngxDirectiveThirdParty contained memc_connect_timeout +syn keyword ngxDirectiveThirdParty contained memc_flags_to_last_modified +syn keyword ngxDirectiveThirdParty contained memc_next_upstream +syn keyword ngxDirectiveThirdParty contained memc_pass +syn keyword ngxDirectiveThirdParty contained memc_read_timeout +syn keyword ngxDirectiveThirdParty contained memc_send_timeout +syn keyword ngxDirectiveThirdParty contained memc_upstream_fail_timeout +syn keyword ngxDirectiveThirdParty contained memc_upstream_max_fails + +" Mod Security Module +" ModSecurity is an open source, cross platform web application firewall (WAF) engine +syn keyword ngxDirectiveThirdParty contained ModSecurityConfig +syn keyword ngxDirectiveThirdParty contained ModSecurityEnabled +syn keyword ngxDirectiveThirdParty contained pool_context +syn keyword ngxDirectiveThirdParty contained pool_context_hash_size " Mogilefs Module -" Implements a MogileFS client, provides a replace to the Perlbal reverse proxy of the original MogileFS. -syn keyword ngxDirectiveThirdParty mogilefs_connect_timeout -syn keyword ngxDirectiveThirdParty mogilefs_domain -syn keyword ngxDirectiveThirdParty mogilefs_methods -syn keyword ngxDirectiveThirdParty mogilefs_noverify -syn keyword ngxDirectiveThirdParty mogilefs_pass -syn keyword ngxDirectiveThirdParty mogilefs_read_timeout -syn keyword ngxDirectiveThirdParty mogilefs_send_timeout -syn keyword ngxDirectiveThirdParty mogilefs_tracker - -" MP4 Streaming Lite Module +" MogileFS client for nginx web server. +syn keyword ngxDirectiveThirdParty contained mogilefs_pass +syn keyword ngxDirectiveThirdParty contained mogilefs_methods +syn keyword ngxDirectiveThirdParty contained mogilefs_domain +syn keyword ngxDirectiveThirdParty contained mogilefs_class +syn keyword ngxDirectiveThirdParty contained mogilefs_tracker +syn keyword ngxDirectiveThirdParty contained mogilefs_noverify +syn keyword ngxDirectiveThirdParty contained mogilefs_connect_timeout +syn keyword ngxDirectiveThirdParty contained mogilefs_send_timeout +syn keyword ngxDirectiveThirdParty contained mogilefs_read_timeout + +" Mongo Module +" Upstream module that allows nginx to communicate directly with MongoDB database. +syn keyword ngxDirectiveThirdParty contained mongo_auth +syn keyword ngxDirectiveThirdParty contained mongo_pass +syn keyword ngxDirectiveThirdParty contained mongo_query +syn keyword ngxDirectiveThirdParty contained mongo_json +syn keyword ngxDirectiveThirdParty contained mongo_bind +syn keyword ngxDirectiveThirdParty contained mongo_connect_timeout +syn keyword ngxDirectiveThirdParty contained mongo_send_timeout +syn keyword ngxDirectiveThirdParty contained mongo_read_timeout +syn keyword ngxDirectiveThirdParty contained mongo_buffering +syn keyword ngxDirectiveThirdParty contained mongo_buffer_size +syn keyword ngxDirectiveThirdParty contained mongo_buffers +syn keyword ngxDirectiveThirdParty contained mongo_busy_buffers_size +syn keyword ngxDirectiveThirdParty contained mongo_next_upstream + +" MP4 Streaming Lite Module " Will seek to a certain time within H.264/MP4 files when provided with a 'start' parameter in the URL. -syn keyword ngxDirectiveThirdParty mp4 +" syn keyword ngxDirectiveThirdParty contained mp4 -" Nginx Notice Module +" NAXSI Module +" NAXSI is an open-source, high performance, low rules maintenance WAF for NGINX +syn keyword ngxDirectiveThirdParty contained DeniedUrl denied_url +syn keyword ngxDirectiveThirdParty contained LearningMode learning_mode +syn keyword ngxDirectiveThirdParty contained SecRulesEnabled rules_enabled +syn keyword ngxDirectiveThirdParty contained SecRulesDisabled rules_disabled +syn keyword ngxDirectiveThirdParty contained CheckRule check_rule +syn keyword ngxDirectiveThirdParty contained BasicRule basic_rule +syn keyword ngxDirectiveThirdParty contained MainRule main_rule +syn keyword ngxDirectiveThirdParty contained LibInjectionSql libinjection_sql +syn keyword ngxDirectiveThirdParty contained LibInjectionXss libinjection_xss + +" Nchan Module +" Fast, horizontally scalable, multiprocess pub/sub queuing server and proxy for HTTP, long-polling, Websockets and EventSource (SSE) +syn keyword ngxDirectiveThirdParty contained nchan_channel_id +syn keyword ngxDirectiveThirdParty contained nchan_channel_id_split_delimiter +syn keyword ngxDirectiveThirdParty contained nchan_eventsource_event +syn keyword ngxDirectiveThirdParty contained nchan_longpoll_multipart_response +syn keyword ngxDirectiveThirdParty contained nchan_publisher +syn keyword ngxDirectiveThirdParty contained nchan_publisher_channel_id +syn keyword ngxDirectiveThirdParty contained nchan_publisher_upstream_request +syn keyword ngxDirectiveThirdParty contained nchan_pubsub +syn keyword ngxDirectiveThirdParty contained nchan_subscribe_request +syn keyword ngxDirectiveThirdParty contained nchan_subscriber +syn keyword ngxDirectiveThirdParty contained nchan_subscriber_channel_id +syn keyword ngxDirectiveThirdParty contained nchan_subscriber_compound_etag_message_id +syn keyword ngxDirectiveThirdParty contained nchan_subscriber_first_message +syn keyword ngxDirectiveThirdParty contained nchan_subscriber_http_raw_stream_separator +syn keyword ngxDirectiveThirdParty contained nchan_subscriber_last_message_id +syn keyword ngxDirectiveThirdParty contained nchan_subscriber_message_id_custom_etag_header +syn keyword ngxDirectiveThirdParty contained nchan_subscriber_timeout +syn keyword ngxDirectiveThirdParty contained nchan_unsubscribe_request +syn keyword ngxDirectiveThirdParty contained nchan_websocket_ping_interval +syn keyword ngxDirectiveThirdParty contained nchan_authorize_request +syn keyword ngxDirectiveThirdParty contained nchan_max_reserved_memory +syn keyword ngxDirectiveThirdParty contained nchan_message_buffer_length +syn keyword ngxDirectiveThirdParty contained nchan_message_timeout +syn keyword ngxDirectiveThirdParty contained nchan_redis_idle_channel_cache_timeout +syn keyword ngxDirectiveThirdParty contained nchan_redis_namespace +syn keyword ngxDirectiveThirdParty contained nchan_redis_pass +syn keyword ngxDirectiveThirdParty contained nchan_redis_ping_interval +syn keyword ngxDirectiveThirdParty contained nchan_redis_server +syn keyword ngxDirectiveThirdParty contained nchan_redis_storage_mode +syn keyword ngxDirectiveThirdParty contained nchan_redis_url +syn keyword ngxDirectiveThirdParty contained nchan_store_messages +syn keyword ngxDirectiveThirdParty contained nchan_use_redis +syn keyword ngxDirectiveThirdParty contained nchan_access_control_allow_origin +syn keyword ngxDirectiveThirdParty contained nchan_channel_group +syn keyword ngxDirectiveThirdParty contained nchan_channel_group_accounting +syn keyword ngxDirectiveThirdParty contained nchan_group_location +syn keyword ngxDirectiveThirdParty contained nchan_group_max_channels +syn keyword ngxDirectiveThirdParty contained nchan_group_max_messages +syn keyword ngxDirectiveThirdParty contained nchan_group_max_messages_disk +syn keyword ngxDirectiveThirdParty contained nchan_group_max_messages_memory +syn keyword ngxDirectiveThirdParty contained nchan_group_max_subscribers +syn keyword ngxDirectiveThirdParty contained nchan_subscribe_existing_channels_only +syn keyword ngxDirectiveThirdParty contained nchan_channel_event_string +syn keyword ngxDirectiveThirdParty contained nchan_channel_events_channel_id +syn keyword ngxDirectiveThirdParty contained nchan_stub_status +syn keyword ngxDirectiveThirdParty contained nchan_max_channel_id_length +syn keyword ngxDirectiveThirdParty contained nchan_max_channel_subscribers +syn keyword ngxDirectiveThirdParty contained nchan_channel_timeout +syn keyword ngxDirectiveThirdParty contained nchan_storage_engine + +" Nginx Notice Module " Serve static file to POST requests. -syn keyword ngxDirectiveThirdParty notice -syn keyword ngxDirectiveThirdParty notice_type - -" Phusion Passenger -" Easy and robust deployment of Ruby on Rails application on Apache and Nginx webservers. -syn keyword ngxDirectiveThirdParty passenger_base_uri -syn keyword ngxDirectiveThirdParty passenger_default_user -syn keyword ngxDirectiveThirdParty passenger_enabled -syn keyword ngxDirectiveThirdParty passenger_log_level -syn keyword ngxDirectiveThirdParty passenger_max_instances_per_app -syn keyword ngxDirectiveThirdParty passenger_max_pool_size -syn keyword ngxDirectiveThirdParty passenger_pool_idle_time -syn keyword ngxDirectiveThirdParty passenger_root -syn keyword ngxDirectiveThirdParty passenger_ruby -syn keyword ngxDirectiveThirdParty passenger_use_global_queue -syn keyword ngxDirectiveThirdParty passenger_user_switching -syn keyword ngxDirectiveThirdParty rack_env -syn keyword ngxDirectiveThirdParty rails_app_spawner_idle_time -syn keyword ngxDirectiveThirdParty rails_env -syn keyword ngxDirectiveThirdParty rails_framework_spawner_idle_time -syn keyword ngxDirectiveThirdParty rails_spawn_method - -" RDS JSON Module -" Help ngx_drizzle and other DBD modules emit JSON data. -syn keyword ngxDirectiveThirdParty rds_json -syn keyword ngxDirectiveThirdParty rds_json_content_type -syn keyword ngxDirectiveThirdParty rds_json_format -syn keyword ngxDirectiveThirdParty rds_json_ret - -" RRD Graph Module +syn keyword ngxDirectiveThirdParty contained notice +syn keyword ngxDirectiveThirdParty contained notice_type + +" OCSP Proxy Module +" Nginx OCSP processing module designed for response caching +syn keyword ngxDirectiveThirdParty contained ocsp_proxy +syn keyword ngxDirectiveThirdParty contained ocsp_cache_timeout + +" Eval Module +" Module for nginx web server evaluates response of proxy or memcached module into variables. +syn keyword ngxDirectiveThirdParty contained eval +syn keyword ngxDirectiveThirdParty contained eval_escalate +syn keyword ngxDirectiveThirdParty contained eval_buffer_size +syn keyword ngxDirectiveThirdParty contained eval_override_content_type +syn keyword ngxDirectiveThirdParty contained eval_subrequest_in_memory + +" OpenSSL Version Module +" Nginx OpenSSL version check at startup +syn keyword ngxDirectiveThirdParty contained openssl_version_minimum +syn keyword ngxDirectiveThirdParty contained openssl_builddate_minimum + +" Owner Match Module +" Control access for specific owners and groups of files +syn keyword ngxDirectiveThirdParty contained omallow +syn keyword ngxDirectiveThirdParty contained omdeny + +" Accept Language Module +" Parses the Accept-Language header and gives the most suitable locale from a list of supported locales. +syn keyword ngxDirectiveThirdParty contained pagespeed + +" PHP Memcache Standard Balancer Module +" Loadbalancer that is compatible to the standard loadbalancer in the php-memcache module +syn keyword ngxDirectiveThirdParty contained hash_key + +" PHP Session Module +" Nginx module to parse php sessions +syn keyword ngxDirectiveThirdParty contained php_session_parse +syn keyword ngxDirectiveThirdParty contained php_session_strip_formatting + +" Phusion Passenger Module +" Passenger is an open source web application server. +syn keyword ngxDirectiveThirdParty contained passenger_root +syn keyword ngxDirectiveThirdParty contained passenger_enabled +syn keyword ngxDirectiveThirdParty contained passenger_base_uri +syn keyword ngxDirectiveThirdParty contained passenger_document_root +syn keyword ngxDirectiveThirdParty contained passenger_ruby +syn keyword ngxDirectiveThirdParty contained passenger_python +syn keyword ngxDirectiveThirdParty contained passenger_nodejs +syn keyword ngxDirectiveThirdParty contained passenger_meteor_app_settings +syn keyword ngxDirectiveThirdParty contained passenger_app_env +syn keyword ngxDirectiveThirdParty contained passenger_app_root +syn keyword ngxDirectiveThirdParty contained passenger_app_group_name +syn keyword ngxDirectiveThirdParty contained passenger_app_type +syn keyword ngxDirectiveThirdParty contained passenger_startup_file +syn keyword ngxDirectiveThirdParty contained passenger_restart_dir +syn keyword ngxDirectiveThirdParty contained passenger_spawn_method +syn keyword ngxDirectiveThirdParty contained passenger_env_var +syn keyword ngxDirectiveThirdParty contained passenger_load_shell_envvars +syn keyword ngxDirectiveThirdParty contained passenger_rolling_restarts +syn keyword ngxDirectiveThirdParty contained passenger_resist_deployment_errors +syn keyword ngxDirectiveThirdParty contained passenger_user_switching +syn keyword ngxDirectiveThirdParty contained passenger_user +syn keyword ngxDirectiveThirdParty contained passenger_group +syn keyword ngxDirectiveThirdParty contained passenger_default_user +syn keyword ngxDirectiveThirdParty contained passenger_default_group +syn keyword ngxDirectiveThirdParty contained passenger_show_version_in_header +syn keyword ngxDirectiveThirdParty contained passenger_friendly_error_pages +syn keyword ngxDirectiveThirdParty contained passenger_disable_security_update_check +syn keyword ngxDirectiveThirdParty contained passenger_security_update_check_proxy +syn keyword ngxDirectiveThirdParty contained passenger_max_pool_size +syn keyword ngxDirectiveThirdParty contained passenger_min_instances +syn keyword ngxDirectiveThirdParty contained passenger_max_instances +syn keyword ngxDirectiveThirdParty contained passenger_max_instances_per_app +syn keyword ngxDirectiveThirdParty contained passenger_pool_idle_time +syn keyword ngxDirectiveThirdParty contained passenger_max_preloader_idle_time +syn keyword ngxDirectiveThirdParty contained passenger_force_max_concurrent_requests_per_process +syn keyword ngxDirectiveThirdParty contained passenger_start_timeout +syn keyword ngxDirectiveThirdParty contained passenger_concurrency_model +syn keyword ngxDirectiveThirdParty contained passenger_thread_count +syn keyword ngxDirectiveThirdParty contained passenger_max_requests +syn keyword ngxDirectiveThirdParty contained passenger_max_request_time +syn keyword ngxDirectiveThirdParty contained passenger_memory_limit +syn keyword ngxDirectiveThirdParty contained passenger_stat_throttle_rate +syn keyword ngxDirectiveThirdParty contained passenger_core_file_descriptor_ulimit +syn keyword ngxDirectiveThirdParty contained passenger_app_file_descriptor_ulimit +syn keyword ngxDirectiveThirdParty contained passenger_pre_start +syn keyword ngxDirectiveThirdParty contained passenger_set_header +syn keyword ngxDirectiveThirdParty contained passenger_max_request_queue_size +syn keyword ngxDirectiveThirdParty contained passenger_request_queue_overflow_status_code +syn keyword ngxDirectiveThirdParty contained passenger_sticky_sessions +syn keyword ngxDirectiveThirdParty contained passenger_sticky_sessions_cookie_name +syn keyword ngxDirectiveThirdParty contained passenger_abort_websockets_on_process_shutdown +syn keyword ngxDirectiveThirdParty contained passenger_ignore_client_abort +syn keyword ngxDirectiveThirdParty contained passenger_intercept_errors +syn keyword ngxDirectiveThirdParty contained passenger_pass_header +syn keyword ngxDirectiveThirdParty contained passenger_ignore_headers +syn keyword ngxDirectiveThirdParty contained passenger_headers_hash_bucket_size +syn keyword ngxDirectiveThirdParty contained passenger_headers_hash_max_size +syn keyword ngxDirectiveThirdParty contained passenger_buffer_response +syn keyword ngxDirectiveThirdParty contained passenger_response_buffer_high_watermark +syn keyword ngxDirectiveThirdParty contained passenger_buffer_size, passenger_buffers, passenger_busy_buffers_size +syn keyword ngxDirectiveThirdParty contained passenger_socket_backlog +syn keyword ngxDirectiveThirdParty contained passenger_log_level +syn keyword ngxDirectiveThirdParty contained passenger_log_file +syn keyword ngxDirectiveThirdParty contained passenger_file_descriptor_log_file +syn keyword ngxDirectiveThirdParty contained passenger_debugger +syn keyword ngxDirectiveThirdParty contained passenger_instance_registry_dir +syn keyword ngxDirectiveThirdParty contained passenger_data_buffer_dir +syn keyword ngxDirectiveThirdParty contained passenger_fly_with +syn keyword ngxDirectiveThirdParty contained union_station_support +syn keyword ngxDirectiveThirdParty contained union_station_key +syn keyword ngxDirectiveThirdParty contained union_station_proxy_address +syn keyword ngxDirectiveThirdParty contained union_station_filter +syn keyword ngxDirectiveThirdParty contained union_station_gateway_address +syn keyword ngxDirectiveThirdParty contained union_station_gateway_port +syn keyword ngxDirectiveThirdParty contained union_station_gateway_cert +syn keyword ngxDirectiveDeprecated contained rails_spawn_method +syn keyword ngxDirectiveDeprecated contained passenger_debug_log_file + +" Postgres Module +" Upstream module that allows nginx to communicate directly with PostgreSQL database. +syn keyword ngxDirectiveThirdParty contained postgres_server +syn keyword ngxDirectiveThirdParty contained postgres_keepalive +syn keyword ngxDirectiveThirdParty contained postgres_pass +syn keyword ngxDirectiveThirdParty contained postgres_query +syn keyword ngxDirectiveThirdParty contained postgres_rewrite +syn keyword ngxDirectiveThirdParty contained postgres_output +syn keyword ngxDirectiveThirdParty contained postgres_set +syn keyword ngxDirectiveThirdParty contained postgres_escape +syn keyword ngxDirectiveThirdParty contained postgres_connect_timeout +syn keyword ngxDirectiveThirdParty contained postgres_result_timeout + +" Pubcookie Module +" Authorizes users using encrypted cookies +syn keyword ngxDirectiveThirdParty contained pubcookie_inactive_expire +syn keyword ngxDirectiveThirdParty contained pubcookie_hard_expire +syn keyword ngxDirectiveThirdParty contained pubcookie_app_id +syn keyword ngxDirectiveThirdParty contained pubcookie_dir_depth +syn keyword ngxDirectiveThirdParty contained pubcookie_catenate_app_ids +syn keyword ngxDirectiveThirdParty contained pubcookie_app_srv_id +syn keyword ngxDirectiveThirdParty contained pubcookie_login +syn keyword ngxDirectiveThirdParty contained pubcookie_login_method +syn keyword ngxDirectiveThirdParty contained pubcookie_post +syn keyword ngxDirectiveThirdParty contained pubcookie_domain +syn keyword ngxDirectiveThirdParty contained pubcookie_granting_cert_file +syn keyword ngxDirectiveThirdParty contained pubcookie_session_key_file +syn keyword ngxDirectiveThirdParty contained pubcookie_session_cert_file +syn keyword ngxDirectiveThirdParty contained pubcookie_crypt_key_file +syn keyword ngxDirectiveThirdParty contained pubcookie_end_session +syn keyword ngxDirectiveThirdParty contained pubcookie_encryption +syn keyword ngxDirectiveThirdParty contained pubcookie_session_reauth +syn keyword ngxDirectiveThirdParty contained pubcookie_auth_type_names +syn keyword ngxDirectiveThirdParty contained pubcookie_no_prompt +syn keyword ngxDirectiveThirdParty contained pubcookie_on_demand +syn keyword ngxDirectiveThirdParty contained pubcookie_addl_request +syn keyword ngxDirectiveThirdParty contained pubcookie_no_obscure_cookies +syn keyword ngxDirectiveThirdParty contained pubcookie_no_clean_creds +syn keyword ngxDirectiveThirdParty contained pubcookie_egd_device +syn keyword ngxDirectiveThirdParty contained pubcookie_no_blank +syn keyword ngxDirectiveThirdParty contained pubcookie_super_debug +syn keyword ngxDirectiveThirdParty contained pubcookie_set_remote_user + +" Push Stream Module +" A pure stream http push technology for your Nginx setup +syn keyword ngxDirectiveThirdParty contained push_stream_channels_statistics +syn keyword ngxDirectiveThirdParty contained push_stream_publisher +syn keyword ngxDirectiveThirdParty contained push_stream_subscriber +syn keyword ngxDirectiveThirdParty contained push_stream_shared_memory_size +syn keyword ngxDirectiveThirdParty contained push_stream_channel_deleted_message_text +syn keyword ngxDirectiveThirdParty contained push_stream_channel_inactivity_time +syn keyword ngxDirectiveThirdParty contained push_stream_ping_message_text +syn keyword ngxDirectiveThirdParty contained push_stream_timeout_with_body +syn keyword ngxDirectiveThirdParty contained push_stream_message_ttl +syn keyword ngxDirectiveThirdParty contained push_stream_max_subscribers_per_channel +syn keyword ngxDirectiveThirdParty contained push_stream_max_messages_stored_per_channel +syn keyword ngxDirectiveThirdParty contained push_stream_max_channel_id_length +syn keyword ngxDirectiveThirdParty contained push_stream_max_number_of_channels +syn keyword ngxDirectiveThirdParty contained push_stream_max_number_of_wildcard_channels +syn keyword ngxDirectiveThirdParty contained push_stream_wildcard_channel_prefix +syn keyword ngxDirectiveThirdParty contained push_stream_events_channel_id +syn keyword ngxDirectiveThirdParty contained push_stream_channels_path +syn keyword ngxDirectiveThirdParty contained push_stream_store_messages +syn keyword ngxDirectiveThirdParty contained push_stream_channel_info_on_publish +syn keyword ngxDirectiveThirdParty contained push_stream_authorized_channels_only +syn keyword ngxDirectiveThirdParty contained push_stream_header_template_file +syn keyword ngxDirectiveThirdParty contained push_stream_header_template +syn keyword ngxDirectiveThirdParty contained push_stream_message_template +syn keyword ngxDirectiveThirdParty contained push_stream_footer_template +syn keyword ngxDirectiveThirdParty contained push_stream_wildcard_channel_max_qtd +syn keyword ngxDirectiveThirdParty contained push_stream_ping_message_interval +syn keyword ngxDirectiveThirdParty contained push_stream_subscriber_connection_ttl +syn keyword ngxDirectiveThirdParty contained push_stream_longpolling_connection_ttl +syn keyword ngxDirectiveThirdParty contained push_stream_websocket_allow_publish +syn keyword ngxDirectiveThirdParty contained push_stream_last_received_message_time +syn keyword ngxDirectiveThirdParty contained push_stream_last_received_message_tag +syn keyword ngxDirectiveThirdParty contained push_stream_last_event_id +syn keyword ngxDirectiveThirdParty contained push_stream_user_agent +syn keyword ngxDirectiveThirdParty contained push_stream_padding_by_user_agent +syn keyword ngxDirectiveThirdParty contained push_stream_allowed_origins +syn keyword ngxDirectiveThirdParty contained push_stream_allow_connections_to_events_channel + +" rDNS Module +" Make a reverse DNS (rDNS) lookup for incoming connection and provides simple access control of incoming hostname by allow/deny rules +syn keyword ngxDirectiveThirdParty contained rdns +syn keyword ngxDirectiveThirdParty contained rdns_allow +syn keyword ngxDirectiveThirdParty contained rdns_deny + +" RDS CSV Module +" Nginx output filter module to convert Resty-DBD-Streams (RDS) to Comma-Separated Values (CSV) +syn keyword ngxDirectiveThirdParty contained rds_csv +syn keyword ngxDirectiveThirdParty contained rds_csv_row_terminator +syn keyword ngxDirectiveThirdParty contained rds_csv_field_separator +syn keyword ngxDirectiveThirdParty contained rds_csv_field_name_header +syn keyword ngxDirectiveThirdParty contained rds_csv_content_type +syn keyword ngxDirectiveThirdParty contained rds_csv_buffer_size + +" RDS JSON Module +" An output filter that formats Resty DBD Streams generated by ngx_drizzle and others to JSON +syn keyword ngxDirectiveThirdParty contained rds_json +syn keyword ngxDirectiveThirdParty contained rds_json_buffer_size +syn keyword ngxDirectiveThirdParty contained rds_json_format +syn keyword ngxDirectiveThirdParty contained rds_json_root +syn keyword ngxDirectiveThirdParty contained rds_json_success_property +syn keyword ngxDirectiveThirdParty contained rds_json_user_property +syn keyword ngxDirectiveThirdParty contained rds_json_errcode_key +syn keyword ngxDirectiveThirdParty contained rds_json_errstr_key +syn keyword ngxDirectiveThirdParty contained rds_json_ret +syn keyword ngxDirectiveThirdParty contained rds_json_content_type + +" Redis Module +" Use this module to perform simple caching +syn keyword ngxDirectiveThirdParty contained redis_pass +syn keyword ngxDirectiveThirdParty contained redis_bind +syn keyword ngxDirectiveThirdParty contained redis_connect_timeout +syn keyword ngxDirectiveThirdParty contained redis_read_timeout +syn keyword ngxDirectiveThirdParty contained redis_send_timeout +syn keyword ngxDirectiveThirdParty contained redis_buffer_size +syn keyword ngxDirectiveThirdParty contained redis_next_upstream +syn keyword ngxDirectiveThirdParty contained redis_gzip_flag + +" Redis 2 Module +" Nginx upstream module for the Redis 2.0 protocol +syn keyword ngxDirectiveThirdParty contained redis2_query +syn keyword ngxDirectiveThirdParty contained redis2_raw_query +syn keyword ngxDirectiveThirdParty contained redis2_raw_queries +syn keyword ngxDirectiveThirdParty contained redis2_literal_raw_query +syn keyword ngxDirectiveThirdParty contained redis2_pass +syn keyword ngxDirectiveThirdParty contained redis2_connect_timeout +syn keyword ngxDirectiveThirdParty contained redis2_send_timeout +syn keyword ngxDirectiveThirdParty contained redis2_read_timeout +syn keyword ngxDirectiveThirdParty contained redis2_buffer_size +syn keyword ngxDirectiveThirdParty contained redis2_next_upstream + +" Replace Filter Module +" Streaming regular expression replacement in response bodies +syn keyword ngxDirectiveThirdParty contained replace_filter +syn keyword ngxDirectiveThirdParty contained replace_filter_types +syn keyword ngxDirectiveThirdParty contained replace_filter_max_buffered_size +syn keyword ngxDirectiveThirdParty contained replace_filter_last_modified +syn keyword ngxDirectiveThirdParty contained replace_filter_skip + +" Roboo Module +" HTTP Robot Mitigator + +" RRD Graph Module " This module provides an HTTP interface to RRDtool's graphing facilities. -syn keyword ngxDirectiveThirdParty rrd_graph -syn keyword ngxDirectiveThirdParty rrd_graph_root +syn keyword ngxDirectiveThirdParty contained rrd_graph +syn keyword ngxDirectiveThirdParty contained rrd_graph_root + +" RTMP Module +" NGINX-based Media Streaming Server +syn keyword ngxDirectiveThirdParty contained rtmp +" syn keyword ngxDirectiveThirdParty contained server +" syn keyword ngxDirectiveThirdParty contained listen +syn keyword ngxDirectiveThirdParty contained application +" syn keyword ngxDirectiveThirdParty contained timeout +syn keyword ngxDirectiveThirdParty contained ping +syn keyword ngxDirectiveThirdParty contained ping_timeout +syn keyword ngxDirectiveThirdParty contained max_streams +syn keyword ngxDirectiveThirdParty contained ack_window +syn keyword ngxDirectiveThirdParty contained chunk_size +syn keyword ngxDirectiveThirdParty contained max_queue +syn keyword ngxDirectiveThirdParty contained max_message +syn keyword ngxDirectiveThirdParty contained out_queue +syn keyword ngxDirectiveThirdParty contained out_cork +" syn keyword ngxDirectiveThirdParty contained allow +" syn keyword ngxDirectiveThirdParty contained deny +syn keyword ngxDirectiveThirdParty contained exec_push +syn keyword ngxDirectiveThirdParty contained exec_pull +syn keyword ngxDirectiveThirdParty contained exec +syn keyword ngxDirectiveThirdParty contained exec_options +syn keyword ngxDirectiveThirdParty contained exec_static +syn keyword ngxDirectiveThirdParty contained exec_kill_signal +syn keyword ngxDirectiveThirdParty contained respawn +syn keyword ngxDirectiveThirdParty contained respawn_timeout +syn keyword ngxDirectiveThirdParty contained exec_publish +syn keyword ngxDirectiveThirdParty contained exec_play +syn keyword ngxDirectiveThirdParty contained exec_play_done +syn keyword ngxDirectiveThirdParty contained exec_publish_done +syn keyword ngxDirectiveThirdParty contained exec_record_done +syn keyword ngxDirectiveThirdParty contained live +syn keyword ngxDirectiveThirdParty contained meta +syn keyword ngxDirectiveThirdParty contained interleave +syn keyword ngxDirectiveThirdParty contained wait_key +syn keyword ngxDirectiveThirdParty contained wait_video +syn keyword ngxDirectiveThirdParty contained publish_notify +syn keyword ngxDirectiveThirdParty contained drop_idle_publisher +syn keyword ngxDirectiveThirdParty contained sync +syn keyword ngxDirectiveThirdParty contained play_restart +syn keyword ngxDirectiveThirdParty contained idle_streams +syn keyword ngxDirectiveThirdParty contained record +syn keyword ngxDirectiveThirdParty contained record_path +syn keyword ngxDirectiveThirdParty contained record_suffix +syn keyword ngxDirectiveThirdParty contained record_unique +syn keyword ngxDirectiveThirdParty contained record_append +syn keyword ngxDirectiveThirdParty contained record_lock +syn keyword ngxDirectiveThirdParty contained record_max_size +syn keyword ngxDirectiveThirdParty contained record_max_frames +syn keyword ngxDirectiveThirdParty contained record_interval +syn keyword ngxDirectiveThirdParty contained recorder +syn keyword ngxDirectiveThirdParty contained record_notify +syn keyword ngxDirectiveThirdParty contained play +syn keyword ngxDirectiveThirdParty contained play_temp_path +syn keyword ngxDirectiveThirdParty contained play_local_path +syn keyword ngxDirectiveThirdParty contained pull +syn keyword ngxDirectiveThirdParty contained push +syn keyword ngxDirectiveThirdParty contained push_reconnect +syn keyword ngxDirectiveThirdParty contained session_relay +syn keyword ngxDirectiveThirdParty contained on_connect +syn keyword ngxDirectiveThirdParty contained on_play +syn keyword ngxDirectiveThirdParty contained on_publish +syn keyword ngxDirectiveThirdParty contained on_done +syn keyword ngxDirectiveThirdParty contained on_play_done +syn keyword ngxDirectiveThirdParty contained on_publish_done +syn keyword ngxDirectiveThirdParty contained on_record_done +syn keyword ngxDirectiveThirdParty contained on_update +syn keyword ngxDirectiveThirdParty contained notify_update_timeout +syn keyword ngxDirectiveThirdParty contained notify_update_strict +syn keyword ngxDirectiveThirdParty contained notify_relay_redirect +syn keyword ngxDirectiveThirdParty contained notify_method +syn keyword ngxDirectiveThirdParty contained hls +syn keyword ngxDirectiveThirdParty contained hls_path +syn keyword ngxDirectiveThirdParty contained hls_fragment +syn keyword ngxDirectiveThirdParty contained hls_playlist_length +syn keyword ngxDirectiveThirdParty contained hls_sync +syn keyword ngxDirectiveThirdParty contained hls_continuous +syn keyword ngxDirectiveThirdParty contained hls_nested +syn keyword ngxDirectiveThirdParty contained hls_base_url +syn keyword ngxDirectiveThirdParty contained hls_cleanup +syn keyword ngxDirectiveThirdParty contained hls_fragment_naming +syn keyword ngxDirectiveThirdParty contained hls_fragment_slicing +syn keyword ngxDirectiveThirdParty contained hls_variant +syn keyword ngxDirectiveThirdParty contained hls_type +syn keyword ngxDirectiveThirdParty contained hls_keys +syn keyword ngxDirectiveThirdParty contained hls_key_path +syn keyword ngxDirectiveThirdParty contained hls_key_url +syn keyword ngxDirectiveThirdParty contained hls_fragments_per_key +syn keyword ngxDirectiveThirdParty contained dash +syn keyword ngxDirectiveThirdParty contained dash_path +syn keyword ngxDirectiveThirdParty contained dash_fragment +syn keyword ngxDirectiveThirdParty contained dash_playlist_length +syn keyword ngxDirectiveThirdParty contained dash_nested +syn keyword ngxDirectiveThirdParty contained dash_cleanup +" syn keyword ngxDirectiveThirdParty contained access_log +" syn keyword ngxDirectiveThirdParty contained log_format +syn keyword ngxDirectiveThirdParty contained max_connections +syn keyword ngxDirectiveThirdParty contained rtmp_stat +syn keyword ngxDirectiveThirdParty contained rtmp_stat_stylesheet +syn keyword ngxDirectiveThirdParty contained rtmp_auto_push +syn keyword ngxDirectiveThirdParty contained rtmp_auto_push_reconnect +syn keyword ngxDirectiveThirdParty contained rtmp_socket_dir +syn keyword ngxDirectiveThirdParty contained rtmp_control + +" RTMPT Module +" Module for nginx to proxy rtmp using http protocol +syn keyword ngxDirectiveThirdParty contained rtmpt_proxy_target +syn keyword ngxDirectiveThirdParty contained rtmpt_proxy_rtmp_timeout +syn keyword ngxDirectiveThirdParty contained rtmpt_proxy_http_timeout +syn keyword ngxDirectiveThirdParty contained rtmpt_proxy +syn keyword ngxDirectiveThirdParty contained rtmpt_proxy_stat +syn keyword ngxDirectiveThirdParty contained rtmpt_proxy_stylesheet + +" Syntactically Awesome Module +" Providing on-the-fly compiling of Sass files as an NGINX module. +syn keyword ngxDirectiveThirdParty contained sass_compile +syn keyword ngxDirectiveThirdParty contained sass_error_log +syn keyword ngxDirectiveThirdParty contained sass_include_path +syn keyword ngxDirectiveThirdParty contained sass_indent +syn keyword ngxDirectiveThirdParty contained sass_is_indented_syntax +syn keyword ngxDirectiveThirdParty contained sass_linefeed +syn keyword ngxDirectiveThirdParty contained sass_precision +syn keyword ngxDirectiveThirdParty contained sass_output_style +syn keyword ngxDirectiveThirdParty contained sass_source_comments +syn keyword ngxDirectiveThirdParty contained sass_source_map_embed + +" Secure Download Module +" Enables you to create links which are only valid until a certain datetime is reached +syn keyword ngxDirectiveThirdParty contained secure_download +syn keyword ngxDirectiveThirdParty contained secure_download_secret +syn keyword ngxDirectiveThirdParty contained secure_download_path_mode -" Secure Download -" Create expiring links. -syn keyword ngxDirectiveThirdParty secure_download -syn keyword ngxDirectiveThirdParty secure_download_fail_location -syn keyword ngxDirectiveThirdParty secure_download_path_mode -syn keyword ngxDirectiveThirdParty secure_download_secret +" Selective Cache Purge Module +" A module to purge cache by GLOB patterns. The supported patterns are the same as supported by Redis. +syn keyword ngxDirectiveThirdParty contained selective_cache_purge_redis_unix_socket +syn keyword ngxDirectiveThirdParty contained selective_cache_purge_redis_host +syn keyword ngxDirectiveThirdParty contained selective_cache_purge_redis_port +syn keyword ngxDirectiveThirdParty contained selective_cache_purge_redis_database +syn keyword ngxDirectiveThirdParty contained selective_cache_purge_query -" SlowFS Cache Module +" Set cconv Module +" Cconv rewrite set commands +syn keyword ngxDirectiveThirdParty contained set_cconv_to_simp +syn keyword ngxDirectiveThirdParty contained set_cconv_to_trad +syn keyword ngxDirectiveThirdParty contained set_pinyin_to_normal + +" Set Hash Module +" Nginx module that allows the setting of variables to the value of a variety of hashes +syn keyword ngxDirectiveThirdParty contained set_md5 +syn keyword ngxDirectiveThirdParty contained set_md5_upper +syn keyword ngxDirectiveThirdParty contained set_murmur2 +syn keyword ngxDirectiveThirdParty contained set_murmur2_upper +syn keyword ngxDirectiveThirdParty contained set_sha1 +syn keyword ngxDirectiveThirdParty contained set_sha1_upper + +" Set Lang Module +" Provides a variety of ways for setting a variable denoting the langauge that content should be returned in. +syn keyword ngxDirectiveThirdParty contained set_lang +syn keyword ngxDirectiveThirdParty contained set_lang_method +syn keyword ngxDirectiveThirdParty contained lang_cookie +syn keyword ngxDirectiveThirdParty contained lang_get_var +syn keyword ngxDirectiveThirdParty contained lang_list +syn keyword ngxDirectiveThirdParty contained lang_post_var +syn keyword ngxDirectiveThirdParty contained lang_host +syn keyword ngxDirectiveThirdParty contained lang_referer + +" Set Misc Module +" Various set_xxx directives added to nginx's rewrite module +syn keyword ngxDirectiveThirdParty contained set_if_empty +syn keyword ngxDirectiveThirdParty contained set_quote_sql_str +syn keyword ngxDirectiveThirdParty contained set_quote_pgsql_str +syn keyword ngxDirectiveThirdParty contained set_quote_json_str +syn keyword ngxDirectiveThirdParty contained set_unescape_uri +syn keyword ngxDirectiveThirdParty contained set_escape_uri +syn keyword ngxDirectiveThirdParty contained set_hashed_upstream +syn keyword ngxDirectiveThirdParty contained set_encode_base32 +syn keyword ngxDirectiveThirdParty contained set_base32_padding +syn keyword ngxDirectiveThirdParty contained set_misc_base32_padding +syn keyword ngxDirectiveThirdParty contained set_base32_alphabet +syn keyword ngxDirectiveThirdParty contained set_decode_base32 +syn keyword ngxDirectiveThirdParty contained set_encode_base64 +syn keyword ngxDirectiveThirdParty contained set_decode_base64 +syn keyword ngxDirectiveThirdParty contained set_encode_hex +syn keyword ngxDirectiveThirdParty contained set_decode_hex +syn keyword ngxDirectiveThirdParty contained set_sha1 +syn keyword ngxDirectiveThirdParty contained set_md5 +syn keyword ngxDirectiveThirdParty contained set_hmac_sha1 +syn keyword ngxDirectiveThirdParty contained set_random +syn keyword ngxDirectiveThirdParty contained set_secure_random_alphanum +syn keyword ngxDirectiveThirdParty contained set_secure_random_lcalpha +syn keyword ngxDirectiveThirdParty contained set_rotate +syn keyword ngxDirectiveThirdParty contained set_local_today +syn keyword ngxDirectiveThirdParty contained set_formatted_gmt_time +syn keyword ngxDirectiveThirdParty contained set_formatted_local_time + +" SFlow Module +" A binary, random-sampling nginx module designed for: lightweight, centralized, continuous, real-time monitoring of very large and very busy web farms. +syn keyword ngxDirectiveThirdParty contained sflow + +" Shibboleth Module +" Shibboleth auth request module for nginx +syn keyword ngxDirectiveThirdParty contained shib_request +syn keyword ngxDirectiveThirdParty contained shib_request_set +syn keyword ngxDirectiveThirdParty contained shib_request_use_headers + +" Slice Module +" Nginx module for serving a file in slices (reverse byte-range) +" syn keyword ngxDirectiveThirdParty contained slice +syn keyword ngxDirectiveThirdParty contained slice_arg_begin +syn keyword ngxDirectiveThirdParty contained slice_arg_end +syn keyword ngxDirectiveThirdParty contained slice_header +syn keyword ngxDirectiveThirdParty contained slice_footer +syn keyword ngxDirectiveThirdParty contained slice_header_first +syn keyword ngxDirectiveThirdParty contained slice_footer_last + +" SlowFS Cache Module " Module adding ability to cache static files. -syn keyword ngxDirectiveThirdParty slowfs_big_file_size -syn keyword ngxDirectiveThirdParty slowfs_cache -syn keyword ngxDirectiveThirdParty slowfs_cache_key -syn keyword ngxDirectiveThirdParty slowfs_cache_min_uses -syn keyword ngxDirectiveThirdParty slowfs_cache_path -syn keyword ngxDirectiveThirdParty slowfs_cache_purge -syn keyword ngxDirectiveThirdParty slowfs_cache_valid -syn keyword ngxDirectiveThirdParty slowfs_temp_path - -" Strip Module +syn keyword ngxDirectiveThirdParty contained slowfs_big_file_size +syn keyword ngxDirectiveThirdParty contained slowfs_cache +syn keyword ngxDirectiveThirdParty contained slowfs_cache_key +syn keyword ngxDirectiveThirdParty contained slowfs_cache_min_uses +syn keyword ngxDirectiveThirdParty contained slowfs_cache_path +syn keyword ngxDirectiveThirdParty contained slowfs_cache_purge +syn keyword ngxDirectiveThirdParty contained slowfs_cache_valid +syn keyword ngxDirectiveThirdParty contained slowfs_temp_path + +" Small Light Module +" Dynamic Image Transformation Module For nginx. +syn keyword ngxDirectiveThirdParty contained small_light +syn keyword ngxDirectiveThirdParty contained small_light_getparam_mode +syn keyword ngxDirectiveThirdParty contained small_light_material_dir +syn keyword ngxDirectiveThirdParty contained small_light_pattern_define +syn keyword ngxDirectiveThirdParty contained small_light_radius_max +syn keyword ngxDirectiveThirdParty contained small_light_sigma_max +syn keyword ngxDirectiveThirdParty contained small_light_imlib2_temp_dir +syn keyword ngxDirectiveThirdParty contained small_light_buffer + +" Sorted Querystring Filter Module +" Nginx module to expose querystring parameters sorted in a variable to be used on cache_key as example +syn keyword ngxDirectiveThirdParty contained sorted_querystring_filter_parameter + +" Sphinx2 Module +" Nginx upstream module for Sphinx 2.x +syn keyword ngxDirectiveThirdParty contained sphinx2_pass +syn keyword ngxDirectiveThirdParty contained sphinx2_bind +syn keyword ngxDirectiveThirdParty contained sphinx2_connect_timeout +syn keyword ngxDirectiveThirdParty contained sphinx2_send_timeout +syn keyword ngxDirectiveThirdParty contained sphinx2_buffer_size +syn keyword ngxDirectiveThirdParty contained sphinx2_read_timeout +syn keyword ngxDirectiveThirdParty contained sphinx2_next_upstream + +" HTTP SPNEGO auth Module +" This module implements adds SPNEGO support to nginx(http://nginx.org). It currently supports only Kerberos authentication via GSSAPI +syn keyword ngxDirectiveThirdParty contained auth_gss +syn keyword ngxDirectiveThirdParty contained auth_gss_keytab +syn keyword ngxDirectiveThirdParty contained auth_gss_realm +syn keyword ngxDirectiveThirdParty contained auth_gss_service_name +syn keyword ngxDirectiveThirdParty contained auth_gss_authorized_principal +syn keyword ngxDirectiveThirdParty contained auth_gss_allow_basic_fallback + +" SR Cache Module +" Transparent subrequest-based caching layout for arbitrary nginx locations +syn keyword ngxDirectiveThirdParty contained srcache_fetch +syn keyword ngxDirectiveThirdParty contained srcache_fetch_skip +syn keyword ngxDirectiveThirdParty contained srcache_store +syn keyword ngxDirectiveThirdParty contained srcache_store_max_size +syn keyword ngxDirectiveThirdParty contained srcache_store_skip +syn keyword ngxDirectiveThirdParty contained srcache_store_statuses +syn keyword ngxDirectiveThirdParty contained srcache_store_ranges +syn keyword ngxDirectiveThirdParty contained srcache_header_buffer_size +syn keyword ngxDirectiveThirdParty contained srcache_store_hide_header +syn keyword ngxDirectiveThirdParty contained srcache_store_pass_header +syn keyword ngxDirectiveThirdParty contained srcache_methods +syn keyword ngxDirectiveThirdParty contained srcache_ignore_content_encoding +syn keyword ngxDirectiveThirdParty contained srcache_request_cache_control +syn keyword ngxDirectiveThirdParty contained srcache_response_cache_control +syn keyword ngxDirectiveThirdParty contained srcache_store_no_store +syn keyword ngxDirectiveThirdParty contained srcache_store_no_cache +syn keyword ngxDirectiveThirdParty contained srcache_store_private +syn keyword ngxDirectiveThirdParty contained srcache_default_expire +syn keyword ngxDirectiveThirdParty contained srcache_max_expire + +" SSSD Info Module +" Retrives additional attributes from SSSD for current authentizated user +syn keyword ngxDirectiveThirdParty contained sssd_info +syn keyword ngxDirectiveThirdParty contained sssd_info_output_to +syn keyword ngxDirectiveThirdParty contained sssd_info_groups +syn keyword ngxDirectiveThirdParty contained sssd_info_group +syn keyword ngxDirectiveThirdParty contained sssd_info_group_separator +syn keyword ngxDirectiveThirdParty contained sssd_info_attributes +syn keyword ngxDirectiveThirdParty contained sssd_info_attribute +syn keyword ngxDirectiveThirdParty contained sssd_info_attribute_separator + +" Static Etags Module +" Generate etags for static content +syn keyword ngxDirectiveThirdParty contained FileETag + +" Statsd Module +" An nginx module for sending statistics to statsd +syn keyword ngxDirectiveThirdParty contained statsd_server +syn keyword ngxDirectiveThirdParty contained statsd_sample_rate +syn keyword ngxDirectiveThirdParty contained statsd_count +syn keyword ngxDirectiveThirdParty contained statsd_timing + +" Sticky Module +" Add a sticky cookie to be always forwarded to the same upstream server +" syn keyword ngxDirectiveThirdParty contained sticky + +" Stream Echo Module +" TCP/stream echo module for NGINX (a port of ngx_http_echo_module) +syn keyword ngxDirectiveThirdParty contained echo +syn keyword ngxDirectiveThirdParty contained echo_duplicate +syn keyword ngxDirectiveThirdParty contained echo_flush_wait +syn keyword ngxDirectiveThirdParty contained echo_sleep +syn keyword ngxDirectiveThirdParty contained echo_send_timeout +syn keyword ngxDirectiveThirdParty contained echo_read_bytes +syn keyword ngxDirectiveThirdParty contained echo_read_line +syn keyword ngxDirectiveThirdParty contained echo_request_data +syn keyword ngxDirectiveThirdParty contained echo_discard_request +syn keyword ngxDirectiveThirdParty contained echo_read_buffer_size +syn keyword ngxDirectiveThirdParty contained echo_read_timeout +syn keyword ngxDirectiveThirdParty contained echo_client_error_log_level +syn keyword ngxDirectiveThirdParty contained echo_lingering_close +syn keyword ngxDirectiveThirdParty contained echo_lingering_time +syn keyword ngxDirectiveThirdParty contained echo_lingering_timeout + +" Stream Lua Module +" Embed the power of Lua into Nginx stream/TCP Servers. +syn keyword ngxDirectiveThirdParty contained lua_resolver +syn keyword ngxDirectiveThirdParty contained lua_resolver_timeout +syn keyword ngxDirectiveThirdParty contained lua_lingering_close +syn keyword ngxDirectiveThirdParty contained lua_lingering_time +syn keyword ngxDirectiveThirdParty contained lua_lingering_timeout + +" Stream Upsync Module +" Sync upstreams from consul or others, dynamiclly modify backend-servers attribute(weight, max_fails,...), needn't reload nginx. +syn keyword ngxDirectiveThirdParty contained upsync +syn keyword ngxDirectiveThirdParty contained upsync_dump_path +syn keyword ngxDirectiveThirdParty contained upsync_lb +syn keyword ngxDirectiveThirdParty contained upsync_show + +" Strip Module " Whitespace remover. -syn keyword ngxDirectiveThirdParty strip +syn keyword ngxDirectiveThirdParty contained strip + +" Subrange Module +" Split one big HTTP/Range request to multiple subrange requesets +syn keyword ngxDirectiveThirdParty contained subrange -" Substitutions Module +" Substitutions Module " A filter module which can do both regular expression and fixed string substitutions on response bodies. -syn keyword ngxDirectiveThirdParty subs_filter -syn keyword ngxDirectiveThirdParty subs_filter_types +syn keyword ngxDirectiveThirdParty contained subs_filter +syn keyword ngxDirectiveThirdParty contained subs_filter_types -" Supervisord Module +" Summarizer Module +" Upstream nginx module to get summaries of documents using the summarizer daemon service +syn keyword ngxDirectiveThirdParty contained smrzr_filename +syn keyword ngxDirectiveThirdParty contained smrzr_ratio + +" Supervisord Module " Module providing nginx with API to communicate with supervisord and manage (start/stop) backends on-demand. -syn keyword ngxDirectiveThirdParty supervisord -syn keyword ngxDirectiveThirdParty supervisord_inherit_backend_status -syn keyword ngxDirectiveThirdParty supervisord_name -syn keyword ngxDirectiveThirdParty supervisord_start -syn keyword ngxDirectiveThirdParty supervisord_stop - -" Upload Module -" Parses multipart/form-data allowing arbitrary handling of uploaded files. -syn keyword ngxDirectiveThirdParty upload_aggregate_form_field -syn keyword ngxDirectiveThirdParty upload_buffer_size -syn keyword ngxDirectiveThirdParty upload_cleanup -syn keyword ngxDirectiveThirdParty upload_limit_rate -syn keyword ngxDirectiveThirdParty upload_max_file_size -syn keyword ngxDirectiveThirdParty upload_max_output_body_len -syn keyword ngxDirectiveThirdParty upload_max_part_header_len -syn keyword ngxDirectiveThirdParty upload_pass -syn keyword ngxDirectiveThirdParty upload_pass_args -syn keyword ngxDirectiveThirdParty upload_pass_form_field -syn keyword ngxDirectiveThirdParty upload_set_form_field -syn keyword ngxDirectiveThirdParty upload_store -syn keyword ngxDirectiveThirdParty upload_store_access - -" Upload Progress Module -" Tracks and reports upload progress. -syn keyword ngxDirectiveThirdParty report_uploads -syn keyword ngxDirectiveThirdParty track_uploads -syn keyword ngxDirectiveThirdParty upload_progress -syn keyword ngxDirectiveThirdParty upload_progress_content_type -syn keyword ngxDirectiveThirdParty upload_progress_header -syn keyword ngxDirectiveThirdParty upload_progress_json_output -syn keyword ngxDirectiveThirdParty upload_progress_template - -" Upstream Fair Balancer -" Sends an incoming request to the least-busy backend server, rather than distributing requests round-robin. -syn keyword ngxDirectiveThirdParty fair -syn keyword ngxDirectiveThirdParty upstream_fair_shm_size +syn keyword ngxDirectiveThirdParty contained supervisord +syn keyword ngxDirectiveThirdParty contained supervisord_inherit_backend_status +syn keyword ngxDirectiveThirdParty contained supervisord_name +syn keyword ngxDirectiveThirdParty contained supervisord_start +syn keyword ngxDirectiveThirdParty contained supervisord_stop + +" Tarantool Upstream Module +" Tarantool NginX upstream module (REST, JSON API, websockets, load balancing) +syn keyword ngxDirectiveThirdParty contained tnt_pass +syn keyword ngxDirectiveThirdParty contained tnt_http_methods +syn keyword ngxDirectiveThirdParty contained tnt_http_rest_methods +syn keyword ngxDirectiveThirdParty contained tnt_pass_http_request +syn keyword ngxDirectiveThirdParty contained tnt_pass_http_request_buffer_size +syn keyword ngxDirectiveThirdParty contained tnt_method +syn keyword ngxDirectiveThirdParty contained tnt_http_allowed_methods - experemental +syn keyword ngxDirectiveThirdParty contained tnt_send_timeout +syn keyword ngxDirectiveThirdParty contained tnt_read_timeout +syn keyword ngxDirectiveThirdParty contained tnt_buffer_size +syn keyword ngxDirectiveThirdParty contained tnt_next_upstream +syn keyword ngxDirectiveThirdParty contained tnt_connect_timeout +syn keyword ngxDirectiveThirdParty contained tnt_next_upstream +syn keyword ngxDirectiveThirdParty contained tnt_next_upstream_tries +syn keyword ngxDirectiveThirdParty contained tnt_next_upstream_timeout + +" TCP Proxy Module +" Add the feature of tcp proxy with nginx, with health check and status monitor +syn keyword ngxDirectiveBlock contained tcp +" syn keyword ngxDirectiveThirdParty contained server +" syn keyword ngxDirectiveThirdParty contained listen +" syn keyword ngxDirectiveThirdParty contained allow +" syn keyword ngxDirectiveThirdParty contained deny +" syn keyword ngxDirectiveThirdParty contained so_keepalive +" syn keyword ngxDirectiveThirdParty contained tcp_nodelay +" syn keyword ngxDirectiveThirdParty contained timeout +" syn keyword ngxDirectiveThirdParty contained server_name +" syn keyword ngxDirectiveThirdParty contained resolver +" syn keyword ngxDirectiveThirdParty contained resolver_timeout +" syn keyword ngxDirectiveThirdParty contained upstream +syn keyword ngxDirectiveThirdParty contained check +syn keyword ngxDirectiveThirdParty contained check_http_send +syn keyword ngxDirectiveThirdParty contained check_http_expect_alive +syn keyword ngxDirectiveThirdParty contained check_smtp_send +syn keyword ngxDirectiveThirdParty contained check_smtp_expect_alive +syn keyword ngxDirectiveThirdParty contained check_shm_size +syn keyword ngxDirectiveThirdParty contained check_status +" syn keyword ngxDirectiveThirdParty contained ip_hash +" syn keyword ngxDirectiveThirdParty contained proxy_pass +" syn keyword ngxDirectiveThirdParty contained proxy_buffer +" syn keyword ngxDirectiveThirdParty contained proxy_connect_timeout +" syn keyword ngxDirectiveThirdParty contained proxy_read_timeout +syn keyword ngxDirectiveThirdParty contained proxy_write_timeout -" Upstream Consistent Hash -" Select backend based on Consistent hash ring. -syn keyword ngxDirectiveThirdParty consistent_hash +" Testcookie Module +" NGINX module for L7 DDoS attack mitigation +syn keyword ngxDirectiveThirdParty contained testcookie +syn keyword ngxDirectiveThirdParty contained testcookie_name +syn keyword ngxDirectiveThirdParty contained testcookie_domain +syn keyword ngxDirectiveThirdParty contained testcookie_expires +syn keyword ngxDirectiveThirdParty contained testcookie_path +syn keyword ngxDirectiveThirdParty contained testcookie_secret +syn keyword ngxDirectiveThirdParty contained testcookie_session +syn keyword ngxDirectiveThirdParty contained testcookie_arg +syn keyword ngxDirectiveThirdParty contained testcookie_max_attempts +syn keyword ngxDirectiveThirdParty contained testcookie_p3p +syn keyword ngxDirectiveThirdParty contained testcookie_fallback +syn keyword ngxDirectiveThirdParty contained testcookie_whitelist +syn keyword ngxDirectiveThirdParty contained testcookie_pass +syn keyword ngxDirectiveThirdParty contained testcookie_redirect_via_refresh +syn keyword ngxDirectiveThirdParty contained testcookie_refresh_template +syn keyword ngxDirectiveThirdParty contained testcookie_refresh_status +syn keyword ngxDirectiveThirdParty contained testcookie_deny_keepalive +syn keyword ngxDirectiveThirdParty contained testcookie_get_only +syn keyword ngxDirectiveThirdParty contained testcookie_https_location +syn keyword ngxDirectiveThirdParty contained testcookie_refresh_encrypt_cookie +syn keyword ngxDirectiveThirdParty contained testcookie_refresh_encrypt_cookie_key +syn keyword ngxDirectiveThirdParty contained testcookie_refresh_encrypt_iv +syn keyword ngxDirectiveThirdParty contained testcookie_internal +syn keyword ngxDirectiveThirdParty contained testcookie_httponly_flag +syn keyword ngxDirectiveThirdParty contained testcookie_secure_flag -" Upstream Hash Module +" Types Filter Module +" Change the `Content-Type` output header depending on an extension variable according to a condition specified in the 'if' clause. +syn keyword ngxDirectiveThirdParty contained types_filter +syn keyword ngxDirectiveThirdParty contained types_filter_use_default + +" Unzip Module +" Enabling fetching of files that are stored in zipped archives. +syn keyword ngxDirectiveThirdParty contained file_in_unzip_archivefile +syn keyword ngxDirectiveThirdParty contained file_in_unzip_extract +syn keyword ngxDirectiveThirdParty contained file_in_unzip + +" Upload Progress Module +" An upload progress system, that monitors RFC1867 POST upload as they are transmitted to upstream servers +syn keyword ngxDirectiveThirdParty contained upload_progress +syn keyword ngxDirectiveThirdParty contained track_uploads +syn keyword ngxDirectiveThirdParty contained report_uploads +syn keyword ngxDirectiveThirdParty contained upload_progress_content_type +syn keyword ngxDirectiveThirdParty contained upload_progress_header +syn keyword ngxDirectiveThirdParty contained upload_progress_jsonp_parameter +syn keyword ngxDirectiveThirdParty contained upload_progress_json_output +syn keyword ngxDirectiveThirdParty contained upload_progress_jsonp_output +syn keyword ngxDirectiveThirdParty contained upload_progress_template + +" Upload Module +" Parses request body storing all files being uploaded to a directory specified by upload_store directive +syn keyword ngxDirectiveThirdParty contained upload_pass +syn keyword ngxDirectiveThirdParty contained upload_resumable +syn keyword ngxDirectiveThirdParty contained upload_store +syn keyword ngxDirectiveThirdParty contained upload_state_store +syn keyword ngxDirectiveThirdParty contained upload_store_access +syn keyword ngxDirectiveThirdParty contained upload_set_form_field +syn keyword ngxDirectiveThirdParty contained upload_aggregate_form_field +syn keyword ngxDirectiveThirdParty contained upload_pass_form_field +syn keyword ngxDirectiveThirdParty contained upload_cleanup +syn keyword ngxDirectiveThirdParty contained upload_buffer_size +syn keyword ngxDirectiveThirdParty contained upload_max_part_header_len +syn keyword ngxDirectiveThirdParty contained upload_max_file_size +syn keyword ngxDirectiveThirdParty contained upload_limit_rate +syn keyword ngxDirectiveThirdParty contained upload_max_output_body_len +syn keyword ngxDirectiveThirdParty contained upload_tame_arrays +syn keyword ngxDirectiveThirdParty contained upload_pass_args + +" Upstream Fair Module +" The fair load balancer module for nginx http://nginx.localdomain.pl +syn keyword ngxDirectiveThirdParty contained fair +syn keyword ngxDirectiveThirdParty contained upstream_fair_shm_size + +" Upstream Hash Module (DEPRECATED) " Provides simple upstream load distribution by hashing a configurable variable. -syn keyword ngxDirectiveThirdParty hash -syn keyword ngxDirectiveThirdParty hash_again +" syn keyword ngxDirectiveDeprecated contained hash +syn keyword ngxDirectiveDeprecated contained hash_again + +" Upstream Domain Resolve Module +" A load-balancer that resolves an upstream domain name asynchronously. +syn keyword ngxDirectiveThirdParty contained jdomain + +" Upsync Module +" Sync upstreams from consul or others, dynamiclly modify backend-servers attribute(weight, max_fails,...), needn't reload nginx +syn keyword ngxDirectiveThirdParty contained upsync +syn keyword ngxDirectiveThirdParty contained upsync_dump_path +syn keyword ngxDirectiveThirdParty contained upsync_lb +syn keyword ngxDirectiveThirdParty contained upstream_show + +" URL Module +" Nginx url encoding converting module +syn keyword ngxDirectiveThirdParty contained url_encoding_convert +syn keyword ngxDirectiveThirdParty contained url_encoding_convert_from +syn keyword ngxDirectiveThirdParty contained url_encoding_convert_to -" XSS Module +" User Agent Module +" Match browsers and crawlers +syn keyword ngxDirectiveThirdParty contained user_agent + +" Upstrema Ketama Chash Module +" Nginx load-balancer module implementing ketama consistent hashing. +syn keyword ngxDirectiveThirdParty contained ketama_chash + +" Video Thumbextractor Module +" Extract thumbs from a video file +syn keyword ngxDirectiveThirdParty contained video_thumbextractor +syn keyword ngxDirectiveThirdParty contained video_thumbextractor_video_filename +syn keyword ngxDirectiveThirdParty contained video_thumbextractor_video_second +syn keyword ngxDirectiveThirdParty contained video_thumbextractor_image_width +syn keyword ngxDirectiveThirdParty contained video_thumbextractor_image_height +syn keyword ngxDirectiveThirdParty contained video_thumbextractor_only_keyframe +syn keyword ngxDirectiveThirdParty contained video_thumbextractor_next_time +syn keyword ngxDirectiveThirdParty contained video_thumbextractor_tile_rows +syn keyword ngxDirectiveThirdParty contained video_thumbextractor_tile_cols +syn keyword ngxDirectiveThirdParty contained video_thumbextractor_tile_max_rows +syn keyword ngxDirectiveThirdParty contained video_thumbextractor_tile_max_cols +syn keyword ngxDirectiveThirdParty contained video_thumbextractor_tile_sample_interval +syn keyword ngxDirectiveThirdParty contained video_thumbextractor_tile_color +syn keyword ngxDirectiveThirdParty contained video_thumbextractor_tile_margin +syn keyword ngxDirectiveThirdParty contained video_thumbextractor_tile_padding +syn keyword ngxDirectiveThirdParty contained video_thumbextractor_threads +syn keyword ngxDirectiveThirdParty contained video_thumbextractor_processes_per_worker + +" Eval Module +" Module for nginx web server evaluates response of proxy or memcached module into variables. +syn keyword ngxDirectiveThirdParty contained eval +syn keyword ngxDirectiveThirdParty contained eval_escalate +syn keyword ngxDirectiveThirdParty contained eval_override_content_type + +" VTS Module +" Nginx virtual host traffic status module +syn keyword ngxDirectiveThirdParty contained vhost_traffic_status +syn keyword ngxDirectiveThirdParty contained vhost_traffic_status_zone +syn keyword ngxDirectiveThirdParty contained vhost_traffic_status_display +syn keyword ngxDirectiveThirdParty contained vhost_traffic_status_display_format +syn keyword ngxDirectiveThirdParty contained vhost_traffic_status_display_jsonp +syn keyword ngxDirectiveThirdParty contained vhost_traffic_status_filter +syn keyword ngxDirectiveThirdParty contained vhost_traffic_status_filter_by_host +syn keyword ngxDirectiveThirdParty contained vhost_traffic_status_filter_by_set_key +syn keyword ngxDirectiveThirdParty contained vhost_traffic_status_filter_check_duplicate +syn keyword ngxDirectiveThirdParty contained vhost_traffic_status_limit +syn keyword ngxDirectiveThirdParty contained vhost_traffic_status_limit_traffic +syn keyword ngxDirectiveThirdParty contained vhost_traffic_status_limit_traffic_by_set_key +syn keyword ngxDirectiveThirdParty contained vhost_traffic_status_limit_check_duplicate + +" XSS Module " Native support for cross-site scripting (XSS) in an nginx. -syn keyword ngxDirectiveThirdParty xss_callback_arg -syn keyword ngxDirectiveThirdParty xss_get -syn keyword ngxDirectiveThirdParty xss_input_types -syn keyword ngxDirectiveThirdParty xss_output_type +syn keyword ngxDirectiveThirdParty contained xss_get +syn keyword ngxDirectiveThirdParty contained xss_callback_arg +syn keyword ngxDirectiveThirdParty contained xss_override_status +syn keyword ngxDirectiveThirdParty contained xss_check_status +syn keyword ngxDirectiveThirdParty contained xss_input_types + +" ZIP Module +" ZIP archiver for nginx + " highlight hi link ngxComment Comment +hi link ngxParamComment Comment +hi link ngxListenComment Comment hi link ngxVariable Identifier -hi link ngxVariableBlock Identifier hi link ngxVariableString PreProc -hi link ngxBlock Normal hi link ngxString String +hi link ngxListenString String hi link ngxBoolean Boolean hi link ngxDirectiveBlock Statement hi link ngxDirectiveImportant Type +hi link ngxDirectiveListen Type hi link ngxDirectiveControl Keyword hi link ngxDirectiveError Constant hi link ngxDirectiveDeprecated Error hi link ngxDirective Identifier hi link ngxDirectiveThirdParty Special +hi link ngxListenOptions Keyword + let b:current_syntax = "nginx" diff --git a/docs/text/LICENSE b/docs/text/LICENSE index 1d3d15cd5e3..3f29d93cd80 100644 --- a/docs/text/LICENSE +++ b/docs/text/LICENSE @@ -1,6 +1,6 @@ /* - * Copyright (C) 2002-2016 Igor Sysoev - * Copyright (C) 2011-2016 Nginx, Inc. + * Copyright (C) 2002-2017 Igor Sysoev + * Copyright (C) 2011-2017 Nginx, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/docs/xml/nginx/changes.xml b/docs/xml/nginx/changes.xml index 97ed7264079..30584626efb 100644 --- a/docs/xml/nginx/changes.xml +++ b/docs/xml/nginx/changes.xml @@ -5,7 +5,1220 @@ - + + + + +при использовании директивы ssl_preread +в модуле stream не работало переключение на следующий бэкенд. + + +switching to the next upstream server in the stream module did not work +when using the "ssl_preread" directive. + + + + + +в модуле ngx_http_v2_module.
+Спасибо Piotr Sikora. +
+ +in the ngx_http_v2_module.
+Thanks to Piotr Sikora. +
+
+ + + +nginx не поддерживал даты после 2038 года +на 32-битных платформах с 64-битным time_t. + + +nginx did not support dates after the year 2038 +on 32-bit platforms with 64-bit time_t. + + + + + +в обработке дат до 1970 года и после 10000 года. + + +in handling of dates prior to the year 1970 and after the year 10000. + + + + + +в модуле stream таймауты ожидания UDP-пакетов от бэкендов +не логгировались или логгировались на уровне info вместо error. + + +in the stream module timeouts waiting for UDP datagrams from upstream servers +were not logged or logged at the "info" level instead of "error". + + + + + +при использовании HTTP/2 nginx мог вернуть ошибку 400, +не указав в логе причину. + + +when using HTTP/2 nginx might return the 400 response +without logging the reason. + + + + + +в обработке повреждённых файлов кэша. + + +in processing of corrupted cache files. + + + + + +при кэшировании ошибок, перехваченных error_page, +не учитывались заголовки управления кэшированием. + + +cache control headers were ignored +when caching errors intercepted by error_page. + + + + + +при использовании HTTP/2 тело запроса могло быть повреждено. + + +when using HTTP/2 client request body might be corrupted. + + + + + +в обработке адресов клиентов при использовании unix domain сокетов. + + +in handling of client addresses when using unix domain sockets. + + + + + +при использовании директивы "hash ... consistent" в блоке upstream +nginx нагружал процессор, если использовались большие веса +и все или почти все бэкенды были недоступны. + + +nginx hogged CPU +when using the "hash ... consistent" directive in the upstream block +if large weights were used and all or most of the servers were unavailable. + + + +
+ + + + + + +переменная $ssl_client_escaped_cert. + + +the $ssl_client_escaped_cert variable. + + + + + +директива ssl_session_ticket_key и параметр include директивы geo +не работали на Windows. + + +the "ssl_session_ticket_key" directive and +the "include" parameter of the "geo" directive did not work on Windows. + + + + + +на 32-битных платформах +при запросе более 4 гигабайт с помощью нескольких диапазонов +возвращалась некорректная длина ответа. + + +incorrect response length was returned +on 32-bit platforms when requesting more than 4 gigabytes +with multiple ranges. + + + + + +директива "expires modified" и +обработка строки If-Range заголовка запроса +не учитывали время последнего изменения ответа, +если использовалось проксирование без кэширования. + + +the "expires modified" directive and +processing of the "If-Range" request header line +did not use the response last modification time +if proxying without caching was used. + + + + + + + + + + +модуль ngx_http_mirror_module. + + +the ngx_http_mirror_module. + + + + + +клиентские соединения могли сбрасываться при тестировании конфигурации, +если использовался параметр reuseport директивы listen на Linux. + + +client connections might be dropped during configuration testing +when using the "reuseport" parameter of the "listen" directive on Linux. + + + + + +тело запроса могло быть недоступно в подзапросах, +если оно было сохранено в файл и использовалось проксирование. + + +request body might not be available in subrequests +if it was saved to a file and proxying was used. + + + + + +очистка кэша по max_size не работала на Windows. + + +cleaning cache based on the "max_size" parameter did not work on Windows. + + + + + +любое выделение разделяемой памяти на Windows требовало 4096 байт памяти. + + +any shared memory allocation required 4096 bytes on Windows. + + + + + +при использовании директивы zone в блоке upstream на Windows +рабочий процесс мог завершаться аварийно. + + +nginx worker might be terminated abnormally +when using the "zone" directive inside the "upstream" block on Windows. + + + + + + + + + + +специально созданный запрос мог вызвать целочисленное переполнение +в range-фильтре и последующую некорректную обработку запрошенных диапазонов, +что потенциально могло привести к утечке конфиденциальной информации +(CVE-2017-7529). + + +a specially crafted request might result in an integer overflow +and incorrect processing of ranges in the range filter, +potentially resulting in sensitive information leak +(CVE-2017-7529). + + + + + + + + + + +теперь при запросе диапазона, начинающегося с 0, из пустого файла +nginx возвращает ответ 200 вместо 416. + + +nginx now returns 200 instead of 416 +when a range starting with 0 is requested from an empty file. + + + + + +директива add_trailer.
+Спасибо Piotr Sikora. +
+ +the "add_trailer" directive.
+Thanks to Piotr Sikora. +
+
+ + + +nginx не собирался под Cygwin и NetBSD; +ошибка появилась в 1.13.0. + + +nginx could not be built on Cygwin and NetBSD; +the bug had appeared in 1.13.0. + + + + + +nginx не собирался под MSYS2 / MinGW 64-bit.
+Спасибо Orgad Shaneh. +
+ +nginx could not be built under MSYS2 / MinGW 64-bit.
+Thanks to Orgad Shaneh. +
+
+ + + +при использовании SSI с большим количеством подзапросов +и proxy_pass с переменными +в рабочем процессе мог произойти segmentation fault. + + +a segmentation fault might occur in a worker process +when using SSI with many includes +and proxy_pass with variables. + + + + + +в модуле ngx_http_v2_module.
+Спасибо Piotr Sikora. +
+ +in the ngx_http_v2_module.
+Thanks to Piotr Sikora. +
+
+ +
+ + + + + + +теперь в качестве параметра директивы set_real_ip_from +можно указывать имя хоста. + + +now a hostname can be used +as the "set_real_ip_from" directive parameter. + + + + + +улучшения в скриптах подсветки синтаксиса для vim. + + +vim syntax highlighting scripts improvements. + + + + + +директива worker_cpu_affinity теперь работает на DragonFly BSD.
+Спасибо Sepherosa Ziehau. +
+ +the "worker_cpu_affinity" directive now works on DragonFly BSD.
+Thanks to Sepherosa Ziehau. +
+
+ + + +SSL renegotiation в соединениях к бэкендам +не работал при использовании OpenSSL до 1.1.0. + + +SSL renegotiation on backend connections +did not work when using OpenSSL before 1.1.0. + + + + + +nginx не собирался с Oracle Developer Studio 12.5. + + +nginx could not be built with Oracle Developer Studio 12.5. + + + + + +теперь cache manager пропускает заблокированные записи +при очистке кэша по max_size. + + +now cache manager ignores long locked cache entries +when cleaning cache based on the "max_size" parameter. + + + + + +клиентские SSL-соединения сразу закрывались, если использовался +отложенный accept и параметр proxy_protocol директивы listen. + + +client SSL connections were immediately closed if deferred accept +and the "proxy_protocol" parameter of the "listen" directive were used. + + + + + +в директиве proxy_cache_background_update. + + +in the "proxy_cache_background_update" directive. + + + + + +теперь директива tcp_nodelay +устанавливает опцию TCP_NODELAY перед SSL handshake. + + +now the "tcp_nodelay" directive +sets the TCP_NODELAY option before an SSL handshake. + + + +
+ + + + + + +теперь SSL renegotiation допускается в соединениях к бэкендам. + + +SSL renegotiation is now allowed on backend connections. + + + + + +параметры rcvbuf и sndbuf директив listen +в почтовом прокси-сервере и модуле stream. + + +the "rcvbuf" and "sndbuf" parameters of the "listen" directives +of the mail proxy and stream modules. + + + + + +директивы return и error_page теперь могут использоваться для возврата +перенаправлений с кодом 308.
+Спасибо Simon Leblanc. +
+ +the "return" and "error_page" directives can now be used to return 308 +redirections.
+Thanks to Simon Leblanc. +
+
+ + + +параметр TLSv1.3 в директиве ssl_protocols. + + +the "TLSv1.3" parameter of the "ssl_protocols" directive. + + + + + +при логгировании сигналов теперь указывается PID отправившего сигнал процесса. + + +when logging signals nginx now logs PID of the process which sent the signal. + + + + + +в обработке ошибок выделения памяти. + + +in memory allocation error handling. + + + + + +если сервер в модуле stream слушал на wildcard-адресе, +исходящий адрес ответного UDP-пакета +мог отличаться от адреса назначения исходного пакета. + + +if a server in the stream module listened on a wildcard address, +the source address of a response UDP datagram could differ +from the original datagram destination address. + + + +
+ + + + + + +параметр http_429 в директивах proxy_next_upstream, fastcgi_next_upstream, +scgi_next_upstream и uwsgi_next_upstream.
+Спасибо Piotr Sikora. +
+ +the "http_429" parameter of the "proxy_next_upstream", "fastcgi_next_upstream", +"scgi_next_upstream", and "uwsgi_next_upstream" directives.
+Thanks to Piotr Sikora. +
+
+ + + +в обработке ошибок выделения памяти. + + +in memory allocation error handling. + + + + + +при использовании директив sendfile и timer_resolution на Linux +запросы могли зависать. + + +requests might hang +when using the "sendfile" and "timer_resolution" directives on Linux. + + + + + +при использовании с подзапросами директив sendfile и aio_write +запросы могли зависать. + + +requests might hang +when using the "sendfile" and "aio_write" directives with subrequests. + + + + + +в модуле ngx_http_v2_module.
+Спасибо Piotr Sikora. +
+ +in the ngx_http_v2_module.
+Thanks to Piotr Sikora. +
+
+ + + +при использовании HTTP/2 в рабочем процессе мог произойти segmentation fault. + + +a segmentation fault might occur in a worker process when using HTTP/2. + + + + + +запросы могли зависать +при использовании с подзапросами директив limit_rate, sendfile_max_chunk, +limit_req или метода $r->sleep() встроенного перла. + + +requests might hang +when using the "limit_rate", "sendfile_max_chunk", "limit_req" directives, +or the $r->sleep() embedded perl method with subrequests. + + + + + +в модуле ngx_http_slice_module. + + +in the ngx_http_slice_module. + + + +
+ + + + + + +nginx мог нагружать процессор; +ошибка появилась в 1.11.11. + + +nginx might hog CPU; +the bug had appeared in 1.11.11. + + + + + + + + + + +директива worker_shutdown_timeout. + + +the "worker_shutdown_timeout" directive. + + + + + +улучшения в скриптах подсветки синтаксиса для vim.
+Спасибо Wei-Ko Kao. +
+ +vim syntax highlighting scripts improvements.
+Thanks to Wei-Ko Kao. +
+
+ + + +при попытке установить переменную $limit_rate в пустую строку +в рабочем процессе мог произойти segmentation fault. + + +a segmentation fault might occur in a worker process +if the $limit_rate variable was set to an empty string. + + + + + +директивы proxy_cache_background_update, fastcgi_cache_background_update, +scgi_cache_background_update и uwsgi_cache_background_update +могли работать некорректно, если использовалась директива if. + + +the "proxy_cache_background_update", "fastcgi_cache_background_update", +"scgi_cache_background_update", and "uwsgi_cache_background_update" directives +might work incorrectly if the "if" directive was used. + + + + + +в рабочем процессе мог произойти segmentation fault, +если количество large_client_header_buffers в виртуальном сервере +отличалось от такового в сервере по умолчанию. + + +a segmentation fault might occur in a worker process +if number of large_client_header_buffers in a virtual server +was different from the one in the default server. + + + + + +в почтовом прокси-сервере. + + +in the mail proxy server. + + + +
+ + + + + + +формат заголовка кэша был изменен, +ранее закэшированные ответы будут загружены заново. + + +cache header format has been changed, +previously cached responses will be invalidated. + + + + + +поддержка расширений stale-while-revalidate и stale-if-error +в строке "Cache-Control" в заголовке ответа бэкенда. + + +support of "stale-while-revalidate" and "stale-if-error" extensions +in the "Cache-Control" backend response header line. + + + + + +директивы proxy_cache_background_update, fastcgi_cache_background_update, +scgi_cache_background_update и uwsgi_cache_background_update. + + +the "proxy_cache_background_update", "fastcgi_cache_background_update", +"scgi_cache_background_update", and "uwsgi_cache_background_update" directives. + + + + + +теперь nginx может кэшировать ответы +со строкой Vary заголовка длиной до 128 символов +(вместо 42 символов в предыдущих версиях). + + +nginx is now able to cache responses +with the "Vary" header line up to 128 characters long +(instead of 42 characters in previous versions). + + + + + +параметр build директивы server_tokens.
+Спасибо Tom Thorogood. +
+ +the "build" parameter of the "server_tokens" directive.
+Thanks to Tom Thorogood. +
+
+ + + +при обработке запросов со строкой "Expect: 100-continue" в заголовке запроса +в логах могли появляться сообщения "[crit] SSL_write() failed". + + +"[crit] SSL_write() failed" messages might appear in logs +when handling requests with the "Expect: 100-continue" request header line. + + + + + +модуль ngx_http_slice_module не работал в именованных location'ах. + + +the ngx_http_slice_module did not work in named locations. + + + + + +при использовании AIO после перенаправления запроса с помощью X-Accel-Redirect +в рабочем процессе мог произойти segmentation fault. + + +a segmentation fault might occur in a worker process +when using AIO after an "X-Accel-Redirect" redirection. + + + + + +уменьшено потребление памяти для долгоживущих запросов, использующих сжатие. + + +reduced memory consumption for long-lived requests using gzipping. + + + +
+ + + + + + +при использовании модуля stream nginx мог нагружать процессор; +ошибка появилась в 1.11.5. + + +nginx might hog CPU when using the stream module; +the bug had appeared in 1.11.5. + + + + + +метод аутентификации EXTERNAL в почтовом прокси-сервере +можно было использовать, даже если он не был разрешён в конфигурации. + + +EXTERNAL authentication mechanism in mail proxy +was accepted even if it was not enabled in the configuration. + + + + + +при использовании директивы ssl_verify_client модуля stream +в рабочем процессе мог произойти segmentation fault. + + +a segmentation fault might occur in a worker process +if the "ssl_verify_client" directive of the stream module was used. + + + + + +директива ssl_verify_client модуля stream могла не работать. + + +the "ssl_verify_client" directive of the stream module might not work. + + + + + +при исчерпании рабочим процессом свободных соединений +keepalive-соединения могли закрываться излишне агрессивно.
+Спасибо Joel Cunningham. +
+ +closing keepalive connections due to no free worker connections +might be too aggressive.
+Thanks to Joel Cunningham. +
+
+ + + +при использовании директивы sendfile на FreeBSD и macOS +мог возвращаться некорректный ответ; +ошибка появилась в 1.7.8. + + +an incorrect response might be returned +when using the "sendfile" directive on FreeBSD and macOS; +the bug had appeared in 1.7.8. + + + + + +при использовании директивы aio_write +ответ мог сохраняться в кэш не полностью. + + +a truncated response might be stored in cache +when using the "aio_write" directive. + + + + + +при использовании директивы aio_write +могла происходить утечка сокетов. + + +a socket leak might occur +when using the "aio_write" directive. + + + +
+ + + + + + +директива absolute_redirect. + + +the "absolute_redirect" directive. + + + + + +параметр escape директивы log_format. + + +the "escape" parameter of the "log_format" directive. + + + + + +проверка клиентских SSL-сертификатов в модуле stream. + + +client SSL certificates verification in the stream module. + + + + + +директива ssl_session_ticket_key поддерживает +шифрование TLS session tickets с помощью AES256 +при использовании с 80-байтными ключами. + + +the "ssl_session_ticket_key" directive supports +AES256 encryption of TLS session tickets +when used with 80-byte keys. + + + + + +поддержка vim-commentary в скриптах для vim.
+Спасибо Armin Grodon. +
+ +vim-commentary support in vim scripts.
+Thanks to Armin Grodon. +
+
+ + + +рекурсия при получении значений переменных не ограничивалась. + + +recursion when evaluating variables was not limited. + + + + + +в модуле ngx_stream_ssl_preread_module. + + +in the ngx_stream_ssl_preread_module. + + + + + +если сервер, описанный в блоке upstream в модуле stream, +был признан неработающим, то после истечения fail_timeout он +признавался работающим только после завершения тестового соединения; +теперь достаточно, чтобы соединение было успешно установлено. + + +if a server in an upstream in the stream module failed, +it was considered alive only when a test connection sent +to it after fail_timeout was closed; +now a successfully established connection is enough. + + + + + +nginx/Windows не собирался с 64-битным Visual Studio. + + +nginx/Windows could not be built with 64-bit Visual Studio. + + + + + +nginx/Windows не собирался с OpenSSL 1.1.0. + + +nginx/Windows could not be built with OpenSSL 1.1.0. + + + +
+ + + + + + +переменная $ssl_client_verify теперь +в случае ошибки проверки клиентского сертификата +содержит строку с описанием ошибки, +например, "FAILED:certificate has expired". + + +now in case of a client certificate verification error +the $ssl_client_verify variable contains a string with the failure reason, +for example, "FAILED:certificate has expired". + + + + + +переменные $ssl_ciphers, $ssl_curves, +$ssl_client_v_start, $ssl_client_v_end и $ssl_client_v_remain. + + +the $ssl_ciphers, $ssl_curves, +$ssl_client_v_start, $ssl_client_v_end, and $ssl_client_v_remain variables. + + + + + +параметр volatile директивы map. + + +the "volatile" parameter of the "map" directive. + + + + + +при сборке динамических модулей +не учитывались заданные для модуля зависимости. + + +dependencies specified for a module +were ignored while building dynamic modules. + + + + + +при использовании HTTP/2 и директив limit_req или auth_request +тело запроса могло быть повреждено; +ошибка появилась в 1.11.0. + + +when using HTTP/2 and the "limit_req" or "auth_request" directives +client request body might be corrupted; +the bug had appeared in 1.11.0. + + + + + +при использовании HTTP/2 в рабочем процессе мог произойти segmentation fault; +ошибка появилась в 1.11.3. + + +a segmentation fault might occur in a worker process when using HTTP/2; +the bug had appeared in 1.11.3. + + + + + +в модуле ngx_http_mp4_module.
+Спасибо Congcong Hu. +
+ +in the ngx_http_mp4_module.
+Thanks to Congcong Hu. +
+
+ + + +в модуле ngx_http_perl_module. + + +in the ngx_http_perl_module. + + + +
+ + + + + + +формат переменных $ssl_client_s_dn и $ssl_client_i_dn +изменён на соответствующий RFC 2253 (RFC 4514); +значения в старом формате доступны через переменные +$ssl_client_s_dn_legacy и $ssl_client_i_dn_legacy. + + +format of the $ssl_client_s_dn and $ssl_client_i_dn variables +has been changed to follow RFC 2253 (RFC 4514); +values in the old format are available in +the $ssl_client_s_dn_legacy and $ssl_client_i_dn_legacy variables. + + + + + +при сохранении временных файлов в каталоге кэша +они теперь располагаются не в отдельном подкаталоге для временных файлов, +а в том же подкаталоге, что и соответствующие файлы в кэше. + + +when storing temporary files in a cache directory +they will be stored in the same subdirectories as corresponding cache files +instead of a separate subdirectory for temporary files. + + + + + +поддержка метода аутентификации EXTERNAL +в почтовом прокси-сервере.
+Спасибо Robert Norris. +
+ +EXTERNAL authentication mechanism support +in mail proxy.
+Thanks to Robert Norris. +
+
+ + + +поддержка WebP в модуле ngx_http_image_filter_module. + + +WebP support in the ngx_http_image_filter_module. + + + + + +директива proxy_method поддерживает переменные.
+Спасибо Дмитрию Лазуркину. +
+ +variables support in the "proxy_method" directive.
+Thanks to Dmitry Lazurkin. +
+
+ + + +директива http2_max_requests в модуле ngx_http_v2_module. + + +the "http2_max_requests" directive in the ngx_http_v2_module. + + + + + +директивы proxy_cache_max_range_offset, fastcgi_cache_max_range_offset, +scgi_cache_max_range_offset и uwsgi_cache_max_range_offset. + + +the "proxy_cache_max_range_offset", "fastcgi_cache_max_range_offset", +"scgi_cache_max_range_offset", and "uwsgi_cache_max_range_offset" directives. + + + + + +плавное завершение старых рабочих процессов могло занимать бесконечное время +при использовании HTTP/2. + + +graceful shutdown of old worker processes might require infinite time +when using HTTP/2. + + + + + +в модуле ngx_http_mp4_module. + + +in the ngx_http_mp4_module. + + + + + +при проксировании WebSocket-соединений и включённом кэшировании +в логах могли появляться сообщения "ignore long locked inactive cache entry". + + +"ignore long locked inactive cache entry" alerts might appear in logs +when proxying WebSocket connections with caching enabled. + + + + + +если во время SSL handshake с бэкендом происходил таймаут, +nginx ничего не писал в лог +и возвращал ответ с кодом 502 вместо 504. + + +nginx did not write anything to log +and returned a response with code 502 instead of 504 +when a timeout occurred during an SSL handshake to a backend. + + + +
+ + + @@ -139,7 +1352,7 @@ with the "-" character in the HTTP method. - + @@ -244,7 +1457,7 @@ the bug had appeared in 1.9.13. - + @@ -325,7 +1538,7 @@ Thanks to Piotr Sikora. - + @@ -438,7 +1651,7 @@ the issue had appeared in 1.9.4. - + @@ -458,7 +1671,7 @@ the bug had appeared in 1.3.9. - + @@ -614,7 +1827,7 @@ when using the "proxy_cache_bypass" directive. - + @@ -669,7 +1882,7 @@ Thanks to Mindaugas Rasiukevicius. - + @@ -727,7 +1940,7 @@ of minor bugs in logging. - + @@ -790,7 +2003,6 @@ and tries to avoid cache keys zone overflows. в логах могли появляться сообщения "task already active" и "second aio post". - "task already active" and "second aio post" alerts might appear in logs when using the "sendfile" and "aio" directives with subrequests. @@ -893,7 +2105,7 @@ regardless of the proxy_next_upstream directive. - + @@ -995,7 +2207,7 @@ in the ngx_http_v2_module. - + @@ -1038,7 +2250,7 @@ in the ngx_http_v2_module. - + @@ -1141,7 +2353,7 @@ after an "X-Accel-Redirect" redirection. - + @@ -1157,7 +2369,7 @@ the bug had appeared in 1.9.8. - + @@ -1211,7 +2423,7 @@ nginx could not be built on OS X in some cases. - + @@ -1287,7 +2499,7 @@ in the ngx_http_v2_module. - + @@ -1371,7 +2583,7 @@ Thanks to Markus Linnala, Kurtis Nusbaum and Piotr Sikora. - + @@ -1468,7 +2680,7 @@ the bug had appeared in 1.9.4. - + @@ -1579,7 +2791,7 @@ nginx could not be built with Visual Studio 2015. - + @@ -1670,7 +2882,7 @@ Thanks to Matthew Baldwin. - + @@ -1753,7 +2965,7 @@ OCSP stapling might return an expired OCSP response in some cases. - + @@ -1827,7 +3039,7 @@ Thanks to Sergey Polovko. - + @@ -1905,7 +3117,7 @@ if not specified in the first "listen" directive for a listen socket. - + @@ -1968,7 +3180,7 @@ in the ngx_http_spdy_module. - + @@ -2136,7 +3348,7 @@ to automatically construct certificate chains. - + @@ -2228,7 +3440,7 @@ Thanks to Goetz T. Fischer. - + @@ -2332,7 +3544,7 @@ Thanks to Lukas Tribus. - + @@ -2498,7 +3710,7 @@ Thanks to Yichun Zhang. - + @@ -2608,7 +3820,7 @@ Thanks to Kouhei Sutou. - + @@ -2653,7 +3865,7 @@ in logging to syslog. - + @@ -2798,7 +4010,7 @@ Thanks to Markus Linnala and Feng Gu. - + @@ -2927,7 +4139,7 @@ Thanks to Tatsuhiko Kubo and Piotr Sikora. - + @@ -3007,7 +4219,7 @@ if caching was used. - + @@ -3076,7 +4288,7 @@ in the ngx_http_spdy_module. - + @@ -3194,7 +4406,7 @@ nginx could not be built with the --with-file-aio option on Linux/aarch64. - + @@ -3235,7 +4447,7 @@ the "if" parameter of the "access_log" directive. - + @@ -3328,7 +4540,7 @@ in the ngx_http_spdy_module. - + @@ -3374,7 +4586,7 @@ Thanks to Lucas Molas. - + @@ -3484,7 +4696,7 @@ nginx/Windows could not be built with Visual Studio 2013. - + @@ -3563,7 +4775,7 @@ Thanks to Piotr Sikora. - + @@ -3705,7 +4917,7 @@ incorrectly handled IPv6 client addresses. - + @@ -3790,7 +5002,7 @@ in the ngx_http_spdy_module. - + @@ -3926,7 +5138,7 @@ memory leak in nginx/Windows. - + @@ -4024,7 +5236,7 @@ in the ngx_http_spdy_module. - + @@ -4103,7 +5315,7 @@ Thanks to Piotr Sikora. - + @@ -4205,7 +5417,7 @@ in the ngx_http_spdy_module. - + @@ -4280,7 +5492,7 @@ in the ngx_http_sub_filter_module. - + @@ -4329,7 +5541,7 @@ Thanks to Serguei Ivantsov. - + @@ -4452,7 +5664,7 @@ if several worker processes were used. - + @@ -4474,7 +5686,7 @@ Thanks to Greg MacManus, iSIGHT Partners Labs. - + @@ -4503,7 +5715,7 @@ the bug had appeared in 1.3.9. - + @@ -4554,7 +5766,7 @@ in the eventport and /dev/poll methods. - + @@ -4671,7 +5883,7 @@ in backend usage accounting. - + @@ -4744,7 +5956,7 @@ Thanks to Gernot Vormayr. - + @@ -4782,7 +5994,7 @@ Thanks to Louis Opter. - + @@ -4882,7 +6094,7 @@ in the "fastcgi_keep_conn" directive. - + @@ -4935,7 +6147,7 @@ for IPv6 addresses. - + @@ -5113,7 +6325,7 @@ if the "gzip" directive was used. - + @@ -5158,7 +6370,7 @@ in the ngx_http_dav_module. - + @@ -5223,7 +6435,7 @@ in the "ssl_stapling" directive. - + @@ -5270,7 +6482,7 @@ OpenSSL 0.9.7 compatibility. - + @@ -5326,7 +6538,7 @@ if the --with-ipv6 option was used. - + @@ -5408,7 +6620,7 @@ Thanks to HAYASHI Kentaro. - + @@ -5471,7 +6683,7 @@ might be inherited incorrectly. - + @@ -5509,7 +6721,7 @@ before an internal redirect to a named location. - + @@ -5614,7 +6826,7 @@ while reconfiguration. - + @@ -5744,7 +6956,7 @@ in the "proxy_cookie_domain" and "proxy_cookie_path" directives. - + @@ -5883,7 +7095,7 @@ in the ngx_http_fastcgi_module. - + @@ -5923,7 +7135,7 @@ Thanks to Maxim Bublis. - + @@ -6005,7 +7217,7 @@ in the ngx_http_mp4_module. - + @@ -6088,7 +7300,7 @@ nginx could not be built on Debian GNU/Hurd. - + @@ -6126,7 +7338,7 @@ in the ngx_http_uwsgi_module. - + @@ -6239,7 +7451,7 @@ the bug had appeared in 1.1.15. - + @@ -6342,7 +7554,7 @@ the bug had appeared in 0.7.25. - + @@ -6403,7 +7615,7 @@ memory leak during reconfiguration if the "pcre_jit" directive was used. - + @@ -6479,7 +7691,7 @@ in the ngx_http_mp4_module. - + @@ -6619,7 +7831,7 @@ the bug had appeared in 1.1.9. - + @@ -6717,7 +7929,7 @@ responses from cache might hang. - + @@ -6733,7 +7945,7 @@ the bug had appeared in 1.1.9. - + @@ -6899,7 +8111,7 @@ nginx could not be built on AIX. - + @@ -6994,7 +8206,7 @@ Thanks to Piotr Sikora. - + @@ -7054,7 +8266,7 @@ in the "expires @time" directive. - + @@ -7174,7 +8386,7 @@ the module ngx_http_mp4_module did not support seeking on 32-bit platforms. - + @@ -7255,7 +8467,7 @@ the bug had appeared in 1.1.1. - + @@ -7338,7 +8550,7 @@ the module ngx_http_mp4_module did not support 64-bit MP4 "co64" atom. - + @@ -7381,7 +8593,7 @@ nginx could not be built on MacOSX 10.7. - + @@ -7426,7 +8638,7 @@ in the "proxy/fastcgi/scgi/uwsgi_ignore_client_abort" directives. - + @@ -7570,7 +8782,7 @@ the bug had appeared in 0.8.40. - + @@ -7703,7 +8915,7 @@ SSL modules could not be built by gcc 4.6 without --with-debug option. - + @@ -7779,7 +8991,7 @@ Thanks to Maxim Dounin. - + @@ -7826,7 +9038,7 @@ the bug had appeared in 1.0.3. - + @@ -7895,7 +9107,7 @@ the bug had appeared in 0.8.46. - + @@ -7931,7 +9143,7 @@ the bug had appeared in 1.0.1. - + @@ -8039,7 +9251,7 @@ Thanks to Igor A. Valcov. - + @@ -8076,7 +9288,7 @@ a "satisfy any" directive disabled custom 401 error page. - + @@ -8116,7 +9328,7 @@ directives is given by expression and refers to a defined upstream. - + @@ -8143,7 +9355,7 @@ Thanks to Michael Lustfield. - + @@ -8197,7 +9409,7 @@ Thanks to Maxim Dounin. - + @@ -8220,7 +9432,7 @@ the "server_name" directive supports the $hostname variable. - + @@ -8247,7 +9459,7 @@ the bug had appeared in 0.9.0. - + @@ -8294,7 +9506,7 @@ Thanks to Maxim Dounin. - + @@ -8310,7 +9522,7 @@ the bug had appeared in 0.9.0. - + @@ -8409,7 +9621,7 @@ the bug had appeared in 0.8.42. - + @@ -8458,7 +9670,7 @@ the bug had appeared in 0.8.21. - + @@ -8475,7 +9687,7 @@ the bug had appeared in 0.8.51. - + @@ -8507,7 +9719,7 @@ now a listen socket "ssl" parameter may be set several times. - + @@ -8569,7 +9781,7 @@ to a process run in other session. - + @@ -8607,7 +9819,7 @@ the bug had appeared in 0.8.48. - + @@ -8704,7 +9916,7 @@ if an image was larger than "image_filter_buffer" size. - + @@ -8739,7 +9951,7 @@ the bug had appeared in 0.8.46. - + @@ -8779,7 +9991,7 @@ time or on memory low condition. - + @@ -8818,7 +10030,7 @@ the "listen" directive did not support the "setfib=0" parameter. - + @@ -8883,7 +10095,7 @@ Thanks to Miroslaw Jaworski. - + @@ -8930,7 +10142,7 @@ the $uid_set variable may be used at any request processing stage. - + @@ -8968,7 +10180,7 @@ a text answer may be added to a "return" directive. - + @@ -9017,7 +10229,7 @@ in "Destination" request header line. - + @@ -9077,7 +10289,7 @@ Thanks to Maxim Dounin. - + @@ -9112,7 +10324,7 @@ Thanks to Maxim Dounin. - + @@ -9159,7 +10371,7 @@ the $uid_got variable might not be used in the SSI and perl modules. - + @@ -9233,7 +10445,7 @@ Thanks to Alan Batie. - + @@ -9306,7 +10518,7 @@ the bug had appeared in 0.8.35. - + @@ -9406,7 +10618,7 @@ Thanks to Maxim Dounin. - + @@ -9517,7 +10729,7 @@ the bug had appeared in 0.8.11. - + @@ -9596,7 +10808,7 @@ the bug had appeared in 0.8.11. - + @@ -9661,7 +10873,7 @@ Thanks to Alex Kapranoff. - + @@ -9757,7 +10969,7 @@ if the file should replace an already existent file. - + @@ -9819,7 +11031,7 @@ Thanks to W-Mark Kubacki. - + @@ -9898,7 +11110,7 @@ Thanks to Maxim Dounin. - + @@ -9914,7 +11126,7 @@ the bug had appeared in 0.8.25. - + @@ -9930,7 +11142,7 @@ the bug had appeared in 0.8.25. - + @@ -9957,7 +11169,7 @@ the bug had appeared in 0.8.25. - + @@ -10034,7 +11246,7 @@ the bug had appeared in 0.8.16. - + @@ -10081,7 +11293,7 @@ in resolving empty name. - + @@ -10137,7 +11349,7 @@ Thanks to Artem Bokhan. - + @@ -10246,7 +11458,7 @@ the bug had appeared in 0.8.21. - + @@ -10309,7 +11521,7 @@ the bug had appeared in 0.8.11. - + @@ -10393,7 +11605,7 @@ nginx counted incorrectly disk cache size. - + @@ -10428,7 +11640,7 @@ the bug had appeared in 0.8.18. - + @@ -10516,7 +11728,7 @@ the bug had appeared in 0.8.11. - + @@ -10559,7 +11771,7 @@ the bug had appeared in 0.8.11. - + @@ -10657,7 +11869,7 @@ Thanks to Igor Artemiev. - + @@ -10726,7 +11938,7 @@ the bug had appeared in 0.8.11. - + @@ -10775,7 +11987,7 @@ the bug had appeared in 0.6.10. - + @@ -10802,7 +12014,7 @@ the bug had appeared in 0.8.12. - + @@ -10837,7 +12049,7 @@ the bug had appeared in 0.8.11. - + @@ -10871,7 +12083,7 @@ the "directio_alignment" directive. - + @@ -10896,7 +12108,7 @@ the bug had appeared in 0.8.9. - + @@ -10923,7 +12135,7 @@ different file systems. - + @@ -10952,7 +12164,7 @@ the bug had appeared in 0.8.7. - + @@ -11072,7 +12284,7 @@ the bug had appeared in 0.8.5. - + @@ -11135,7 +12347,7 @@ Thanks to Maxim Dounin. - + @@ -11180,7 +12392,7 @@ Thanks to Maxim Dounin. - + @@ -11196,7 +12408,7 @@ the bug had appeared in 0.8.3. - + @@ -11245,7 +12457,7 @@ Thanks to Eugene Mychlo. - + @@ -11270,7 +12482,7 @@ the bug had appeared in 0.7.4. - + @@ -11333,7 +12545,7 @@ the bug had appeared in 0.7.56. - + @@ -11396,7 +12608,7 @@ Thanks to Maxim Dounin and Kirill A. Korinskiy. - + @@ -11471,7 +12683,7 @@ responses. - + @@ -11536,7 +12748,7 @@ Thanks to Denis F. Latypoff. - + @@ -11554,7 +12766,7 @@ the bug had appeared in 0.7.56. - + @@ -11577,7 +12789,7 @@ in ngx_http_image_filter_module. - + @@ -11646,7 +12858,7 @@ Thanks to Maxim Dounin. - + @@ -11722,7 +12934,7 @@ the bug had appeared in 0.7.53. - + @@ -11855,7 +13067,7 @@ Thanks to Andrew Vorobyoff. - + @@ -11935,7 +13147,7 @@ the bug had appeared in 0.7.42. - + @@ -11982,7 +13194,7 @@ the bug had appeared in 0.7.39. - + @@ -11998,7 +13210,7 @@ the bug had appeared in 0.7.49. - + @@ -12016,7 +13228,7 @@ the bug had appeared in 0.7.48. - + @@ -12092,7 +13304,7 @@ the bug had appeared in 0.7.46. - + @@ -12161,7 +13373,7 @@ the bug had appeared in 0.7.44. - + @@ -12175,7 +13387,7 @@ the previous release tarball was incorrect. - + @@ -12269,7 +13481,7 @@ the bug had appeared in 0.7.42. - + @@ -12332,7 +13544,7 @@ then captures in regular expressions in a "server_name" directive did not work. - + @@ -12361,7 +13573,7 @@ the bug had appeared in 0.7.36. - + @@ -12445,7 +13657,7 @@ the bug had appeared in 0.7.41. - + @@ -12466,7 +13678,7 @@ Thanks to Vladimir Sopot. - + @@ -12516,7 +13728,7 @@ Thanks to Dmitry Kuzmenko. - + @@ -12545,7 +13757,7 @@ if short static variants are used in a "try_files" directive. - + @@ -12585,7 +13797,7 @@ the bug had appeared in 0.7.36. - + @@ -12601,7 +13813,7 @@ the bug had appeared in 0.7.36. - + @@ -12628,7 +13840,7 @@ preset by a "modern_browser" directives. - + @@ -12672,7 +13884,7 @@ if ".domain.tld" and ".subdomain.domain.tld" wildcards were used; - + @@ -12735,7 +13947,7 @@ nginx could not be built on AIX. - + @@ -12774,7 +13986,7 @@ if "resolver" directive was used in SMTP proxy. - + @@ -12819,7 +14031,7 @@ Thanks to Andrey Kvasov. - + @@ -12891,7 +14103,7 @@ Thanks to Maxim Dounin. - + @@ -12911,7 +14123,7 @@ the bug had appeared in 0.7.29. - + @@ -12958,7 +14170,7 @@ in memory allocation in the ngx_http_gzip_filter_module on Cygwin. - + @@ -12983,7 +14195,7 @@ to 32 4k or 16 8k from 4 4k/8k. - + @@ -13079,7 +14291,7 @@ Thanks to Sergey Bochenkov. - + @@ -13095,7 +14307,7 @@ the bug had appeared in 0.7.25. - + @@ -13136,7 +14348,7 @@ in the "delete" parameter of the "geo" directive. - + @@ -13170,7 +14382,7 @@ the "$cookie_..." variables did not work in the SSI and the perl module. - + @@ -13202,7 +14414,7 @@ decrease of memory required for geo base load. - + @@ -13247,7 +14459,7 @@ Thanks to Zyb. - + @@ -13294,7 +14506,7 @@ the bug had appeared in 0.7.6. - + @@ -13370,7 +14582,7 @@ $server_addr variable might have no value. - + @@ -13384,7 +14596,7 @@ version number update. - + @@ -13475,7 +14687,7 @@ now accept threshold depends on worker_connections. - + @@ -13531,7 +14743,7 @@ received from backend. - + @@ -13547,7 +14759,7 @@ the bug had appeared in 0.7.15. - + @@ -13590,7 +14802,7 @@ now nginx allows underscores in a client request header line names. - + @@ -13658,7 +14870,7 @@ configuration file validity test improvements. - + @@ -13674,7 +14886,7 @@ the bug had appeared in 0.7.12. - + @@ -13744,7 +14956,7 @@ the bug had appeared in 0.7.0. - + @@ -13811,7 +15023,7 @@ the bugs had appeared in 0.7.1. - + @@ -13849,7 +15061,7 @@ but for each request passed via the connection. - + @@ -13951,7 +15163,7 @@ the bug had appeared in 0.3.18. - + @@ -13998,7 +15210,7 @@ Thanks to Maxim Dounin. - + @@ -14097,7 +15309,7 @@ UTF-8 encoding usage in the ngx_http_autoindex_module. - + @@ -14123,7 +15335,7 @@ the ngx_http_flv_module did not support several values in a query string. - + @@ -14163,7 +15375,7 @@ were transferred incorrectly. - + @@ -14213,7 +15425,7 @@ large SSI inclusions might be truncated. - + @@ -14262,7 +15474,7 @@ the bug had appeared in 0.6.9. - + @@ -14332,7 +15544,7 @@ nginx dropped a query string from the original request. - + @@ -14400,7 +15612,7 @@ Thanks to Roxis. - + @@ -14478,7 +15690,7 @@ if keepalive was enabled. - + @@ -14509,7 +15721,7 @@ and the "open_file_cache_errors" directive was off. - + @@ -14585,7 +15797,7 @@ the bug had appeared in 0.6.15. - + @@ -14610,7 +15822,7 @@ the bug had appeared in 0.6.27. - + @@ -14626,7 +15838,7 @@ the bug had appeared in 0.6.27. - + @@ -14796,7 +16008,7 @@ in copying URI part contained escaped symbols into arguments. - + @@ -14879,7 +16091,7 @@ the bug had appeared in 0.6.23. - + @@ -14977,7 +16189,7 @@ the bug had appeared in 0.6.23. - + @@ -14993,7 +16205,7 @@ the bug had appeared in 0.6.23. - + @@ -15132,7 +16344,7 @@ the bug had appeared in 0.5.13. - + @@ -15239,7 +16451,7 @@ Thanks to Manlio Perillo. - + @@ -15307,7 +16519,7 @@ then nginx returned usual response. - + @@ -15325,7 +16537,7 @@ the bug had appeared in 0.6.19. - + @@ -15338,7 +16550,7 @@ the 0.6.18 version could not be built. - + @@ -15403,7 +16615,7 @@ even if limit value was very high. - + @@ -15470,7 +16682,7 @@ in HTTP/0.9 version. - + @@ -15508,7 +16720,7 @@ compatibility with mget. - + @@ -15610,7 +16822,7 @@ the bug had appeared in 0.6.7. - + @@ -15731,7 +16943,7 @@ in sub_filter parsing. - + @@ -15748,7 +16960,7 @@ Thanks to Arkadiusz Patyk. - + @@ -15818,7 +17030,7 @@ Thanks to Manlio Perillo. - + @@ -15866,7 +17078,7 @@ the bug had appeared in 0.6.6. - + @@ -15914,7 +17126,7 @@ if /dev/poll method was used. - + @@ -15962,7 +17174,7 @@ the bug had appeared in 0.6.8. - + @@ -16022,7 +17234,7 @@ nginx did not work on FreeBSD/sparc64. - + @@ -16162,7 +17374,7 @@ to FastCGI-server via the unix domain socket. - + @@ -16245,7 +17457,7 @@ the bug had appeared in 0.6.4. - + @@ -16314,7 +17526,7 @@ Thanks to Coverity's Scan. - + @@ -16370,7 +17582,7 @@ Thanks to Jiang Hong. - + @@ -16442,7 +17654,7 @@ the bug had appeared in 0.5.13. - + @@ -16458,7 +17670,7 @@ then nginx passed garbage in the header to a client. - + @@ -16504,7 +17716,7 @@ process identification number. - + @@ -16520,7 +17732,7 @@ the "www.example.*" wildcards. - + @@ -16536,7 +17748,7 @@ the bug had appeared in 0.5.24. - + @@ -16563,7 +17775,7 @@ the bug had appeared in 0.5.23. - + @@ -16621,7 +17833,7 @@ in the HTTPS protocol in the "proxy_pass" directive. - + @@ -16637,7 +17849,7 @@ the bug had appeared in 0.5.21. - + @@ -16688,7 +17900,7 @@ in the HTTPS protocol in the "proxy_pass" directive. - + @@ -16757,7 +17969,7 @@ Thanks to Andrei Nigmatulin. - + @@ -16823,7 +18035,7 @@ the files more than 2G could not be transferred using sendfile on 64-bit Linux. - + @@ -16887,7 +18099,7 @@ the bug had appeared in 0.3.38. - + @@ -16941,7 +18153,7 @@ returned old cached value. - + @@ -16995,7 +18207,7 @@ the bug had appeared in 0.5.15. - + @@ -17088,7 +18300,7 @@ now nginx does not log some alerts if eventport or /dev/poll methods are used. - + @@ -17103,7 +18315,7 @@ nginx ignored superfluous closing "}" in the end of configuration file. - + @@ -17174,7 +18386,7 @@ the bug had appeared in 0.5.8. - + @@ -17224,7 +18436,7 @@ ngx_http_perl_module could not be built on Solaris. - + @@ -17285,7 +18497,7 @@ if nginx was built with -O2 optimization. - + @@ -17316,7 +18528,7 @@ the bug had appeared in 0.5.1. - + @@ -17388,7 +18600,7 @@ the "access_log off" directive did not always turn off the logging. - + @@ -17465,7 +18677,7 @@ Bugfixes in the "limit_zone" directive. - + @@ -17532,7 +18744,7 @@ the PCRE-6.5+ library and the icc compiler compatibility. - + @@ -17594,7 +18806,7 @@ the byte-ranges were transferred incorrectly if the $r->sendfile() was used. - + @@ -17655,7 +18867,7 @@ the ppc platform specific bugs. - + @@ -17702,7 +18914,7 @@ the bug had appeared in 0.4.14. - + @@ -17737,7 +18949,7 @@ the $r->has_request_body method did not work. - + @@ -17755,7 +18967,7 @@ the bug had appeared in 0.5.1. - + @@ -17847,7 +19059,7 @@ response time was more than 1 millisecond. - + @@ -17919,7 +19131,7 @@ the bug had appeared in 0.4.14. - + @@ -18015,7 +19227,7 @@ authentication server failed. - + @@ -18102,7 +19314,7 @@ the bug had appeared in 0.3.50. - + @@ -18136,11 +19348,11 @@ nginx did not omit the "#fragment" part in URI. - + -POP3 прокси поддерживает AUTH LOIGN PLAIN и CRAM-MD5. +POP3 прокси поддерживает AUTH LOGIN PLAIN и CRAM-MD5. the POP3 proxy supports the AUTH LOGIN PLAIN and CRAM-MD5. @@ -18172,7 +19384,7 @@ the bug had appeared in 0.4.10. - + @@ -18230,7 +19442,7 @@ the bug had appeared in 0.4.9. - + @@ -18253,7 +19465,7 @@ the ngx_http_perl_module now tests the nginx.pm module version. - + @@ -18280,7 +19492,7 @@ Thanks to Alexey Kovyrin. - + @@ -18343,7 +19555,7 @@ nginx did not run on 64-bit platforms except amd64, sparc64, and ppc64. - + @@ -18383,7 +19595,7 @@ the bug had appeared in 0.4.4. - + @@ -18399,7 +19611,7 @@ the bug had appeared in 0.4.4. - + @@ -18465,7 +19677,7 @@ in the "proxy_redirect" directive. - + @@ -18540,7 +19752,7 @@ of the Sun Studio PAUSE hardware capability bug. - + @@ -18556,7 +19768,7 @@ the bug had appeared in 0.4.1. - + @@ -18592,7 +19804,7 @@ Thanks to Yusuf Goolamabbas. - + @@ -18661,7 +19873,7 @@ the bug had appeared in 0.1.29. - + @@ -18704,7 +19916,7 @@ had the captured escaped symbols from original URI. - + @@ -18721,7 +19933,7 @@ the bug had appeared in 0.3.59. - + @@ -18757,7 +19969,7 @@ the bug had appeared in 0.3.58. - + @@ -18820,7 +20032,7 @@ nginx could not run on 64-bit FreeBSD 7.0-CURRENT. - + @@ -18866,7 +20078,7 @@ directive. - + @@ -18901,7 +20113,7 @@ some sent to client header lines were logged in the access log. - + @@ -18991,7 +20203,7 @@ the bug had appeared in 0.3.50. - + @@ -19058,7 +20270,7 @@ the bug had appeared in 0.3.53. - + @@ -19131,7 +20343,7 @@ anyway. - + @@ -19182,7 +20394,7 @@ was not removed. - + @@ -19198,7 +20410,7 @@ the bug had appeared in 0.3.50. - + @@ -19272,7 +20484,7 @@ in nonbuffered proxying mode the client connection was not closed. - + @@ -19298,7 +20510,7 @@ was included instead of second and following subrequests. - + @@ -19354,7 +20566,7 @@ the bug had appeared in 0.3.46. - + @@ -19378,7 +20590,7 @@ is always removed. - + @@ -19424,7 +20636,7 @@ the reconfiguration bug and memory leaks in the ngx_http_perl_module. - + @@ -19479,7 +20691,7 @@ backend only instead of being distributed among the rest. - + @@ -19512,7 +20724,7 @@ in the SSI. - + @@ -19526,7 +20738,7 @@ in the SSI. - + @@ -19574,7 +20786,7 @@ response header line. - + @@ -19620,7 +20832,7 @@ the segmentation fault was occurred. - + @@ -19652,7 +20864,7 @@ the "$limit_rate" variable. - + @@ -19712,7 +20924,7 @@ the bug had appeared in 0.3.38. - + @@ -19793,7 +21005,7 @@ Thanks to Maxim Dounin. - + @@ -19834,7 +21046,7 @@ in the ngx_http_addition_filter_module. - + @@ -19930,7 +21142,7 @@ to a server prefix. - + @@ -19957,7 +21169,7 @@ in the "proxy_pass" directive without the URI part in a subrequest. - + @@ -19971,7 +21183,7 @@ the "add_header" directive supports the variables. - + @@ -20006,7 +21218,7 @@ in the "post_action" directive. - + @@ -20022,7 +21234,7 @@ the bug had appeared in 0.3.31. - + @@ -20101,7 +21313,7 @@ perl 5.8.8 compatibility. - + @@ -20136,7 +21348,7 @@ the bug had appeared in 0.3.27. - + @@ -20185,7 +21397,7 @@ only after a successful completion of a request. - + @@ -20252,7 +21464,7 @@ was transferred to a client. - + @@ -20326,7 +21538,7 @@ the requests with the body was not transferred. - + @@ -20351,7 +21563,7 @@ URI was transferred to a backend while proxying the SSI subrequest. - + @@ -20369,7 +21581,7 @@ the bug had appeared in 0.3.24. - + @@ -20424,7 +21636,7 @@ the bug had appeared in 0.3.18. - + @@ -20456,7 +21668,7 @@ the ngx_http_perl_module was incorrectly built on Linux and Solaris. - + @@ -20492,7 +21704,7 @@ the bug had appeared in 0.3.18. - + @@ -20515,7 +21727,7 @@ the "valid_referers" directive allows the referrers without URI part. - + @@ -20537,7 +21749,7 @@ the ngx_http_memcached_module did not support the keys in the "/usr?args" form. - + @@ -20569,7 +21781,7 @@ in SSI handling. - + @@ -20664,7 +21876,7 @@ the bug had appeared in 0.3.16. - + @@ -20718,7 +21930,7 @@ was used by default. - + @@ -20805,7 +22017,7 @@ the bug had appeared in 0.3.13. - + @@ -20839,7 +22051,7 @@ quit and active "debug_points" directive. - + @@ -20855,7 +22067,7 @@ the bug had appeared in 0.3.13. - + @@ -20909,7 +22121,7 @@ the bug had appeared in 0.3.11. - + @@ -21032,7 +22244,7 @@ bracket in the "if" directive. - + @@ -21048,7 +22260,7 @@ the bug had appeared in 0.3.10. - + @@ -21167,7 +22379,7 @@ response was encoded incorrectly. - + @@ -21184,7 +22396,7 @@ the bug had appeared in 0.3.8. - + @@ -21358,7 +22570,7 @@ then the response did not transferred complete or did not transferred at all. - + @@ -21384,7 +22596,7 @@ the bug had appeared in 0.3.2. - + @@ -21430,7 +22642,7 @@ always used. - + @@ -21470,7 +22682,7 @@ directive were used. - + @@ -21486,7 +22698,7 @@ the bug had appeared in 0.3.3. - + @@ -21621,7 +22833,7 @@ the "ssl_protocols" directive allowed to specify the single protocol only. - + @@ -21647,7 +22859,7 @@ directives. - + @@ -21674,7 +22886,7 @@ correct handling of the "\\", "\"", "\'", and "\$" pairs in SSI. - + @@ -21690,7 +22902,7 @@ The limit was introduced because of millisecond timers overflow. - + @@ -21765,7 +22977,7 @@ the bug had appeared in 0.2.2. - + @@ -21810,7 +23022,7 @@ expressions of the "if" command. - + @@ -21850,7 +23062,7 @@ the bug had appeared in 0.2.0. - + @@ -21866,7 +23078,7 @@ the bug had appeared in 0.2.2. - + @@ -21940,7 +23152,7 @@ the export versions of MSIE 5.x could not connect via HTTPS. - + @@ -21958,7 +23170,7 @@ the bug had appeared in 0.2.0. - + @@ -22092,7 +23304,7 @@ Thanks to Alexandr Kukushkin. - + @@ -22127,7 +23339,7 @@ Various bug fixes in the IMAP/POP3 proxy. - + @@ -22170,7 +23382,7 @@ authorization use. - + @@ -22235,7 +23447,7 @@ in the proxied mode the bug had appeared in 0.1.29. - + @@ -22264,7 +23476,7 @@ the bug had appeared in 0.1.38. - + @@ -22280,7 +23492,7 @@ then it can not be used in SSI. - + @@ -22339,7 +23551,7 @@ became shorter in the "ps" command. - + @@ -22458,7 +23670,7 @@ Bugfixes in IMAP/POP3 proxy in interaction with a backend at the login state. - + @@ -22581,7 +23793,7 @@ the IMAP/POP3 proxy. - + @@ -22619,7 +23831,7 @@ then nginx started to request all backends again. - + @@ -22692,7 +23904,7 @@ the reconfiguration by the -HUP signal was made twice. - + @@ -22764,7 +23976,7 @@ the bug had appeared in 0.1.28. - + @@ -22807,7 +24019,7 @@ request header line passing. - + @@ -22854,7 +24066,7 @@ the 500 error code was returned. - + @@ -22900,7 +24112,7 @@ mode. - + @@ -22943,7 +24155,7 @@ the bug had appeared in 0.1.30. - + @@ -23006,7 +24218,7 @@ the "ignore_invalid_headers" directive. - + @@ -23319,7 +24531,7 @@ nginx could not be built on MacOS X. - + @@ -23342,7 +24554,7 @@ nginx could not be built by gcc 4.0 on Linux. - + @@ -23401,7 +24613,7 @@ nginx could not be built on FreeBSD and Linux, if the - + @@ -23437,7 +24649,7 @@ auth_basic_user_file directives. - + @@ -23554,7 +24766,7 @@ the --with-openssl-opt=OPTIONS autoconfiguration directive. - + @@ -23600,7 +24812,7 @@ the lack of the "Referer" header line was always accounted as valid referrer. - + @@ -23676,7 +24888,7 @@ of the response header if the no response was transferred to a client. - + @@ -23704,7 +24916,7 @@ the bug had appeared in 0.1.21. - + @@ -23741,7 +24953,7 @@ nginx could not be built on NetBSD 2.0. - + @@ -23765,7 +24977,7 @@ the FastCGI stderr stream was handled incorrectly. - + @@ -23800,7 +25012,7 @@ via SSL connections. - + @@ -23895,7 +25107,7 @@ the rewrite/location cycle and sets the current configuration to the request. - + @@ -23992,7 +25204,7 @@ the system error message was not logged on Linux. - + @@ -24069,7 +25281,7 @@ the bug had appeared in 0.1.14. - + @@ -24157,7 +25369,7 @@ caused segmentation fault. - + @@ -24281,7 +25493,7 @@ Thanks to Sergey Skvortsov for SSL-accelerator. - + @@ -24313,7 +25525,7 @@ the %request_length log parameter logged the incorrect length. - + @@ -24353,7 +25565,7 @@ the SO_SNDLOWAT option. - + @@ -24494,7 +25706,7 @@ the double slashes in "://" in the URI were converted to ":/". - + @@ -24521,7 +25733,7 @@ the fix in 0.1.9 for the files bigger than 2G on Linux did not work. - + @@ -24569,7 +25781,7 @@ the bug had appeared in 0.1.8. - + @@ -24601,7 +25813,7 @@ the proxy_max_temp_file_size directive. - + @@ -24619,7 +25831,7 @@ the bug had appeared in 0.1.5. - + @@ -24635,7 +25847,7 @@ the wrong configuration choose. - + @@ -24721,7 +25933,7 @@ the userid_p3p directive. - + @@ -24735,7 +25947,7 @@ in the ngx_http_autoindex_module. - + @@ -24768,7 +25980,7 @@ proxy module may get caught in an endless loop when sendfile is not used. - + @@ -24854,7 +26066,7 @@ the gzip module compressed the proxied responses that was already compressed. - + @@ -24954,7 +26166,7 @@ was required. - + diff --git a/docs/xsls/changes.xsls b/docs/xsls/changes.xsls index 8be25a20a77..4b34254747c 100644 --- a/docs/xsls/changes.xsls +++ b/docs/xsls/changes.xsls @@ -25,13 +25,19 @@ X:template = "changes" { ' '), 1, $conf/changes[@lang=$lang]/length)} - X:if "$lang='ru'" { !{@date} } + X:if "$lang='ru'" { + !{substring(@date, 9, 2)} + X:text {.} + !{substring(@date, 6, 2)} + X:text {.} + !{substring(@date, 1, 4)} + } X:if "$lang='en'" { - !{substring(@date, 1, 2)} + !{substring(@date, 9, 2)} !{$conf/changes[@lang=$lang]/month[number(substring(current()/@date, - 4, 2))]} - !{substring(@date, 7, 4)} + 6, 2))]} + !{substring(@date, 1, 4)} } X:text { } diff --git a/docs/xslt/changes.xslt b/docs/xslt/changes.xslt index a0178f6784f..55ee5157dee 100644 --- a/docs/xslt/changes.xslt +++ b/docs/xslt/changes.xslt @@ -26,13 +26,19 @@ ' '), 1, $conf/changes[@lang=$lang]/length)"/> - + + + . + + . + + - + - + 6, 2))]"/> + diff --git a/misc/GNUmakefile b/misc/GNUmakefile index 9ab41930647..074a47bf05e 100644 --- a/misc/GNUmakefile +++ b/misc/GNUmakefile @@ -4,10 +4,11 @@ VER = $(shell grep 'define NGINX_VERSION' src/core/nginx.h \ NGINX = nginx-$(VER) TEMP = tmp +CC = cl OBJS = objs.msvc8 -OPENSSL = openssl-1.0.2j -ZLIB = zlib-1.2.8 -PCRE = pcre-8.39 +OPENSSL = openssl-1.0.2l +ZLIB = zlib-1.2.11 +PCRE = pcre-8.41 release: export @@ -47,7 +48,7 @@ RELEASE: win32: ./auto/configure \ - --with-cc=cl \ + --with-cc=$(CC) \ --builddir=$(OBJS) \ --with-debug \ --prefix= \ @@ -65,6 +66,7 @@ win32: --with-pcre=$(OBJS)/lib/$(PCRE) \ --with-zlib=$(OBJS)/lib/$(ZLIB) \ --with-select_module \ + --with-http_v2_module \ --with-http_realip_module \ --with-http_addition_module \ --with-http_sub_module \ diff --git a/src/core/nginx.c b/src/core/nginx.c index 60f8fe7d47d..c3a29cc40d8 100644 --- a/src/core/nginx.c +++ b/src/core/nginx.c @@ -12,6 +12,7 @@ static void ngx_show_version_info(void); static ngx_int_t ngx_add_inherited_sockets(ngx_cycle_t *cycle); +static void ngx_cleanup_environment(void *data); static ngx_int_t ngx_get_options(int argc, char *const *argv); static ngx_int_t ngx_process_options(ngx_cycle_t *cycle); static ngx_int_t ngx_save_argv(ngx_cycle_t *cycle, int argc, char *const *argv); @@ -123,6 +124,13 @@ static ngx_command_t ngx_core_commands[] = { offsetof(ngx_core_conf_t, rlimit_core), NULL }, + { ngx_string("worker_shutdown_timeout"), + NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1, + ngx_conf_set_msec_slot, + 0, + offsetof(ngx_core_conf_t, shutdown_timeout), + NULL }, + { ngx_string("working_directory"), NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1, ngx_conf_set_str_slot, @@ -265,6 +273,12 @@ main(int argc, char *const *argv) return 1; } + /* + * ngx_slab_sizes_init() requires ngx_pagesize set in ngx_os_init() + */ + + ngx_slab_sizes_init(); + if (ngx_add_inherited_sockets(&init_cycle) != NGX_OK) { return 1; } @@ -495,10 +509,11 @@ ngx_add_inherited_sockets(ngx_cycle_t *cycle) char ** ngx_set_environment(ngx_cycle_t *cycle, ngx_uint_t *last) { - char **p, **env; - ngx_str_t *var; - ngx_uint_t i, n; - ngx_core_conf_t *ccf; + char **p, **env; + ngx_str_t *var; + ngx_uint_t i, n; + ngx_core_conf_t *ccf; + ngx_pool_cleanup_t *cln; ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module); @@ -550,14 +565,25 @@ ngx_set_environment(ngx_cycle_t *cycle, ngx_uint_t *last) if (last) { env = ngx_alloc((*last + n + 1) * sizeof(char *), cycle->log); + if (env == NULL) { + return NULL; + } + *last = n; } else { - env = ngx_palloc(cycle->pool, (n + 1) * sizeof(char *)); - } + cln = ngx_pool_cleanup_add(cycle->pool, 0); + if (cln == NULL) { + return NULL; + } - if (env == NULL) { - return NULL; + env = ngx_alloc((n + 1) * sizeof(char *), cycle->log); + if (env == NULL) { + return NULL; + } + + cln->handler = ngx_cleanup_environment; + cln->data = env; } n = 0; @@ -591,6 +617,25 @@ ngx_set_environment(ngx_cycle_t *cycle, ngx_uint_t *last) } +static void +ngx_cleanup_environment(void *data) +{ + char **env = data; + + if (environ == env) { + + /* + * if the environment is still used, as it happens on exit, + * the only option is to leak it + */ + + return; + } + + ngx_free(env); +} + + ngx_pid_t ngx_exec_new_binary(ngx_cycle_t *cycle, char *const *argv) { @@ -982,6 +1027,7 @@ ngx_core_module_create_conf(ngx_cycle_t *cycle) ccf->daemon = NGX_CONF_UNSET; ccf->master = NGX_CONF_UNSET; ccf->timer_resolution = NGX_CONF_UNSET_MSEC; + ccf->shutdown_timeout = NGX_CONF_UNSET_MSEC; ccf->worker_processes = NGX_CONF_UNSET; ccf->debug_points = NGX_CONF_UNSET; @@ -1010,6 +1056,7 @@ ngx_core_module_init_conf(ngx_cycle_t *cycle, void *conf) ngx_conf_init_value(ccf->daemon, 1); ngx_conf_init_value(ccf->master, 1); ngx_conf_init_msec_value(ccf->timer_resolution, 0); + ngx_conf_init_msec_value(ccf->shutdown_timeout, 0); ngx_conf_init_value(ccf->worker_processes, 1); ngx_conf_init_value(ccf->debug_points, 0); diff --git a/src/core/nginx.h b/src/core/nginx.h index a75ef04e434..02b51ab1d07 100644 --- a/src/core/nginx.h +++ b/src/core/nginx.h @@ -9,8 +9,8 @@ #define _NGINX_H_INCLUDED_ -#define nginx_version 1011006 -#define NGINX_VERSION "1.11.6" +#define nginx_version 1013007 +#define NGINX_VERSION "1.13.7" #define NGINX_VER "nginx/" NGINX_VERSION #ifdef NGX_BUILD diff --git a/src/core/ngx_buf.c b/src/core/ngx_buf.c index 00b6644585a..1862a0606ab 100644 --- a/src/core/ngx_buf.c +++ b/src/core/ngx_buf.c @@ -186,16 +186,18 @@ ngx_chain_update_chains(ngx_pool_t *p, ngx_chain_t **free, ngx_chain_t **busy, { ngx_chain_t *cl; - if (*busy == NULL) { - *busy = *out; + if (*out) { + if (*busy == NULL) { + *busy = *out; - } else { - for (cl = *busy; cl->next; cl = cl->next) { /* void */ } + } else { + for (cl = *busy; cl->next; cl = cl->next) { /* void */ } - cl->next = *out; - } + cl->next = *out; + } - *out = NULL; + *out = NULL; + } while (*busy) { cl = *busy; @@ -244,6 +246,9 @@ ngx_chain_coalesce_file(ngx_chain_t **in, off_t limit) if (aligned <= cl->buf->file_last) { size = aligned - cl->buf->file_pos; } + + total += size; + break; } total += size; diff --git a/src/core/ngx_conf_file.c b/src/core/ngx_conf_file.c index ce8c602de44..fb28a5a946f 100644 --- a/src/core/ngx_conf_file.c +++ b/src/core/ngx_conf_file.c @@ -178,6 +178,7 @@ ngx_conf_parse(ngx_conf_t *cf, ngx_str_t *filename) /* open configuration file */ fd = ngx_open_file(filename->data, NGX_FILE_RDONLY, NGX_FILE_OPEN, 0); + if (fd == NGX_INVALID_FILE) { ngx_conf_log_error(NGX_LOG_EMERG, cf, ngx_errno, ngx_open_file_n " \"%s\" failed", diff --git a/src/core/ngx_conf_file.h b/src/core/ngx_conf_file.h index 213611faf12..9cd58064369 100644 --- a/src/core/ngx_conf_file.h +++ b/src/core/ngx_conf_file.h @@ -128,7 +128,7 @@ struct ngx_conf_s { ngx_uint_t cmd_type; ngx_conf_handler_pt handler; - char *handler_conf; + void *handler_conf; }; diff --git a/src/core/ngx_connection.c b/src/core/ngx_connection.c index a789d8c5132..9a747589c2b 100644 --- a/src/core/ngx_connection.c +++ b/src/core/ngx_connection.c @@ -13,7 +13,7 @@ ngx_os_io_t ngx_io; -static void ngx_drain_connections(void); +static void ngx_drain_connections(ngx_cycle_t *cycle); ngx_listening_t * @@ -165,6 +165,10 @@ ngx_set_inherited_sockets(ngx_cycle_t *cycle) continue; } + if (ls[i].socklen > (socklen_t) sizeof(ngx_sockaddr_t)) { + ls[i].socklen = sizeof(ngx_sockaddr_t); + } + switch (ls[i].sockaddr->sa_family) { #if (NGX_HAVE_INET6) @@ -473,7 +477,7 @@ ngx_open_listening_sockets(ngx_cycle_t *cycle) #if (NGX_HAVE_REUSEPORT) - if (ls[i].reuseport) { + if (ls[i].reuseport && !ngx_test_config) { int reuseport; reuseport = 1; @@ -483,7 +487,7 @@ ngx_open_listening_sockets(ngx_cycle_t *cycle) == -1) { ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno, - "setsockopt(SO_REUSEPORT) %V failed, ignored", + "setsockopt(SO_REUSEPORT) %V failed", &ls[i].addr_text); if (ngx_close_socket(s) == -1) { @@ -1046,7 +1050,7 @@ ngx_get_connection(ngx_socket_t s, ngx_log_t *log) c = ngx_cycle->free_connections; if (c == NULL) { - ngx_drain_connections(); + ngx_drain_connections((ngx_cycle_t *) ngx_cycle); c = ngx_cycle->free_connections; } @@ -1204,6 +1208,7 @@ ngx_reusable_connection(ngx_connection_t *c, ngx_uint_t reusable) if (c->reusable) { ngx_queue_remove(&c->queue); + ngx_cycle->reusable_connections_n--; #if (NGX_STAT_STUB) (void) ngx_atomic_fetch_add(ngx_stat_waiting, -1); @@ -1217,6 +1222,7 @@ ngx_reusable_connection(ngx_connection_t *c, ngx_uint_t reusable) ngx_queue_insert_head( (ngx_queue_t *) &ngx_cycle->reusable_connections_queue, &c->queue); + ngx_cycle->reusable_connections_n++; #if (NGX_STAT_STUB) (void) ngx_atomic_fetch_add(ngx_stat_waiting, 1); @@ -1226,18 +1232,20 @@ ngx_reusable_connection(ngx_connection_t *c, ngx_uint_t reusable) static void -ngx_drain_connections(void) +ngx_drain_connections(ngx_cycle_t *cycle) { - ngx_int_t i; + ngx_uint_t i, n; ngx_queue_t *q; ngx_connection_t *c; - for (i = 0; i < 32; i++) { - if (ngx_queue_empty(&ngx_cycle->reusable_connections_queue)) { + n = ngx_max(ngx_min(32, cycle->reusable_connections_n / 8), 1); + + for (i = 0; i < n; i++) { + if (ngx_queue_empty(&cycle->reusable_connections_queue)) { break; } - q = ngx_queue_last(&ngx_cycle->reusable_connections_queue); + q = ngx_queue_last(&cycle->reusable_connections_queue); c = ngx_queue_data(q, ngx_connection_t, queue); ngx_log_debug0(NGX_LOG_DEBUG_CORE, c->log, 0, @@ -1341,6 +1349,49 @@ ngx_connection_local_sockaddr(ngx_connection_t *c, ngx_str_t *s, } +ngx_int_t +ngx_tcp_nodelay(ngx_connection_t *c) +{ + int tcp_nodelay; + + if (c->tcp_nodelay != NGX_TCP_NODELAY_UNSET) { + return NGX_OK; + } + + ngx_log_debug0(NGX_LOG_DEBUG_CORE, c->log, 0, "tcp_nodelay"); + + tcp_nodelay = 1; + + if (setsockopt(c->fd, IPPROTO_TCP, TCP_NODELAY, + (const void *) &tcp_nodelay, sizeof(int)) + == -1) + { +#if (NGX_SOLARIS) + if (c->log_error == NGX_ERROR_INFO) { + + /* Solaris returns EINVAL if a socket has been shut down */ + c->log_error = NGX_ERROR_IGNORE_EINVAL; + + ngx_connection_error(c, ngx_socket_errno, + "setsockopt(TCP_NODELAY) failed"); + + c->log_error = NGX_ERROR_INFO; + + return NGX_ERROR; + } +#endif + + ngx_connection_error(c, ngx_socket_errno, + "setsockopt(TCP_NODELAY) failed"); + return NGX_ERROR; + } + + c->tcp_nodelay = NGX_TCP_NODELAY_SET; + + return NGX_OK; +} + + ngx_int_t ngx_connection_error(ngx_connection_t *c, ngx_err_t err, char *text) { diff --git a/src/core/ngx_connection.h b/src/core/ngx_connection.h index 1d3e3a3a15d..e4dfe5879cc 100644 --- a/src/core/ngx_connection.h +++ b/src/core/ngx_connection.h @@ -214,6 +214,7 @@ void ngx_close_connection(ngx_connection_t *c); void ngx_close_idle_connections(ngx_cycle_t *cycle); ngx_int_t ngx_connection_local_sockaddr(ngx_connection_t *c, ngx_str_t *s, ngx_uint_t port); +ngx_int_t ngx_tcp_nodelay(ngx_connection_t *c); ngx_int_t ngx_connection_error(ngx_connection_t *c, ngx_err_t err, char *text); ngx_connection_t *ngx_get_connection(ngx_socket_t s, ngx_log_t *log); diff --git a/src/core/ngx_cycle.c b/src/core/ngx_cycle.c index a57991c69ab..f3ac24d7a59 100644 --- a/src/core/ngx_cycle.c +++ b/src/core/ngx_cycle.c @@ -15,6 +15,7 @@ static ngx_int_t ngx_init_zone_pool(ngx_cycle_t *cycle, ngx_shm_zone_t *shm_zone); static ngx_int_t ngx_test_lockfile(u_char *file, ngx_log_t *log); static void ngx_clean_old_cycles(ngx_event_t *ev); +static void ngx_shutdown_timer_handler(ngx_event_t *ev); volatile ngx_cycle_t *ngx_cycle; @@ -22,6 +23,7 @@ ngx_array_t ngx_old_cycles; static ngx_pool_t *ngx_temp_pool; static ngx_event_t ngx_cleaner_event; +static ngx_event_t ngx_shutdown_event; ngx_uint_t ngx_test_config; ngx_uint_t ngx_dump_config; @@ -37,7 +39,7 @@ ngx_cycle_t * ngx_init_cycle(ngx_cycle_t *old_cycle) { void *rv; - char **senv, **env; + char **senv; ngx_uint_t i, n; ngx_log_t *log; ngx_time_t *tp; @@ -113,16 +115,14 @@ ngx_init_cycle(ngx_cycle_t *old_cycle) n = old_cycle->paths.nelts ? old_cycle->paths.nelts : 10; - cycle->paths.elts = ngx_pcalloc(pool, n * sizeof(ngx_path_t *)); - if (cycle->paths.elts == NULL) { + if (ngx_array_init(&cycle->paths, pool, n, sizeof(ngx_path_t *)) + != NGX_OK) + { ngx_destroy_pool(pool); return NULL; } - cycle->paths.nelts = 0; - cycle->paths.size = sizeof(ngx_path_t *); - cycle->paths.nalloc = n; - cycle->paths.pool = pool; + ngx_memzero(cycle->paths.elts, n * sizeof(ngx_path_t *)); if (ngx_array_init(&cycle->config_dump, pool, 1, sizeof(ngx_conf_dump_t)) @@ -173,16 +173,14 @@ ngx_init_cycle(ngx_cycle_t *old_cycle) n = old_cycle->listening.nelts ? old_cycle->listening.nelts : 10; - cycle->listening.elts = ngx_pcalloc(pool, n * sizeof(ngx_listening_t)); - if (cycle->listening.elts == NULL) { + if (ngx_array_init(&cycle->listening, pool, n, sizeof(ngx_listening_t)) + != NGX_OK) + { ngx_destroy_pool(pool); return NULL; } - cycle->listening.nelts = 0; - cycle->listening.size = sizeof(ngx_listening_t); - cycle->listening.nalloc = n; - cycle->listening.pool = pool; + ngx_memzero(cycle->listening.elts, n * sizeof(ngx_listening_t)); ngx_queue_init(&cycle->reusable_connections_queue); @@ -472,8 +470,6 @@ ngx_init_cycle(ngx_cycle_t *old_cycle) goto shm_zone_found; } - ngx_shm_free(&oshm_zone[n].shm); - break; } @@ -664,14 +660,26 @@ ngx_init_cycle(ngx_cycle_t *old_cycle) n = 0; } - if (oshm_zone[i].shm.name.len == shm_zone[n].shm.name.len - && ngx_strncmp(oshm_zone[i].shm.name.data, - shm_zone[n].shm.name.data, - oshm_zone[i].shm.name.len) - == 0) + if (oshm_zone[i].shm.name.len != shm_zone[n].shm.name.len) { + continue; + } + + if (ngx_strncmp(oshm_zone[i].shm.name.data, + shm_zone[n].shm.name.data, + oshm_zone[i].shm.name.len) + != 0) + { + continue; + } + + if (oshm_zone[i].tag == shm_zone[n].tag + && oshm_zone[i].shm.size == shm_zone[n].shm.size + && !oshm_zone[i].noreuse) { goto live_shm_zone; } + + break; } ngx_shm_free(&oshm_zone[i].shm); @@ -750,20 +758,9 @@ ngx_init_cycle(ngx_cycle_t *old_cycle) if (ngx_process == NGX_PROCESS_MASTER || ngx_is_init_cycle(old_cycle)) { - /* - * perl_destruct() frees environ, if it is not the same as it was at - * perl_construct() time, therefore we save the previous cycle - * environment before ngx_conf_parse() where it will be changed. - */ - - env = environ; - environ = senv; - ngx_destroy_pool(old_cycle->pool); cycle->old_cycle = NULL; - environ = env; - return cycle; } @@ -777,15 +774,15 @@ ngx_init_cycle(ngx_cycle_t *old_cycle) } n = 10; - ngx_old_cycles.elts = ngx_pcalloc(ngx_temp_pool, - n * sizeof(ngx_cycle_t *)); - if (ngx_old_cycles.elts == NULL) { + + if (ngx_array_init(&ngx_old_cycles, ngx_temp_pool, n, + sizeof(ngx_cycle_t *)) + != NGX_OK) + { exit(1); } - ngx_old_cycles.nelts = 0; - ngx_old_cycles.size = sizeof(ngx_cycle_t *); - ngx_old_cycles.nalloc = n; - ngx_old_cycles.pool = ngx_temp_pool; + + ngx_memzero(ngx_old_cycles.elts, n * sizeof(ngx_cycle_t *)); ngx_cleaner_event.handler = ngx_clean_old_cycles; ngx_cleaner_event.log = cycle->log; @@ -1137,9 +1134,7 @@ ngx_reopen_files(ngx_cycle_t *cycle, ngx_uid_t user) if (user != (ngx_uid_t) NGX_CONF_UNSET_UINT) { ngx_file_info_t fi; - if (ngx_file_info((const char *) file[i].name.data, &fi) - == NGX_FILE_ERROR) - { + if (ngx_file_info(file[i].name.data, &fi) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, ngx_file_info_n " \"%s\" failed", file[i].name.data); @@ -1344,3 +1339,54 @@ ngx_clean_old_cycles(ngx_event_t *ev) ngx_old_cycles.nelts = 0; } } + + +void +ngx_set_shutdown_timer(ngx_cycle_t *cycle) +{ + ngx_core_conf_t *ccf; + + ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module); + + if (ccf->shutdown_timeout) { + ngx_shutdown_event.handler = ngx_shutdown_timer_handler; + ngx_shutdown_event.data = cycle; + ngx_shutdown_event.log = cycle->log; + ngx_shutdown_event.cancelable = 1; + + ngx_add_timer(&ngx_shutdown_event, ccf->shutdown_timeout); + } +} + + +static void +ngx_shutdown_timer_handler(ngx_event_t *ev) +{ + ngx_uint_t i; + ngx_cycle_t *cycle; + ngx_connection_t *c; + + cycle = ev->data; + + c = cycle->connections; + + for (i = 0; i < cycle->connection_n; i++) { + + if (c[i].fd == (ngx_socket_t) -1 + || c[i].read == NULL + || c[i].read->accept + || c[i].read->channel + || c[i].read->resolver) + { + continue; + } + + ngx_log_debug1(NGX_LOG_DEBUG_CORE, ev->log, 0, + "*%uA shutdown timeout", c[i].number); + + c[i].close = 1; + c[i].error = 1; + + c[i].read->handler(c[i].read); + } +} diff --git a/src/core/ngx_cycle.h b/src/core/ngx_cycle.h index 5cdacf14c1e..2b48ccbd6dd 100644 --- a/src/core/ngx_cycle.h +++ b/src/core/ngx_cycle.h @@ -53,6 +53,7 @@ struct ngx_cycle_s { ngx_uint_t modules_used; /* unsigned modules_used:1; */ ngx_queue_t reusable_connections_queue; + ngx_uint_t reusable_connections_n; ngx_array_t listening; ngx_array_t paths; @@ -87,6 +88,7 @@ typedef struct { ngx_flag_t master; ngx_msec_t timer_resolution; + ngx_msec_t shutdown_timeout; ngx_int_t worker_processes; ngx_int_t debug_points; @@ -128,6 +130,7 @@ ngx_pid_t ngx_exec_new_binary(ngx_cycle_t *cycle, char *const *argv); ngx_cpuset_t *ngx_get_cpu_affinity(ngx_uint_t n); ngx_shm_zone_t *ngx_shared_memory_add(ngx_conf_t *cf, ngx_str_t *name, size_t size, void *tag); +void ngx_set_shutdown_timer(ngx_cycle_t *cycle); extern volatile ngx_cycle_t *ngx_cycle; diff --git a/src/core/ngx_file.c b/src/core/ngx_file.c index 8359c0feee4..3a94089decd 100644 --- a/src/core/ngx_file.c +++ b/src/core/ngx_file.c @@ -141,12 +141,27 @@ ngx_int_t ngx_create_temp_file(ngx_file_t *file, ngx_path_t *path, ngx_pool_t *pool, ngx_uint_t persistent, ngx_uint_t clean, ngx_uint_t access) { + size_t levels; + u_char *p; uint32_t n; ngx_err_t err; + ngx_str_t name; + ngx_uint_t prefix; ngx_pool_cleanup_t *cln; ngx_pool_cleanup_file_t *clnf; - file->name.len = path->name.len + 1 + path->len + 10; + if (file->name.len) { + name = file->name; + levels = 0; + prefix = 1; + + } else { + name = path->name; + levels = path->len; + prefix = 0; + } + + file->name.len = name.len + 1 + levels + 10; file->name.data = ngx_pnalloc(pool, file->name.len + 1); if (file->name.data == NULL) { @@ -159,7 +174,13 @@ ngx_create_temp_file(ngx_file_t *file, ngx_path_t *path, ngx_pool_t *pool, } #endif - ngx_memcpy(file->name.data, path->name.data, path->name.len); + p = ngx_cpymem(file->name.data, name.data, name.len); + + if (prefix) { + *p = '.'; + } + + p += 1 + levels; n = (uint32_t) ngx_next_temp_number(0); @@ -169,10 +190,11 @@ ngx_create_temp_file(ngx_file_t *file, ngx_path_t *path, ngx_pool_t *pool, } for ( ;; ) { - (void) ngx_sprintf(file->name.data + path->name.len + 1 + path->len, - "%010uD%Z", n); + (void) ngx_sprintf(p, "%010uD%Z", n); - ngx_create_hashed_filename(path, file->name.data, file->name.len); + if (!prefix) { + ngx_create_hashed_filename(path, file->name.data, file->name.len); + } ngx_log_debug1(NGX_LOG_DEBUG_CORE, file->log, 0, "hashed path: %s", file->name.data); @@ -600,9 +622,7 @@ ngx_create_paths(ngx_cycle_t *cycle, ngx_uid_t user) { ngx_file_info_t fi; - if (ngx_file_info((const char *) path[i]->name.data, &fi) - == NGX_FILE_ERROR) - { + if (ngx_file_info(path[i]->name.data, &fi) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, ngx_file_info_n " \"%s\" failed", path[i]->name.data); return NGX_ERROR; diff --git a/src/core/ngx_inet.c b/src/core/ngx_inet.c index 3bcd3e79961..db48b93c11a 100644 --- a/src/core/ngx_inet.c +++ b/src/core/ngx_inet.c @@ -182,9 +182,11 @@ ngx_sock_ntop(struct sockaddr *sa, socklen_t socklen, u_char *text, size_t len, ngx_uint_t port) { u_char *p; +#if (NGX_HAVE_INET6 || NGX_HAVE_UNIX_DOMAIN) + size_t n; +#endif struct sockaddr_in *sin; #if (NGX_HAVE_INET6) - size_t n; struct sockaddr_in6 *sin6; #endif #if (NGX_HAVE_UNIX_DOMAIN) @@ -241,7 +243,9 @@ ngx_sock_ntop(struct sockaddr *sa, socklen_t socklen, u_char *text, size_t len, p = ngx_snprintf(text, len, "unix:%Z"); } else { - p = ngx_snprintf(text, len, "unix:%s%Z", saun->sun_path); + n = ngx_strnlen((u_char *) saun->sun_path, + socklen - offsetof(struct sockaddr_un, sun_path)); + p = ngx_snprintf(text, len, "unix:%*s%Z", n, saun->sun_path); } /* we do not include trailing zero in address length */ diff --git a/src/core/ngx_inet.h b/src/core/ngx_inet.h index 538771e113f..a3b392ee766 100644 --- a/src/core/ngx_inet.h +++ b/src/core/ngx_inet.h @@ -17,10 +17,11 @@ #define NGX_INET6_ADDRSTRLEN \ (sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255") - 1) #define NGX_UNIX_ADDRSTRLEN \ - (sizeof(struct sockaddr_un) - offsetof(struct sockaddr_un, sun_path)) + (sizeof("unix:") - 1 + \ + sizeof(struct sockaddr_un) - offsetof(struct sockaddr_un, sun_path)) #if (NGX_HAVE_UNIX_DOMAIN) -#define NGX_SOCKADDR_STRLEN (sizeof("unix:") - 1 + NGX_UNIX_ADDRSTRLEN) +#define NGX_SOCKADDR_STRLEN NGX_UNIX_ADDRSTRLEN #elif (NGX_HAVE_INET6) #define NGX_SOCKADDR_STRLEN (NGX_INET6_ADDRSTRLEN + sizeof("[]:65535") - 1) #else diff --git a/src/core/ngx_murmurhash.c b/src/core/ngx_murmurhash.c index c31e0e03500..5ade658dd05 100644 --- a/src/core/ngx_murmurhash.c +++ b/src/core/ngx_murmurhash.c @@ -35,8 +35,10 @@ ngx_murmur_hash2(u_char *data, size_t len) switch (len) { case 3: h ^= data[2] << 16; + /* fall through */ case 2: h ^= data[1] << 8; + /* fall through */ case 1: h ^= data[0]; h *= 0x5bd1e995; diff --git a/src/core/ngx_output_chain.c b/src/core/ngx_output_chain.c index f7845787b6a..7f5dc787ed3 100644 --- a/src/core/ngx_output_chain.c +++ b/src/core/ngx_output_chain.c @@ -512,7 +512,7 @@ ngx_output_chain_copy_buf(ngx_output_chain_ctx_t *ctx) size = ngx_buf_size(src); size = ngx_min(size, dst->end - dst->pos); - sendfile = ctx->sendfile & !ctx->directio; + sendfile = ctx->sendfile && !ctx->directio; #if (NGX_SENDFILE_LIMIT) diff --git a/src/core/ngx_palloc.h b/src/core/ngx_palloc.h index d6528291053..376e0128372 100644 --- a/src/core/ngx_palloc.h +++ b/src/core/ngx_palloc.h @@ -72,9 +72,6 @@ typedef struct { } ngx_pool_cleanup_file_t; -void *ngx_alloc(size_t size, ngx_log_t *log); -void *ngx_calloc(size_t size, ngx_log_t *log); - ngx_pool_t *ngx_create_pool(size_t size, ngx_log_t *log); void ngx_destroy_pool(ngx_pool_t *pool); void ngx_reset_pool(ngx_pool_t *pool); diff --git a/src/core/ngx_parse.c b/src/core/ngx_parse.c index 7b60c5fb65a..d35e60fac8b 100644 --- a/src/core/ngx_parse.c +++ b/src/core/ngx_parse.c @@ -17,6 +17,11 @@ ngx_parse_size(ngx_str_t *line) ssize_t size, scale, max; len = line->len; + + if (len == 0) { + return NGX_ERROR; + } + unit = line->data[len - 1]; switch (unit) { @@ -58,6 +63,11 @@ ngx_parse_offset(ngx_str_t *line) size_t len; len = line->len; + + if (len == 0) { + return NGX_ERROR; + } + unit = line->data[len - 1]; switch (unit) { diff --git a/src/core/ngx_parse_time.c b/src/core/ngx_parse_time.c index 13afde363f2..232ac91dd4c 100644 --- a/src/core/ngx_parse_time.c +++ b/src/core/ngx_parse_time.c @@ -44,21 +44,22 @@ ngx_parse_http_time(u_char *value, size_t len) } } - for (p++; p < end; p++) + for (p++; p < end; p++) { if (*p != ' ') { break; } + } if (end - p < 18) { return NGX_ERROR; - } + } if (fmt != isoc) { if (*p < '0' || *p > '9' || *(p + 1) < '0' || *(p + 1) > '9') { return NGX_ERROR; } - day = (*p - '0') * 10 + *(p + 1) - '0'; + day = (*p - '0') * 10 + (*(p + 1) - '0'); p += 2; if (*p == ' ') { @@ -132,7 +133,7 @@ ngx_parse_http_time(u_char *value, size_t len) } year = (*p - '0') * 1000 + (*(p + 1) - '0') * 100 - + (*(p + 2) - '0') * 10 + *(p + 3) - '0'; + + (*(p + 2) - '0') * 10 + (*(p + 3) - '0'); p += 4; } else if (fmt == rfc850) { @@ -140,7 +141,7 @@ ngx_parse_http_time(u_char *value, size_t len) return NGX_ERROR; } - year = (*p - '0') * 10 + *(p + 1) - '0'; + year = (*p - '0') * 10 + (*(p + 1) - '0'); year += (year < 70) ? 2000 : 1900; p += 2; } @@ -161,7 +162,7 @@ ngx_parse_http_time(u_char *value, size_t len) return NGX_ERROR; } - day = day * 10 + *p++ - '0'; + day = day * 10 + (*p++ - '0'); } if (end - p < 14) { @@ -177,7 +178,7 @@ ngx_parse_http_time(u_char *value, size_t len) return NGX_ERROR; } - hour = (*p - '0') * 10 + *(p + 1) - '0'; + hour = (*p - '0') * 10 + (*(p + 1) - '0'); p += 2; if (*p++ != ':') { @@ -188,7 +189,7 @@ ngx_parse_http_time(u_char *value, size_t len) return NGX_ERROR; } - min = (*p - '0') * 10 + *(p + 1) - '0'; + min = (*p - '0') * 10 + (*(p + 1) - '0'); p += 2; if (*p++ != ':') { @@ -199,7 +200,7 @@ ngx_parse_http_time(u_char *value, size_t len) return NGX_ERROR; } - sec = (*p - '0') * 10 + *(p + 1) - '0'; + sec = (*p - '0') * 10 + (*(p + 1) - '0'); if (fmt == isoc) { p += 2; @@ -216,7 +217,7 @@ ngx_parse_http_time(u_char *value, size_t len) } year = (*p - '0') * 1000 + (*(p + 1) - '0') * 100 - + (*(p + 2) - '0') * 10 + *(p + 3) - '0'; + + (*(p + 2) - '0') * 10 + (*(p + 3) - '0'); } if (hour > 23 || min > 59 || sec > 59) { diff --git a/src/core/ngx_rbtree.c b/src/core/ngx_rbtree.c index 6c66f4061b2..969d549c857 100644 --- a/src/core/ngx_rbtree.c +++ b/src/core/ngx_rbtree.c @@ -28,7 +28,7 @@ ngx_rbtree_insert(ngx_rbtree_t *tree, ngx_rbtree_node_t *node) /* a binary tree insert */ - root = (ngx_rbtree_node_t **) &tree->root; + root = &tree->root; sentinel = tree->sentinel; if (*root == sentinel) { @@ -161,7 +161,7 @@ ngx_rbtree_delete(ngx_rbtree_t *tree, ngx_rbtree_node_t *node) /* a binary tree delete */ - root = (ngx_rbtree_node_t **) &tree->root; + root = &tree->root; sentinel = tree->sentinel; if (node->left == sentinel) { @@ -378,3 +378,32 @@ ngx_rbtree_right_rotate(ngx_rbtree_node_t **root, ngx_rbtree_node_t *sentinel, temp->right = node; node->parent = temp; } + + +ngx_rbtree_node_t * +ngx_rbtree_next(ngx_rbtree_t *tree, ngx_rbtree_node_t *node) +{ + ngx_rbtree_node_t *root, *sentinel, *parent; + + sentinel = tree->sentinel; + + if (node->right != sentinel) { + return ngx_rbtree_min(node->right, sentinel); + } + + root = tree->root; + + for ( ;; ) { + parent = node->parent; + + if (node == root) { + return NULL; + } + + if (node == parent->left) { + return parent; + } + + node = parent; + } +} diff --git a/src/core/ngx_rbtree.h b/src/core/ngx_rbtree.h index 1d33e3f6e06..97f0e3e1183 100644 --- a/src/core/ngx_rbtree.h +++ b/src/core/ngx_rbtree.h @@ -54,6 +54,8 @@ void ngx_rbtree_insert_value(ngx_rbtree_node_t *root, ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel); void ngx_rbtree_insert_timer_value(ngx_rbtree_node_t *root, ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel); +ngx_rbtree_node_t *ngx_rbtree_next(ngx_rbtree_t *tree, + ngx_rbtree_node_t *node); #define ngx_rbt_red(node) ((node)->color = 1) diff --git a/src/core/ngx_regex.c b/src/core/ngx_regex.c index 9939dce7e5b..52169f6553c 100644 --- a/src/core/ngx_regex.c +++ b/src/core/ngx_regex.c @@ -262,7 +262,7 @@ ngx_pcre_free_studies(void *data) part = &studies->part; elts = part->elts; - for (i = 0 ; /* void */ ; i++) { + for (i = 0; /* void */ ; i++) { if (i >= part->nelts) { if (part->next == NULL) { @@ -326,7 +326,7 @@ ngx_regex_module_init(ngx_cycle_t *cycle) part = &ngx_pcre_studies->part; elts = part->elts; - for (i = 0 ; /* void */ ; i++) { + for (i = 0; /* void */ ; i++) { if (i >= part->nelts) { if (part->next == NULL) { diff --git a/src/core/ngx_resolver.c b/src/core/ngx_resolver.c index bdfed88edde..cd55520cb4f 100644 --- a/src/core/ngx_resolver.c +++ b/src/core/ngx_resolver.c @@ -56,8 +56,8 @@ typedef struct { ((u_char *) (n) - offsetof(ngx_resolver_node_t, node)) -ngx_int_t ngx_udp_connect(ngx_resolver_connection_t *rec); -ngx_int_t ngx_tcp_connect(ngx_resolver_connection_t *rec); +static ngx_int_t ngx_udp_connect(ngx_resolver_connection_t *rec); +static ngx_int_t ngx_tcp_connect(ngx_resolver_connection_t *rec); static void ngx_resolver_cleanup(void *data); @@ -105,6 +105,8 @@ static void ngx_resolver_rbtree_insert_value(ngx_rbtree_node_t *temp, ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel); static ngx_int_t ngx_resolver_copy(ngx_resolver_t *r, ngx_str_t *name, u_char *buf, u_char *src, u_char *last); +static ngx_int_t ngx_resolver_set_timeout(ngx_resolver_t *r, + ngx_resolver_ctx_t *ctx); static void ngx_resolver_timeout_handler(ngx_event_t *ev); static void ngx_resolver_free_node(ngx_resolver_t *r, ngx_resolver_node_t *rn); static void *ngx_resolver_alloc(ngx_resolver_t *r, size_t size); @@ -189,6 +191,7 @@ ngx_resolver_create(ngx_conf_t *cf, ngx_str_t *names, ngx_uint_t n) r->event->handler = ngx_resolver_resend_handler; r->event->data = r; r->event->log = &cf->cycle->new_log; + r->event->cancelable = 1; r->ident = -1; r->resend_timeout = 5; @@ -300,6 +303,10 @@ ngx_resolver_cleanup(void *data) #endif if (r->event) { + if (r->event->timer_set) { + ngx_del_timer(r->event); + } + ngx_free(r->event); } @@ -347,6 +354,10 @@ ngx_resolver_cleanup_tree(ngx_resolver_t *r, ngx_rbtree_t *tree) next = ctx->next; if (ctx->event) { + if (ctx->event->timer_set) { + ngx_del_timer(ctx->event); + } + ngx_resolver_free(r, ctx->event); } @@ -435,7 +446,7 @@ ngx_resolve_name(ngx_resolver_ctx_t *ctx) name.data = ngx_resolver_alloc(r, name.len); if (name.data == NULL) { - return NGX_ERROR; + goto failed; } if (slen == ctx->service.len) { @@ -473,6 +484,8 @@ ngx_resolve_name(ngx_resolver_ctx_t *ctx) ngx_resolver_free(r, ctx->event); } +failed: + ngx_resolver_free(r, ctx); return NGX_ERROR; @@ -718,24 +731,14 @@ ngx_resolve_name_locked(ngx_resolver_t *r, ngx_resolver_ctx_t *ctx, } if (rn->waiting) { - - if (ctx->event == NULL && ctx->timeout) { - ctx->event = ngx_resolver_calloc(r, sizeof(ngx_event_t)); - if (ctx->event == NULL) { - return NGX_ERROR; - } - - ctx->event->handler = ngx_resolver_timeout_handler; - ctx->event->data = ctx; - ctx->event->log = r->log; - ctx->ident = -1; - - ngx_add_timer(ctx->event, ctx->timeout); + if (ngx_resolver_set_timeout(r, ctx) != NGX_OK) { + return NGX_ERROR; } last->next = rn->waiting; rn->waiting = ctx; ctx->state = NGX_AGAIN; + ctx->async = 1; do { ctx->node = rn; @@ -772,7 +775,7 @@ ngx_resolve_name_locked(ngx_resolver_t *r, ngx_resolver_ctx_t *ctx, #endif if (rn->nsrvs) { - for (i = 0; i < rn->nsrvs; i++) { + for (i = 0; i < (ngx_uint_t) rn->nsrvs; i++) { if (rn->u.srvs[i].name.data) { ngx_resolver_free_locked(r, rn->u.srvs[i].name.data); } @@ -853,21 +856,11 @@ ngx_resolve_name_locked(ngx_resolver_t *r, ngx_resolver_ctx_t *ctx, goto failed; } - if (ctx->event == NULL && ctx->timeout) { - ctx->event = ngx_resolver_calloc(r, sizeof(ngx_event_t)); - if (ctx->event == NULL) { - goto failed; - } - - ctx->event->handler = ngx_resolver_timeout_handler; - ctx->event->data = ctx; - ctx->event->log = r->log; - ctx->ident = -1; - - ngx_add_timer(ctx->event, ctx->timeout); + if (ngx_resolver_set_timeout(r, ctx) != NGX_OK) { + goto failed; } - if (ngx_queue_empty(resend_queue)) { + if (ngx_resolver_resend_empty(r)) { ngx_add_timer(r->event, (ngx_msec_t) (r->resend_timeout * 1000)); } @@ -882,6 +875,7 @@ ngx_resolve_name_locked(ngx_resolver_t *r, ngx_resolver_ctx_t *ctx, rn->waiting = ctx; ctx->state = NGX_AGAIN; + ctx->async = 1; do { ctx->node = rn; @@ -995,24 +989,14 @@ ngx_resolve_addr(ngx_resolver_ctx_t *ctx) } if (rn->waiting) { - - if (ctx->event == NULL && ctx->timeout) { - ctx->event = ngx_resolver_calloc(r, sizeof(ngx_event_t)); - if (ctx->event == NULL) { - return NGX_ERROR; - } - - ctx->event->handler = ngx_resolver_timeout_handler; - ctx->event->data = ctx; - ctx->event->log = r->log; - ctx->ident = -1; - - ngx_add_timer(ctx->event, ctx->timeout); + if (ngx_resolver_set_timeout(r, ctx) != NGX_OK) { + return NGX_ERROR; } ctx->next = rn->waiting; rn->waiting = ctx; ctx->state = NGX_AGAIN; + ctx->async = 1; ctx->node = rn; /* unlock addr mutex */ @@ -1076,21 +1060,11 @@ ngx_resolve_addr(ngx_resolver_ctx_t *ctx) goto failed; } - if (ctx->event == NULL && ctx->timeout) { - ctx->event = ngx_resolver_calloc(r, sizeof(ngx_event_t)); - if (ctx->event == NULL) { - goto failed; - } - - ctx->event->handler = ngx_resolver_timeout_handler; - ctx->event->data = ctx; - ctx->event->log = r->log; - ctx->ident = -1; - - ngx_add_timer(ctx->event, ctx->timeout); + if (ngx_resolver_set_timeout(r, ctx) != NGX_OK) { + goto failed; } - if (ngx_queue_empty(resend_queue)) { + if (ngx_resolver_resend_empty(r)) { ngx_add_timer(r->event, (ngx_msec_t) (r->resend_timeout * 1000)); } @@ -1109,6 +1083,7 @@ ngx_resolve_addr(ngx_resolver_ctx_t *ctx) /* unlock addr mutex */ ctx->state = NGX_AGAIN; + ctx->async = 1; ctx->node = rn; return NGX_OK; @@ -1548,6 +1523,7 @@ static ngx_uint_t ngx_resolver_resend_empty(ngx_resolver_t *r) { return ngx_queue_empty(&r->name_resend_queue) + && ngx_queue_empty(&r->srv_resend_queue) #if (NGX_HAVE_INET6) && ngx_queue_empty(&r->addr6_resend_queue) #endif @@ -2946,7 +2922,11 @@ ngx_resolver_resolve_srv_names(ngx_resolver_ctx_t *ctx, ngx_resolver_node_t *rn) ctx->srvs = srvs; ctx->nsrvs = rn->nsrvs; - for (i = 0; i < rn->nsrvs; i++) { + if (ctx->event && ctx->event->timer_set) { + ngx_del_timer(ctx->event); + } + + for (i = 0; i < (ngx_uint_t) rn->nsrvs; i++) { srvs[i].name.data = ngx_resolver_alloc(r, rn->u.srvs[i].name.len); if (srvs[i].name.data == NULL) { goto failed; @@ -2965,7 +2945,7 @@ ngx_resolver_resolve_srv_names(ngx_resolver_ctx_t *ctx, ngx_resolver_node_t *rn) cctx->handler = ngx_resolver_srv_names_handler; cctx->data = ctx; cctx->srvs = &srvs[i]; - cctx->timeout = 0; + cctx->timeout = ctx->timeout; srvs[i].priority = rn->u.srvs[i].priority; srvs[i].weight = rn->u.srvs[i].weight; @@ -3004,6 +2984,7 @@ ngx_resolver_srv_names_handler(ngx_resolver_ctx_t *cctx) srv = cctx->srvs; ctx->count--; + ctx->async |= cctx->async; srv->ctx = NULL; srv->state = cctx->state; @@ -3014,25 +2995,15 @@ ngx_resolver_srv_names_handler(ngx_resolver_ctx_t *cctx) addrs = ngx_resolver_calloc(r, cctx->naddrs * sizeof(ngx_addr_t)); if (addrs == NULL) { - ngx_resolve_name_done(cctx); - - ctx->state = NGX_ERROR; - ctx->valid = ngx_time() + (r->valid ? r->valid : 10); - - ctx->handler(ctx); - return; + srv->state = NGX_ERROR; + goto done; } sockaddr = ngx_resolver_alloc(r, cctx->naddrs * sizeof(ngx_sockaddr_t)); if (sockaddr == NULL) { ngx_resolver_free(r, addrs); - ngx_resolve_name_done(cctx); - - ctx->state = NGX_ERROR; - ctx->valid = ngx_time() + (r->valid ? r->valid : 10); - - ctx->handler(ctx); - return; + srv->state = NGX_ERROR; + goto done; } for (i = 0; i < cctx->naddrs; i++) { @@ -3049,6 +3020,8 @@ ngx_resolver_srv_names_handler(ngx_resolver_ctx_t *cctx) srv->naddrs = cctx->naddrs; } +done: + ngx_resolve_name_done(cctx); if (ctx->count == 0) { @@ -4021,6 +3994,30 @@ ngx_resolver_copy(ngx_resolver_t *r, ngx_str_t *name, u_char *buf, u_char *src, } +static ngx_int_t +ngx_resolver_set_timeout(ngx_resolver_t *r, ngx_resolver_ctx_t *ctx) +{ + if (ctx->event || ctx->timeout == 0) { + return NGX_OK; + } + + ctx->event = ngx_resolver_calloc(r, sizeof(ngx_event_t)); + if (ctx->event == NULL) { + return NGX_ERROR; + } + + ctx->event->handler = ngx_resolver_timeout_handler; + ctx->event->data = ctx; + ctx->event->log = r->log; + ctx->event->cancelable = ctx->cancelable; + ctx->ident = -1; + + ngx_add_timer(ctx->event, ctx->timeout); + + return NGX_OK; +} + + static void ngx_resolver_timeout_handler(ngx_event_t *ev) { @@ -4064,7 +4061,7 @@ ngx_resolver_free_node(ngx_resolver_t *r, ngx_resolver_node_t *rn) #endif if (rn->nsrvs) { - for (i = 0; i < rn->nsrvs; i++) { + for (i = 0; i < (ngx_uint_t) rn->nsrvs; i++) { if (rn->u.srvs[i].name.data) { ngx_resolver_free_locked(r, rn->u.srvs[i].name.data); } @@ -4193,10 +4190,10 @@ ngx_resolver_export(ngx_resolver_t *r, ngx_resolver_node_t *rn, d = 0; } - if (j == rn->naddrs) { + if (j == (ngx_uint_t) rn->naddrs) { j = 0; } - } while (++i < rn->naddrs); + } while (++i < (ngx_uint_t) rn->naddrs); } #if (NGX_HAVE_INET6) @@ -4234,10 +4231,21 @@ ngx_resolver_report_srv(ngx_resolver_t *r, ngx_resolver_ctx_t *ctx) ngx_resolver_addr_t *addrs; ngx_resolver_srv_name_t *srvs; + srvs = ctx->srvs; + nsrvs = ctx->nsrvs; + naddrs = 0; - for (i = 0; i < ctx->nsrvs; i++) { - naddrs += ctx->srvs[i].naddrs; + for (i = 0; i < nsrvs; i++) { + if (srvs[i].state == NGX_ERROR) { + ctx->state = NGX_ERROR; + ctx->valid = ngx_time() + (r->valid ? r->valid : 10); + + ctx->handler(ctx); + return; + } + + naddrs += srvs[i].naddrs; } if (naddrs == 0) { @@ -4257,9 +4265,6 @@ ngx_resolver_report_srv(ngx_resolver_t *r, ngx_resolver_ctx_t *ctx) return; } - srvs = ctx->srvs; - nsrvs = ctx->nsrvs; - i = 0; n = 0; @@ -4366,7 +4371,7 @@ ngx_resolver_log_error(ngx_log_t *log, u_char *buf, size_t len) } -ngx_int_t +static ngx_int_t ngx_udp_connect(ngx_resolver_connection_t *rec) { int rc; @@ -4450,7 +4455,7 @@ ngx_udp_connect(ngx_resolver_connection_t *rec) } -ngx_int_t +static ngx_int_t ngx_tcp_connect(ngx_resolver_connection_t *rec) { int rc; diff --git a/src/core/ngx_resolver.h b/src/core/ngx_resolver.h index a0d6fc341ae..0bd392189d9 100644 --- a/src/core/ngx_resolver.h +++ b/src/core/ngx_resolver.h @@ -218,7 +218,9 @@ struct ngx_resolver_ctx_s { void *data; ngx_msec_t timeout; - ngx_uint_t quick; /* unsigned quick:1; */ + unsigned quick:1; + unsigned async:1; + unsigned cancelable:1; ngx_uint_t recursion; ngx_event_t *event; }; diff --git a/src/core/ngx_rwlock.c b/src/core/ngx_rwlock.c index 905de780a87..ed2b0f81050 100644 --- a/src/core/ngx_rwlock.c +++ b/src/core/ngx_rwlock.c @@ -94,7 +94,7 @@ ngx_rwlock_unlock(ngx_atomic_t *lock) readers = *lock; if (readers == NGX_RWLOCK_WLOCK) { - *lock = 0; + (void) ngx_atomic_cmp_set(lock, NGX_RWLOCK_WLOCK, 0); return; } @@ -109,6 +109,15 @@ ngx_rwlock_unlock(ngx_atomic_t *lock) } +void +ngx_rwlock_downgrade(ngx_atomic_t *lock) +{ + if (*lock == NGX_RWLOCK_WLOCK) { + *lock = 1; + } +} + + #else #if (NGX_HTTP_UPSTREAM_ZONE || NGX_STREAM_UPSTREAM_ZONE) diff --git a/src/core/ngx_rwlock.h b/src/core/ngx_rwlock.h index 8b16eca20f5..41b42aa82d6 100644 --- a/src/core/ngx_rwlock.h +++ b/src/core/ngx_rwlock.h @@ -16,6 +16,7 @@ void ngx_rwlock_wlock(ngx_atomic_t *lock); void ngx_rwlock_rlock(ngx_atomic_t *lock); void ngx_rwlock_unlock(ngx_atomic_t *lock); +void ngx_rwlock_downgrade(ngx_atomic_t *lock); #endif /* _NGX_RWLOCK_H_INCLUDED_ */ diff --git a/src/core/ngx_slab.c b/src/core/ngx_slab.c index 56e7765c0f3..40238705394 100644 --- a/src/core/ngx_slab.c +++ b/src/core/ngx_slab.c @@ -41,6 +41,19 @@ #endif +#define ngx_slab_slots(pool) \ + (ngx_slab_page_t *) ((u_char *) (pool) + sizeof(ngx_slab_pool_t)) + +#define ngx_slab_page_type(page) ((page)->prev & NGX_SLAB_PAGE_MASK) + +#define ngx_slab_page_prev(page) \ + (ngx_slab_page_t *) ((page)->prev & ~NGX_SLAB_PAGE_MASK) + +#define ngx_slab_page_addr(pool, page) \ + ((((page) - (pool)->pages) << ngx_pagesize_shift) \ + + (uintptr_t) (pool)->start) + + #if (NGX_DEBUG_MALLOC) #define ngx_slab_junk(p, size) ngx_memset(p, 0xA5, size) @@ -69,6 +82,19 @@ static ngx_uint_t ngx_slab_exact_size; static ngx_uint_t ngx_slab_exact_shift; +void +ngx_slab_sizes_init(void) +{ + ngx_uint_t n; + + ngx_slab_max_size = ngx_pagesize / 2; + ngx_slab_exact_size = ngx_pagesize / (8 * sizeof(uintptr_t)); + for (n = ngx_slab_exact_size; n >>= 1; ngx_slab_exact_shift++) { + /* void */ + } +} + + void ngx_slab_init(ngx_slab_pool_t *pool) { @@ -76,29 +102,21 @@ ngx_slab_init(ngx_slab_pool_t *pool) size_t size; ngx_int_t m; ngx_uint_t i, n, pages; - ngx_slab_page_t *slots; - - /* STUB */ - if (ngx_slab_max_size == 0) { - ngx_slab_max_size = ngx_pagesize / 2; - ngx_slab_exact_size = ngx_pagesize / (8 * sizeof(uintptr_t)); - for (n = ngx_slab_exact_size; n >>= 1; ngx_slab_exact_shift++) { - /* void */ - } - } - /**/ + ngx_slab_page_t *slots, *page; - pool->min_size = 1 << pool->min_shift; + pool->min_size = (size_t) 1 << pool->min_shift; - p = (u_char *) pool + sizeof(ngx_slab_pool_t); + slots = ngx_slab_slots(pool); + + p = (u_char *) slots; size = pool->end - p; ngx_slab_junk(p, size); - slots = (ngx_slab_page_t *) p; n = ngx_pagesize_shift - pool->min_shift; for (i = 0; i < n; i++) { + /* only "next" is used in list head */ slots[i].slab = 0; slots[i].next = &slots[i]; slots[i].prev = 0; @@ -106,30 +124,40 @@ ngx_slab_init(ngx_slab_pool_t *pool) p += n * sizeof(ngx_slab_page_t); - pages = (ngx_uint_t) (size / (ngx_pagesize + sizeof(ngx_slab_page_t))); + pool->stats = (ngx_slab_stat_t *) p; + ngx_memzero(pool->stats, n * sizeof(ngx_slab_stat_t)); + + p += n * sizeof(ngx_slab_stat_t); - ngx_memzero(p, pages * sizeof(ngx_slab_page_t)); + size -= n * (sizeof(ngx_slab_page_t) + sizeof(ngx_slab_stat_t)); + + pages = (ngx_uint_t) (size / (ngx_pagesize + sizeof(ngx_slab_page_t))); pool->pages = (ngx_slab_page_t *) p; + ngx_memzero(pool->pages, pages * sizeof(ngx_slab_page_t)); + + page = pool->pages; + /* only "next" is used in list head */ + pool->free.slab = 0; + pool->free.next = page; pool->free.prev = 0; - pool->free.next = (ngx_slab_page_t *) p; - pool->pages->slab = pages; - pool->pages->next = &pool->free; - pool->pages->prev = (uintptr_t) &pool->free; + page->slab = pages; + page->next = &pool->free; + page->prev = (uintptr_t) &pool->free; - pool->start = (u_char *) - ngx_align_ptr((uintptr_t) p + pages * sizeof(ngx_slab_page_t), - ngx_pagesize); + pool->start = ngx_align_ptr(p + pages * sizeof(ngx_slab_page_t), + ngx_pagesize); m = pages - (pool->end - pool->start) / ngx_pagesize; if (m > 0) { pages -= m; - pool->pages->slab = pages; + page->slab = pages; } pool->last = pool->pages + pages; + pool->pfree = pages; pool->log_nomem = 1; pool->log_ctx = &pool->zero; @@ -156,8 +184,8 @@ void * ngx_slab_alloc_locked(ngx_slab_pool_t *pool, size_t size) { size_t s; - uintptr_t p, n, m, mask, *bitmap; - ngx_uint_t i, slot, shift, map; + uintptr_t p, m, mask, *bitmap; + ngx_uint_t i, n, slot, shift, map; ngx_slab_page_t *page, *prev, *slots; if (size > ngx_slab_max_size) { @@ -168,8 +196,7 @@ ngx_slab_alloc_locked(ngx_slab_pool_t *pool, size_t size) page = ngx_slab_alloc_pages(pool, (size >> ngx_pagesize_shift) + ((size % ngx_pagesize) ? 1 : 0)); if (page) { - p = (page - pool->pages) << ngx_pagesize_shift; - p += (uintptr_t) pool->start; + p = ngx_slab_page_addr(pool, page); } else { p = 0; @@ -184,168 +211,148 @@ ngx_slab_alloc_locked(ngx_slab_pool_t *pool, size_t size) slot = shift - pool->min_shift; } else { - size = pool->min_size; shift = pool->min_shift; slot = 0; } + pool->stats[slot].reqs++; + ngx_log_debug2(NGX_LOG_DEBUG_ALLOC, ngx_cycle->log, 0, "slab alloc: %uz slot: %ui", size, slot); - slots = (ngx_slab_page_t *) ((u_char *) pool + sizeof(ngx_slab_pool_t)); + slots = ngx_slab_slots(pool); page = slots[slot].next; if (page->next != page) { if (shift < ngx_slab_exact_shift) { - do { - p = (page - pool->pages) << ngx_pagesize_shift; - bitmap = (uintptr_t *) (pool->start + p); - - map = (1 << (ngx_pagesize_shift - shift)) - / (sizeof(uintptr_t) * 8); - - for (n = 0; n < map; n++) { - - if (bitmap[n] != NGX_SLAB_BUSY) { - - for (m = 1, i = 0; m; m <<= 1, i++) { - if ((bitmap[n] & m)) { - continue; - } - - bitmap[n] |= m; - - i = ((n * sizeof(uintptr_t) * 8) << shift) - + (i << shift); - - if (bitmap[n] == NGX_SLAB_BUSY) { - for (n = n + 1; n < map; n++) { - if (bitmap[n] != NGX_SLAB_BUSY) { - p = (uintptr_t) bitmap + i; - - goto done; - } - } + bitmap = (uintptr_t *) ngx_slab_page_addr(pool, page); - prev = (ngx_slab_page_t *) - (page->prev & ~NGX_SLAB_PAGE_MASK); - prev->next = page->next; - page->next->prev = page->prev; + map = (ngx_pagesize >> shift) / (8 * sizeof(uintptr_t)); - page->next = NULL; - page->prev = NGX_SLAB_SMALL; - } + for (n = 0; n < map; n++) { - p = (uintptr_t) bitmap + i; + if (bitmap[n] != NGX_SLAB_BUSY) { - goto done; + for (m = 1, i = 0; m; m <<= 1, i++) { + if (bitmap[n] & m) { + continue; } - } - } - page = page->next; + bitmap[n] |= m; - } while (page); + i = (n * 8 * sizeof(uintptr_t) + i) << shift; - } else if (shift == ngx_slab_exact_shift) { + p = (uintptr_t) bitmap + i; - do { - if (page->slab != NGX_SLAB_BUSY) { + pool->stats[slot].used++; - for (m = 1, i = 0; m; m <<= 1, i++) { - if ((page->slab & m)) { - continue; - } - - page->slab |= m; + if (bitmap[n] == NGX_SLAB_BUSY) { + for (n = n + 1; n < map; n++) { + if (bitmap[n] != NGX_SLAB_BUSY) { + goto done; + } + } - if (page->slab == NGX_SLAB_BUSY) { - prev = (ngx_slab_page_t *) - (page->prev & ~NGX_SLAB_PAGE_MASK); + prev = ngx_slab_page_prev(page); prev->next = page->next; page->next->prev = page->prev; page->next = NULL; - page->prev = NGX_SLAB_EXACT; + page->prev = NGX_SLAB_SMALL; } - p = (page - pool->pages) << ngx_pagesize_shift; - p += i << shift; - p += (uintptr_t) pool->start; - goto done; } } + } - page = page->next; + } else if (shift == ngx_slab_exact_shift) { - } while (page); + for (m = 1, i = 0; m; m <<= 1, i++) { + if (page->slab & m) { + continue; + } - } else { /* shift > ngx_slab_exact_shift */ + page->slab |= m; - n = ngx_pagesize_shift - (page->slab & NGX_SLAB_SHIFT_MASK); - n = 1 << n; - n = ((uintptr_t) 1 << n) - 1; - mask = n << NGX_SLAB_MAP_SHIFT; + if (page->slab == NGX_SLAB_BUSY) { + prev = ngx_slab_page_prev(page); + prev->next = page->next; + page->next->prev = page->prev; - do { - if ((page->slab & NGX_SLAB_MAP_MASK) != mask) { + page->next = NULL; + page->prev = NGX_SLAB_EXACT; + } - for (m = (uintptr_t) 1 << NGX_SLAB_MAP_SHIFT, i = 0; - m & mask; - m <<= 1, i++) - { - if ((page->slab & m)) { - continue; - } + p = ngx_slab_page_addr(pool, page) + (i << shift); - page->slab |= m; + pool->stats[slot].used++; - if ((page->slab & NGX_SLAB_MAP_MASK) == mask) { - prev = (ngx_slab_page_t *) - (page->prev & ~NGX_SLAB_PAGE_MASK); - prev->next = page->next; - page->next->prev = page->prev; + goto done; + } - page->next = NULL; - page->prev = NGX_SLAB_BIG; - } + } else { /* shift > ngx_slab_exact_shift */ - p = (page - pool->pages) << ngx_pagesize_shift; - p += i << shift; - p += (uintptr_t) pool->start; + mask = ((uintptr_t) 1 << (ngx_pagesize >> shift)) - 1; + mask <<= NGX_SLAB_MAP_SHIFT; - goto done; - } + for (m = (uintptr_t) 1 << NGX_SLAB_MAP_SHIFT, i = 0; + m & mask; + m <<= 1, i++) + { + if (page->slab & m) { + continue; + } + + page->slab |= m; + + if ((page->slab & NGX_SLAB_MAP_MASK) == mask) { + prev = ngx_slab_page_prev(page); + prev->next = page->next; + page->next->prev = page->prev; + + page->next = NULL; + page->prev = NGX_SLAB_BIG; } - page = page->next; + p = ngx_slab_page_addr(pool, page) + (i << shift); - } while (page); + pool->stats[slot].used++; + + goto done; + } } + + ngx_slab_error(pool, NGX_LOG_ALERT, "ngx_slab_alloc(): page is busy"); + ngx_debug_point(); } page = ngx_slab_alloc_pages(pool, 1); if (page) { if (shift < ngx_slab_exact_shift) { - p = (page - pool->pages) << ngx_pagesize_shift; - bitmap = (uintptr_t *) (pool->start + p); + bitmap = (uintptr_t *) ngx_slab_page_addr(pool, page); - s = 1 << shift; - n = (1 << (ngx_pagesize_shift - shift)) / 8 / s; + n = (ngx_pagesize >> shift) / ((1 << shift) * 8); if (n == 0) { n = 1; } - bitmap[0] = (2 << n) - 1; + /* "n" elements for bitmap, plus one requested */ + + for (i = 0; i < (n + 1) / (8 * sizeof(uintptr_t)); i++) { + bitmap[i] = NGX_SLAB_BUSY; + } - map = (1 << (ngx_pagesize_shift - shift)) / (sizeof(uintptr_t) * 8); + m = ((uintptr_t) 1 << ((n + 1) % (8 * sizeof(uintptr_t)))) - 1; + bitmap[i] = m; - for (i = 1; i < map; i++) { + map = (ngx_pagesize >> shift) / (8 * sizeof(uintptr_t)); + + for (i = i + 1; i < map; i++) { bitmap[i] = 0; } @@ -355,8 +362,11 @@ ngx_slab_alloc_locked(ngx_slab_pool_t *pool, size_t size) slots[slot].next = page; - p = ((page - pool->pages) << ngx_pagesize_shift) + s * n; - p += (uintptr_t) pool->start; + pool->stats[slot].total += (ngx_pagesize >> shift) - n; + + p = ngx_slab_page_addr(pool, page) + (n << shift); + + pool->stats[slot].used++; goto done; @@ -368,8 +378,11 @@ ngx_slab_alloc_locked(ngx_slab_pool_t *pool, size_t size) slots[slot].next = page; - p = (page - pool->pages) << ngx_pagesize_shift; - p += (uintptr_t) pool->start; + pool->stats[slot].total += 8 * sizeof(uintptr_t); + + p = ngx_slab_page_addr(pool, page); + + pool->stats[slot].used++; goto done; @@ -381,8 +394,11 @@ ngx_slab_alloc_locked(ngx_slab_pool_t *pool, size_t size) slots[slot].next = page; - p = (page - pool->pages) << ngx_pagesize_shift; - p += (uintptr_t) pool->start; + pool->stats[slot].total += ngx_pagesize >> shift; + + p = ngx_slab_page_addr(pool, page); + + pool->stats[slot].used++; goto done; } @@ -390,6 +406,8 @@ ngx_slab_alloc_locked(ngx_slab_pool_t *pool, size_t size) p = 0; + pool->stats[slot].fails++; + done: ngx_log_debug1(NGX_LOG_DEBUG_ALLOC, ngx_cycle->log, 0, @@ -444,7 +462,7 @@ ngx_slab_free_locked(ngx_slab_pool_t *pool, void *p) { size_t size; uintptr_t slab, m, *bitmap; - ngx_uint_t n, type, slot, shift, map; + ngx_uint_t i, n, type, slot, shift, map; ngx_slab_page_t *slots, *page; ngx_log_debug1(NGX_LOG_DEBUG_ALLOC, ngx_cycle->log, 0, "slab free: %p", p); @@ -457,31 +475,30 @@ ngx_slab_free_locked(ngx_slab_pool_t *pool, void *p) n = ((u_char *) p - pool->start) >> ngx_pagesize_shift; page = &pool->pages[n]; slab = page->slab; - type = page->prev & NGX_SLAB_PAGE_MASK; + type = ngx_slab_page_type(page); switch (type) { case NGX_SLAB_SMALL: shift = slab & NGX_SLAB_SHIFT_MASK; - size = 1 << shift; + size = (size_t) 1 << shift; if ((uintptr_t) p & (size - 1)) { goto wrong_chunk; } n = ((uintptr_t) p & (ngx_pagesize - 1)) >> shift; - m = (uintptr_t) 1 << (n & (sizeof(uintptr_t) * 8 - 1)); - n /= (sizeof(uintptr_t) * 8); + m = (uintptr_t) 1 << (n % (8 * sizeof(uintptr_t))); + n /= 8 * sizeof(uintptr_t); bitmap = (uintptr_t *) ((uintptr_t) p & ~((uintptr_t) ngx_pagesize - 1)); if (bitmap[n] & m) { + slot = shift - pool->min_shift; if (page->next == NULL) { - slots = (ngx_slab_page_t *) - ((u_char *) pool + sizeof(ngx_slab_pool_t)); - slot = shift - pool->min_shift; + slots = ngx_slab_slots(pool); page->next = slots[slot].next; slots[slot].next = page; @@ -492,26 +509,31 @@ ngx_slab_free_locked(ngx_slab_pool_t *pool, void *p) bitmap[n] &= ~m; - n = (1 << (ngx_pagesize_shift - shift)) / 8 / (1 << shift); + n = (ngx_pagesize >> shift) / ((1 << shift) * 8); if (n == 0) { n = 1; } - if (bitmap[0] & ~(((uintptr_t) 1 << n) - 1)) { + i = n / (8 * sizeof(uintptr_t)); + m = ((uintptr_t) 1 << (n % (8 * sizeof(uintptr_t)))) - 1; + + if (bitmap[i] & ~m) { goto done; } - map = (1 << (ngx_pagesize_shift - shift)) / (sizeof(uintptr_t) * 8); + map = (ngx_pagesize >> shift) / (8 * sizeof(uintptr_t)); - for (n = 1; n < map; n++) { - if (bitmap[n]) { + for (i = i + 1; i < map; i++) { + if (bitmap[i]) { goto done; } } ngx_slab_free_pages(pool, page, 1); + pool->stats[slot].total -= (ngx_pagesize >> shift) - n; + goto done; } @@ -528,10 +550,10 @@ ngx_slab_free_locked(ngx_slab_pool_t *pool, void *p) } if (slab & m) { + slot = ngx_slab_exact_shift - pool->min_shift; + if (slab == NGX_SLAB_BUSY) { - slots = (ngx_slab_page_t *) - ((u_char *) pool + sizeof(ngx_slab_pool_t)); - slot = ngx_slab_exact_shift - pool->min_shift; + slots = ngx_slab_slots(pool); page->next = slots[slot].next; slots[slot].next = page; @@ -548,6 +570,8 @@ ngx_slab_free_locked(ngx_slab_pool_t *pool, void *p) ngx_slab_free_pages(pool, page, 1); + pool->stats[slot].total -= 8 * sizeof(uintptr_t); + goto done; } @@ -556,7 +580,7 @@ ngx_slab_free_locked(ngx_slab_pool_t *pool, void *p) case NGX_SLAB_BIG: shift = slab & NGX_SLAB_SHIFT_MASK; - size = 1 << shift; + size = (size_t) 1 << shift; if ((uintptr_t) p & (size - 1)) { goto wrong_chunk; @@ -566,11 +590,10 @@ ngx_slab_free_locked(ngx_slab_pool_t *pool, void *p) + NGX_SLAB_MAP_SHIFT); if (slab & m) { + slot = shift - pool->min_shift; if (page->next == NULL) { - slots = (ngx_slab_page_t *) - ((u_char *) pool + sizeof(ngx_slab_pool_t)); - slot = shift - pool->min_shift; + slots = ngx_slab_slots(pool); page->next = slots[slot].next; slots[slot].next = page; @@ -587,6 +610,8 @@ ngx_slab_free_locked(ngx_slab_pool_t *pool, void *p) ngx_slab_free_pages(pool, page, 1); + pool->stats[slot].total -= ngx_pagesize >> shift; + goto done; } @@ -598,7 +623,7 @@ ngx_slab_free_locked(ngx_slab_pool_t *pool, void *p) goto wrong_chunk; } - if (slab == NGX_SLAB_PAGE_FREE) { + if (!(slab & NGX_SLAB_PAGE_START)) { ngx_slab_error(pool, NGX_LOG_ALERT, "ngx_slab_free(): page is already free"); goto fail; @@ -626,6 +651,8 @@ ngx_slab_free_locked(ngx_slab_pool_t *pool, void *p) done: + pool->stats[slot].used--; + ngx_slab_junk(p, size); return; @@ -678,6 +705,8 @@ ngx_slab_alloc_pages(ngx_slab_pool_t *pool, ngx_uint_t pages) page->next = NULL; page->prev = NGX_SLAB_PAGE; + pool->pfree -= pages; + if (--pages == 0) { return page; } @@ -706,9 +735,10 @@ static void ngx_slab_free_pages(ngx_slab_pool_t *pool, ngx_slab_page_t *page, ngx_uint_t pages) { - ngx_uint_t type; ngx_slab_page_t *prev, *join; + pool->pfree += pages; + page->slab = pages--; if (pages) { @@ -716,7 +746,7 @@ ngx_slab_free_pages(ngx_slab_pool_t *pool, ngx_slab_page_t *page, } if (page->next) { - prev = (ngx_slab_page_t *) (page->prev & ~NGX_SLAB_PAGE_MASK); + prev = ngx_slab_page_prev(page); prev->next = page->next; page->next->prev = page->prev; } @@ -724,15 +754,14 @@ ngx_slab_free_pages(ngx_slab_pool_t *pool, ngx_slab_page_t *page, join = page + page->slab; if (join < pool->last) { - type = join->prev & NGX_SLAB_PAGE_MASK; - if (type == NGX_SLAB_PAGE) { + if (ngx_slab_page_type(join) == NGX_SLAB_PAGE) { if (join->next != NULL) { pages += join->slab; page->slab += join->slab; - prev = (ngx_slab_page_t *) (join->prev & ~NGX_SLAB_PAGE_MASK); + prev = ngx_slab_page_prev(join); prev->next = join->next; join->next->prev = join->prev; @@ -745,19 +774,18 @@ ngx_slab_free_pages(ngx_slab_pool_t *pool, ngx_slab_page_t *page, if (page > pool->pages) { join = page - 1; - type = join->prev & NGX_SLAB_PAGE_MASK; - if (type == NGX_SLAB_PAGE) { + if (ngx_slab_page_type(join) == NGX_SLAB_PAGE) { if (join->slab == NGX_SLAB_PAGE_FREE) { - join = (ngx_slab_page_t *) (join->prev & ~NGX_SLAB_PAGE_MASK); + join = ngx_slab_page_prev(join); } if (join->next != NULL) { pages += join->slab; join->slab += page->slab; - prev = (ngx_slab_page_t *) (join->prev & ~NGX_SLAB_PAGE_MASK); + prev = ngx_slab_page_prev(join); prev->next = join->next; join->next->prev = join->prev; diff --git a/src/core/ngx_slab.h b/src/core/ngx_slab.h index 2922a80c714..d1876bbec94 100644 --- a/src/core/ngx_slab.h +++ b/src/core/ngx_slab.h @@ -22,6 +22,15 @@ struct ngx_slab_page_s { }; +typedef struct { + ngx_uint_t total; + ngx_uint_t used; + + ngx_uint_t reqs; + ngx_uint_t fails; +} ngx_slab_stat_t; + + typedef struct { ngx_shmtx_sh_t lock; @@ -32,6 +41,9 @@ typedef struct { ngx_slab_page_t *last; ngx_slab_page_t free; + ngx_slab_stat_t *stats; + ngx_uint_t pfree; + u_char *start; u_char *end; @@ -47,6 +59,7 @@ typedef struct { } ngx_slab_pool_t; +void ngx_slab_sizes_init(void); void ngx_slab_init(ngx_slab_pool_t *pool); void *ngx_slab_alloc(ngx_slab_pool_t *pool, size_t size); void *ngx_slab_alloc_locked(ngx_slab_pool_t *pool, size_t size); diff --git a/src/core/ngx_string.c b/src/core/ngx_string.c index 7a73ef527e8..2ee07bfc823 100644 --- a/src/core/ngx_string.c +++ b/src/core/ngx_string.c @@ -29,6 +29,22 @@ ngx_strlow(u_char *dst, u_char *src, size_t n) } +size_t +ngx_strnlen(u_char *p, size_t n) +{ + size_t i; + + for (i = 0; i < n; i++) { + + if (p[i] == '\0') { + return i; + } + } + + return n; +} + + u_char * ngx_cpystrn(u_char *dst, u_char *src, size_t n) { @@ -178,7 +194,7 @@ ngx_vslprintf(u_char *buf, u_char *last, const char *fmt, va_list args) slen = (size_t) -1; while (*fmt >= '0' && *fmt <= '9') { - width = width * 10 + *fmt++ - '0'; + width = width * 10 + (*fmt++ - '0'); } @@ -211,7 +227,7 @@ ngx_vslprintf(u_char *buf, u_char *last, const char *fmt, va_list args) fmt++; while (*fmt >= '0' && *fmt <= '9') { - frac_width = frac_width * 10 + *fmt++ - '0'; + frac_width = frac_width * 10 + (*fmt++ - '0'); } break; @@ -1655,7 +1671,7 @@ ngx_unescape_uri(u_char **dst, u_char **src, size_t size, ngx_uint_t type) state = sw_usual; if (ch >= '0' && ch <= '9') { - ch = (u_char) ((decoded << 4) + ch - '0'); + ch = (u_char) ((decoded << 4) + (ch - '0')); if (type & NGX_UNESCAPE_REDIRECT) { if (ch > '%' && ch < 0x7f) { @@ -1675,7 +1691,7 @@ ngx_unescape_uri(u_char **dst, u_char **src, size_t size, ngx_uint_t type) c = (u_char) (ch | 0x20); if (c >= 'a' && c <= 'f') { - ch = (u_char) ((decoded << 4) + c - 'a' + 10); + ch = (u_char) ((decoded << 4) + (c - 'a') + 10); if (type & NGX_UNESCAPE_URI) { if (ch == '?') { @@ -1808,7 +1824,19 @@ ngx_escape_json(u_char *dst, u_char *src, size_t size) len++; } else if (ch <= 0x1f) { - len += sizeof("\\u001F") - 2; + + switch (ch) { + case '\n': + case '\r': + case '\t': + case '\b': + case '\f': + len++; + break; + + default: + len += sizeof("\\u001F") - 2; + } } size--; @@ -1829,12 +1857,37 @@ ngx_escape_json(u_char *dst, u_char *src, size_t size) *dst++ = ch; } else { - *dst++ = '\\'; *dst++ = 'u'; *dst++ = '0'; *dst++ = '0'; - *dst++ = '0' + (ch >> 4); + *dst++ = '\\'; + + switch (ch) { + case '\n': + *dst++ = 'n'; + break; + + case '\r': + *dst++ = 'r'; + break; + + case '\t': + *dst++ = 't'; + break; - ch &= 0xf; + case '\b': + *dst++ = 'b'; + break; + + case '\f': + *dst++ = 'f'; + break; - *dst++ = (ch < 10) ? ('0' + ch) : ('A' + ch - 10); + default: + *dst++ = 'u'; *dst++ = '0'; *dst++ = '0'; + *dst++ = '0' + (ch >> 4); + + ch &= 0xf; + + *dst++ = (ch < 10) ? ('0' + ch) : ('A' + ch - 10); + } } size--; diff --git a/src/core/ngx_string.h b/src/core/ngx_string.h index 7363bd24263..882ae7cea9b 100644 --- a/src/core/ngx_string.h +++ b/src/core/ngx_string.h @@ -60,6 +60,8 @@ void ngx_strlow(u_char *dst, u_char *src, size_t n); #define ngx_strstr(s1, s2) strstr((const char *) s1, (const char *) s2) #define ngx_strlen(s) strlen((const char *) s) +size_t ngx_strnlen(u_char *p, size_t n); + #define ngx_strchr(s1, c) strchr((const char *) s1, (int) c) static ngx_inline u_char * diff --git a/src/core/ngx_times.c b/src/core/ngx_times.c index 843314aba7b..b2edf1a5f97 100644 --- a/src/core/ngx_times.c +++ b/src/core/ngx_times.c @@ -300,27 +300,39 @@ void ngx_gmtime(time_t t, ngx_tm_t *tp) { ngx_int_t yday; - ngx_uint_t n, sec, min, hour, mday, mon, year, wday, days, leap; + ngx_uint_t sec, min, hour, mday, mon, year, wday, days, leap; /* the calculation is valid for positive time_t only */ - n = (ngx_uint_t) t; + if (t < 0) { + t = 0; + } + + days = t / 86400; + sec = t % 86400; + + /* + * no more than 4 year digits supported, + * truncate to December 31, 9999, 23:59:59 + */ - days = n / 86400; + if (days > 2932896) { + days = 2932896; + sec = 86399; + } /* January 1, 1970 was Thursday */ wday = (4 + days) % 7; - n %= 86400; - hour = n / 3600; - n %= 3600; - min = n / 60; - sec = n % 60; + hour = sec / 3600; + sec %= 3600; + min = sec / 60; + sec %= 60; /* * the algorithm based on Gauss' formula, - * see src/http/ngx_http_parse_time.c + * see src/core/ngx_parse_time.c */ /* days since March 1, 1 BC */ diff --git a/src/event/modules/ngx_devpoll_module.c b/src/event/modules/ngx_devpoll_module.c index f985fbdfb47..ee9f854b6f5 100644 --- a/src/event/modules/ngx_devpoll_module.c +++ b/src/event/modules/ngx_devpoll_module.c @@ -78,7 +78,7 @@ static ngx_command_t ngx_devpoll_commands[] = { }; -ngx_event_module_t ngx_devpoll_module_ctx = { +static ngx_event_module_t ngx_devpoll_module_ctx = { &devpoll_name, ngx_devpoll_create_conf, /* create configuration */ ngx_devpoll_init_conf, /* init configuration */ @@ -336,7 +336,7 @@ ngx_devpoll_set_event(ngx_event_t *ev, ngx_int_t event, ngx_uint_t flags) } -ngx_int_t +static ngx_int_t ngx_devpoll_process_events(ngx_cycle_t *cycle, ngx_msec_t timer, ngx_uint_t flags) { @@ -481,13 +481,11 @@ ngx_devpoll_process_events(ngx_cycle_t *cycle, ngx_msec_t timer, fd, event_list[i].events, revents); } - if ((revents & (POLLERR|POLLHUP|POLLNVAL)) - && (revents & (POLLIN|POLLOUT)) == 0) - { + if (revents & (POLLERR|POLLHUP|POLLNVAL)) { + /* - * if the error events were returned without POLLIN or POLLOUT, - * then add these flags to handle the events at least in one - * active handler + * if the error events were returned, add POLLIN and POLLOUT + * to handle the events at least in one active handler */ revents |= POLLIN|POLLOUT; diff --git a/src/event/modules/ngx_epoll_module.c b/src/event/modules/ngx_epoll_module.c index c267fd6c7a8..76aee08c390 100644 --- a/src/event/modules/ngx_epoll_module.c +++ b/src/event/modules/ngx_epoll_module.c @@ -176,7 +176,7 @@ static ngx_command_t ngx_epoll_commands[] = { }; -ngx_event_module_t ngx_epoll_module_ctx = { +static ngx_event_module_t ngx_epoll_module_ctx = { &epoll_name, ngx_epoll_create_conf, /* create configuration */ ngx_epoll_init_conf, /* init configuration */ @@ -863,6 +863,13 @@ ngx_epoll_process_events(ngx_cycle_t *cycle, ngx_msec_t timer, ngx_uint_t flags) ngx_log_debug2(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "epoll_wait() error on fd:%d ev:%04XD", c->fd, revents); + + /* + * if the error events were returned, add EPOLLIN and EPOLLOUT + * to handle the events at least in one active handler + */ + + revents |= EPOLLIN|EPOLLOUT; } #if 0 @@ -873,18 +880,6 @@ ngx_epoll_process_events(ngx_cycle_t *cycle, ngx_msec_t timer, ngx_uint_t flags) } #endif - if ((revents & (EPOLLERR|EPOLLHUP)) - && (revents & (EPOLLIN|EPOLLOUT)) == 0) - { - /* - * if the error events were returned without EPOLLIN or EPOLLOUT, - * then add these flags to handle the events at least in one - * active handler - */ - - revents |= EPOLLIN|EPOLLOUT; - } - if ((revents & EPOLLIN) && rev->active) { #if (NGX_HAVE_EPOLLRDHUP) diff --git a/src/event/modules/ngx_eventport_module.c b/src/event/modules/ngx_eventport_module.c index dafa27f6a3a..e723f921624 100644 --- a/src/event/modules/ngx_eventport_module.c +++ b/src/event/modules/ngx_eventport_module.c @@ -169,7 +169,7 @@ static ngx_command_t ngx_eventport_commands[] = { }; -ngx_event_module_t ngx_eventport_module_ctx = { +static ngx_event_module_t ngx_eventport_module_ctx = { &eventport_name, ngx_eventport_create_conf, /* create configuration */ ngx_eventport_init_conf, /* init configuration */ @@ -432,7 +432,7 @@ ngx_eventport_notify(ngx_event_handler_pt handler) } -ngx_int_t +static ngx_int_t ngx_eventport_process_events(ngx_cycle_t *cycle, ngx_msec_t timer, ngx_uint_t flags) { @@ -540,13 +540,11 @@ ngx_eventport_process_events(ngx_cycle_t *cycle, ngx_msec_t timer, (int) event_list[i].portev_object, revents); } - if ((revents & (POLLERR|POLLHUP|POLLNVAL)) - && (revents & (POLLIN|POLLOUT)) == 0) - { + if (revents & (POLLERR|POLLHUP|POLLNVAL)) { + /* - * if the error events were returned without POLLIN or POLLOUT, - * then add these flags to handle the events at least in one - * active handler + * if the error events were returned, add POLLIN and POLLOUT + * to handle the events at least in one active handler */ revents |= POLLIN|POLLOUT; diff --git a/src/event/modules/ngx_iocp_module.c b/src/event/modules/ngx_iocp_module.c index e00d967d03a..b03944bb042 100644 --- a/src/event/modules/ngx_iocp_module.c +++ b/src/event/modules/ngx_iocp_module.c @@ -52,7 +52,7 @@ static ngx_command_t ngx_iocp_commands[] = { }; -ngx_event_module_t ngx_iocp_module_ctx = { +static ngx_event_module_t ngx_iocp_module_ctx = { &iocp_name, ngx_iocp_create_conf, /* create configuration */ ngx_iocp_init_conf, /* init configuration */ diff --git a/src/event/modules/ngx_kqueue_module.c b/src/event/modules/ngx_kqueue_module.c index ca3bfe472cd..9c7244c4587 100644 --- a/src/event/modules/ngx_kqueue_module.c +++ b/src/event/modules/ngx_kqueue_module.c @@ -73,7 +73,7 @@ static ngx_command_t ngx_kqueue_commands[] = { }; -ngx_event_module_t ngx_kqueue_module_ctx = { +static ngx_event_module_t ngx_kqueue_module_ctx = { &kqueue_name, ngx_kqueue_create_conf, /* create configuration */ ngx_kqueue_init_conf, /* init configuration */ diff --git a/src/event/modules/ngx_poll_module.c b/src/event/modules/ngx_poll_module.c index 4370950c09e..4e03dabf2a9 100644 --- a/src/event/modules/ngx_poll_module.c +++ b/src/event/modules/ngx_poll_module.c @@ -25,9 +25,9 @@ static struct pollfd *event_list; static ngx_uint_t nevents; -static ngx_str_t poll_name = ngx_string("poll"); +static ngx_str_t poll_name = ngx_string("poll"); -ngx_event_module_t ngx_poll_module_ctx = { +static ngx_event_module_t ngx_poll_module_ctx = { &poll_name, NULL, /* create configuration */ ngx_poll_init_conf, /* init configuration */ @@ -353,13 +353,11 @@ ngx_poll_process_events(ngx_cycle_t *cycle, ngx_msec_t timer, ngx_uint_t flags) continue; } - if ((revents & (POLLERR|POLLHUP|POLLNVAL)) - && (revents & (POLLIN|POLLOUT)) == 0) - { + if (revents & (POLLERR|POLLHUP|POLLNVAL)) { + /* - * if the error events were returned without POLLIN or POLLOUT, - * then add these flags to handle the events at least in one - * active handler + * if the error events were returned, add POLLIN and POLLOUT + * to handle the events at least in one active handler */ revents |= POLLIN|POLLOUT; diff --git a/src/event/modules/ngx_select_module.c b/src/event/modules/ngx_select_module.c index 5a976bd926a..06446219f3a 100644 --- a/src/event/modules/ngx_select_module.c +++ b/src/event/modules/ngx_select_module.c @@ -33,9 +33,9 @@ static ngx_uint_t nevents; static ngx_event_t **event_index; -static ngx_str_t select_name = ngx_string("select"); +static ngx_str_t select_name = ngx_string("select"); -ngx_event_module_t ngx_select_module_ctx = { +static ngx_event_module_t ngx_select_module_ctx = { &select_name, NULL, /* create configuration */ ngx_select_init_conf, /* init configuration */ diff --git a/src/event/modules/ngx_win32_select_module.c b/src/event/modules/ngx_win32_select_module.c index c671f836b13..a98a83f2817 100644 --- a/src/event/modules/ngx_win32_select_module.c +++ b/src/event/modules/ngx_win32_select_module.c @@ -34,9 +34,9 @@ static ngx_uint_t nevents; static ngx_event_t **event_index; -static ngx_str_t select_name = ngx_string("select"); +static ngx_str_t select_name = ngx_string("select"); -ngx_event_module_t ngx_select_module_ctx = { +static ngx_event_module_t ngx_select_module_ctx = { &select_name, NULL, /* create configuration */ ngx_select_init_conf, /* init configuration */ diff --git a/src/event/ngx_event.c b/src/event/ngx_event.c index 9d6c4c91b3a..57af813249e 100644 --- a/src/event/ngx_event.c +++ b/src/event/ngx_event.c @@ -59,20 +59,20 @@ ngx_int_t ngx_accept_disabled; #if (NGX_STAT_STUB) -ngx_atomic_t ngx_stat_accepted0; -ngx_atomic_t *ngx_stat_accepted = &ngx_stat_accepted0; -ngx_atomic_t ngx_stat_handled0; -ngx_atomic_t *ngx_stat_handled = &ngx_stat_handled0; -ngx_atomic_t ngx_stat_requests0; -ngx_atomic_t *ngx_stat_requests = &ngx_stat_requests0; -ngx_atomic_t ngx_stat_active0; -ngx_atomic_t *ngx_stat_active = &ngx_stat_active0; -ngx_atomic_t ngx_stat_reading0; -ngx_atomic_t *ngx_stat_reading = &ngx_stat_reading0; -ngx_atomic_t ngx_stat_writing0; -ngx_atomic_t *ngx_stat_writing = &ngx_stat_writing0; -ngx_atomic_t ngx_stat_waiting0; -ngx_atomic_t *ngx_stat_waiting = &ngx_stat_waiting0; +static ngx_atomic_t ngx_stat_accepted0; +ngx_atomic_t *ngx_stat_accepted = &ngx_stat_accepted0; +static ngx_atomic_t ngx_stat_handled0; +ngx_atomic_t *ngx_stat_handled = &ngx_stat_handled0; +static ngx_atomic_t ngx_stat_requests0; +ngx_atomic_t *ngx_stat_requests = &ngx_stat_requests0; +static ngx_atomic_t ngx_stat_active0; +ngx_atomic_t *ngx_stat_active = &ngx_stat_active0; +static ngx_atomic_t ngx_stat_reading0; +ngx_atomic_t *ngx_stat_reading = &ngx_stat_reading0; +static ngx_atomic_t ngx_stat_writing0; +ngx_atomic_t *ngx_stat_writing = &ngx_stat_writing0; +static ngx_atomic_t ngx_stat_waiting0; +ngx_atomic_t *ngx_stat_waiting = &ngx_stat_waiting0; #endif @@ -165,7 +165,7 @@ static ngx_command_t ngx_event_core_commands[] = { }; -ngx_event_module_t ngx_event_core_module_ctx = { +static ngx_event_module_t ngx_event_core_module_ctx = { &event_core_name, ngx_event_core_create_conf, /* create configuration */ ngx_event_core_init_conf, /* init configuration */ @@ -500,8 +500,7 @@ ngx_event_module_init(ngx_cycle_t *cycle) #endif shm.size = size; - shm.name.len = sizeof("nginx_shared_zone") - 1; - shm.name.data = (u_char *) "nginx_shared_zone"; + ngx_str_set(&shm.name, "nginx_shared_zone"); shm.log = cycle->log; if (ngx_shm_alloc(&shm) != NGX_OK) { diff --git a/src/event/ngx_event.h b/src/event/ngx_event.h index 053bd16f8ce..19fec681bbf 100644 --- a/src/event/ngx_event.h +++ b/src/event/ngx_event.h @@ -152,12 +152,12 @@ struct ngx_event_aio_s { ngx_event_handler_pt handler; ngx_file_t *file; + ngx_fd_t fd; + #if (NGX_HAVE_AIO_SENDFILE || NGX_COMPAT) ssize_t (*preload_handler)(ngx_buf_t *file); #endif - ngx_fd_t fd; - #if (NGX_HAVE_EVENTFD) int64_t res; #endif diff --git a/src/event/ngx_event_accept.c b/src/event/ngx_event_accept.c index 1fce2e89bba..77563709057 100644 --- a/src/event/ngx_event_accept.c +++ b/src/event/ngx_event_accept.c @@ -164,6 +164,10 @@ ngx_event_accept(ngx_event_t *ev) return; } + if (socklen > (socklen_t) sizeof(ngx_sockaddr_t)) { + socklen = sizeof(ngx_sockaddr_t); + } + c->sockaddr = ngx_palloc(c->pool, socklen); if (c->sockaddr == NULL) { ngx_close_accepted_connection(c); @@ -238,7 +242,7 @@ ngx_event_accept(ngx_event_t *ev) if (ev->deferred_accept) { rev->ready = 1; -#if (NGX_HAVE_KQUEUE) +#if (NGX_HAVE_KQUEUE || NGX_HAVE_EPOLLRDHUP) rev->available = 1; #endif } @@ -440,6 +444,10 @@ ngx_event_recvmsg(ngx_event_t *ev) c->type = SOCK_DGRAM; c->socklen = msg.msg_namelen; + if (c->socklen > (socklen_t) sizeof(ngx_sockaddr_t)) { + c->socklen = sizeof(ngx_sockaddr_t); + } + #if (NGX_STAT_STUB) (void) ngx_atomic_fetch_add(ngx_stat_active, 1); #endif diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c index 5c7734d8028..88a6dbed314 100644 --- a/src/event/ngx_event_openssl.c +++ b/src/event/ngx_event_openssl.c @@ -59,6 +59,12 @@ static int ngx_ssl_session_ticket_key_callback(ngx_ssl_conn_t *ssl_conn, static ngx_int_t ngx_ssl_check_name(ngx_str_t *name, ASN1_STRING *str); #endif +static time_t ngx_ssl_parse_time( +#if OPENSSL_VERSION_NUMBER > 0x10100000L + const +#endif + ASN1_TIME *asn1time); + static void *ngx_openssl_create_conf(ngx_cycle_t *cycle); static char *ngx_openssl_engine(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); static void ngx_openssl_exit(ngx_cycle_t *cycle); @@ -106,6 +112,7 @@ int ngx_ssl_session_cache_index; int ngx_ssl_session_ticket_keys_index; int ngx_ssl_certificate_index; int ngx_ssl_next_certificate_index; +int ngx_ssl_certificate_name_index; int ngx_ssl_stapling_index; @@ -114,7 +121,17 @@ ngx_ssl_init(ngx_log_t *log) { #if OPENSSL_VERSION_NUMBER >= 0x10100003L - OPENSSL_init_ssl(OPENSSL_INIT_LOAD_CONFIG, NULL); + if (OPENSSL_init_ssl(OPENSSL_INIT_LOAD_CONFIG, NULL) == 0) { + ngx_ssl_error(NGX_LOG_ALERT, log, 0, "OPENSSL_init_ssl() failed"); + return NGX_ERROR; + } + + /* + * OPENSSL_init_ssl() may leave errors in the error queue + * while returning success + */ + + ERR_clear_error(); #else @@ -193,6 +210,14 @@ ngx_ssl_init(ngx_log_t *log) return NGX_ERROR; } + ngx_ssl_certificate_name_index = X509_get_ex_new_index(0, NULL, NULL, NULL, + NULL); + + if (ngx_ssl_certificate_name_index == -1) { + ngx_ssl_error(NGX_LOG_ALERT, log, 0, "X509_get_ex_new_index() failed"); + return NGX_ERROR; + } + ngx_ssl_stapling_index = X509_get_ex_new_index(0, NULL, NULL, NULL, NULL); if (ngx_ssl_stapling_index == -1) { @@ -298,6 +323,12 @@ ngx_ssl_create(ngx_ssl_t *ssl, ngx_uint_t protocols, void *data) SSL_CTX_set_options(ssl->ctx, SSL_OP_NO_TLSv1_2); } #endif +#ifdef SSL_OP_NO_TLSv1_3 + SSL_CTX_clear_options(ssl->ctx, SSL_OP_NO_TLSv1_3); + if (!(protocols & NGX_SSL_TLSv1_3)) { + SSL_CTX_set_options(ssl->ctx, SSL_OP_NO_TLSv1_3); + } +#endif #ifdef SSL_OP_NO_COMPRESSION SSL_CTX_set_options(ssl->ctx, SSL_OP_NO_COMPRESSION); @@ -385,6 +416,15 @@ ngx_ssl_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert, return NGX_ERROR; } + if (X509_set_ex_data(x509, ngx_ssl_certificate_name_index, cert->data) + == 0) + { + ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "X509_set_ex_data() failed"); + X509_free(x509); + BIO_free(bio); + return NGX_ERROR; + } + if (X509_set_ex_data(x509, ngx_ssl_next_certificate_index, SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_certificate_index)) == 0) @@ -797,7 +837,9 @@ ngx_ssl_info_callback(const ngx_ssl_conn_t *ssl_conn, int where, int ret) BIO *rbio, *wbio; ngx_connection_t *c; - if (where & SSL_CB_HANDSHAKE_START) { + if ((where & SSL_CB_HANDSHAKE_START) + && SSL_is_server((ngx_ssl_conn_t *) ssl_conn)) + { c = ngx_ssl_get_connection((ngx_ssl_conn_t *) ssl_conn); if (c->ssl->handshaked) { @@ -882,6 +924,7 @@ ngx_ssl_read_password_file(ngx_conf_t *cf, ngx_str_t *file) cln->data = passwords; fd = ngx_open_file(file->data, NGX_FILE_RDONLY, NGX_FILE_OPEN, 0); + if (fd == NGX_INVALID_FILE) { ngx_conf_log_error(NGX_LOG_EMERG, cf, ngx_errno, ngx_open_file_n " \"%s\" failed", file->data); @@ -1048,7 +1091,7 @@ ngx_ssl_ecdh_curve(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *name) * maximum interoperability. */ -#ifdef SSL_CTRL_SET_CURVES_LIST +#if (defined SSL_CTX_set1_curves_list || defined SSL_CTRL_SET_CURVES_LIST) /* * OpenSSL 1.0.2+ allows configuring a curve list instead of a single @@ -1258,7 +1301,7 @@ ngx_ssl_handshake(ngx_connection_t *c) #ifdef SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS /* initial handshake done, disable renegotiation (CVE-2009-3555) */ - if (c->ssl->connection->s3) { + if (c->ssl->connection->s3 && SSL_is_server(c->ssl->connection)) { c->ssl->connection->s3->flags |= SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS; } @@ -2832,7 +2875,8 @@ ngx_ssl_session_rbtree_insert_value(ngx_rbtree_node_t *temp, ngx_int_t ngx_ssl_session_ticket_keys(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_array_t *paths) { - u_char buf[48]; + u_char buf[80]; + size_t size; ssize_t n; ngx_str_t *path; ngx_file_t file; @@ -2862,7 +2906,9 @@ ngx_ssl_session_ticket_keys(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_array_t *paths) file.name = path[i]; file.log = cf->log; - file.fd = ngx_open_file(file.name.data, NGX_FILE_RDONLY, 0, 0); + file.fd = ngx_open_file(file.name.data, NGX_FILE_RDONLY, + NGX_FILE_OPEN, 0); + if (file.fd == NGX_INVALID_FILE) { ngx_conf_log_error(NGX_LOG_EMERG, cf, ngx_errno, ngx_open_file_n " \"%V\" failed", &file.name); @@ -2875,13 +2921,15 @@ ngx_ssl_session_ticket_keys(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_array_t *paths) goto failed; } - if (ngx_file_size(&fi) != 48) { + size = ngx_file_size(&fi); + + if (size != 48 && size != 80) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "\"%V\" must be 48 bytes", &file.name); + "\"%V\" must be 48 or 80 bytes", &file.name); goto failed; } - n = ngx_read_file(&file, buf, 48, 0); + n = ngx_read_file(&file, buf, size, 0); if (n == NGX_ERROR) { ngx_conf_log_error(NGX_LOG_CRIT, cf, ngx_errno, @@ -2889,10 +2937,10 @@ ngx_ssl_session_ticket_keys(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_array_t *paths) goto failed; } - if (n != 48) { + if ((size_t) n != size) { ngx_conf_log_error(NGX_LOG_CRIT, cf, 0, ngx_read_file_n " \"%V\" returned only " - "%z bytes instead of 48", &file.name, n); + "%z bytes instead of %uz", &file.name, n, size); goto failed; } @@ -2901,9 +2949,18 @@ ngx_ssl_session_ticket_keys(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_array_t *paths) goto failed; } - ngx_memcpy(key->name, buf, 16); - ngx_memcpy(key->aes_key, buf + 16, 16); - ngx_memcpy(key->hmac_key, buf + 32, 16); + if (size == 48) { + key->size = 48; + ngx_memcpy(key->name, buf, 16); + ngx_memcpy(key->aes_key, buf + 16, 16); + ngx_memcpy(key->hmac_key, buf + 32, 16); + + } else { + key->size = 80; + ngx_memcpy(key->name, buf, 16); + ngx_memcpy(key->hmac_key, buf + 16, 32); + ngx_memcpy(key->aes_key, buf + 48, 32); + } if (ngx_close_file(file.fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ALERT, cf->log, ngx_errno, @@ -2948,6 +3005,7 @@ ngx_ssl_session_ticket_key_callback(ngx_ssl_conn_t *ssl_conn, unsigned char *name, unsigned char *iv, EVP_CIPHER_CTX *ectx, HMAC_CTX *hctx, int enc) { + size_t size; SSL_CTX *ssl_ctx; ngx_uint_t i; ngx_array_t *keys; @@ -2962,7 +3020,6 @@ ngx_ssl_session_ticket_key_callback(ngx_ssl_conn_t *ssl_conn, c = ngx_ssl_get_connection(ssl_conn); ssl_ctx = c->ssl->session_ctx; - cipher = EVP_aes_128_cbc(); #ifdef OPENSSL_NO_SHA256 digest = EVP_sha1(); #else @@ -2984,6 +3041,15 @@ ngx_ssl_session_ticket_key_callback(ngx_ssl_conn_t *ssl_conn, ngx_hex_dump(buf, key[0].name, 16) - buf, buf, SSL_session_reused(ssl_conn) ? "reused" : "new"); + if (key[0].size == 48) { + cipher = EVP_aes_128_cbc(); + size = 16; + + } else { + cipher = EVP_aes_256_cbc(); + size = 32; + } + if (RAND_bytes(iv, EVP_CIPHER_iv_length(cipher)) != 1) { ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "RAND_bytes() failed"); return -1; @@ -2996,12 +3062,12 @@ ngx_ssl_session_ticket_key_callback(ngx_ssl_conn_t *ssl_conn, } #if OPENSSL_VERSION_NUMBER >= 0x10000000L - if (HMAC_Init_ex(hctx, key[0].hmac_key, 16, digest, NULL) != 1) { + if (HMAC_Init_ex(hctx, key[0].hmac_key, size, digest, NULL) != 1) { ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "HMAC_Init_ex() failed"); return -1; } #else - HMAC_Init_ex(hctx, key[0].hmac_key, 16, digest, NULL); + HMAC_Init_ex(hctx, key[0].hmac_key, size, digest, NULL); #endif ngx_memcpy(name, key[0].name, 16); @@ -3030,13 +3096,22 @@ ngx_ssl_session_ticket_key_callback(ngx_ssl_conn_t *ssl_conn, ngx_hex_dump(buf, key[i].name, 16) - buf, buf, (i == 0) ? " (default)" : ""); + if (key[i].size == 48) { + cipher = EVP_aes_128_cbc(); + size = 16; + + } else { + cipher = EVP_aes_256_cbc(); + size = 32; + } + #if OPENSSL_VERSION_NUMBER >= 0x10000000L - if (HMAC_Init_ex(hctx, key[i].hmac_key, 16, digest, NULL) != 1) { + if (HMAC_Init_ex(hctx, key[i].hmac_key, size, digest, NULL) != 1) { ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "HMAC_Init_ex() failed"); return -1; } #else - HMAC_Init_ex(hctx, key[i].hmac_key, 16, digest, NULL); + HMAC_Init_ex(hctx, key[i].hmac_key, size, digest, NULL); #endif if (EVP_DecryptInit_ex(ectx, cipher, NULL, key[i].aes_key, iv) != 1) { @@ -3056,7 +3131,7 @@ ngx_ssl_session_ticket_keys(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_array_t *paths) { if (paths) { ngx_log_error(NGX_LOG_WARN, ssl->log, 0, - "\"ssl_session_ticket_keys\" ignored, not supported"); + "\"ssl_session_ticket_key\" ignored, not supported"); } return NGX_OK; @@ -3269,6 +3344,158 @@ ngx_ssl_get_cipher_name(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s) } +ngx_int_t +ngx_ssl_get_ciphers(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s) +{ +#ifdef SSL_CTRL_GET_RAW_CIPHERLIST + + int n, i, bytes; + size_t len; + u_char *ciphers, *p; + const SSL_CIPHER *cipher; + + bytes = SSL_get0_raw_cipherlist(c->ssl->connection, NULL); + n = SSL_get0_raw_cipherlist(c->ssl->connection, &ciphers); + + if (n <= 0) { + s->len = 0; + return NGX_OK; + } + + len = 0; + n /= bytes; + + for (i = 0; i < n; i++) { + cipher = SSL_CIPHER_find(c->ssl->connection, ciphers + i * bytes); + + if (cipher) { + len += ngx_strlen(SSL_CIPHER_get_name(cipher)); + + } else { + len += sizeof("0x") - 1 + bytes * (sizeof("00") - 1); + } + + len += sizeof(":") - 1; + } + + s->data = ngx_pnalloc(pool, len); + if (s->data == NULL) { + return NGX_ERROR; + } + + p = s->data; + + for (i = 0; i < n; i++) { + cipher = SSL_CIPHER_find(c->ssl->connection, ciphers + i * bytes); + + if (cipher) { + p = ngx_sprintf(p, "%s", SSL_CIPHER_get_name(cipher)); + + } else { + p = ngx_sprintf(p, "0x"); + p = ngx_hex_dump(p, ciphers + i * bytes, bytes); + } + + *p++ = ':'; + } + + p--; + + s->len = p - s->data; + +#else + + u_char buf[4096]; + + if (SSL_get_shared_ciphers(c->ssl->connection, (char *) buf, 4096) + == NULL) + { + s->len = 0; + return NGX_OK; + } + + s->len = ngx_strlen(buf); + s->data = ngx_pnalloc(pool, s->len); + if (s->data == NULL) { + return NGX_ERROR; + } + + ngx_memcpy(s->data, buf, s->len); + +#endif + + return NGX_OK; +} + + +ngx_int_t +ngx_ssl_get_curves(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s) +{ +#ifdef SSL_CTRL_GET_CURVES + + int *curves, n, i, nid; + u_char *p; + size_t len; + + n = SSL_get1_curves(c->ssl->connection, NULL); + + if (n <= 0) { + s->len = 0; + return NGX_OK; + } + + curves = ngx_palloc(pool, n * sizeof(int)); + + n = SSL_get1_curves(c->ssl->connection, curves); + len = 0; + + for (i = 0; i < n; i++) { + nid = curves[i]; + + if (nid & TLSEXT_nid_unknown) { + len += sizeof("0x0000") - 1; + + } else { + len += ngx_strlen(OBJ_nid2sn(nid)); + } + + len += sizeof(":") - 1; + } + + s->data = ngx_pnalloc(pool, len); + if (s->data == NULL) { + return NGX_ERROR; + } + + p = s->data; + + for (i = 0; i < n; i++) { + nid = curves[i]; + + if (nid & TLSEXT_nid_unknown) { + p = ngx_sprintf(p, "0x%04xd", nid & 0xffff); + + } else { + p = ngx_sprintf(p, "%s", OBJ_nid2sn(nid)); + } + + *p++ = ':'; + } + + p--; + + s->len = p - s->data; + +#else + + s->len = 0; + +#endif + + return NGX_OK; +} + + ngx_int_t ngx_ssl_get_session_id(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s) { @@ -3324,13 +3551,22 @@ ngx_ssl_get_server_name(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s) { #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME - const char *servername; + size_t len; + const char *name; + + name = SSL_get_servername(c->ssl->connection, TLSEXT_NAMETYPE_host_name); + + if (name) { + len = ngx_strlen(name); + + s->len = len; + s->data = ngx_pnalloc(pool, len); + if (s->data == NULL) { + return NGX_ERROR; + } + + ngx_memcpy(s->data, name, len); - servername = SSL_get_servername(c->ssl->connection, - TLSEXT_NAMETYPE_host_name); - if (servername) { - s->data = (u_char *) servername; - s->len = ngx_strlen(servername); return NGX_OK; } @@ -3435,6 +3671,36 @@ ngx_ssl_get_certificate(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s) } +ngx_int_t +ngx_ssl_get_escaped_certificate(ngx_connection_t *c, ngx_pool_t *pool, + ngx_str_t *s) +{ + ngx_str_t cert; + uintptr_t n; + + if (ngx_ssl_get_raw_certificate(c, pool, &cert) != NGX_OK) { + return NGX_ERROR; + } + + if (cert.len == 0) { + s->len = 0; + return NGX_OK; + } + + n = ngx_escape_uri(NULL, cert.data, cert.len, NGX_ESCAPE_URI_COMPONENT); + + s->len = cert.len + n * 2; + s->data = ngx_pnalloc(pool, s->len); + if (s->data == NULL) { + return NGX_ERROR; + } + + ngx_escape_uri(s->data, cert.data, cert.len, NGX_ESCAPE_URI_COMPONENT); + + return NGX_OK; +} + + ngx_int_t ngx_ssl_get_subject_dn(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s) { @@ -3699,28 +3965,210 @@ ngx_ssl_get_fingerprint(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s) ngx_int_t ngx_ssl_get_client_verify(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s) { - X509 *cert; + X509 *cert; + long rc; + const char *str; - if (SSL_get_verify_result(c->ssl->connection) != X509_V_OK) { - ngx_str_set(s, "FAILED"); + cert = SSL_get_peer_certificate(c->ssl->connection); + if (cert == NULL) { + ngx_str_set(s, "NONE"); return NGX_OK; } - cert = SSL_get_peer_certificate(c->ssl->connection); + X509_free(cert); + + rc = SSL_get_verify_result(c->ssl->connection); - if (cert) { + if (rc == X509_V_OK) { ngx_str_set(s, "SUCCESS"); + return NGX_OK; + } - } else { - ngx_str_set(s, "NONE"); + str = X509_verify_cert_error_string(rc); + + s->data = ngx_pnalloc(pool, sizeof("FAILED:") - 1 + ngx_strlen(str)); + if (s->data == NULL) { + return NGX_ERROR; + } + + s->len = ngx_sprintf(s->data, "FAILED:%s", str) - s->data; + + return NGX_OK; +} + + +ngx_int_t +ngx_ssl_get_client_v_start(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s) +{ + BIO *bio; + X509 *cert; + size_t len; + + s->len = 0; + + cert = SSL_get_peer_certificate(c->ssl->connection); + if (cert == NULL) { + return NGX_OK; } + bio = BIO_new(BIO_s_mem()); + if (bio == NULL) { + X509_free(cert); + return NGX_ERROR; + } + +#if OPENSSL_VERSION_NUMBER > 0x10100000L + ASN1_TIME_print(bio, X509_get0_notBefore(cert)); +#else + ASN1_TIME_print(bio, X509_get_notBefore(cert)); +#endif + + len = BIO_pending(bio); + + s->len = len; + s->data = ngx_pnalloc(pool, len); + if (s->data == NULL) { + BIO_free(bio); + X509_free(cert); + return NGX_ERROR; + } + + BIO_read(bio, s->data, len); + BIO_free(bio); X509_free(cert); return NGX_OK; } +ngx_int_t +ngx_ssl_get_client_v_end(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s) +{ + BIO *bio; + X509 *cert; + size_t len; + + s->len = 0; + + cert = SSL_get_peer_certificate(c->ssl->connection); + if (cert == NULL) { + return NGX_OK; + } + + bio = BIO_new(BIO_s_mem()); + if (bio == NULL) { + X509_free(cert); + return NGX_ERROR; + } + +#if OPENSSL_VERSION_NUMBER > 0x10100000L + ASN1_TIME_print(bio, X509_get0_notAfter(cert)); +#else + ASN1_TIME_print(bio, X509_get_notAfter(cert)); +#endif + + len = BIO_pending(bio); + + s->len = len; + s->data = ngx_pnalloc(pool, len); + if (s->data == NULL) { + BIO_free(bio); + X509_free(cert); + return NGX_ERROR; + } + + BIO_read(bio, s->data, len); + BIO_free(bio); + X509_free(cert); + + return NGX_OK; +} + + +ngx_int_t +ngx_ssl_get_client_v_remain(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s) +{ + X509 *cert; + time_t now, end; + + s->len = 0; + + cert = SSL_get_peer_certificate(c->ssl->connection); + if (cert == NULL) { + return NGX_OK; + } + +#if OPENSSL_VERSION_NUMBER > 0x10100000L + end = ngx_ssl_parse_time(X509_get0_notAfter(cert)); +#else + end = ngx_ssl_parse_time(X509_get_notAfter(cert)); +#endif + + if (end == (time_t) NGX_ERROR) { + X509_free(cert); + return NGX_OK; + } + + now = ngx_time(); + + if (end < now + 86400) { + ngx_str_set(s, "0"); + X509_free(cert); + return NGX_OK; + } + + s->data = ngx_pnalloc(pool, NGX_TIME_T_LEN); + if (s->data == NULL) { + X509_free(cert); + return NGX_ERROR; + } + + s->len = ngx_sprintf(s->data, "%T", (end - now) / 86400) - s->data; + + X509_free(cert); + + return NGX_OK; +} + + +static time_t +ngx_ssl_parse_time( +#if OPENSSL_VERSION_NUMBER > 0x10100000L + const +#endif + ASN1_TIME *asn1time) +{ + BIO *bio; + char *value; + size_t len; + time_t time; + + /* + * OpenSSL doesn't provide a way to convert ASN1_TIME + * into time_t. To do this, we use ASN1_TIME_print(), + * which uses the "MMM DD HH:MM:SS YYYY [GMT]" format (e.g., + * "Feb 3 00:55:52 2015 GMT"), and parse the result. + */ + + bio = BIO_new(BIO_s_mem()); + if (bio == NULL) { + return NGX_ERROR; + } + + /* fake weekday prepended to match C asctime() format */ + + BIO_write(bio, "Tue ", sizeof("Tue ") - 1); + ASN1_TIME_print(bio, asn1time); + len = BIO_get_mem_data(bio, &value); + + time = ngx_parse_http_time((u_char *) value, len); + + BIO_free(bio); + + return time; +} + + static void * ngx_openssl_create_conf(ngx_cycle_t *cycle) { diff --git a/src/event/ngx_event_openssl.h b/src/event/ngx_event_openssl.h index d233c02fe5f..623d851dc4e 100644 --- a/src/event/ngx_event_openssl.h +++ b/src/event/ngx_event_openssl.h @@ -22,6 +22,7 @@ #include #endif #include +#include #ifndef OPENSSL_NO_OCSP #include #endif @@ -54,6 +55,11 @@ #define ngx_ssl_conn_t SSL +#if (OPENSSL_VERSION_NUMBER < 0x10002000L) +#define SSL_is_server(s) (s)->server +#endif + + struct ngx_ssl_s { SSL_CTX *ctx; ngx_log_t *log; @@ -117,9 +123,10 @@ typedef struct { #ifdef SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB typedef struct { + size_t size; u_char name[16]; - u_char aes_key[16]; - u_char hmac_key[16]; + u_char hmac_key[32]; + u_char aes_key[32]; } ngx_ssl_session_ticket_key_t; #endif @@ -130,6 +137,7 @@ typedef struct { #define NGX_SSL_TLSv1 0x0008 #define NGX_SSL_TLSv1_1 0x0010 #define NGX_SSL_TLSv1_2 0x0020 +#define NGX_SSL_TLSv1_3 0x0040 #define NGX_SSL_BUFFER 1 @@ -191,6 +199,10 @@ ngx_int_t ngx_ssl_get_protocol(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s); ngx_int_t ngx_ssl_get_cipher_name(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s); +ngx_int_t ngx_ssl_get_ciphers(ngx_connection_t *c, ngx_pool_t *pool, + ngx_str_t *s); +ngx_int_t ngx_ssl_get_curves(ngx_connection_t *c, ngx_pool_t *pool, + ngx_str_t *s); ngx_int_t ngx_ssl_get_session_id(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s); ngx_int_t ngx_ssl_get_session_reused(ngx_connection_t *c, ngx_pool_t *pool, @@ -201,6 +213,8 @@ ngx_int_t ngx_ssl_get_raw_certificate(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s); ngx_int_t ngx_ssl_get_certificate(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s); +ngx_int_t ngx_ssl_get_escaped_certificate(ngx_connection_t *c, ngx_pool_t *pool, + ngx_str_t *s); ngx_int_t ngx_ssl_get_subject_dn(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s); ngx_int_t ngx_ssl_get_issuer_dn(ngx_connection_t *c, ngx_pool_t *pool, @@ -215,6 +229,12 @@ ngx_int_t ngx_ssl_get_fingerprint(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s); ngx_int_t ngx_ssl_get_client_verify(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s); +ngx_int_t ngx_ssl_get_client_v_start(ngx_connection_t *c, ngx_pool_t *pool, + ngx_str_t *s); +ngx_int_t ngx_ssl_get_client_v_end(ngx_connection_t *c, ngx_pool_t *pool, + ngx_str_t *s); +ngx_int_t ngx_ssl_get_client_v_remain(ngx_connection_t *c, ngx_pool_t *pool, + ngx_str_t *s); ngx_int_t ngx_ssl_handshake(ngx_connection_t *c); @@ -236,6 +256,7 @@ extern int ngx_ssl_session_cache_index; extern int ngx_ssl_session_ticket_keys_index; extern int ngx_ssl_certificate_index; extern int ngx_ssl_next_certificate_index; +extern int ngx_ssl_certificate_name_index; extern int ngx_ssl_stapling_index; diff --git a/src/event/ngx_event_openssl_stapling.c b/src/event/ngx_event_openssl_stapling.c index 09fab769076..0bea5e74db7 100644 --- a/src/event/ngx_event_openssl_stapling.c +++ b/src/event/ngx_event_openssl_stapling.c @@ -31,6 +31,8 @@ typedef struct { X509 *cert; X509 *issuer; + u_char *name; + time_t valid; time_t refresh; @@ -45,6 +47,8 @@ struct ngx_ssl_ocsp_ctx_s { X509 *cert; X509 *issuer; + u_char *name; + ngx_uint_t naddrs; ngx_addr_t *addrs; @@ -57,14 +61,14 @@ struct ngx_ssl_ocsp_ctx_s { ngx_msec_t timeout; - void (*handler)(ngx_ssl_ocsp_ctx_t *r); + void (*handler)(ngx_ssl_ocsp_ctx_t *ctx); void *data; ngx_buf_t *request; ngx_buf_t *response; ngx_peer_connection_t peer; - ngx_int_t (*process)(ngx_ssl_ocsp_ctx_t *r); + ngx_int_t (*process)(ngx_ssl_ocsp_ctx_t *ctx); ngx_uint_t state; @@ -173,6 +177,8 @@ ngx_ssl_stapling_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, X509 *cert, staple->timeout = 60000; staple->verify = verify; staple->cert = cert; + staple->name = X509_get_ex_data(staple->cert, + ngx_ssl_certificate_name_index); if (file->len) { /* use OCSP response from the file */ @@ -354,7 +360,9 @@ ngx_ssl_stapling_issuer(ngx_conf_t *cf, ngx_ssl_t *ssl, if (rc == 0) { ngx_log_error(NGX_LOG_WARN, ssl->log, 0, - "\"ssl_stapling\" ignored, issuer certificate not found"); + "\"ssl_stapling\" ignored, " + "issuer certificate not found for certificate \"%s\"", + staple->name); X509_STORE_CTX_free(store_ctx); return NGX_DECLINED; } @@ -374,9 +382,9 @@ static ngx_int_t ngx_ssl_stapling_responder(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_ssl_stapling_t *staple, ngx_str_t *responder) { - ngx_url_t u; char *s; ngx_str_t rsp; + ngx_url_t u; STACK_OF(OPENSSL_STRING) *aia; if (responder->len == 0) { @@ -387,7 +395,8 @@ ngx_ssl_stapling_responder(ngx_conf_t *cf, ngx_ssl_t *ssl, if (aia == NULL) { ngx_log_error(NGX_LOG_WARN, ssl->log, 0, "\"ssl_stapling\" ignored, " - "no OCSP responder URL in the certificate"); + "no OCSP responder URL in the certificate \"%s\"", + staple->name); return NGX_DECLINED; } @@ -399,7 +408,8 @@ ngx_ssl_stapling_responder(ngx_conf_t *cf, ngx_ssl_t *ssl, if (s == NULL) { ngx_log_error(NGX_LOG_WARN, ssl->log, 0, "\"ssl_stapling\" ignored, " - "no OCSP responder URL in the certificate"); + "no OCSP responder URL in the certificate \"%s\"", + staple->name); X509_email_free(aia); return NGX_DECLINED; } @@ -432,7 +442,9 @@ ngx_ssl_stapling_responder(ngx_conf_t *cf, ngx_ssl_t *ssl, } else { ngx_log_error(NGX_LOG_WARN, ssl->log, 0, "\"ssl_stapling\" ignored, " - "invalid URL prefix in OCSP responder \"%V\"", &u.url); + "invalid URL prefix in OCSP responder \"%V\" " + "in the certificate \"%s\"", + &u.url, staple->name); return NGX_DECLINED; } @@ -440,7 +452,9 @@ ngx_ssl_stapling_responder(ngx_conf_t *cf, ngx_ssl_t *ssl, if (u.err) { ngx_log_error(NGX_LOG_WARN, ssl->log, 0, "\"ssl_stapling\" ignored, " - "%s in OCSP responder \"%V\"", u.err, &u.url); + "%s in OCSP responder \"%V\" " + "in the certificate \"%s\"", + u.err, &u.url, staple->name); return NGX_DECLINED; } @@ -547,6 +561,7 @@ ngx_ssl_stapling_update(ngx_ssl_stapling_t *staple) ctx->cert = staple->cert; ctx->issuer = staple->issuer; + ctx->name = staple->name; ctx->addrs = staple->addrs; ctx->host = staple->host; @@ -757,10 +772,10 @@ ngx_ssl_stapling_ocsp_handler(ngx_ssl_ocsp_ctx_t *ctx) static time_t ngx_ssl_stapling_time(ASN1_GENERALIZEDTIME *asn1time) { - u_char *value; + BIO *bio; + char *value; size_t len; time_t time; - BIO *bio; /* * OpenSSL doesn't provide a way to convert ASN1_GENERALIZEDTIME @@ -780,7 +795,7 @@ ngx_ssl_stapling_time(ASN1_GENERALIZEDTIME *asn1time) ASN1_GENERALIZEDTIME_print(bio, asn1time); len = BIO_get_mem_data(bio, &value); - time = ngx_parse_http_time(value, len); + time = ngx_parse_http_time((u_char *) value, len); BIO_free(bio); @@ -1005,7 +1020,7 @@ ngx_ssl_ocsp_resolve_handler(ngx_resolver_ctx_t *resolve) static void ngx_ssl_ocsp_connect(ngx_ssl_ocsp_ctx_t *ctx) { - ngx_int_t rc; + ngx_int_t rc; ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0, "ssl ocsp connect"); @@ -1103,10 +1118,10 @@ ngx_ssl_ocsp_write_handler(ngx_event_t *wev) static void ngx_ssl_ocsp_read_handler(ngx_event_t *rev) { - ssize_t n, size; - ngx_int_t rc; - ngx_ssl_ocsp_ctx_t *ctx; - ngx_connection_t *c; + ssize_t n, size; + ngx_int_t rc; + ngx_connection_t *c; + ngx_ssl_ocsp_ctx_t *ctx; c = rev->data; ctx = c->data; @@ -1310,12 +1325,11 @@ ngx_ssl_ocsp_process_status_line(ngx_ssl_ocsp_ctx_t *ctx) rc = ngx_ssl_ocsp_parse_status_line(ctx); if (rc == NGX_OK) { -#if 0 - ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ctx->log, 0, - "ssl ocsp status line \"%*s\"", - ctx->response->pos - ctx->response->start, - ctx->response->start); -#endif + ngx_log_debug3(NGX_LOG_DEBUG_EVENT, ctx->log, 0, + "ssl ocsp status %ui \"%*s\"", + ctx->code, + ctx->header_end - ctx->header_start, + ctx->header_start); ctx->process = ngx_ssl_ocsp_process_headers; return ctx->process(ctx); @@ -1472,10 +1486,11 @@ ngx_ssl_ocsp_parse_status_line(ngx_ssl_ocsp_ctx_t *ctx) return NGX_ERROR; } - ctx->code = ctx->code * 10 + ch - '0'; + ctx->code = ctx->code * 10 + (ch - '0'); if (++ctx->count == 3) { state = sw_space_after_status; + ctx->header_start = p - 2; } break; @@ -1493,6 +1508,7 @@ ngx_ssl_ocsp_parse_status_line(ngx_ssl_ocsp_ctx_t *ctx) state = sw_almost_done; break; case LF: + ctx->header_end = p; goto done; default: return NGX_ERROR; @@ -1506,6 +1522,7 @@ ngx_ssl_ocsp_parse_status_line(ngx_ssl_ocsp_ctx_t *ctx) state = sw_almost_done; break; case LF: + ctx->header_end = p; goto done; } break; @@ -1514,6 +1531,7 @@ ngx_ssl_ocsp_parse_status_line(ngx_ssl_ocsp_ctx_t *ctx) case sw_almost_done: switch (ch) { case LF: + ctx->header_end = p - 1; goto done; default: return NGX_ERROR; @@ -1608,10 +1626,11 @@ ngx_ssl_ocsp_process_headers(ngx_ssl_ocsp_ctx_t *ctx) return ctx->process(ctx); } + static ngx_int_t ngx_ssl_ocsp_parse_header_line(ngx_ssl_ocsp_ctx_t *ctx) { - u_char c, ch, *p; + u_char c, ch, *p; enum { sw_start = 0, sw_name, @@ -1821,12 +1840,27 @@ ngx_ssl_ocsp_log_error(ngx_log_t *log, u_char *buf, size_t len) if (log->action) { p = ngx_snprintf(buf, len, " while %s", log->action); len -= p - buf; + buf = p; } ctx = log->data; if (ctx) { - p = ngx_snprintf(p, len, ", responder: %V", &ctx->host); + p = ngx_snprintf(buf, len, ", responder: %V", &ctx->host); + len -= p - buf; + buf = p; + } + + if (ctx && ctx->peer.name) { + p = ngx_snprintf(buf, len, ", peer: %V", ctx->peer.name); + len -= p - buf; + buf = p; + } + + if (ctx && ctx->name) { + p = ngx_snprintf(buf, len, ", certificate: \"%s\"", ctx->name); + len -= p - buf; + buf = p; } return p; @@ -1846,6 +1880,7 @@ ngx_ssl_stapling(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *file, return NGX_OK; } + ngx_int_t ngx_ssl_stapling_resolver(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_resolver_t *resolver, ngx_msec_t resolver_timeout) diff --git a/src/event/ngx_event_pipe.c b/src/event/ngx_event_pipe.c index 249433adcfe..da7c4ee7fb7 100644 --- a/src/event/ngx_event_pipe.c +++ b/src/event/ngx_event_pipe.c @@ -113,11 +113,24 @@ ngx_event_pipe_read_upstream(ngx_event_pipe_t *p) } #if (NGX_THREADS) + if (p->aio) { ngx_log_debug0(NGX_LOG_DEBUG_EVENT, p->log, 0, "pipe read upstream: aio"); return NGX_AGAIN; } + + if (p->writing) { + ngx_log_debug0(NGX_LOG_DEBUG_EVENT, p->log, 0, + "pipe read upstream: writing"); + + rc = ngx_event_pipe_write_chain_to_temp_file(p); + + if (rc != NGX_OK) { + return rc; + } + } + #endif ngx_log_debug1(NGX_LOG_DEBUG_EVENT, p->log, 0, diff --git a/src/event/ngx_event_timer.c b/src/event/ngx_event_timer.c index 8f547b215ac..698b88faeca 100644 --- a/src/event/ngx_event_timer.c +++ b/src/event/ngx_event_timer.c @@ -67,7 +67,7 @@ ngx_event_expire_timers(void) node = ngx_rbtree_min(root, sentinel); - /* node->key > ngx_current_time */ + /* node->key > ngx_current_msec */ if ((ngx_msec_int_t) (node->key - ngx_current_msec) > 0) { return; @@ -96,43 +96,31 @@ ngx_event_expire_timers(void) } -void -ngx_event_cancel_timers(void) +ngx_int_t +ngx_event_no_timers_left(void) { ngx_event_t *ev; ngx_rbtree_node_t *node, *root, *sentinel; sentinel = ngx_event_timer_rbtree.sentinel; + root = ngx_event_timer_rbtree.root; - for ( ;; ) { - root = ngx_event_timer_rbtree.root; - - if (root == sentinel) { - return; - } - - node = ngx_rbtree_min(root, sentinel); + if (root == sentinel) { + return NGX_OK; + } + for (node = ngx_rbtree_min(root, sentinel); + node; + node = ngx_rbtree_next(&ngx_event_timer_rbtree, node)) + { ev = (ngx_event_t *) ((char *) node - offsetof(ngx_event_t, timer)); if (!ev->cancelable) { - return; + return NGX_AGAIN; } + } - ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0, - "event timer cancel: %d: %M", - ngx_event_ident(ev->data), ev->timer.key); - - ngx_rbtree_delete(&ngx_event_timer_rbtree, &ev->timer); - -#if (NGX_DEBUG) - ev->timer.left = NULL; - ev->timer.right = NULL; - ev->timer.parent = NULL; -#endif - - ev->timer_set = 0; + /* only cancelable timers left */ - ev->handler(ev); - } + return NGX_OK; } diff --git a/src/event/ngx_event_timer.h b/src/event/ngx_event_timer.h index 99f8a48fbda..be81b157f41 100644 --- a/src/event/ngx_event_timer.h +++ b/src/event/ngx_event_timer.h @@ -22,7 +22,7 @@ ngx_int_t ngx_event_timer_init(ngx_log_t *log); ngx_msec_t ngx_event_find_timer(void); void ngx_event_expire_timers(void); -void ngx_event_cancel_timers(void); +ngx_int_t ngx_event_no_timers_left(void); extern ngx_rbtree_t ngx_event_timer_rbtree; diff --git a/src/http/modules/ngx_http_access_module.c b/src/http/modules/ngx_http_access_module.c index c553e46106b..7355de9e735 100644 --- a/src/http/modules/ngx_http_access_module.c +++ b/src/http/modules/ngx_http_access_module.c @@ -309,27 +309,21 @@ ngx_http_access_rule(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) ngx_http_access_rule_un_t *rule_un; #endif + all = 0; ngx_memzero(&cidr, sizeof(ngx_cidr_t)); value = cf->args->elts; - all = (value[1].len == 3 && ngx_strcmp(value[1].data, "all") == 0); - - if (!all) { + if (value[1].len == 3 && ngx_strcmp(value[1].data, "all") == 0) { + all = 1; #if (NGX_HAVE_UNIX_DOMAIN) + } else if (value[1].len == 5 && ngx_strcmp(value[1].data, "unix:") == 0) { + cidr.family = AF_UNIX; +#endif - if (value[1].len == 5 && ngx_strcmp(value[1].data, "unix:") == 0) { - cidr.family = AF_UNIX; - rc = NGX_OK; - - } else { - rc = ngx_ptocidr(&value[1], &cidr); - } - -#else + } else { rc = ngx_ptocidr(&value[1], &cidr); -#endif if (rc == NGX_ERROR) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, diff --git a/src/http/modules/ngx_http_addition_filter_module.c b/src/http/modules/ngx_http_addition_filter_module.c index 2fad0e59bf9..e546f0d60b8 100644 --- a/src/http/modules/ngx_http_addition_filter_module.c +++ b/src/http/modules/ngx_http_addition_filter_module.c @@ -123,6 +123,8 @@ ngx_http_addition_header_filter(ngx_http_request_t *r) ngx_http_clear_accept_ranges(r); ngx_http_weak_etag(r); + r->preserve_body = 1; + return ngx_http_next_header_filter(r); } diff --git a/src/http/modules/ngx_http_auth_basic_module.c b/src/http/modules/ngx_http_auth_basic_module.c index 1e7a0c2df8d..2f345b6d592 100644 --- a/src/http/modules/ngx_http_auth_basic_module.c +++ b/src/http/modules/ngx_http_auth_basic_module.c @@ -14,11 +14,6 @@ #define NGX_HTTP_AUTH_BUF_SIZE 2048 -typedef struct { - ngx_str_t passwd; -} ngx_http_auth_basic_ctx_t; - - typedef struct { ngx_http_complex_value_t *realm; ngx_http_complex_value_t user_file; @@ -27,7 +22,7 @@ typedef struct { static ngx_int_t ngx_http_auth_basic_handler(ngx_http_request_t *r); static ngx_int_t ngx_http_auth_basic_crypt_handler(ngx_http_request_t *r, - ngx_http_auth_basic_ctx_t *ctx, ngx_str_t *passwd, ngx_str_t *realm); + ngx_str_t *passwd, ngx_str_t *realm); static ngx_int_t ngx_http_auth_basic_set_realm(ngx_http_request_t *r, ngx_str_t *realm); static void ngx_http_auth_basic_close(ngx_file_t *file); @@ -103,7 +98,6 @@ ngx_http_auth_basic_handler(ngx_http_request_t *r) ngx_str_t pwd, realm, user_file; ngx_uint_t i, level, login, left, passwd; ngx_file_t file; - ngx_http_auth_basic_ctx_t *ctx; ngx_http_auth_basic_loc_conf_t *alcf; u_char buf[NGX_HTTP_AUTH_BUF_SIZE]; enum { @@ -126,13 +120,6 @@ ngx_http_auth_basic_handler(ngx_http_request_t *r) return NGX_DECLINED; } - ctx = ngx_http_get_module_ctx(r, ngx_http_auth_basic_module); - - if (ctx) { - return ngx_http_auth_basic_crypt_handler(r, ctx, &ctx->passwd, - &realm); - } - rc = ngx_http_auth_basic_user(r); if (rc == NGX_DECLINED) { @@ -237,8 +224,7 @@ ngx_http_auth_basic_handler(ngx_http_request_t *r) pwd.len = i - passwd; pwd.data = &buf[passwd]; - return ngx_http_auth_basic_crypt_handler(r, NULL, &pwd, - &realm); + return ngx_http_auth_basic_crypt_handler(r, &pwd, &realm); } break; @@ -276,7 +262,7 @@ ngx_http_auth_basic_handler(ngx_http_request_t *r) ngx_cpystrn(pwd.data, &buf[passwd], pwd.len + 1); - return ngx_http_auth_basic_crypt_handler(r, NULL, &pwd, &realm); + return ngx_http_auth_basic_crypt_handler(r, &pwd, &realm); } ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, @@ -288,8 +274,8 @@ ngx_http_auth_basic_handler(ngx_http_request_t *r) static ngx_int_t -ngx_http_auth_basic_crypt_handler(ngx_http_request_t *r, - ngx_http_auth_basic_ctx_t *ctx, ngx_str_t *passwd, ngx_str_t *realm) +ngx_http_auth_basic_crypt_handler(ngx_http_request_t *r, ngx_str_t *passwd, + ngx_str_t *realm) { ngx_int_t rc; u_char *encrypted; @@ -301,48 +287,22 @@ ngx_http_auth_basic_crypt_handler(ngx_http_request_t *r, "rc: %i user: \"%V\" salt: \"%s\"", rc, &r->headers_in.user, passwd->data); - if (rc == NGX_OK) { - if (ngx_strcmp(encrypted, passwd->data) == 0) { - return NGX_OK; - } - - ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "encrypted: \"%s\"", encrypted); - - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "user \"%V\": password mismatch", - &r->headers_in.user); - - return ngx_http_auth_basic_set_realm(r, realm); - } - - if (rc == NGX_ERROR) { + if (rc != NGX_OK) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } - /* rc == NGX_AGAIN */ - - if (ctx == NULL) { - ctx = ngx_palloc(r->pool, sizeof(ngx_http_auth_basic_ctx_t)); - if (ctx == NULL) { - return NGX_HTTP_INTERNAL_SERVER_ERROR; - } - - ngx_http_set_ctx(r, ctx, ngx_http_auth_basic_module); - - ctx->passwd.len = passwd->len; - passwd->len++; - - ctx->passwd.data = ngx_pstrdup(r->pool, passwd); - if (ctx->passwd.data == NULL) { - return NGX_HTTP_INTERNAL_SERVER_ERROR; - } - + if (ngx_strcmp(encrypted, passwd->data) == 0) { + return NGX_OK; } - /* TODO: add mutex event */ + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "encrypted: \"%s\"", encrypted); + + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "user \"%V\": password mismatch", + &r->headers_in.user); - return rc; + return ngx_http_auth_basic_set_realm(r, realm); } @@ -361,6 +321,8 @@ ngx_http_auth_basic_set_realm(ngx_http_request_t *r, ngx_str_t *realm) basic = ngx_pnalloc(r->pool, len); if (basic == NULL) { + r->headers_out.www_authenticate->hash = 0; + r->headers_out.www_authenticate = NULL; return NGX_HTTP_INTERNAL_SERVER_ERROR; } diff --git a/src/http/modules/ngx_http_browser_module.c b/src/http/modules/ngx_http_browser_module.c index 80da0d8fa86..f7742548428 100644 --- a/src/http/modules/ngx_http_browser_module.c +++ b/src/http/modules/ngx_http_browser_module.c @@ -37,13 +37,6 @@ typedef struct { } ngx_http_modern_browser_t; -typedef struct { - ngx_str_t name; - ngx_http_get_variable_pt handler; - uintptr_t data; -} ngx_http_browser_variable_t; - - typedef struct { ngx_array_t *modern_browsers; ngx_array_t *ancient_browsers; @@ -63,7 +56,7 @@ static ngx_int_t ngx_http_browser_variable(ngx_http_request_t *r, static ngx_uint_t ngx_http_browser(ngx_http_request_t *r, ngx_http_browser_conf_t *cf); -static ngx_int_t ngx_http_browser_add_variable(ngx_conf_t *cf); +static ngx_int_t ngx_http_browser_add_variables(ngx_conf_t *cf); static void *ngx_http_browser_create_conf(ngx_conf_t *cf); static char *ngx_http_browser_merge_conf(ngx_conf_t *cf, void *parent, void *child); @@ -114,7 +107,7 @@ static ngx_command_t ngx_http_browser_commands[] = { static ngx_http_module_t ngx_http_browser_module_ctx = { - ngx_http_browser_add_variable, /* preconfiguration */ + ngx_http_browser_add_variables, /* preconfiguration */ NULL, /* postconfiguration */ NULL, /* create main configuration */ @@ -218,13 +211,18 @@ static ngx_http_modern_browser_mask_t ngx_http_modern_browser_masks[] = { }; -static ngx_http_browser_variable_t ngx_http_browsers[] = { - { ngx_string("msie"), ngx_http_msie_variable, 0 }, - { ngx_string("modern_browser"), ngx_http_browser_variable, - NGX_HTTP_MODERN_BROWSER }, - { ngx_string("ancient_browser"), ngx_http_browser_variable, - NGX_HTTP_ANCIENT_BROWSER }, - { ngx_null_string, NULL, 0 } +static ngx_http_variable_t ngx_http_browser_vars[] = { + + { ngx_string("msie"), NULL, ngx_http_msie_variable, + 0, NGX_HTTP_VAR_CHANGEABLE, 0 }, + + { ngx_string("modern_browser"), NULL, ngx_http_browser_variable, + NGX_HTTP_MODERN_BROWSER, NGX_HTTP_VAR_CHANGEABLE, 0 }, + + { ngx_string("ancient_browser"), NULL, ngx_http_browser_variable, + NGX_HTTP_ANCIENT_BROWSER, NGX_HTTP_VAR_CHANGEABLE, 0 }, + + ngx_http_null_variable }; @@ -397,20 +395,19 @@ ngx_http_msie_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v, static ngx_int_t -ngx_http_browser_add_variable(ngx_conf_t *cf) +ngx_http_browser_add_variables(ngx_conf_t *cf) { - ngx_http_browser_variable_t *var; - ngx_http_variable_t *v; + ngx_http_variable_t *var, *v; - for (var = ngx_http_browsers; var->name.len; var++) { + for (v = ngx_http_browser_vars; v->name.len; v++) { - v = ngx_http_add_variable(cf, &var->name, NGX_HTTP_VAR_CHANGEABLE); - if (v == NULL) { + var = ngx_http_add_variable(cf, &v->name, v->flags); + if (var == NULL) { return NGX_ERROR; } - v->get_handler = var->handler; - v->data = var->data; + var->get_handler = v->get_handler; + var->data = v->data; } return NGX_OK; diff --git a/src/http/modules/ngx_http_charset_filter_module.c b/src/http/modules/ngx_http_charset_filter_module.c index 4ea98184b26..e52b96e9b15 100644 --- a/src/http/modules/ngx_http_charset_filter_module.c +++ b/src/http/modules/ngx_http_charset_filter_module.c @@ -123,7 +123,7 @@ static char *ngx_http_charset_merge_loc_conf(ngx_conf_t *cf, static ngx_int_t ngx_http_charset_postconfiguration(ngx_conf_t *cf); -ngx_str_t ngx_http_charset_default_types[] = { +static ngx_str_t ngx_http_charset_default_types[] = { ngx_string("text/html"), ngx_string("text/xml"), ngx_string("text/plain"), diff --git a/src/http/modules/ngx_http_chunked_filter_module.c b/src/http/modules/ngx_http_chunked_filter_module.c index ac2e3e8f99a..4d6fd3eed0b 100644 --- a/src/http/modules/ngx_http_chunked_filter_module.c +++ b/src/http/modules/ngx_http_chunked_filter_module.c @@ -17,6 +17,8 @@ typedef struct { static ngx_int_t ngx_http_chunked_filter_init(ngx_conf_t *cf); +static ngx_chain_t *ngx_http_chunked_create_trailers(ngx_http_request_t *r, + ngx_http_chunked_filter_ctx_t *ctx); static ngx_http_module_t ngx_http_chunked_filter_module_ctx = { @@ -69,27 +71,29 @@ ngx_http_chunked_header_filter(ngx_http_request_t *r) return ngx_http_next_header_filter(r); } - if (r->headers_out.content_length_n == -1) { - if (r->http_version < NGX_HTTP_VERSION_11) { - r->keepalive = 0; + if (r->headers_out.content_length_n == -1 + || r->expect_trailers) + { + clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); - } else { - clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); + if (r->http_version >= NGX_HTTP_VERSION_11 + && clcf->chunked_transfer_encoding) + { + if (r->expect_trailers) { + ngx_http_clear_content_length(r); + } - if (clcf->chunked_transfer_encoding) { - r->chunked = 1; + r->chunked = 1; - ctx = ngx_pcalloc(r->pool, - sizeof(ngx_http_chunked_filter_ctx_t)); - if (ctx == NULL) { - return NGX_ERROR; - } + ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_chunked_filter_ctx_t)); + if (ctx == NULL) { + return NGX_ERROR; + } - ngx_http_set_ctx(r, ctx, ngx_http_chunked_filter_module); + ngx_http_set_ctx(r, ctx, ngx_http_chunked_filter_module); - } else { - r->keepalive = 0; - } + } else if (r->headers_out.content_length_n == -1) { + r->keepalive = 0; } } @@ -179,26 +183,17 @@ ngx_http_chunked_body_filter(ngx_http_request_t *r, ngx_chain_t *in) } if (cl->buf->last_buf) { - tl = ngx_chain_get_free_buf(r->pool, &ctx->free); + tl = ngx_http_chunked_create_trailers(r, ctx); if (tl == NULL) { return NGX_ERROR; } - b = tl->buf; - - b->tag = (ngx_buf_tag_t) &ngx_http_chunked_filter_module; - b->temporary = 0; - b->memory = 1; - b->last_buf = 1; - b->pos = (u_char *) CRLF "0" CRLF CRLF; - b->last = b->pos + 7; - cl->buf->last_buf = 0; *ll = tl; if (size == 0) { - b->pos += 2; + tl->buf->pos += 2; } } else if (size > 0) { @@ -230,6 +225,109 @@ ngx_http_chunked_body_filter(ngx_http_request_t *r, ngx_chain_t *in) } +static ngx_chain_t * +ngx_http_chunked_create_trailers(ngx_http_request_t *r, + ngx_http_chunked_filter_ctx_t *ctx) +{ + size_t len; + ngx_buf_t *b; + ngx_uint_t i; + ngx_chain_t *cl; + ngx_list_part_t *part; + ngx_table_elt_t *header; + + len = 0; + + part = &r->headers_out.trailers.part; + header = part->elts; + + for (i = 0; /* void */; i++) { + + if (i >= part->nelts) { + if (part->next == NULL) { + break; + } + + part = part->next; + header = part->elts; + i = 0; + } + + if (header[i].hash == 0) { + continue; + } + + len += header[i].key.len + sizeof(": ") - 1 + + header[i].value.len + sizeof(CRLF) - 1; + } + + cl = ngx_chain_get_free_buf(r->pool, &ctx->free); + if (cl == NULL) { + return NULL; + } + + b = cl->buf; + + b->tag = (ngx_buf_tag_t) &ngx_http_chunked_filter_module; + b->temporary = 0; + b->memory = 1; + b->last_buf = 1; + + if (len == 0) { + b->pos = (u_char *) CRLF "0" CRLF CRLF; + b->last = b->pos + sizeof(CRLF "0" CRLF CRLF) - 1; + return cl; + } + + len += sizeof(CRLF "0" CRLF CRLF) - 1; + + b->pos = ngx_palloc(r->pool, len); + if (b->pos == NULL) { + return NULL; + } + + b->last = b->pos; + + *b->last++ = CR; *b->last++ = LF; + *b->last++ = '0'; + *b->last++ = CR; *b->last++ = LF; + + part = &r->headers_out.trailers.part; + header = part->elts; + + for (i = 0; /* void */; i++) { + + if (i >= part->nelts) { + if (part->next == NULL) { + break; + } + + part = part->next; + header = part->elts; + i = 0; + } + + if (header[i].hash == 0) { + continue; + } + + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "http trailer: \"%V: %V\"", + &header[i].key, &header[i].value); + + b->last = ngx_copy(b->last, header[i].key.data, header[i].key.len); + *b->last++ = ':'; *b->last++ = ' '; + + b->last = ngx_copy(b->last, header[i].value.data, header[i].value.len); + *b->last++ = CR; *b->last++ = LF; + } + + *b->last++ = CR; *b->last++ = LF; + + return cl; +} + + static ngx_int_t ngx_http_chunked_filter_init(ngx_conf_t *cf) { diff --git a/src/http/modules/ngx_http_dav_module.c b/src/http/modules/ngx_http_dav_module.c index 012a0fba84b..566b08ba19b 100644 --- a/src/http/modules/ngx_http_dav_module.c +++ b/src/http/modules/ngx_http_dav_module.c @@ -1067,7 +1067,7 @@ ngx_http_dav_location(ngx_http_request_t *r, u_char *path) u_char *location; ngx_http_core_loc_conf_t *clcf; - r->headers_out.location = ngx_palloc(r->pool, sizeof(ngx_table_elt_t)); + r->headers_out.location = ngx_list_push(&r->headers_out.headers); if (r->headers_out.location == NULL) { return NGX_ERROR; } @@ -1080,17 +1080,15 @@ ngx_http_dav_location(ngx_http_request_t *r, u_char *path) } else { location = ngx_pnalloc(r->pool, r->uri.len); if (location == NULL) { + ngx_http_clear_location(r); return NGX_ERROR; } ngx_memcpy(location, r->uri.data, r->uri.len); } - /* - * we do not need to set the r->headers_out.location->hash and - * r->headers_out.location->key fields - */ - + r->headers_out.location->hash = 1; + ngx_str_set(&r->headers_out.location->key, "Location"); r->headers_out.location->value.len = r->uri.len; r->headers_out.location->value.data = location; diff --git a/src/http/modules/ngx_http_fastcgi_module.c b/src/http/modules/ngx_http_fastcgi_module.c index 4e2dff87a0a..ea16ecae9eb 100644 --- a/src/http/modules/ngx_http_fastcgi_module.c +++ b/src/http/modules/ngx_http_fastcgi_module.c @@ -211,6 +211,7 @@ static ngx_conf_bitmask_t ngx_http_fastcgi_next_upstream_masks[] = { { ngx_string("http_503"), NGX_HTTP_UPSTREAM_FT_HTTP_503 }, { ngx_string("http_403"), NGX_HTTP_UPSTREAM_FT_HTTP_403 }, { ngx_string("http_404"), NGX_HTTP_UPSTREAM_FT_HTTP_404 }, + { ngx_string("http_429"), NGX_HTTP_UPSTREAM_FT_HTTP_429 }, { ngx_string("updating"), NGX_HTTP_UPSTREAM_FT_UPDATING }, { ngx_string("off"), NGX_HTTP_UPSTREAM_FT_OFF }, { ngx_null_string, 0 } @@ -420,6 +421,13 @@ static ngx_command_t ngx_http_fastcgi_commands[] = { offsetof(ngx_http_fastcgi_loc_conf_t, upstream.cache_min_uses), NULL }, + { ngx_string("fastcgi_cache_max_range_offset"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_conf_set_off_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_fastcgi_loc_conf_t, upstream.cache_max_range_offset), + NULL }, + { ngx_string("fastcgi_cache_use_stale"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE, ngx_conf_set_bitmask_slot, @@ -462,6 +470,13 @@ static ngx_command_t ngx_http_fastcgi_commands[] = { offsetof(ngx_http_fastcgi_loc_conf_t, upstream.cache_revalidate), NULL }, + { ngx_string("fastcgi_cache_background_update"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, + ngx_conf_set_flag_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_fastcgi_loc_conf_t, upstream.cache_background_update), + NULL }, + #endif { ngx_string("fastcgi_temp_path"), @@ -616,7 +631,7 @@ static ngx_http_variable_t ngx_http_fastcgi_vars[] = { ngx_http_fastcgi_path_info_variable, 0, NGX_HTTP_VAR_NOCACHEABLE|NGX_HTTP_VAR_NOHASH, 0 }, - { ngx_null_string, NULL, NULL, 0, 0, 0 } + ngx_http_null_variable }; @@ -1863,6 +1878,7 @@ ngx_http_fastcgi_process_header(ngx_http_request_t *r) p = ngx_pnalloc(r->pool, size); if (p == NULL) { + h->hash = 0; return NGX_ERROR; } @@ -1885,6 +1901,7 @@ ngx_http_fastcgi_process_header(ngx_http_request_t *r) ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, "invalid header after joining " "FastCGI records"); + h->hash = 0; return NGX_ERROR; } @@ -1910,6 +1927,7 @@ ngx_http_fastcgi_process_header(ngx_http_request_t *r) h->key.len + 1 + h->value.len + 1 + h->key.len); if (h->key.data == NULL) { + h->hash = 0; return NGX_ERROR; } @@ -2754,6 +2772,7 @@ ngx_http_fastcgi_create_loc_conf(ngx_conf_t *cf) #if (NGX_HTTP_CACHE) conf->upstream.cache = NGX_CONF_UNSET; conf->upstream.cache_min_uses = NGX_CONF_UNSET_UINT; + conf->upstream.cache_max_range_offset = NGX_CONF_UNSET; conf->upstream.cache_bypass = NGX_CONF_UNSET_PTR; conf->upstream.no_cache = NGX_CONF_UNSET_PTR; conf->upstream.cache_valid = NGX_CONF_UNSET_PTR; @@ -2761,6 +2780,7 @@ ngx_http_fastcgi_create_loc_conf(ngx_conf_t *cf) conf->upstream.cache_lock_timeout = NGX_CONF_UNSET_MSEC; conf->upstream.cache_lock_age = NGX_CONF_UNSET_MSEC; conf->upstream.cache_revalidate = NGX_CONF_UNSET; + conf->upstream.cache_background_update = NGX_CONF_UNSET; #endif conf->upstream.hide_headers = NGX_CONF_UNSET_PTR; @@ -2999,6 +3019,10 @@ ngx_http_fastcgi_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) ngx_conf_merge_uint_value(conf->upstream.cache_min_uses, prev->upstream.cache_min_uses, 1); + ngx_conf_merge_off_value(conf->upstream.cache_max_range_offset, + prev->upstream.cache_max_range_offset, + NGX_MAX_OFF_T_VALUE); + ngx_conf_merge_bitmask_value(conf->upstream.cache_use_stale, prev->upstream.cache_use_stale, (NGX_CONF_BITMASK_SET @@ -3049,6 +3073,9 @@ ngx_http_fastcgi_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) ngx_conf_merge_value(conf->upstream.cache_revalidate, prev->upstream.cache_revalidate, 0); + ngx_conf_merge_value(conf->upstream.cache_background_update, + prev->upstream.cache_background_update, 0); + #endif ngx_conf_merge_value(conf->upstream.pass_request_headers, diff --git a/src/http/modules/ngx_http_flv_module.c b/src/http/modules/ngx_http_flv_module.c index cc2532027cc..7b72fae0337 100644 --- a/src/http/modules/ngx_http_flv_module.c +++ b/src/http/modules/ngx_http_flv_module.c @@ -203,7 +203,7 @@ ngx_http_flv_handler(ngx_http_request_t *r) } if (i == 0) { - b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t)); + b = ngx_calloc_buf(r->pool); if (b == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } @@ -217,7 +217,7 @@ ngx_http_flv_handler(ngx_http_request_t *r) } - b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t)); + b = ngx_calloc_buf(r->pool); if (b == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } diff --git a/src/http/modules/ngx_http_geo_module.c b/src/http/modules/ngx_http_geo_module.c index 46a8d7c14ef..8262c9d61ff 100644 --- a/src/http/modules/ngx_http_geo_module.c +++ b/src/http/modules/ngx_http_geo_module.c @@ -1400,7 +1400,8 @@ ngx_http_geo_include_binary_base(ngx_conf_t *cf, ngx_http_geo_conf_ctx_t *ctx, file.name = *name; file.log = cf->log; - file.fd = ngx_open_file(name->data, NGX_FILE_RDONLY, 0, 0); + file.fd = ngx_open_file(name->data, NGX_FILE_RDONLY, NGX_FILE_OPEN, 0); + if (file.fd == NGX_INVALID_FILE) { err = ngx_errno; if (err != NGX_ENOENT) { diff --git a/src/http/modules/ngx_http_geoip_module.c b/src/http/modules/ngx_http_geoip_module.c index 8e151aa8f20..5ea4f5fb05f 100644 --- a/src/http/modules/ngx_http_geoip_module.c +++ b/src/http/modules/ngx_http_geoip_module.c @@ -232,7 +232,7 @@ static ngx_http_variable_t ngx_http_geoip_vars[] = { ngx_http_geoip_city_int_variable, offsetof(GeoIPRecord, area_code), 0, 0 }, - { ngx_null_string, NULL, NULL, 0, 0, 0 } + ngx_http_null_variable }; diff --git a/src/http/modules/ngx_http_gzip_filter_module.c b/src/http/modules/ngx_http_gzip_filter_module.c index 536fdf8ad42..73b6d89bea4 100644 --- a/src/http/modules/ngx_http_gzip_filter_module.c +++ b/src/http/modules/ngx_http_gzip_filter_module.c @@ -644,7 +644,7 @@ ngx_http_gzip_filter_gzheader(ngx_http_request_t *r, ngx_http_gzip_ctx_t *ctx) static u_char gzheader[10] = { 0x1f, 0x8b, Z_DEFLATED, 0, 0, 0, 0, 0, 0, 3 }; - b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t)); + b = ngx_calloc_buf(r->pool); if (b == NULL) { return NGX_ERROR; } @@ -671,6 +671,8 @@ ngx_http_gzip_filter_gzheader(ngx_http_request_t *r, ngx_http_gzip_ctx_t *ctx) static ngx_int_t ngx_http_gzip_filter_add_data(ngx_http_request_t *r, ngx_http_gzip_ctx_t *ctx) { + ngx_chain_t *cl; + if (ctx->zstream.avail_in || ctx->flush != Z_NO_FLUSH || ctx->redo) { return NGX_OK; } @@ -694,13 +696,16 @@ ngx_http_gzip_filter_add_data(ngx_http_request_t *r, ngx_http_gzip_ctx_t *ctx) ctx->copy_buf = NULL; } - ctx->in_buf = ctx->in->buf; + cl = ctx->in; + ctx->in_buf = cl->buf; + ctx->in = cl->next; if (ctx->in_buf->tag == (ngx_buf_tag_t) &ngx_http_gzip_filter_module) { - ctx->copy_buf = ctx->in; - } + ctx->copy_buf = cl; - ctx->in = ctx->in->next; + } else { + ngx_free_chain(r->pool, cl); + } ctx->zstream.next_in = ctx->in_buf->pos; ctx->zstream.avail_in = ctx->in_buf->last - ctx->in_buf->pos; @@ -733,6 +738,7 @@ ngx_http_gzip_filter_add_data(ngx_http_request_t *r, ngx_http_gzip_ctx_t *ctx) static ngx_int_t ngx_http_gzip_filter_get_buf(ngx_http_request_t *r, ngx_http_gzip_ctx_t *ctx) { + ngx_chain_t *cl; ngx_http_gzip_conf_t *conf; if (ctx->zstream.avail_out) { @@ -742,8 +748,12 @@ ngx_http_gzip_filter_get_buf(ngx_http_request_t *r, ngx_http_gzip_ctx_t *ctx) conf = ngx_http_get_module_loc_conf(r, ngx_http_gzip_filter_module); if (ctx->free) { - ctx->out_buf = ctx->free->buf; - ctx->free = ctx->free->next; + + cl = ctx->free; + ctx->out_buf = cl->buf; + ctx->free = cl->next; + + ngx_free_chain(r->pool, cl); } else if (ctx->bufs < conf->bufs.num) { @@ -1074,10 +1084,6 @@ ngx_http_gzip_ratio_variable(ngx_http_request_t *r, ngx_uint_t zint, zfrac; ngx_http_gzip_ctx_t *ctx; - v->valid = 1; - v->no_cacheable = 0; - v->not_found = 0; - ctx = ngx_http_get_module_ctx(r, ngx_http_gzip_filter_module); if (ctx == NULL || ctx->zout == 0) { @@ -1085,6 +1091,10 @@ ngx_http_gzip_ratio_variable(ngx_http_request_t *r, return NGX_OK; } + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + v->data = ngx_pnalloc(r->pool, NGX_INT32_LEN + 3); if (v->data == NULL) { return NGX_ERROR; diff --git a/src/http/modules/ngx_http_gzip_static_module.c b/src/http/modules/ngx_http_gzip_static_module.c index 4d54090772b..7652a9af3ef 100644 --- a/src/http/modules/ngx_http_gzip_static_module.c +++ b/src/http/modules/ngx_http_gzip_static_module.c @@ -48,7 +48,7 @@ static ngx_command_t ngx_http_gzip_static_commands[] = { }; -ngx_http_module_t ngx_http_gzip_static_module_ctx = { +static ngx_http_module_t ngx_http_gzip_static_module_ctx = { NULL, /* preconfiguration */ ngx_http_gzip_static_init, /* postconfiguration */ @@ -238,7 +238,7 @@ ngx_http_gzip_static_handler(ngx_http_request_t *r) h = ngx_list_push(&r->headers_out.headers); if (h == NULL) { - return NGX_ERROR; + return NGX_HTTP_INTERNAL_SERVER_ERROR; } h->hash = 1; @@ -248,7 +248,7 @@ ngx_http_gzip_static_handler(ngx_http_request_t *r) /* we need to allocate all before the header would be sent */ - b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t)); + b = ngx_calloc_buf(r->pool); if (b == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } diff --git a/src/http/modules/ngx_http_headers_filter_module.c b/src/http/modules/ngx_http_headers_filter_module.c index 6738afe9fbd..e5f1eb53364 100644 --- a/src/http/modules/ngx_http_headers_filter_module.c +++ b/src/http/modules/ngx_http_headers_filter_module.c @@ -48,6 +48,7 @@ typedef struct { time_t expires_time; ngx_http_complex_value_t *expires_value; ngx_array_t *headers; + ngx_array_t *trailers; } ngx_http_headers_conf_t; @@ -98,15 +99,23 @@ static ngx_command_t ngx_http_headers_filter_commands[] = { ngx_http_headers_expires, NGX_HTTP_LOC_CONF_OFFSET, 0, - NULL}, + NULL }, { ngx_string("add_header"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF |NGX_CONF_TAKE23, ngx_http_headers_add, NGX_HTTP_LOC_CONF_OFFSET, - 0, - NULL}, + offsetof(ngx_http_headers_conf_t, headers), + NULL }, + + { ngx_string("add_trailer"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF + |NGX_CONF_TAKE23, + ngx_http_headers_add, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_headers_conf_t, trailers), + NULL }, ngx_null_command }; @@ -144,6 +153,7 @@ ngx_module_t ngx_http_headers_filter_module = { static ngx_http_output_header_filter_pt ngx_http_next_header_filter; +static ngx_http_output_body_filter_pt ngx_http_next_body_filter; static ngx_int_t @@ -154,10 +164,15 @@ ngx_http_headers_filter(ngx_http_request_t *r) ngx_http_header_val_t *h; ngx_http_headers_conf_t *conf; + if (r != r->main) { + return ngx_http_next_header_filter(r); + } + conf = ngx_http_get_module_loc_conf(r, ngx_http_headers_filter_module); - if ((conf->expires == NGX_HTTP_EXPIRES_OFF && conf->headers == NULL) - || r != r->main) + if (conf->expires == NGX_HTTP_EXPIRES_OFF + && conf->headers == NULL + && conf->trailers == NULL) { return ngx_http_next_header_filter(r); } @@ -173,6 +188,7 @@ ngx_http_headers_filter(ngx_http_request_t *r) case NGX_HTTP_SEE_OTHER: case NGX_HTTP_NOT_MODIFIED: case NGX_HTTP_TEMPORARY_REDIRECT: + case NGX_HTTP_PERMANENT_REDIRECT: safe_status = 1; break; @@ -205,10 +221,100 @@ ngx_http_headers_filter(ngx_http_request_t *r) } } + if (conf->trailers) { + h = conf->trailers->elts; + for (i = 0; i < conf->trailers->nelts; i++) { + + if (!safe_status && !h[i].always) { + continue; + } + + r->expect_trailers = 1; + break; + } + } + return ngx_http_next_header_filter(r); } +static ngx_int_t +ngx_http_trailers_filter(ngx_http_request_t *r, ngx_chain_t *in) +{ + ngx_str_t value; + ngx_uint_t i, safe_status; + ngx_chain_t *cl; + ngx_table_elt_t *t; + ngx_http_header_val_t *h; + ngx_http_headers_conf_t *conf; + + conf = ngx_http_get_module_loc_conf(r, ngx_http_headers_filter_module); + + if (in == NULL + || conf->trailers == NULL + || !r->expect_trailers + || r->header_only) + { + return ngx_http_next_body_filter(r, in); + } + + for (cl = in; cl; cl = cl->next) { + if (cl->buf->last_buf) { + break; + } + } + + if (cl == NULL) { + return ngx_http_next_body_filter(r, in); + } + + switch (r->headers_out.status) { + + case NGX_HTTP_OK: + case NGX_HTTP_CREATED: + case NGX_HTTP_NO_CONTENT: + case NGX_HTTP_PARTIAL_CONTENT: + case NGX_HTTP_MOVED_PERMANENTLY: + case NGX_HTTP_MOVED_TEMPORARILY: + case NGX_HTTP_SEE_OTHER: + case NGX_HTTP_NOT_MODIFIED: + case NGX_HTTP_TEMPORARY_REDIRECT: + case NGX_HTTP_PERMANENT_REDIRECT: + safe_status = 1; + break; + + default: + safe_status = 0; + break; + } + + h = conf->trailers->elts; + for (i = 0; i < conf->trailers->nelts; i++) { + + if (!safe_status && !h[i].always) { + continue; + } + + if (ngx_http_complex_value(r, &h[i].value, &value) != NGX_OK) { + return NGX_ERROR; + } + + if (value.len) { + t = ngx_list_push(&r->headers_out.trailers); + if (t == NULL) { + return NGX_ERROR; + } + + t->key = h[i].key; + t->value = value; + t->hash = 1; + } + } + + return ngx_http_next_body_filter(r, in); +} + + static ngx_int_t ngx_http_set_expires(ngx_http_request_t *r, ngx_http_headers_conf_t *conf) { @@ -270,11 +376,6 @@ ngx_http_set_expires(ngx_http_request_t *r, ngx_http_headers_conf_t *conf) 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; @@ -282,6 +383,12 @@ ngx_http_set_expires(ngx_http_request_t *r, ngx_http_headers_conf_t *conf) cc->hash = 1; ngx_str_set(&cc->key, "Cache-Control"); + + ccp = ngx_array_push(&r->headers_out.cache_control); + if (ccp == NULL) { + return NGX_ERROR; + } + *ccp = cc; } else { @@ -469,11 +576,6 @@ ngx_http_add_cache_control(ngx_http_request_t *r, ngx_http_header_val_t *hv, } } - 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; @@ -483,6 +585,11 @@ ngx_http_add_cache_control(ngx_http_request_t *r, ngx_http_header_val_t *hv, ngx_str_set(&cc->key, "Cache-Control"); cc->value = *value; + ccp = ngx_array_push(&r->headers_out.cache_control); + if (ccp == NULL) { + return NGX_ERROR; + } + *ccp = cc; return NGX_OK; @@ -555,6 +662,7 @@ ngx_http_headers_create_conf(ngx_conf_t *cf) * set by ngx_pcalloc(): * * conf->headers = NULL; + * conf->trailers = NULL; * conf->expires_time = 0; * conf->expires_value = NULL; */ @@ -585,6 +693,10 @@ ngx_http_headers_merge_conf(ngx_conf_t *cf, void *parent, void *child) conf->headers = prev->headers; } + if (conf->trailers == NULL) { + conf->trailers = prev->trailers; + } + return NGX_CONF_OK; } @@ -595,6 +707,9 @@ ngx_http_headers_filter_init(ngx_conf_t *cf) ngx_http_next_header_filter = ngx_http_top_header_filter; ngx_http_top_header_filter = ngx_http_headers_filter; + ngx_http_next_body_filter = ngx_http_top_body_filter; + ngx_http_top_body_filter = ngx_http_trailers_filter; + return NGX_OK; } @@ -672,42 +787,49 @@ 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_uint_t i; - ngx_http_header_val_t *hv; - ngx_http_set_header_t *set; - ngx_http_compile_complex_value_t ccv; + ngx_str_t *value; + ngx_uint_t i; + ngx_array_t **headers; + ngx_http_header_val_t *hv; + ngx_http_set_header_t *set; + ngx_http_compile_complex_value_t ccv; value = cf->args->elts; - if (hcf->headers == NULL) { - hcf->headers = ngx_array_create(cf->pool, 1, - sizeof(ngx_http_header_val_t)); - if (hcf->headers == NULL) { + headers = (ngx_array_t **) ((char *) hcf + cmd->offset); + + if (*headers == NULL) { + *headers = ngx_array_create(cf->pool, 1, + sizeof(ngx_http_header_val_t)); + if (*headers == NULL) { return NGX_CONF_ERROR; } } - hv = ngx_array_push(hcf->headers); + hv = ngx_array_push(*headers); if (hv == NULL) { return NGX_CONF_ERROR; } hv->key = value[1]; - hv->handler = ngx_http_add_header; + hv->handler = NULL; hv->offset = 0; hv->always = 0; - set = ngx_http_set_headers; - for (i = 0; set[i].name.len; i++) { - if (ngx_strcasecmp(value[1].data, set[i].name.data) != 0) { - continue; - } + if (headers == &hcf->headers) { + hv->handler = ngx_http_add_header; + + set = ngx_http_set_headers; + for (i = 0; set[i].name.len; i++) { + if (ngx_strcasecmp(value[1].data, set[i].name.data) != 0) { + continue; + } - hv->offset = set[i].offset; - hv->handler = set[i].handler; + hv->offset = set[i].offset; + hv->handler = set[i].handler; - break; + break; + } } if (value[2].len == 0) { diff --git a/src/http/modules/ngx_http_image_filter_module.c b/src/http/modules/ngx_http_image_filter_module.c index dbec5d8e5ad..6c03e8aecec 100644 --- a/src/http/modules/ngx_http_image_filter_module.c +++ b/src/http/modules/ngx_http_image_filter_module.c @@ -581,7 +581,7 @@ ngx_http_image_json(ngx_http_request_t *r, ngx_http_image_filter_ctx_t *ctx) size_t len; ngx_buf_t *b; - b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t)); + b = ngx_calloc_buf(r->pool); if (b == NULL) { return NULL; } @@ -633,7 +633,7 @@ ngx_http_image_asis(ngx_http_request_t *r, ngx_http_image_filter_ctx_t *ctx) { ngx_buf_t *b; - b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t)); + b = ngx_calloc_buf(r->pool); if (b == NULL) { return NULL; } @@ -1067,7 +1067,7 @@ ngx_http_image_resize(ngx_http_request_t *r, ngx_http_image_filter_ctx_t *ctx) return NULL; } - b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t)); + b = ngx_calloc_buf(r->pool); if (b == NULL) { gdFree(out); return NULL; diff --git a/src/http/modules/ngx_http_index_module.c b/src/http/modules/ngx_http_index_module.c index d3544db5bf5..c144b31c3a9 100644 --- a/src/http/modules/ngx_http_index_module.c +++ b/src/http/modules/ngx_http_index_module.c @@ -217,13 +217,13 @@ ngx_http_index_handler(ngx_http_request_t *r) if (ngx_open_cached_file(clcf->open_file_cache, &path, &of, r->pool) != NGX_OK) { - ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, of.err, - "%s \"%s\" failed", of.failed, path.data); - if (of.err == 0) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, of.err, + "%s \"%s\" failed", of.failed, path.data); + #if (NGX_HAVE_OPENAT) if (of.err == NGX_EMLINK || of.err == NGX_ELOOP) diff --git a/src/http/modules/ngx_http_limit_req_module.c b/src/http/modules/ngx_http_limit_req_module.c index 2f695f21263..579b13c847f 100644 --- a/src/http/modules/ngx_http_limit_req_module.c +++ b/src/http/modules/ngx_http_limit_req_module.c @@ -276,6 +276,8 @@ ngx_http_limit_req_handler(ngx_http_request_t *r) r->read_event_handler = ngx_http_test_reading; r->write_event_handler = ngx_http_limit_req_delay; + + r->connection->write->delayed = 1; ngx_add_timer(r->connection->write, delay); return NGX_AGAIN; @@ -292,7 +294,7 @@ ngx_http_limit_req_delay(ngx_http_request_t *r) wev = r->connection->write; - if (!wev->timedout) { + if (wev->delayed) { if (ngx_handle_write_event(wev, 0) != NGX_OK) { ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); @@ -301,8 +303,6 @@ ngx_http_limit_req_delay(ngx_http_request_t *r) return; } - wev->timedout = 0; - if (ngx_handle_read_event(r->connection->read, 0) != NGX_OK) { ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); return; diff --git a/src/http/modules/ngx_http_log_module.c b/src/http/modules/ngx_http_log_module.c index c42fb08ed8f..917ed55f40f 100644 --- a/src/http/modules/ngx_http_log_module.c +++ b/src/http/modules/ngx_http_log_module.c @@ -126,12 +126,16 @@ static u_char *ngx_http_log_request_length(ngx_http_request_t *r, u_char *buf, ngx_http_log_op_t *op); static ngx_int_t ngx_http_log_variable_compile(ngx_conf_t *cf, - ngx_http_log_op_t *op, ngx_str_t *value); + ngx_http_log_op_t *op, ngx_str_t *value, ngx_uint_t json); static size_t ngx_http_log_variable_getlen(ngx_http_request_t *r, uintptr_t data); static u_char *ngx_http_log_variable(ngx_http_request_t *r, u_char *buf, ngx_http_log_op_t *op); static uintptr_t ngx_http_log_escape(u_char *dst, u_char *src, size_t size); +static size_t ngx_http_log_json_variable_getlen(ngx_http_request_t *r, + uintptr_t data); +static u_char *ngx_http_log_json_variable(ngx_http_request_t *r, u_char *buf, + ngx_http_log_op_t *op); static void *ngx_http_log_create_main_conf(ngx_conf_t *cf); @@ -548,6 +552,11 @@ ngx_http_log_script_write(ngx_http_request_t *r, ngx_http_log_script_t *script, if (ngx_open_cached_file(llcf->open_file_cache, &log, &of, r->pool) != NGX_OK) { + if (of.err == 0) { + /* simulate successful logging */ + return len; + } + ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno, "%s \"%s\" failed", of.failed, log.data); /* simulate successful logging */ @@ -744,23 +753,10 @@ ngx_http_log_flush(ngx_open_file_t *file, ngx_log_t *log) static void ngx_http_log_flush_handler(ngx_event_t *ev) { - ngx_open_file_t *file; - ngx_http_log_buf_t *buffer; - ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ev->log, 0, "http log buffer flush handler"); - if (ev->timedout) { - ngx_http_log_flush(ev->data, ev->log); - return; - } - - /* cancel the flush timer for graceful shutdown */ - - file = ev->data; - buffer = file->data; - - buffer->event = NULL; + ngx_http_log_flush(ev->data, ev->log); } @@ -909,7 +905,7 @@ ngx_http_log_request_length(ngx_http_request_t *r, u_char *buf, static ngx_int_t ngx_http_log_variable_compile(ngx_conf_t *cf, ngx_http_log_op_t *op, - ngx_str_t *value) + ngx_str_t *value, ngx_uint_t json) { ngx_int_t index; @@ -919,8 +915,16 @@ ngx_http_log_variable_compile(ngx_conf_t *cf, ngx_http_log_op_t *op, } op->len = 0; - op->getlen = ngx_http_log_variable_getlen; - op->run = ngx_http_log_variable; + + if (json) { + op->getlen = ngx_http_log_json_variable_getlen; + op->run = ngx_http_log_json_variable; + + } else { + op->getlen = ngx_http_log_variable_getlen; + op->run = ngx_http_log_variable; + } + op->data = index; return NGX_OK; @@ -1028,6 +1032,47 @@ ngx_http_log_escape(u_char *dst, u_char *src, size_t size) } +static size_t +ngx_http_log_json_variable_getlen(ngx_http_request_t *r, uintptr_t data) +{ + uintptr_t len; + ngx_http_variable_value_t *value; + + value = ngx_http_get_indexed_variable(r, data); + + if (value == NULL || value->not_found) { + return 0; + } + + len = ngx_escape_json(NULL, value->data, value->len); + + value->escape = len ? 1 : 0; + + return value->len + len; +} + + +static u_char * +ngx_http_log_json_variable(ngx_http_request_t *r, u_char *buf, + ngx_http_log_op_t *op) +{ + ngx_http_variable_value_t *value; + + value = ngx_http_get_indexed_variable(r, op->data); + + if (value == NULL || value->not_found) { + return buf; + } + + if (value->escape == 0) { + return ngx_cpymem(buf, value->data, value->len); + + } else { + return (u_char *) ngx_escape_json(buf, value->data, value->len); + } +} + + static void * ngx_http_log_create_main_conf(ngx_conf_t *cf) { @@ -1491,12 +1536,28 @@ ngx_http_log_compile_format(ngx_conf_t *cf, ngx_array_t *flushes, size_t i, len; ngx_str_t *value, var; ngx_int_t *flush; - ngx_uint_t bracket; + ngx_uint_t bracket, json; ngx_http_log_op_t *op; ngx_http_log_var_t *v; + json = 0; value = args->elts; + if (s < args->nelts && ngx_strncmp(value[s].data, "escape=", 7) == 0) { + data = value[s].data + 7; + + if (ngx_strcmp(data, "json") == 0) { + json = 1; + + } else if (ngx_strcmp(data, "default") != 0) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "unknown log format escaping \"%s\"", data); + return NGX_CONF_ERROR; + } + + s++; + } + for ( /* void */ ; s < args->nelts; s++) { i = 0; @@ -1575,7 +1636,9 @@ ngx_http_log_compile_format(ngx_conf_t *cf, ngx_array_t *flushes, } } - if (ngx_http_log_variable_compile(cf, op, &var) != NGX_OK) { + if (ngx_http_log_variable_compile(cf, op, &var, json) + != NGX_OK) + { return NGX_CONF_ERROR; } diff --git a/src/http/modules/ngx_http_map_module.c b/src/http/modules/ngx_http_map_module.c index 732aa5d7d3c..2fc9be90b7a 100644 --- a/src/http/modules/ngx_http_map_module.c +++ b/src/http/modules/ngx_http_map_module.c @@ -26,7 +26,8 @@ typedef struct { ngx_http_variable_value_t *default_value; ngx_conf_t *cf; - ngx_uint_t hostnames; /* unsigned hostnames:1 */ + unsigned hostnames:1; + unsigned no_cacheable:1; } ngx_http_map_conf_ctx_t; @@ -265,6 +266,7 @@ ngx_http_map_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) ctx.default_value = NULL; ctx.cf = &save; ctx.hostnames = 0; + ctx.no_cacheable = 0; save = *cf; cf->pool = pool; @@ -281,6 +283,10 @@ ngx_http_map_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) return rv; } + if (ctx.no_cacheable) { + var->flags |= NGX_HTTP_VAR_NOCACHEABLE; + } + map->default_value = ctx.default_value ? ctx.default_value: &ngx_http_variable_null_value; @@ -393,8 +399,16 @@ ngx_http_map(ngx_conf_t *cf, ngx_command_t *dummy, void *conf) { ctx->hostnames = 1; return NGX_CONF_OK; + } + + if (cf->args->nelts == 1 + && ngx_strcmp(value[0].data, "volatile") == 0) + { + ctx->no_cacheable = 1; + return NGX_CONF_OK; + } - } else if (cf->args->nelts != 2) { + if (cf->args->nelts != 2) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid number of the map parameters"); return NGX_CONF_ERROR; diff --git a/src/http/modules/ngx_http_mirror_module.c b/src/http/modules/ngx_http_mirror_module.c new file mode 100644 index 00000000000..787adb321bf --- /dev/null +++ b/src/http/modules/ngx_http_mirror_module.c @@ -0,0 +1,264 @@ + +/* + * Copyright (C) Roman Arutyunyan + * Copyright (C) Nginx, Inc. + */ + + +#include +#include +#include + + +typedef struct { + ngx_array_t *mirror; + ngx_flag_t request_body; +} ngx_http_mirror_loc_conf_t; + + +typedef struct { + ngx_int_t status; +} ngx_http_mirror_ctx_t; + + +static ngx_int_t ngx_http_mirror_handler(ngx_http_request_t *r); +static void ngx_http_mirror_body_handler(ngx_http_request_t *r); +static ngx_int_t ngx_http_mirror_handler_internal(ngx_http_request_t *r); +static void *ngx_http_mirror_create_loc_conf(ngx_conf_t *cf); +static char *ngx_http_mirror_merge_loc_conf(ngx_conf_t *cf, void *parent, + void *child); +static char *ngx_http_mirror(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); +static ngx_int_t ngx_http_mirror_init(ngx_conf_t *cf); + + +static ngx_command_t ngx_http_mirror_commands[] = { + + { ngx_string("mirror"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_http_mirror, + NGX_HTTP_LOC_CONF_OFFSET, + 0, + NULL }, + + { ngx_string("mirror_request_body"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, + ngx_conf_set_flag_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_mirror_loc_conf_t, request_body), + NULL }, + + ngx_null_command +}; + + +static ngx_http_module_t ngx_http_mirror_module_ctx = { + NULL, /* preconfiguration */ + ngx_http_mirror_init, /* postconfiguration */ + + NULL, /* create main configuration */ + NULL, /* init main configuration */ + + NULL, /* create server configuration */ + NULL, /* merge server configuration */ + + ngx_http_mirror_create_loc_conf, /* create location configuration */ + ngx_http_mirror_merge_loc_conf /* merge location configuration */ +}; + + +ngx_module_t ngx_http_mirror_module = { + NGX_MODULE_V1, + &ngx_http_mirror_module_ctx, /* module context */ + ngx_http_mirror_commands, /* module directives */ + NGX_HTTP_MODULE, /* module type */ + NULL, /* init master */ + NULL, /* 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_mirror_handler(ngx_http_request_t *r) +{ + ngx_int_t rc; + ngx_http_mirror_ctx_t *ctx; + ngx_http_mirror_loc_conf_t *mlcf; + + if (r != r->main) { + return NGX_DECLINED; + } + + mlcf = ngx_http_get_module_loc_conf(r, ngx_http_mirror_module); + + if (mlcf->mirror == NULL) { + return NGX_DECLINED; + } + + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "mirror handler"); + + if (mlcf->request_body) { + ctx = ngx_http_get_module_ctx(r, ngx_http_mirror_module); + + if (ctx) { + return ctx->status; + } + + ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_mirror_ctx_t)); + if (ctx == NULL) { + return NGX_ERROR; + } + + ctx->status = NGX_DONE; + + ngx_http_set_ctx(r, ctx, ngx_http_mirror_module); + + rc = ngx_http_read_client_request_body(r, ngx_http_mirror_body_handler); + if (rc >= NGX_HTTP_SPECIAL_RESPONSE) { + return rc; + } + + ngx_http_finalize_request(r, NGX_DONE); + return NGX_DONE; + } + + return ngx_http_mirror_handler_internal(r); +} + + +static void +ngx_http_mirror_body_handler(ngx_http_request_t *r) +{ + ngx_http_mirror_ctx_t *ctx; + + ctx = ngx_http_get_module_ctx(r, ngx_http_mirror_module); + + ctx->status = ngx_http_mirror_handler_internal(r); + + r->preserve_body = 1; + + r->write_event_handler = ngx_http_core_run_phases; + ngx_http_core_run_phases(r); +} + + +static ngx_int_t +ngx_http_mirror_handler_internal(ngx_http_request_t *r) +{ + ngx_str_t *name; + ngx_uint_t i; + ngx_http_request_t *sr; + ngx_http_mirror_loc_conf_t *mlcf; + + mlcf = ngx_http_get_module_loc_conf(r, ngx_http_mirror_module); + + name = mlcf->mirror->elts; + + for (i = 0; i < mlcf->mirror->nelts; i++) { + if (ngx_http_subrequest(r, &name[i], &r->args, &sr, NULL, + NGX_HTTP_SUBREQUEST_BACKGROUND) + != NGX_OK) + { + return NGX_HTTP_INTERNAL_SERVER_ERROR; + } + + sr->header_only = 1; + sr->method = r->method; + sr->method_name = r->method_name; + } + + return NGX_DECLINED; +} + + +static void * +ngx_http_mirror_create_loc_conf(ngx_conf_t *cf) +{ + ngx_http_mirror_loc_conf_t *mlcf; + + mlcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_mirror_loc_conf_t)); + if (mlcf == NULL) { + return NULL; + } + + mlcf->mirror = NGX_CONF_UNSET_PTR; + mlcf->request_body = NGX_CONF_UNSET; + + return mlcf; +} + + +static char * +ngx_http_mirror_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) +{ + ngx_http_mirror_loc_conf_t *prev = parent; + ngx_http_mirror_loc_conf_t *conf = child; + + ngx_conf_merge_ptr_value(conf->mirror, prev->mirror, NULL); + ngx_conf_merge_value(conf->request_body, prev->request_body, 1); + + return NGX_CONF_OK; +} + + +static char * +ngx_http_mirror(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) +{ + ngx_http_mirror_loc_conf_t *mlcf = conf; + + ngx_str_t *value, *s; + + value = cf->args->elts; + + if (ngx_strcmp(value[1].data, "off") == 0) { + if (mlcf->mirror != NGX_CONF_UNSET_PTR) { + return "is duplicate"; + } + + mlcf->mirror = NULL; + return NGX_CONF_OK; + } + + if (mlcf->mirror == NULL) { + return "is duplicate"; + } + + if (mlcf->mirror == NGX_CONF_UNSET_PTR) { + mlcf->mirror = ngx_array_create(cf->pool, 4, sizeof(ngx_str_t)); + if (mlcf->mirror == NULL) { + return NGX_CONF_ERROR; + } + } + + s = ngx_array_push(mlcf->mirror); + if (s == NULL) { + return NGX_CONF_ERROR; + } + + *s = value[1]; + + return NGX_CONF_OK; +} + + +static ngx_int_t +ngx_http_mirror_init(ngx_conf_t *cf) +{ + ngx_http_handler_pt *h; + ngx_http_core_main_conf_t *cmcf; + + cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module); + + h = ngx_array_push(&cmcf->phases[NGX_HTTP_PRECONTENT_PHASE].handlers); + if (h == NULL) { + return NGX_ERROR; + } + + *h = ngx_http_mirror_handler; + + return NGX_OK; +} diff --git a/src/http/modules/ngx_http_mp4_module.c b/src/http/modules/ngx_http_mp4_module.c index 8f2920f6428..08a68d07b23 100644 --- a/src/http/modules/ngx_http_mp4_module.c +++ b/src/http/modules/ngx_http_mp4_module.c @@ -636,7 +636,7 @@ ngx_http_mp4_handler(ngx_http_request_t *r) } if (mp4 == NULL) { - b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t)); + b = ngx_calloc_buf(r->pool); if (b == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } @@ -1229,7 +1229,9 @@ ngx_http_mp4_update_mdat_atom(ngx_http_mp4_file_t *mp4, off_t start_offset, atom_header = mp4->mdat_atom_header; - if ((uint64_t) atom_data_size > (uint64_t) 0xffffffff) { + if ((uint64_t) atom_data_size + > (uint64_t) 0xffffffff - sizeof(ngx_mp4_atom_header_t)) + { atom_size = 1; atom_header_size = sizeof(ngx_mp4_atom_header64_t); ngx_mp4_set_64value(atom_header + sizeof(ngx_mp4_atom_header_t), diff --git a/src/http/modules/ngx_http_proxy_module.c b/src/http/modules/ngx_http_proxy_module.c index 15cdcc5cf1f..b42839c24a0 100644 --- a/src/http/modules/ngx_http_proxy_module.c +++ b/src/http/modules/ngx_http_proxy_module.c @@ -220,6 +220,7 @@ static ngx_conf_bitmask_t ngx_http_proxy_next_upstream_masks[] = { { ngx_string("http_504"), NGX_HTTP_UPSTREAM_FT_HTTP_504 }, { ngx_string("http_403"), NGX_HTTP_UPSTREAM_FT_HTTP_403 }, { ngx_string("http_404"), NGX_HTTP_UPSTREAM_FT_HTTP_404 }, + { ngx_string("http_429"), NGX_HTTP_UPSTREAM_FT_HTTP_429 }, { ngx_string("updating"), NGX_HTTP_UPSTREAM_FT_UPDATING }, { ngx_string("off"), NGX_HTTP_UPSTREAM_FT_OFF }, { ngx_null_string, 0 } @@ -234,6 +235,7 @@ static ngx_conf_bitmask_t ngx_http_proxy_ssl_protocols[] = { { ngx_string("TLSv1"), NGX_SSL_TLSv1 }, { ngx_string("TLSv1.1"), NGX_SSL_TLSv1_1 }, { ngx_string("TLSv1.2"), NGX_SSL_TLSv1_2 }, + { ngx_string("TLSv1.3"), NGX_SSL_TLSv1_3 }, { ngx_null_string, 0 } }; @@ -492,6 +494,13 @@ static ngx_command_t ngx_http_proxy_commands[] = { offsetof(ngx_http_proxy_loc_conf_t, upstream.cache_min_uses), NULL }, + { ngx_string("proxy_cache_max_range_offset"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_conf_set_off_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_proxy_loc_conf_t, upstream.cache_max_range_offset), + NULL }, + { ngx_string("proxy_cache_use_stale"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE, ngx_conf_set_bitmask_slot, @@ -541,6 +550,13 @@ static ngx_command_t ngx_http_proxy_commands[] = { offsetof(ngx_http_proxy_loc_conf_t, upstream.cache_convert_head), NULL }, + { ngx_string("proxy_cache_background_update"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, + ngx_conf_set_flag_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_proxy_loc_conf_t, upstream.cache_background_update), + NULL }, + #endif { ngx_string("proxy_temp_path"), @@ -813,7 +829,7 @@ static ngx_http_variable_t ngx_http_proxy_vars[] = { ngx_http_proxy_internal_chunked_variable, 0, NGX_HTTP_VAR_NOCACHEABLE|NGX_HTTP_VAR_NOHASH, 0 }, - { ngx_null_string, NULL, NULL, 0, 0, 0 } + ngx_http_null_variable }; @@ -1127,7 +1143,8 @@ ngx_http_proxy_create_key(ngx_http_request_t *r) static ngx_int_t ngx_http_proxy_create_request(ngx_http_request_t *r) { - size_t len, uri_len, loc_len, body_len; + size_t len, uri_len, loc_len, body_len, + key_len, val_len; uintptr_t escape; ngx_buf_t *b; ngx_str_t method; @@ -1242,11 +1259,20 @@ ngx_http_proxy_create_request(ngx_http_request_t *r) le.flushed = 1; while (*(uintptr_t *) le.ip) { - while (*(uintptr_t *) le.ip) { + + lcode = *(ngx_http_script_len_code_pt *) le.ip; + key_len = lcode(&le); + + for (val_len = 0; *(uintptr_t *) le.ip; val_len += lcode(&le)) { lcode = *(ngx_http_script_len_code_pt *) le.ip; - len += lcode(&le); } le.ip += sizeof(uintptr_t); + + if (val_len == 0) { + continue; + } + + len += key_len + sizeof(": ") - 1 + val_len + sizeof(CRLF) - 1; } @@ -1346,30 +1372,41 @@ ngx_http_proxy_create_request(ngx_http_request_t *r) le.ip = headers->lengths->elts; while (*(uintptr_t *) le.ip) { - lcode = *(ngx_http_script_len_code_pt *) le.ip; - /* skip the header line name length */ + lcode = *(ngx_http_script_len_code_pt *) le.ip; (void) lcode(&le); - if (*(ngx_http_script_len_code_pt *) le.ip) { + for (val_len = 0; *(uintptr_t *) le.ip; val_len += lcode(&le)) { + lcode = *(ngx_http_script_len_code_pt *) le.ip; + } + le.ip += sizeof(uintptr_t); - for (len = 0; *(uintptr_t *) le.ip; len += lcode(&le)) { - lcode = *(ngx_http_script_len_code_pt *) le.ip; - } + if (val_len == 0) { + e.skip = 1; - e.skip = (len == sizeof(CRLF) - 1) ? 1 : 0; + while (*(uintptr_t *) e.ip) { + code = *(ngx_http_script_code_pt *) e.ip; + code((ngx_http_script_engine_t *) &e); + } + e.ip += sizeof(uintptr_t); - } else { e.skip = 0; + + continue; } - le.ip += sizeof(uintptr_t); + code = *(ngx_http_script_code_pt *) e.ip; + code((ngx_http_script_engine_t *) &e); + + *e.pos++ = ':'; *e.pos++ = ' '; while (*(uintptr_t *) e.ip) { code = *(ngx_http_script_code_pt *) e.ip; code((ngx_http_script_engine_t *) &e); } e.ip += sizeof(uintptr_t); + + *e.pos++ = CR; *e.pos++ = LF; } b->last = e.pos; @@ -1782,6 +1819,7 @@ ngx_http_proxy_process_header(ngx_http_request_t *r) h->key.data = ngx_pnalloc(r->pool, h->key.len + 1 + h->value.len + 1 + h->key.len); if (h->key.data == NULL) { + h->hash = 0; return NGX_ERROR; } @@ -2847,6 +2885,7 @@ ngx_http_proxy_create_loc_conf(ngx_conf_t *cf) #if (NGX_HTTP_CACHE) conf->upstream.cache = NGX_CONF_UNSET; conf->upstream.cache_min_uses = NGX_CONF_UNSET_UINT; + conf->upstream.cache_max_range_offset = NGX_CONF_UNSET; conf->upstream.cache_bypass = NGX_CONF_UNSET_PTR; conf->upstream.no_cache = NGX_CONF_UNSET_PTR; conf->upstream.cache_valid = NGX_CONF_UNSET_PTR; @@ -2855,6 +2894,7 @@ ngx_http_proxy_create_loc_conf(ngx_conf_t *cf) conf->upstream.cache_lock_age = NGX_CONF_UNSET_MSEC; conf->upstream.cache_revalidate = NGX_CONF_UNSET; conf->upstream.cache_convert_head = NGX_CONF_UNSET; + conf->upstream.cache_background_update = NGX_CONF_UNSET; #endif conf->upstream.hide_headers = NGX_CONF_UNSET_PTR; @@ -3108,6 +3148,10 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) ngx_conf_merge_uint_value(conf->upstream.cache_min_uses, prev->upstream.cache_min_uses, 1); + ngx_conf_merge_off_value(conf->upstream.cache_max_range_offset, + prev->upstream.cache_max_range_offset, + NGX_MAX_OFF_T_VALUE); + ngx_conf_merge_bitmask_value(conf->upstream.cache_use_stale, prev->upstream.cache_use_stale, (NGX_CONF_BITMASK_SET @@ -3156,6 +3200,9 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) ngx_conf_merge_value(conf->upstream.cache_convert_head, prev->upstream.cache_convert_head, 1); + ngx_conf_merge_value(conf->upstream.cache_background_update, + prev->upstream.cache_background_update, 0); + #endif if (conf->method == NULL) { @@ -3472,108 +3519,40 @@ ngx_http_proxy_init_headers(ngx_conf_t *cf, ngx_http_proxy_loc_conf_t *conf, continue; } - if (ngx_http_script_variables_count(&src[i].value) == 0) { - copy = ngx_array_push_n(headers->lengths, - sizeof(ngx_http_script_copy_code_t)); - if (copy == NULL) { - return NGX_ERROR; - } - - copy->code = (ngx_http_script_code_pt) - ngx_http_script_copy_len_code; - copy->len = src[i].key.len + sizeof(": ") - 1 - + src[i].value.len + sizeof(CRLF) - 1; - - - size = (sizeof(ngx_http_script_copy_code_t) - + src[i].key.len + sizeof(": ") - 1 - + src[i].value.len + sizeof(CRLF) - 1 - + sizeof(uintptr_t) - 1) - & ~(sizeof(uintptr_t) - 1); - - copy = ngx_array_push_n(headers->values, size); - if (copy == NULL) { - return NGX_ERROR; - } - - copy->code = ngx_http_script_copy_code; - copy->len = src[i].key.len + sizeof(": ") - 1 - + src[i].value.len + sizeof(CRLF) - 1; - - p = (u_char *) copy + sizeof(ngx_http_script_copy_code_t); - - p = ngx_cpymem(p, src[i].key.data, src[i].key.len); - *p++ = ':'; *p++ = ' '; - p = ngx_cpymem(p, src[i].value.data, src[i].value.len); - *p++ = CR; *p = LF; - - } else { - copy = ngx_array_push_n(headers->lengths, - sizeof(ngx_http_script_copy_code_t)); - if (copy == NULL) { - return NGX_ERROR; - } - - copy->code = (ngx_http_script_code_pt) - ngx_http_script_copy_len_code; - copy->len = src[i].key.len + sizeof(": ") - 1; - - - size = (sizeof(ngx_http_script_copy_code_t) - + src[i].key.len + sizeof(": ") - 1 + sizeof(uintptr_t) - 1) - & ~(sizeof(uintptr_t) - 1); - - copy = ngx_array_push_n(headers->values, size); - if (copy == NULL) { - return NGX_ERROR; - } - - copy->code = ngx_http_script_copy_code; - copy->len = src[i].key.len + sizeof(": ") - 1; - - p = (u_char *) copy + sizeof(ngx_http_script_copy_code_t); - p = ngx_cpymem(p, src[i].key.data, src[i].key.len); - *p++ = ':'; *p = ' '; - - - ngx_memzero(&sc, sizeof(ngx_http_script_compile_t)); - - sc.cf = cf; - sc.source = &src[i].value; - sc.flushes = &headers->flushes; - sc.lengths = &headers->lengths; - sc.values = &headers->values; - - if (ngx_http_script_compile(&sc) != NGX_OK) { - return NGX_ERROR; - } + copy = ngx_array_push_n(headers->lengths, + sizeof(ngx_http_script_copy_code_t)); + if (copy == NULL) { + return NGX_ERROR; + } + copy->code = (ngx_http_script_code_pt) ngx_http_script_copy_len_code; + copy->len = src[i].key.len; - copy = ngx_array_push_n(headers->lengths, - sizeof(ngx_http_script_copy_code_t)); - if (copy == NULL) { - return NGX_ERROR; - } + size = (sizeof(ngx_http_script_copy_code_t) + + src[i].key.len + sizeof(uintptr_t) - 1) + & ~(sizeof(uintptr_t) - 1); - copy->code = (ngx_http_script_code_pt) - ngx_http_script_copy_len_code; - copy->len = sizeof(CRLF) - 1; + copy = ngx_array_push_n(headers->values, size); + if (copy == NULL) { + return NGX_ERROR; + } + copy->code = ngx_http_script_copy_code; + copy->len = src[i].key.len; - size = (sizeof(ngx_http_script_copy_code_t) - + sizeof(CRLF) - 1 + sizeof(uintptr_t) - 1) - & ~(sizeof(uintptr_t) - 1); + p = (u_char *) copy + sizeof(ngx_http_script_copy_code_t); + ngx_memcpy(p, src[i].key.data, src[i].key.len); - copy = ngx_array_push_n(headers->values, size); - if (copy == NULL) { - return NGX_ERROR; - } + ngx_memzero(&sc, sizeof(ngx_http_script_compile_t)); - copy->code = ngx_http_script_copy_code; - copy->len = sizeof(CRLF) - 1; + sc.cf = cf; + sc.source = &src[i].value; + sc.flushes = &headers->flushes; + sc.lengths = &headers->lengths; + sc.values = &headers->values; - p = (u_char *) copy + sizeof(ngx_http_script_copy_code_t); - *p++ = CR; *p = LF; + if (ngx_http_script_compile(&sc) != NGX_OK) { + return NGX_ERROR; } code = ngx_array_push_n(headers->lengths, sizeof(uintptr_t)); diff --git a/src/http/modules/ngx_http_range_filter_module.c b/src/http/modules/ngx_http_range_filter_module.c index 095ef0621b7..819c5c94294 100644 --- a/src/http/modules/ngx_http_range_filter_module.c +++ b/src/http/modules/ngx_http_range_filter_module.c @@ -224,12 +224,6 @@ ngx_http_range_header_filter(ngx_http_request_t *r) ctx->offset = r->headers_out.content_offset; - if (ngx_array_init(&ctx->ranges, r->pool, 1, sizeof(ngx_http_range_t)) - != NGX_OK) - { - return NGX_ERROR; - } - ranges = r->single_range ? 1 : clcf->max_ranges; switch (ngx_http_range_parse(r, ctx, ranges)) { @@ -291,6 +285,12 @@ ngx_http_range_parse(ngx_http_request_t *r, ngx_http_range_filter_ctx_t *ctx, } } + if (ngx_array_init(&ctx->ranges, r->pool, 1, sizeof(ngx_http_range_t)) + != NGX_OK) + { + return NGX_ERROR; + } + p = r->headers_in.range->value.data + 6; size = 0; content_length = r->headers_out.content_length_n; @@ -315,7 +315,7 @@ ngx_http_range_parse(ngx_http_request_t *r, ngx_http_range_filter_ctx_t *ctx, return NGX_HTTP_RANGE_NOT_SATISFIABLE; } - start = start * 10 + *p++ - '0'; + start = start * 10 + (*p++ - '0'); } while (*p == ' ') { p++; } @@ -345,7 +345,7 @@ ngx_http_range_parse(ngx_http_request_t *r, ngx_http_range_filter_ctx_t *ctx, return NGX_HTTP_RANGE_NOT_SATISFIABLE; } - end = end * 10 + *p++ - '0'; + end = end * 10 + (*p++ - '0'); } while (*p == ' ') { p++; } @@ -355,7 +355,7 @@ ngx_http_range_parse(ngx_http_request_t *r, ngx_http_range_filter_ctx_t *ctx, } if (suffix) { - start = content_length - end; + start = (end < content_length) ? content_length - end : 0; end = content_length - 1; } @@ -377,11 +377,18 @@ ngx_http_range_parse(ngx_http_request_t *r, ngx_http_range_filter_ctx_t *ctx, range->start = start; range->end = end; + if (size > NGX_MAX_OFF_T_VALUE - (end - start)) { + return NGX_HTTP_RANGE_NOT_SATISFIABLE; + } + size += end - start; if (ranges-- == 0) { return NGX_DECLINED; } + + } else if (start == 0) { + return NGX_DECLINED; } if (*p++ != ',') { @@ -425,6 +432,8 @@ ngx_http_range_singlepart_header(ngx_http_request_t *r, content_range->value.data = ngx_pnalloc(r->pool, sizeof("bytes -/") - 1 + 3 * NGX_OFF_T_LEN); if (content_range->value.data == NULL) { + content_range->hash = 0; + r->headers_out.content_range = NULL; return NGX_ERROR; } @@ -454,23 +463,24 @@ static ngx_int_t ngx_http_range_multipart_header(ngx_http_request_t *r, ngx_http_range_filter_ctx_t *ctx) { - size_t len; + off_t len; + size_t size; ngx_uint_t i; ngx_http_range_t *range; ngx_atomic_uint_t boundary; - len = sizeof(CRLF "--") - 1 + NGX_ATOMIC_T_LEN - + sizeof(CRLF "Content-Type: ") - 1 - + r->headers_out.content_type.len - + sizeof(CRLF "Content-Range: bytes ") - 1; + size = sizeof(CRLF "--") - 1 + NGX_ATOMIC_T_LEN + + sizeof(CRLF "Content-Type: ") - 1 + + r->headers_out.content_type.len + + sizeof(CRLF "Content-Range: bytes ") - 1; if (r->headers_out.content_type_len == r->headers_out.content_type.len && r->headers_out.charset.len) { - len += sizeof("; charset=") - 1 + r->headers_out.charset.len; + size += sizeof("; charset=") - 1 + r->headers_out.charset.len; } - ctx->boundary_header.data = ngx_pnalloc(r->pool, len); + ctx->boundary_header.data = ngx_pnalloc(r->pool, size); if (ctx->boundary_header.data == NULL) { return NGX_ERROR; } @@ -560,7 +570,7 @@ ngx_http_range_multipart_header(ngx_http_request_t *r, - range[i].content_range.data; len += ctx->boundary_header.len + range[i].content_range.len - + (size_t) (range[i].end - range[i].start); + + (range[i].end - range[i].start); } r->headers_out.content_length_n = len; @@ -594,6 +604,8 @@ ngx_http_range_not_satisfiable(ngx_http_request_t *r) content_range->value.data = ngx_pnalloc(r->pool, sizeof("bytes */") - 1 + NGX_OFF_T_LEN); if (content_range->value.data == NULL) { + content_range->hash = 0; + r->headers_out.content_range = NULL; return NGX_ERROR; } diff --git a/src/http/modules/ngx_http_realip_module.c b/src/http/modules/ngx_http_realip_module.c index 5e3355c9671..7d3f2a91d17 100644 --- a/src/http/modules/ngx_http_realip_module.c +++ b/src/http/modules/ngx_http_realip_module.c @@ -122,7 +122,7 @@ static ngx_http_variable_t ngx_http_realip_vars[] = { { ngx_string("realip_remote_port"), NULL, ngx_http_realip_remote_port_variable, 0, 0, 0 }, - { ngx_null_string, NULL, NULL, 0, 0, 0 } + ngx_http_null_variable }; @@ -317,9 +317,15 @@ ngx_http_realip_from(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { ngx_http_realip_loc_conf_t *rlcf = conf; - ngx_int_t rc; - ngx_str_t *value; - ngx_cidr_t *cidr; + ngx_int_t rc; + ngx_str_t *value; + ngx_url_t u; + ngx_cidr_t c, *cidr; + ngx_uint_t i; + struct sockaddr_in *sin; +#if (NGX_HAVE_INET6) + struct sockaddr_in6 *sin6; +#endif value = cf->args->elts; @@ -331,31 +337,78 @@ ngx_http_realip_from(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) } } - cidr = ngx_array_push(rlcf->from); - if (cidr == NULL) { - return NGX_CONF_ERROR; - } - #if (NGX_HAVE_UNIX_DOMAIN) if (ngx_strcmp(value[1].data, "unix:") == 0) { + cidr = ngx_array_push(rlcf->from); + if (cidr == NULL) { + return NGX_CONF_ERROR; + } + cidr->family = AF_UNIX; return NGX_CONF_OK; } #endif - rc = ngx_ptocidr(&value[1], cidr); + rc = ngx_ptocidr(&value[1], &c); + + if (rc != NGX_ERROR) { + if (rc == NGX_DONE) { + ngx_conf_log_error(NGX_LOG_WARN, cf, 0, + "low address bits of %V are meaningless", + &value[1]); + } + + cidr = ngx_array_push(rlcf->from); + if (cidr == NULL) { + return NGX_CONF_ERROR; + } + + *cidr = c; + + return NGX_CONF_OK; + } + + ngx_memzero(&u, sizeof(ngx_url_t)); + u.host = value[1]; + + if (ngx_inet_resolve_host(cf->pool, &u) != NGX_OK) { + if (u.err) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "%s in set_real_ip_from \"%V\"", + u.err, &u.host); + } - if (rc == NGX_ERROR) { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid parameter \"%V\"", - &value[1]); return NGX_CONF_ERROR; } - if (rc == NGX_DONE) { - ngx_conf_log_error(NGX_LOG_WARN, cf, 0, - "low address bits of %V are meaningless", &value[1]); + cidr = ngx_array_push_n(rlcf->from, u.naddrs); + if (cidr == NULL) { + return NGX_CONF_ERROR; + } + + ngx_memzero(cidr, u.naddrs * sizeof(ngx_cidr_t)); + + for (i = 0; i < u.naddrs; i++) { + cidr[i].family = u.addrs[i].sockaddr->sa_family; + + switch (cidr[i].family) { + +#if (NGX_HAVE_INET6) + case AF_INET6: + sin6 = (struct sockaddr_in6 *) u.addrs[i].sockaddr; + cidr[i].u.in6.addr = sin6->sin6_addr; + ngx_memset(cidr[i].u.in6.mask.s6_addr, 0xff, 16); + break; +#endif + + default: /* AF_INET */ + sin = (struct sockaddr_in *) u.addrs[i].sockaddr; + cidr[i].u.in.addr = sin->sin_addr.s_addr; + cidr[i].u.in.mask = 0xffffffff; + break; + } } return NGX_CONF_OK; diff --git a/src/http/modules/ngx_http_referer_module.c b/src/http/modules/ngx_http_referer_module.c index 3f0f78e1154..599dd3a1297 100644 --- a/src/http/modules/ngx_http_referer_module.c +++ b/src/http/modules/ngx_http_referer_module.c @@ -32,6 +32,7 @@ typedef struct { } ngx_http_referer_conf_t; +static ngx_int_t ngx_http_referer_add_variables(ngx_conf_t *cf); static void * ngx_http_referer_create_conf(ngx_conf_t *cf); static char * ngx_http_referer_merge_conf(ngx_conf_t *cf, void *parent, void *child); @@ -77,7 +78,7 @@ static ngx_command_t ngx_http_referer_commands[] = { static ngx_http_module_t ngx_http_referer_module_ctx = { - NULL, /* preconfiguration */ + ngx_http_referer_add_variables, /* preconfiguration */ NULL, /* postconfiguration */ NULL, /* create main configuration */ @@ -107,6 +108,9 @@ ngx_module_t ngx_http_referer_module = { }; +static ngx_str_t ngx_http_invalid_referer_name = ngx_string("invalid_referer"); + + static ngx_int_t ngx_http_referer_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data) @@ -263,6 +267,23 @@ ngx_http_referer_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v, } +static ngx_int_t +ngx_http_referer_add_variables(ngx_conf_t *cf) +{ + ngx_http_variable_t *var; + + var = ngx_http_add_variable(cf, &ngx_http_invalid_referer_name, + NGX_HTTP_VAR_CHANGEABLE); + if (var == NULL) { + return NGX_ERROR; + } + + var->get_handler = ngx_http_referer_variable; + + return NGX_OK; +} + + static void * ngx_http_referer_create_conf(ngx_conf_t *cf) { @@ -452,19 +473,9 @@ ngx_http_valid_referers(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { ngx_http_referer_conf_t *rlcf = conf; - u_char *p; - ngx_str_t *value, uri, name; - ngx_uint_t i; - ngx_http_variable_t *var; - - ngx_str_set(&name, "invalid_referer"); - - var = ngx_http_add_variable(cf, &name, NGX_HTTP_VAR_CHANGEABLE); - if (var == NULL) { - return NGX_CONF_ERROR; - } - - var->get_handler = ngx_http_referer_variable; + u_char *p; + ngx_str_t *value, uri; + ngx_uint_t i; if (rlcf->keys == NULL) { rlcf->keys = ngx_pcalloc(cf->temp_pool, sizeof(ngx_hash_keys_arrays_t)); diff --git a/src/http/modules/ngx_http_rewrite_module.c b/src/http/modules/ngx_http_rewrite_module.c index 6b2444cbde4..a6f1fc820d4 100644 --- a/src/http/modules/ngx_http_rewrite_module.c +++ b/src/http/modules/ngx_http_rewrite_module.c @@ -917,7 +917,8 @@ ngx_http_rewrite_set(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) value[1].len--; value[1].data++; - v = ngx_http_add_variable(cf, &value[1], NGX_HTTP_VAR_CHANGEABLE); + v = ngx_http_add_variable(cf, &value[1], + NGX_HTTP_VAR_CHANGEABLE|NGX_HTTP_VAR_WEAK); if (v == NULL) { return NGX_CONF_ERROR; } @@ -927,15 +928,7 @@ ngx_http_rewrite_set(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) return NGX_CONF_ERROR; } - if (v->get_handler == NULL - && ngx_strncasecmp(value[1].data, (u_char *) "http_", 5) != 0 - && ngx_strncasecmp(value[1].data, (u_char *) "sent_http_", 10) != 0 - && ngx_strncasecmp(value[1].data, (u_char *) "upstream_http_", 14) != 0 - && ngx_strncasecmp(value[1].data, (u_char *) "cookie_", 7) != 0 - && ngx_strncasecmp(value[1].data, (u_char *) "upstream_cookie_", 16) - != 0 - && ngx_strncasecmp(value[1].data, (u_char *) "arg_", 4) != 0) - { + if (v->get_handler == NULL) { v->get_handler = ngx_http_rewrite_var; v->data = index; } diff --git a/src/http/modules/ngx_http_scgi_module.c b/src/http/modules/ngx_http_scgi_module.c index 5a18f557e64..3fb227b28cd 100644 --- a/src/http/modules/ngx_http_scgi_module.c +++ b/src/http/modules/ngx_http_scgi_module.c @@ -82,6 +82,7 @@ static ngx_conf_bitmask_t ngx_http_scgi_next_upstream_masks[] = { { ngx_string("http_503"), NGX_HTTP_UPSTREAM_FT_HTTP_503 }, { ngx_string("http_403"), NGX_HTTP_UPSTREAM_FT_HTTP_403 }, { ngx_string("http_404"), NGX_HTTP_UPSTREAM_FT_HTTP_404 }, + { ngx_string("http_429"), NGX_HTTP_UPSTREAM_FT_HTTP_429 }, { ngx_string("updating"), NGX_HTTP_UPSTREAM_FT_UPDATING }, { ngx_string("off"), NGX_HTTP_UPSTREAM_FT_OFF }, { ngx_null_string, 0 } @@ -270,6 +271,13 @@ static ngx_command_t ngx_http_scgi_commands[] = { offsetof(ngx_http_scgi_loc_conf_t, upstream.cache_min_uses), NULL }, + { ngx_string("scgi_cache_max_range_offset"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_conf_set_off_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_scgi_loc_conf_t, upstream.cache_max_range_offset), + NULL }, + { ngx_string("scgi_cache_use_stale"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE, ngx_conf_set_bitmask_slot, @@ -312,6 +320,13 @@ static ngx_command_t ngx_http_scgi_commands[] = { offsetof(ngx_http_scgi_loc_conf_t, upstream.cache_revalidate), NULL }, + { ngx_string("scgi_cache_background_update"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, + ngx_conf_set_flag_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_scgi_loc_conf_t, upstream.cache_background_update), + NULL }, + #endif { ngx_string("scgi_temp_path"), @@ -804,7 +819,7 @@ ngx_http_scgi_create_request(ngx_http_request_t *r) key = e.pos; #endif code = *(ngx_http_script_code_pt *) e.ip; - code((ngx_http_script_engine_t *) & e); + code((ngx_http_script_engine_t *) &e); #if (NGX_DEBUG) val = e.pos; @@ -1025,6 +1040,7 @@ ngx_http_scgi_process_header(ngx_http_request_t *r) h->key.len + 1 + h->value.len + 1 + h->key.len); if (h->key.data == NULL) { + h->hash = 0; return NGX_ERROR; } @@ -1204,6 +1220,7 @@ ngx_http_scgi_create_loc_conf(ngx_conf_t *cf) #if (NGX_HTTP_CACHE) conf->upstream.cache = NGX_CONF_UNSET; conf->upstream.cache_min_uses = NGX_CONF_UNSET_UINT; + conf->upstream.cache_max_range_offset = NGX_CONF_UNSET; conf->upstream.cache_bypass = NGX_CONF_UNSET_PTR; conf->upstream.no_cache = NGX_CONF_UNSET_PTR; conf->upstream.cache_valid = NGX_CONF_UNSET_PTR; @@ -1211,6 +1228,7 @@ ngx_http_scgi_create_loc_conf(ngx_conf_t *cf) conf->upstream.cache_lock_timeout = NGX_CONF_UNSET_MSEC; conf->upstream.cache_lock_age = NGX_CONF_UNSET_MSEC; conf->upstream.cache_revalidate = NGX_CONF_UNSET; + conf->upstream.cache_background_update = NGX_CONF_UNSET; #endif conf->upstream.hide_headers = NGX_CONF_UNSET_PTR; @@ -1444,6 +1462,10 @@ ngx_http_scgi_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) ngx_conf_merge_uint_value(conf->upstream.cache_min_uses, prev->upstream.cache_min_uses, 1); + ngx_conf_merge_off_value(conf->upstream.cache_max_range_offset, + prev->upstream.cache_max_range_offset, + NGX_MAX_OFF_T_VALUE); + ngx_conf_merge_bitmask_value(conf->upstream.cache_use_stale, prev->upstream.cache_use_stale, (NGX_CONF_BITMASK_SET @@ -1494,6 +1516,9 @@ ngx_http_scgi_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) ngx_conf_merge_value(conf->upstream.cache_revalidate, prev->upstream.cache_revalidate, 0); + ngx_conf_merge_value(conf->upstream.cache_background_update, + prev->upstream.cache_background_update, 0); + #endif ngx_conf_merge_value(conf->upstream.pass_request_headers, diff --git a/src/http/modules/ngx_http_secure_link_module.c b/src/http/modules/ngx_http_secure_link_module.c index 907ba6ef50c..536e09a7268 100644 --- a/src/http/modules/ngx_http_secure_link_module.c +++ b/src/http/modules/ngx_http_secure_link_module.c @@ -107,7 +107,7 @@ ngx_http_secure_link_variable(ngx_http_request_t *r, ngx_md5_t md5; ngx_http_secure_link_ctx_t *ctx; ngx_http_secure_link_conf_t *conf; - u_char hash_buf[16], md5_buf[16]; + u_char hash_buf[18], md5_buf[16]; conf = ngx_http_get_module_loc_conf(r, ngx_http_secure_link_module); @@ -154,7 +154,6 @@ ngx_http_secure_link_variable(ngx_http_request_t *r, goto not_found; } - hash.len = 16; hash.data = hash_buf; if (ngx_decode_base64url(&hash, &val) != NGX_OK) { diff --git a/src/http/modules/ngx_http_slice_filter_module.c b/src/http/modules/ngx_http_slice_filter_module.c index 5e149b4c189..c1edbca2b6b 100644 --- a/src/http/modules/ngx_http_slice_filter_module.c +++ b/src/http/modules/ngx_http_slice_filter_module.c @@ -11,23 +11,25 @@ typedef struct { - size_t size; + size_t size; } ngx_http_slice_loc_conf_t; typedef struct { - off_t start; - off_t end; - ngx_str_t range; - ngx_str_t etag; - ngx_uint_t last; /* unsigned last:1; */ + off_t start; + off_t end; + ngx_str_t range; + ngx_str_t etag; + unsigned last:1; + unsigned active:1; + ngx_http_request_t *sr; } ngx_http_slice_ctx_t; typedef struct { - off_t start; - off_t end; - off_t complete_length; + off_t start; + off_t end; + off_t complete_length; } ngx_http_slice_content_range_t; @@ -169,6 +171,7 @@ ngx_http_slice_header_filter(ngx_http_request_t *r) } ctx->start = end; + ctx->active = 1; r->headers_out.status = NGX_HTTP_OK; r->headers_out.status_line.len = 0; @@ -187,6 +190,8 @@ ngx_http_slice_header_filter(ngx_http_request_t *r) return rc; } + r->preserve_body = 1; + if (r->headers_out.status == NGX_HTTP_PARTIAL_CONTENT) { if (ctx->start + (off_t) slcf->size <= r->headers_out.content_offset) { ctx->start = slcf->size @@ -209,7 +214,6 @@ ngx_http_slice_body_filter(ngx_http_request_t *r, ngx_chain_t *in) { ngx_int_t rc; ngx_chain_t *cl; - ngx_http_request_t *sr; ngx_http_slice_ctx_t *ctx; ngx_http_slice_loc_conf_t *slcf; @@ -234,6 +238,16 @@ ngx_http_slice_body_filter(ngx_http_request_t *r, ngx_chain_t *in) return rc; } + if (ctx->sr && !ctx->sr->done) { + return rc; + } + + if (!ctx->active) { + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "missing slice response"); + return NGX_ERROR; + } + if (ctx->start >= ctx->end) { ngx_http_set_ctx(r, NULL, ngx_http_slice_filter_module); ngx_http_send_special(r, NGX_HTTP_LAST); @@ -244,11 +258,14 @@ ngx_http_slice_body_filter(ngx_http_request_t *r, ngx_chain_t *in) return rc; } - if (ngx_http_subrequest(r, &r->uri, &r->args, &sr, NULL, 0) != NGX_OK) { + if (ngx_http_subrequest(r, &r->uri, &r->args, &ctx->sr, NULL, + NGX_HTTP_SUBREQUEST_CLONE) + != NGX_OK) + { return NGX_ERROR; } - ngx_http_set_ctx(sr, ctx, ngx_http_slice_filter_module); + ngx_http_set_ctx(ctx->sr, ctx, ngx_http_slice_filter_module); slcf = ngx_http_get_module_loc_conf(r, ngx_http_slice_filter_module); @@ -256,6 +273,8 @@ ngx_http_slice_body_filter(ngx_http_request_t *r, ngx_chain_t *in) ctx->start + (off_t) slcf->size - 1) - ctx->range.data; + ctx->active = 0; + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http slice subrequest: \"%V\"", &ctx->range); @@ -300,7 +319,7 @@ ngx_http_slice_parse_content_range(ngx_http_request_t *r, return NGX_ERROR; } - start = start * 10 + *p++ - '0'; + start = start * 10 + (*p++ - '0'); } while (*p == ' ') { p++; } @@ -320,7 +339,7 @@ ngx_http_slice_parse_content_range(ngx_http_request_t *r, return NGX_ERROR; } - end = end * 10 + *p++ - '0'; + end = end * 10 + (*p++ - '0'); } end++; @@ -345,7 +364,7 @@ ngx_http_slice_parse_content_range(ngx_http_request_t *r, return NGX_ERROR; } - complete_length = complete_length * 10 + *p++ - '0'; + complete_length = complete_length * 10 + (*p++ - '0'); } } else { @@ -462,7 +481,7 @@ ngx_http_slice_get_start(ngx_http_request_t *r) return 0; } - start = start * 10 + *p++ - '0'; + start = start * 10 + (*p++ - '0'); } return start; diff --git a/src/http/modules/ngx_http_ssi_filter_module.c b/src/http/modules/ngx_http_ssi_filter_module.c index 6fb1fbe4588..e29e1739bbd 100644 --- a/src/http/modules/ngx_http_ssi_filter_module.c +++ b/src/http/modules/ngx_http_ssi_filter_module.c @@ -321,7 +321,7 @@ static ngx_http_variable_t ngx_http_ssi_vars[] = { { ngx_string("date_gmt"), NULL, ngx_http_ssi_date_gmt_local_variable, 1, NGX_HTTP_VAR_NOCACHEABLE, 0 }, - { ngx_null_string, NULL, NULL, 0, 0, 0 } + ngx_http_null_variable }; @@ -370,6 +370,8 @@ ngx_http_ssi_header_filter(ngx_http_request_t *r) ngx_http_clear_content_length(r); ngx_http_clear_accept_ranges(r); + r->preserve_body = 1; + if (!slcf->last_modified) { ngx_http_clear_last_modified(r); ngx_http_clear_etag(r); @@ -2388,7 +2390,7 @@ ngx_http_ssi_config(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx, ctx->timefmt.len = value->len; ctx->timefmt.data = ngx_pnalloc(r->pool, value->len + 1); if (ctx->timefmt.data == NULL) { - return NGX_HTTP_SSI_ERROR; + return NGX_ERROR; } ngx_cpystrn(ctx->timefmt.data, value->data, value->len + 1); diff --git a/src/http/modules/ngx_http_ssl_module.c b/src/http/modules/ngx_http_ssl_module.c index e75f5d8a367..7d62176e0d2 100644 --- a/src/http/modules/ngx_http_ssl_module.c +++ b/src/http/modules/ngx_http_ssl_module.c @@ -57,6 +57,7 @@ static ngx_conf_bitmask_t ngx_http_ssl_protocols[] = { { ngx_string("TLSv1"), NGX_SSL_TLSv1 }, { ngx_string("TLSv1.1"), NGX_SSL_TLSv1_1 }, { ngx_string("TLSv1.2"), NGX_SSL_TLSv1_2 }, + { ngx_string("TLSv1.3"), NGX_SSL_TLSv1_3 }, { ngx_null_string, 0 } }; @@ -276,6 +277,12 @@ static ngx_http_variable_t ngx_http_ssl_vars[] = { { ngx_string("ssl_cipher"), NULL, ngx_http_ssl_static_variable, (uintptr_t) ngx_ssl_get_cipher_name, NGX_HTTP_VAR_CHANGEABLE, 0 }, + { ngx_string("ssl_ciphers"), NULL, ngx_http_ssl_variable, + (uintptr_t) ngx_ssl_get_ciphers, NGX_HTTP_VAR_CHANGEABLE, 0 }, + + { ngx_string("ssl_curves"), NULL, ngx_http_ssl_variable, + (uintptr_t) ngx_ssl_get_curves, NGX_HTTP_VAR_CHANGEABLE, 0 }, + { ngx_string("ssl_session_id"), NULL, ngx_http_ssl_variable, (uintptr_t) ngx_ssl_get_session_id, NGX_HTTP_VAR_CHANGEABLE, 0 }, @@ -292,6 +299,10 @@ static ngx_http_variable_t ngx_http_ssl_vars[] = { (uintptr_t) ngx_ssl_get_raw_certificate, NGX_HTTP_VAR_CHANGEABLE, 0 }, + { ngx_string("ssl_client_escaped_cert"), NULL, ngx_http_ssl_variable, + (uintptr_t) ngx_ssl_get_escaped_certificate, + NGX_HTTP_VAR_CHANGEABLE, 0 }, + { ngx_string("ssl_client_s_dn"), NULL, ngx_http_ssl_variable, (uintptr_t) ngx_ssl_get_subject_dn, NGX_HTTP_VAR_CHANGEABLE, 0 }, @@ -313,7 +324,16 @@ static ngx_http_variable_t ngx_http_ssl_vars[] = { { ngx_string("ssl_client_verify"), NULL, ngx_http_ssl_variable, (uintptr_t) ngx_ssl_get_client_verify, NGX_HTTP_VAR_CHANGEABLE, 0 }, - { ngx_null_string, NULL, NULL, 0, 0, 0 } + { ngx_string("ssl_client_v_start"), NULL, ngx_http_ssl_variable, + (uintptr_t) ngx_ssl_get_client_v_start, NGX_HTTP_VAR_CHANGEABLE, 0 }, + + { ngx_string("ssl_client_v_end"), NULL, ngx_http_ssl_variable, + (uintptr_t) ngx_ssl_get_client_v_end, NGX_HTTP_VAR_CHANGEABLE, 0 }, + + { ngx_string("ssl_client_v_remain"), NULL, ngx_http_ssl_variable, + (uintptr_t) ngx_ssl_get_client_v_remain, NGX_HTTP_VAR_CHANGEABLE, 0 }, + + ngx_http_null_variable }; diff --git a/src/http/modules/ngx_http_static_module.c b/src/http/modules/ngx_http_static_module.c index f79c4aeeed0..0e16c05a562 100644 --- a/src/http/modules/ngx_http_static_module.c +++ b/src/http/modules/ngx_http_static_module.c @@ -14,7 +14,7 @@ static ngx_int_t ngx_http_static_handler(ngx_http_request_t *r); static ngx_int_t ngx_http_static_init(ngx_conf_t *cf); -ngx_http_module_t ngx_http_static_module_ctx = { +static ngx_http_module_t ngx_http_static_module_ctx = { NULL, /* preconfiguration */ ngx_http_static_init, /* postconfiguration */ @@ -150,7 +150,7 @@ ngx_http_static_handler(ngx_http_request_t *r) ngx_http_clear_location(r); - r->headers_out.location = ngx_palloc(r->pool, sizeof(ngx_table_elt_t)); + r->headers_out.location = ngx_list_push(&r->headers_out.headers); if (r->headers_out.location == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } @@ -169,6 +169,7 @@ ngx_http_static_handler(ngx_http_request_t *r) location = ngx_pnalloc(r->pool, len); if (location == NULL) { + ngx_http_clear_location(r); return NGX_HTTP_INTERNAL_SERVER_ERROR; } @@ -182,11 +183,8 @@ ngx_http_static_handler(ngx_http_request_t *r) } } - /* - * we do not need to set the r->headers_out.location->hash and - * r->headers_out.location->key fields - */ - + r->headers_out.location->hash = 1; + ngx_str_set(&r->headers_out.location->key, "Location"); r->headers_out.location->value.len = len; r->headers_out.location->value.data = location; @@ -236,7 +234,7 @@ ngx_http_static_handler(ngx_http_request_t *r) /* we need to allocate all before the header would be sent */ - b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t)); + b = ngx_calloc_buf(r->pool); if (b == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } diff --git a/src/http/modules/ngx_http_stub_status_module.c b/src/http/modules/ngx_http_stub_status_module.c index 61199f2fbb1..9bdf88129db 100644 --- a/src/http/modules/ngx_http_stub_status_module.c +++ b/src/http/modules/ngx_http_stub_status_module.c @@ -76,7 +76,7 @@ static ngx_http_variable_t ngx_http_stub_status_vars[] = { { ngx_string("connections_waiting"), NULL, ngx_http_stub_status_variable, 3, NGX_HTTP_VAR_NOCACHEABLE, 0 }, - { ngx_null_string, NULL, NULL, 0, 0, 0 } + ngx_http_null_variable }; diff --git a/src/http/modules/ngx_http_sub_filter_module.c b/src/http/modules/ngx_http_sub_filter_module.c index e8d1d801d64..6d3de59b09a 100644 --- a/src/http/modules/ngx_http_sub_filter_module.c +++ b/src/http/modules/ngx_http_sub_filter_module.c @@ -248,8 +248,6 @@ ngx_http_sub_header_filter(ngx_http_request_t *r) ctx->matches->nelts); } - ngx_http_set_ctx(r, ctx, ngx_http_sub_filter_module); - ctx->saved.data = ngx_pnalloc(r->pool, ctx->tables->max_match_len - 1); if (ctx->saved.data == NULL) { return NGX_ERROR; @@ -260,6 +258,8 @@ ngx_http_sub_header_filter(ngx_http_request_t *r) return NGX_ERROR; } + ngx_http_set_ctx(r, ctx, ngx_http_sub_filter_module); + ctx->offset = ctx->tables->min_match_len - 1; ctx->last_out = &ctx->out; @@ -645,7 +645,7 @@ ngx_http_sub_parse(ngx_http_request_t *r, ngx_http_sub_ctx_t *ctx, start = offset - (ngx_int_t) tables->min_match_len + 1; - i = ngx_max(tables->index[c], ctx->index); + i = ngx_max((ngx_uint_t) tables->index[c], ctx->index); j = tables->index[c + 1]; while (i != j) { @@ -978,7 +978,7 @@ ngx_http_sub_init_tables(ngx_http_sub_tables_t *tables, } c = match[i].match.data[tables->min_match_len - 1]; - while (ch <= c) { + while (ch <= (ngx_uint_t) c) { tables->index[ch++] = (u_char) i; } } diff --git a/src/http/modules/ngx_http_try_files_module.c b/src/http/modules/ngx_http_try_files_module.c new file mode 100644 index 00000000000..ce783a24da6 --- /dev/null +++ b/src/http/modules/ngx_http_try_files_module.c @@ -0,0 +1,404 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Nginx, Inc. + */ + + +#include +#include +#include + + +typedef struct { + ngx_array_t *lengths; + ngx_array_t *values; + ngx_str_t name; + + unsigned code:10; + unsigned test_dir:1; +} ngx_http_try_file_t; + + +typedef struct { + ngx_http_try_file_t *try_files; +} ngx_http_try_files_loc_conf_t; + + +static ngx_int_t ngx_http_try_files_handler(ngx_http_request_t *r); +static char *ngx_http_try_files(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); +static void *ngx_http_try_files_create_loc_conf(ngx_conf_t *cf); +static ngx_int_t ngx_http_try_files_init(ngx_conf_t *cf); + + +static ngx_command_t ngx_http_try_files_commands[] = { + + { ngx_string("try_files"), + NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_2MORE, + ngx_http_try_files, + NGX_HTTP_LOC_CONF_OFFSET, + 0, + NULL }, + + ngx_null_command +}; + + +static ngx_http_module_t ngx_http_try_files_module_ctx = { + NULL, /* preconfiguration */ + ngx_http_try_files_init, /* postconfiguration */ + + NULL, /* create main configuration */ + NULL, /* init main configuration */ + + NULL, /* create server configuration */ + NULL, /* merge server configuration */ + + ngx_http_try_files_create_loc_conf, /* create location configuration */ + NULL /* merge location configuration */ +}; + + +ngx_module_t ngx_http_try_files_module = { + NGX_MODULE_V1, + &ngx_http_try_files_module_ctx, /* module context */ + ngx_http_try_files_commands, /* module directives */ + NGX_HTTP_MODULE, /* module type */ + NULL, /* init master */ + NULL, /* 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_try_files_handler(ngx_http_request_t *r) +{ + size_t len, root, alias, reserve, allocated; + u_char *p, *name; + ngx_str_t path, args; + ngx_uint_t test_dir; + ngx_http_try_file_t *tf; + ngx_open_file_info_t of; + ngx_http_script_code_pt code; + ngx_http_script_engine_t e; + ngx_http_core_loc_conf_t *clcf; + ngx_http_script_len_code_pt lcode; + ngx_http_try_files_loc_conf_t *tlcf; + + tlcf = ngx_http_get_module_loc_conf(r, ngx_http_try_files_module); + + if (tlcf->try_files == NULL) { + return NGX_DECLINED; + } + + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "try files handler"); + + allocated = 0; + root = 0; + name = NULL; + /* suppress MSVC warning */ + path.data = NULL; + + tf = tlcf->try_files; + + clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); + + alias = clcf->alias; + + for ( ;; ) { + + if (tf->lengths) { + ngx_memzero(&e, sizeof(ngx_http_script_engine_t)); + + e.ip = tf->lengths->elts; + e.request = r; + + /* 1 is for terminating '\0' as in static names */ + len = 1; + + while (*(uintptr_t *) e.ip) { + lcode = *(ngx_http_script_len_code_pt *) e.ip; + len += lcode(&e); + } + + } else { + len = tf->name.len; + } + + if (!alias) { + reserve = len > r->uri.len ? len - r->uri.len : 0; + + } else if (alias == NGX_MAX_SIZE_T_VALUE) { + reserve = len; + + } else { + reserve = len > r->uri.len - alias ? len - (r->uri.len - alias) : 0; + } + + if (reserve > allocated || !allocated) { + + /* 16 bytes are preallocation */ + allocated = reserve + 16; + + if (ngx_http_map_uri_to_path(r, &path, &root, allocated) == NULL) { + return NGX_HTTP_INTERNAL_SERVER_ERROR; + } + + name = path.data + root; + } + + if (tf->values == NULL) { + + /* tf->name.len includes the terminating '\0' */ + + ngx_memcpy(name, tf->name.data, tf->name.len); + + path.len = (name + tf->name.len - 1) - path.data; + + } else { + e.ip = tf->values->elts; + e.pos = name; + e.flushed = 1; + + while (*(uintptr_t *) e.ip) { + code = *(ngx_http_script_code_pt *) e.ip; + code((ngx_http_script_engine_t *) &e); + } + + path.len = e.pos - path.data; + + *e.pos = '\0'; + + if (alias && alias != NGX_MAX_SIZE_T_VALUE + && ngx_strncmp(name, r->uri.data, alias) == 0) + { + ngx_memmove(name, name + alias, len - alias); + path.len -= alias; + } + } + + test_dir = tf->test_dir; + + tf++; + + ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "trying to use %s: \"%s\" \"%s\"", + test_dir ? "dir" : "file", name, path.data); + + if (tf->lengths == NULL && tf->name.len == 0) { + + if (tf->code) { + return tf->code; + } + + path.len -= root; + path.data += root; + + if (path.data[0] == '@') { + (void) ngx_http_named_location(r, &path); + + } else { + ngx_http_split_args(r, &path, &args); + + (void) ngx_http_internal_redirect(r, &path, &args); + } + + ngx_http_finalize_request(r, NGX_DONE); + return NGX_DONE; + } + + ngx_memzero(&of, sizeof(ngx_open_file_info_t)); + + of.read_ahead = clcf->read_ahead; + of.directio = clcf->directio; + of.valid = clcf->open_file_cache_valid; + of.min_uses = clcf->open_file_cache_min_uses; + of.test_only = 1; + of.errors = clcf->open_file_cache_errors; + of.events = clcf->open_file_cache_events; + + if (ngx_http_set_disable_symlinks(r, clcf, &path, &of) != NGX_OK) { + return NGX_HTTP_INTERNAL_SERVER_ERROR; + } + + if (ngx_open_cached_file(clcf->open_file_cache, &path, &of, r->pool) + != NGX_OK) + { + if (of.err == 0) { + return NGX_HTTP_INTERNAL_SERVER_ERROR; + } + + if (of.err != NGX_ENOENT + && of.err != NGX_ENOTDIR + && of.err != NGX_ENAMETOOLONG) + { + ngx_log_error(NGX_LOG_CRIT, r->connection->log, of.err, + "%s \"%s\" failed", of.failed, path.data); + } + + continue; + } + + if (of.is_dir != test_dir) { + continue; + } + + path.len -= root; + path.data += root; + + if (!alias) { + r->uri = path; + + } else if (alias == NGX_MAX_SIZE_T_VALUE) { + if (!test_dir) { + r->uri = path; + r->add_uri_to_alias = 1; + } + + } else { + name = r->uri.data; + + r->uri.len = alias + path.len; + r->uri.data = ngx_pnalloc(r->pool, r->uri.len); + if (r->uri.data == NULL) { + r->uri.len = 0; + return NGX_HTTP_INTERNAL_SERVER_ERROR; + } + + p = ngx_copy(r->uri.data, name, alias); + ngx_memcpy(p, path.data, path.len); + } + + ngx_http_set_exten(r); + + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "try file uri: \"%V\"", &r->uri); + + return NGX_DECLINED; + } + + /* not reached */ +} + + +static char * +ngx_http_try_files(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) +{ + ngx_http_try_files_loc_conf_t *tlcf = conf; + + ngx_str_t *value; + ngx_int_t code; + ngx_uint_t i, n; + ngx_http_try_file_t *tf; + ngx_http_script_compile_t sc; + + if (tlcf->try_files) { + return "is duplicate"; + } + + tf = ngx_pcalloc(cf->pool, cf->args->nelts * sizeof(ngx_http_try_file_t)); + if (tf == NULL) { + return NGX_CONF_ERROR; + } + + tlcf->try_files = tf; + + value = cf->args->elts; + + for (i = 0; i < cf->args->nelts - 1; i++) { + + tf[i].name = value[i + 1]; + + if (tf[i].name.len > 0 + && tf[i].name.data[tf[i].name.len - 1] == '/' + && i + 2 < cf->args->nelts) + { + tf[i].test_dir = 1; + tf[i].name.len--; + tf[i].name.data[tf[i].name.len] = '\0'; + } + + n = ngx_http_script_variables_count(&tf[i].name); + + if (n) { + ngx_memzero(&sc, sizeof(ngx_http_script_compile_t)); + + sc.cf = cf; + sc.source = &tf[i].name; + sc.lengths = &tf[i].lengths; + sc.values = &tf[i].values; + sc.variables = n; + sc.complete_lengths = 1; + sc.complete_values = 1; + + if (ngx_http_script_compile(&sc) != NGX_OK) { + return NGX_CONF_ERROR; + } + + } else { + /* add trailing '\0' to length */ + tf[i].name.len++; + } + } + + if (tf[i - 1].name.data[0] == '=') { + + code = ngx_atoi(tf[i - 1].name.data + 1, tf[i - 1].name.len - 2); + + if (code == NGX_ERROR || code > 999) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "invalid code \"%*s\"", + tf[i - 1].name.len - 1, tf[i - 1].name.data); + return NGX_CONF_ERROR; + } + + tf[i].code = code; + } + + return NGX_CONF_OK; +} + + +static void * +ngx_http_try_files_create_loc_conf(ngx_conf_t *cf) +{ + ngx_http_try_files_loc_conf_t *tlcf; + + tlcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_try_files_loc_conf_t)); + if (tlcf == NULL) { + return NULL; + } + + /* + * set by ngx_pcalloc(): + * + * tlcf->try_files = NULL; + */ + + return tlcf; +} + + +static ngx_int_t +ngx_http_try_files_init(ngx_conf_t *cf) +{ + ngx_http_handler_pt *h; + ngx_http_core_main_conf_t *cmcf; + + cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module); + + h = ngx_array_push(&cmcf->phases[NGX_HTTP_PRECONTENT_PHASE].handlers); + if (h == NULL) { + return NGX_ERROR; + } + + *h = ngx_http_try_files_handler; + + return NGX_OK; +} diff --git a/src/http/modules/ngx_http_upstream_hash_module.c b/src/http/modules/ngx_http_upstream_hash_module.c index 6c28c6456e9..d67f34d58e5 100644 --- a/src/http/modules/ngx_http_upstream_hash_module.c +++ b/src/http/modules/ngx_http_upstream_hash_module.c @@ -503,6 +503,11 @@ ngx_http_upstream_get_chash_peer(ngx_peer_connection_t *pc, void *data) ngx_http_upstream_rr_peers_wlock(hp->rrp.peers); + if (hp->tries > 20 || hp->rrp.peers->single) { + ngx_http_upstream_rr_peers_unlock(hp->rrp.peers); + return hp->get_rr_peer(pc, &hp->rrp); + } + pc->cached = 0; pc->connection = NULL; @@ -538,13 +543,6 @@ ngx_http_upstream_get_chash_peer(ngx_peer_connection_t *pc, void *data) continue; } - if (peer->server.len != server->len - || ngx_strncmp(peer->server.data, server->data, server->len) - != 0) - { - continue; - } - if (peer->max_fails && peer->fails >= peer->max_fails && now - peer->checked <= peer->fail_timeout) @@ -556,6 +554,13 @@ ngx_http_upstream_get_chash_peer(ngx_peer_connection_t *pc, void *data) continue; } + if (peer->server.len != server->len + || ngx_strncmp(peer->server.data, server->data, server->len) + != 0) + { + continue; + } + peer->current_weight += peer->effective_weight; total += peer->effective_weight; @@ -577,10 +582,9 @@ ngx_http_upstream_get_chash_peer(ngx_peer_connection_t *pc, void *data) hp->hash++; hp->tries++; - if (hp->tries >= points->number) { - pc->name = hp->rrp.peers->name; + if (hp->tries > 20) { ngx_http_upstream_rr_peers_unlock(hp->rrp.peers); - return NGX_BUSY; + return hp->get_rr_peer(pc, &hp->rrp); } } diff --git a/src/http/modules/ngx_http_upstream_zone_module.c b/src/http/modules/ngx_http_upstream_zone_module.c index 7e5bd74764e..3229cfe84a4 100644 --- a/src/http/modules/ngx_http_upstream_zone_module.c +++ b/src/http/modules/ngx_http_upstream_zone_module.c @@ -16,6 +16,8 @@ static ngx_int_t ngx_http_upstream_init_zone(ngx_shm_zone_t *shm_zone, void *data); static ngx_http_upstream_rr_peers_t *ngx_http_upstream_zone_copy_peers( ngx_slab_pool_t *shpool, ngx_http_upstream_srv_conf_t *uscf); +static ngx_http_upstream_rr_peer_t *ngx_http_upstream_zone_copy_peer( + ngx_http_upstream_rr_peers_t *peers, ngx_http_upstream_rr_peer_t *src); static ngx_command_t ngx_http_upstream_zone_commands[] = { @@ -185,6 +187,7 @@ static ngx_http_upstream_rr_peers_t * ngx_http_upstream_zone_copy_peers(ngx_slab_pool_t *shpool, ngx_http_upstream_srv_conf_t *uscf) { + ngx_str_t *name; ngx_http_upstream_rr_peer_t *peer, **peerp; ngx_http_upstream_rr_peers_t *peers, *backup; @@ -195,18 +198,30 @@ ngx_http_upstream_zone_copy_peers(ngx_slab_pool_t *shpool, ngx_memcpy(peers, uscf->peer.data, sizeof(ngx_http_upstream_rr_peers_t)); + name = ngx_slab_alloc(shpool, sizeof(ngx_str_t)); + if (name == NULL) { + return NULL; + } + + name->data = ngx_slab_alloc(shpool, peers->name->len); + if (name->data == NULL) { + return NULL; + } + + ngx_memcpy(name->data, peers->name->data, peers->name->len); + name->len = peers->name->len; + + peers->name = name; + peers->shpool = shpool; for (peerp = &peers->peer; *peerp; peerp = &peer->next) { /* pool is unlocked */ - peer = ngx_slab_calloc_locked(shpool, - sizeof(ngx_http_upstream_rr_peer_t)); + peer = ngx_http_upstream_zone_copy_peer(peers, *peerp); if (peer == NULL) { return NULL; } - ngx_memcpy(peer, *peerp, sizeof(ngx_http_upstream_rr_peer_t)); - *peerp = peer; } @@ -221,18 +236,17 @@ ngx_http_upstream_zone_copy_peers(ngx_slab_pool_t *shpool, ngx_memcpy(backup, peers->next, sizeof(ngx_http_upstream_rr_peers_t)); + backup->name = name; + backup->shpool = shpool; for (peerp = &backup->peer; *peerp; peerp = &peer->next) { /* pool is unlocked */ - peer = ngx_slab_calloc_locked(shpool, - sizeof(ngx_http_upstream_rr_peer_t)); + peer = ngx_http_upstream_zone_copy_peer(backup, *peerp); if (peer == NULL) { return NULL; } - ngx_memcpy(peer, *peerp, sizeof(ngx_http_upstream_rr_peer_t)); - *peerp = peer; } @@ -244,3 +258,68 @@ ngx_http_upstream_zone_copy_peers(ngx_slab_pool_t *shpool, return peers; } + + +static ngx_http_upstream_rr_peer_t * +ngx_http_upstream_zone_copy_peer(ngx_http_upstream_rr_peers_t *peers, + ngx_http_upstream_rr_peer_t *src) +{ + ngx_slab_pool_t *pool; + ngx_http_upstream_rr_peer_t *dst; + + pool = peers->shpool; + + dst = ngx_slab_calloc_locked(pool, sizeof(ngx_http_upstream_rr_peer_t)); + if (dst == NULL) { + return NULL; + } + + if (src) { + ngx_memcpy(dst, src, sizeof(ngx_http_upstream_rr_peer_t)); + dst->sockaddr = NULL; + dst->name.data = NULL; + dst->server.data = NULL; + } + + dst->sockaddr = ngx_slab_calloc_locked(pool, sizeof(ngx_sockaddr_t)); + if (dst->sockaddr == NULL) { + goto failed; + } + + dst->name.data = ngx_slab_calloc_locked(pool, NGX_SOCKADDR_STRLEN); + if (dst->name.data == NULL) { + goto failed; + } + + if (src) { + ngx_memcpy(dst->sockaddr, src->sockaddr, src->socklen); + ngx_memcpy(dst->name.data, src->name.data, src->name.len); + + dst->server.data = ngx_slab_alloc_locked(pool, src->server.len); + if (dst->server.data == NULL) { + goto failed; + } + + ngx_memcpy(dst->server.data, src->server.data, src->server.len); + } + + return dst; + +failed: + + if (dst->server.data) { + ngx_slab_free_locked(pool, dst->server.data); + } + + if (dst->name.data) { + ngx_slab_free_locked(pool, dst->name.data); + } + + if (dst->sockaddr) { + ngx_slab_free_locked(pool, dst->sockaddr); + } + + ngx_slab_free_locked(pool, dst); + + return NULL; +} diff --git a/src/http/modules/ngx_http_userid_filter_module.c b/src/http/modules/ngx_http_userid_filter_module.c index 0dbacba087c..a1a54936bd6 100644 --- a/src/http/modules/ngx_http_userid_filter_module.c +++ b/src/http/modules/ngx_http_userid_filter_module.c @@ -472,6 +472,10 @@ ngx_http_userid_create_uid(ngx_http_request_t *r, ngx_http_userid_ctx_t *ctx, vv = ngx_http_get_indexed_variable(r, ngx_http_userid_reset_index); + if (vv == NULL || vv->not_found) { + return NGX_ERROR; + } + if (vv->len == 0 || (vv->len == 1 && vv->data[0] == '0')) { if (conf->mark == '\0' diff --git a/src/http/modules/ngx_http_uwsgi_module.c b/src/http/modules/ngx_http_uwsgi_module.c index fa2248e3bf2..124da4db56f 100644 --- a/src/http/modules/ngx_http_uwsgi_module.c +++ b/src/http/modules/ngx_http_uwsgi_module.c @@ -114,6 +114,7 @@ static ngx_conf_bitmask_t ngx_http_uwsgi_next_upstream_masks[] = { { ngx_string("http_503"), NGX_HTTP_UPSTREAM_FT_HTTP_503 }, { ngx_string("http_403"), NGX_HTTP_UPSTREAM_FT_HTTP_403 }, { ngx_string("http_404"), NGX_HTTP_UPSTREAM_FT_HTTP_404 }, + { ngx_string("http_429"), NGX_HTTP_UPSTREAM_FT_HTTP_429 }, { ngx_string("updating"), NGX_HTTP_UPSTREAM_FT_UPDATING }, { ngx_string("off"), NGX_HTTP_UPSTREAM_FT_OFF }, { ngx_null_string, 0 } @@ -128,6 +129,7 @@ static ngx_conf_bitmask_t ngx_http_uwsgi_ssl_protocols[] = { { ngx_string("TLSv1"), NGX_SSL_TLSv1 }, { ngx_string("TLSv1.1"), NGX_SSL_TLSv1_1 }, { ngx_string("TLSv1.2"), NGX_SSL_TLSv1_2 }, + { ngx_string("TLSv1.3"), NGX_SSL_TLSv1_3 }, { ngx_null_string, 0 } }; @@ -330,6 +332,13 @@ static ngx_command_t ngx_http_uwsgi_commands[] = { offsetof(ngx_http_uwsgi_loc_conf_t, upstream.cache_min_uses), NULL }, + { ngx_string("uwsgi_cache_max_range_offset"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_conf_set_off_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_uwsgi_loc_conf_t, upstream.cache_max_range_offset), + NULL }, + { ngx_string("uwsgi_cache_use_stale"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE, ngx_conf_set_bitmask_slot, @@ -372,6 +381,13 @@ static ngx_command_t ngx_http_uwsgi_commands[] = { offsetof(ngx_http_uwsgi_loc_conf_t, upstream.cache_revalidate), NULL }, + { ngx_string("uwsgi_cache_background_update"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_conf_set_flag_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_uwsgi_loc_conf_t, upstream.cache_background_update), + NULL }, + #endif { ngx_string("uwsgi_temp_path"), @@ -849,7 +865,7 @@ ngx_http_uwsgi_create_request(ngx_http_request_t *r) lcode = *(ngx_http_script_len_code_pt *) le.ip; skip_empty = lcode(&le); - for (val_len = 0; *(uintptr_t *) le.ip; val_len += lcode (&le)) { + for (val_len = 0; *(uintptr_t *) le.ip; val_len += lcode(&le)) { lcode = *(ngx_http_script_len_code_pt *) le.ip; } le.ip += sizeof(uintptr_t); @@ -974,7 +990,7 @@ ngx_http_uwsgi_create_request(ngx_http_request_t *r) while (*(uintptr_t *) le.ip) { lcode = *(ngx_http_script_len_code_pt *) le.ip; - key_len = (u_char) lcode (&le); + key_len = (u_char) lcode(&le); lcode = *(ngx_http_script_len_code_pt *) le.ip; skip_empty = lcode(&le); @@ -1002,14 +1018,14 @@ ngx_http_uwsgi_create_request(ngx_http_request_t *r) *e.pos++ = (u_char) ((key_len >> 8) & 0xff); code = *(ngx_http_script_code_pt *) e.ip; - code((ngx_http_script_engine_t *) & e); + code((ngx_http_script_engine_t *) &e); *e.pos++ = (u_char) (val_len & 0xff); *e.pos++ = (u_char) ((val_len >> 8) & 0xff); while (*(uintptr_t *) e.ip) { code = *(ngx_http_script_code_pt *) e.ip; - code((ngx_http_script_engine_t *) & e); + code((ngx_http_script_engine_t *) &e); } e.ip += sizeof(uintptr_t); @@ -1228,6 +1244,7 @@ ngx_http_uwsgi_process_header(ngx_http_request_t *r) h->key.len + 1 + h->value.len + 1 + h->key.len); if (h->key.data == NULL) { + h->hash = 0; return NGX_ERROR; } @@ -1410,6 +1427,7 @@ ngx_http_uwsgi_create_loc_conf(ngx_conf_t *cf) #if (NGX_HTTP_CACHE) conf->upstream.cache = NGX_CONF_UNSET; conf->upstream.cache_min_uses = NGX_CONF_UNSET_UINT; + conf->upstream.cache_max_range_offset = NGX_CONF_UNSET; conf->upstream.cache_bypass = NGX_CONF_UNSET_PTR; conf->upstream.no_cache = NGX_CONF_UNSET_PTR; conf->upstream.cache_valid = NGX_CONF_UNSET_PTR; @@ -1417,6 +1435,7 @@ ngx_http_uwsgi_create_loc_conf(ngx_conf_t *cf) conf->upstream.cache_lock_timeout = NGX_CONF_UNSET_MSEC; conf->upstream.cache_lock_age = NGX_CONF_UNSET_MSEC; conf->upstream.cache_revalidate = NGX_CONF_UNSET; + conf->upstream.cache_background_update = NGX_CONF_UNSET; #endif conf->upstream.hide_headers = NGX_CONF_UNSET_PTR; @@ -1658,6 +1677,10 @@ ngx_http_uwsgi_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) ngx_conf_merge_uint_value(conf->upstream.cache_min_uses, prev->upstream.cache_min_uses, 1); + ngx_conf_merge_off_value(conf->upstream.cache_max_range_offset, + prev->upstream.cache_max_range_offset, + NGX_MAX_OFF_T_VALUE); + ngx_conf_merge_bitmask_value(conf->upstream.cache_use_stale, prev->upstream.cache_use_stale, (NGX_CONF_BITMASK_SET @@ -1708,6 +1731,9 @@ ngx_http_uwsgi_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) ngx_conf_merge_value(conf->upstream.cache_revalidate, prev->upstream.cache_revalidate, 0); + ngx_conf_merge_value(conf->upstream.cache_background_update, + prev->upstream.cache_background_update, 0); + #endif ngx_conf_merge_value(conf->upstream.pass_request_headers, diff --git a/src/http/modules/ngx_http_xslt_filter_module.c b/src/http/modules/ngx_http_xslt_filter_module.c index 315081e47bd..fae5895508c 100644 --- a/src/http/modules/ngx_http_xslt_filter_module.c +++ b/src/http/modules/ngx_http_xslt_filter_module.c @@ -109,7 +109,7 @@ static ngx_int_t ngx_http_xslt_filter_init(ngx_conf_t *cf); static void ngx_http_xslt_filter_exit(ngx_cycle_t *cycle); -ngx_str_t ngx_http_xslt_default_types[] = { +static ngx_str_t ngx_http_xslt_default_types[] = { ngx_string("text/xml"), ngx_null_string }; @@ -584,7 +584,7 @@ ngx_http_xslt_apply_stylesheet(ngx_http_request_t *r, return NULL; } - b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t)); + b = ngx_calloc_buf(r->pool); if (b == NULL) { ngx_free(buf); return NULL; diff --git a/src/http/modules/perl/nginx.pm b/src/http/modules/perl/nginx.pm index e3f73611025..d4663dc3b4f 100644 --- a/src/http/modules/perl/nginx.pm +++ b/src/http/modules/perl/nginx.pm @@ -24,6 +24,7 @@ our @EXPORT = qw( HTTP_SEE_OTHER HTTP_NOT_MODIFIED HTTP_TEMPORARY_REDIRECT + HTTP_PERMANENT_REDIRECT HTTP_BAD_REQUEST HTTP_UNAUTHORIZED @@ -72,6 +73,7 @@ use constant HTTP_REDIRECT => 302; use constant HTTP_SEE_OTHER => 303; use constant HTTP_NOT_MODIFIED => 304; use constant HTTP_TEMPORARY_REDIRECT => 307; +use constant HTTP_PERMANENT_REDIRECT => 308; use constant HTTP_BAD_REQUEST => 400; use constant HTTP_UNAUTHORIZED => 401; diff --git a/src/http/modules/perl/nginx.xs b/src/http/modules/perl/nginx.xs index 6716620afc3..ad126328722 100644 --- a/src/http/modules/perl/nginx.xs +++ b/src/http/modules/perl/nginx.xs @@ -510,10 +510,12 @@ header_out(r, key, value) header->hash = 1; if (ngx_http_perl_sv2str(aTHX_ r, &header->key, key) != NGX_OK) { + header->hash = 0; XSRETURN_EMPTY; } if (ngx_http_perl_sv2str(aTHX_ r, &header->value, value) != NGX_OK) { + header->hash = 0; XSRETURN_EMPTY; } @@ -1001,6 +1003,7 @@ sleep(r, sleep, next) ctx->next = SvRV(ST(2)); + r->connection->write->delayed = 1; ngx_add_timer(r->connection->write, sleep); r->write_event_handler = ngx_http_perl_sleep_handler; diff --git a/src/http/modules/perl/ngx_http_perl_module.c b/src/http/modules/perl/ngx_http_perl_module.c index f9a9a84c051..6d3be912809 100644 --- a/src/http/modules/perl/ngx_http_perl_module.c +++ b/src/http/modules/perl/ngx_http_perl_module.c @@ -207,6 +207,7 @@ ngx_http_perl_handle_request(ngx_http_request_t *r) dTHXa(pmcf->perl); PERL_SET_CONTEXT(pmcf->perl); + PERL_SET_INTERP(pmcf->perl); if (ctx->next == NULL) { plcf = ngx_http_get_module_loc_conf(r, ngx_http_perl_module); @@ -277,15 +278,16 @@ ngx_http_perl_sleep_handler(ngx_http_request_t *r) wev = r->connection->write; - if (wev->timedout) { - wev->timedout = 0; - ngx_http_perl_handle_request(r); + if (wev->delayed) { + + if (ngx_handle_write_event(wev, 0) != NGX_OK) { + ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); + } + return; } - if (ngx_handle_write_event(wev, 0) != NGX_OK) { - ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); - } + ngx_http_perl_handle_request(r); } @@ -322,6 +324,7 @@ ngx_http_perl_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v, dTHXa(pmcf->perl); PERL_SET_CONTEXT(pmcf->perl); + PERL_SET_INTERP(pmcf->perl); rc = ngx_http_perl_call_handler(aTHX_ r, pmcf->nginx, pv->sub, NULL, &pv->handler, &value); @@ -387,6 +390,7 @@ ngx_http_perl_ssi(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ssi_ctx, dTHXa(pmcf->perl); PERL_SET_CONTEXT(pmcf->perl); + PERL_SET_INTERP(pmcf->perl); #if 0 @@ -568,6 +572,7 @@ ngx_http_perl_create_interpreter(ngx_conf_t *cf, dTHXa(perl); PERL_SET_CONTEXT(perl); + PERL_SET_INTERP(perl); perl_construct(perl); @@ -828,6 +833,7 @@ ngx_http_perl_cleanup_perl(void *data) PerlInterpreter *perl = data; PERL_SET_CONTEXT(perl); + PERL_SET_INTERP(perl); (void) perl_destruct(perl); @@ -936,6 +942,7 @@ ngx_http_perl(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) dTHXa(pmcf->perl); PERL_SET_CONTEXT(pmcf->perl); + PERL_SET_INTERP(pmcf->perl); ngx_http_perl_eval_anon_sub(aTHX_ &value[1], &plcf->sub); @@ -1007,6 +1014,7 @@ ngx_http_perl_set(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) dTHXa(pmcf->perl); PERL_SET_CONTEXT(pmcf->perl); + PERL_SET_INTERP(pmcf->perl); ngx_http_perl_eval_anon_sub(aTHX_ &value[2], &pv->sub); @@ -1039,6 +1047,7 @@ ngx_http_perl_init_worker(ngx_cycle_t *cycle) if (pmcf) { dTHXa(pmcf->perl); PERL_SET_CONTEXT(pmcf->perl); + PERL_SET_INTERP(pmcf->perl); /* set worker's $$ */ diff --git a/src/http/ngx_http.c b/src/http/ngx_http.c index ba559f23141..9d8b6d79a95 100644 --- a/src/http/ngx_http.c +++ b/src/http/ngx_http.c @@ -382,6 +382,13 @@ ngx_http_init_phases(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf) return NGX_ERROR; } + if (ngx_array_init(&cmcf->phases[NGX_HTTP_PRECONTENT_PHASE].handlers, + cf->pool, 2, sizeof(ngx_http_handler_pt)) + != NGX_OK) + { + return NGX_ERROR; + } + if (ngx_array_init(&cmcf->phases[NGX_HTTP_CONTENT_PHASE].handlers, cf->pool, 4, sizeof(ngx_http_handler_pt)) != NGX_OK) @@ -457,7 +464,9 @@ ngx_http_init_phase_handlers(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf) use_rewrite = cmcf->phases[NGX_HTTP_REWRITE_PHASE].handlers.nelts ? 1 : 0; use_access = cmcf->phases[NGX_HTTP_ACCESS_PHASE].handlers.nelts ? 1 : 0; - n = use_rewrite + use_access + cmcf->try_files + 1 /* find config phase */; + n = 1 /* find config phase */ + + use_rewrite /* post rewrite phase */ + + use_access; /* post access phase */ for (i = 0; i < NGX_HTTP_LOG_PHASE; i++) { n += cmcf->phases[i].handlers.nelts; @@ -526,15 +535,6 @@ ngx_http_init_phase_handlers(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf) continue; - case NGX_HTTP_TRY_FILES_PHASE: - if (cmcf->try_files) { - ph->checker = ngx_http_core_try_files_phase; - n++; - ph++; - } - - continue; - case NGX_HTTP_CONTENT_PHASE: checker = ngx_http_core_content_phase; break; @@ -545,7 +545,7 @@ ngx_http_init_phase_handlers(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf) n += cmcf->phases[i].handlers.nelts; - for (j = cmcf->phases[i].handlers.nelts - 1; j >=0; j--) { + for (j = cmcf->phases[i].handlers.nelts - 1; j >= 0; j--) { ph->checker = checker; ph->handler = h[j]; ph->next = n; diff --git a/src/http/ngx_http_cache.h b/src/http/ngx_http_cache.h index 70342d0ed37..f9e96640998 100644 --- a/src/http/ngx_http_cache.h +++ b/src/http/ngx_http_cache.h @@ -24,10 +24,10 @@ #define NGX_HTTP_CACHE_SCARCE 8 #define NGX_HTTP_CACHE_KEY_LEN 16 -#define NGX_HTTP_CACHE_ETAG_LEN 42 -#define NGX_HTTP_CACHE_VARY_LEN 42 +#define NGX_HTTP_CACHE_ETAG_LEN 128 +#define NGX_HTTP_CACHE_VARY_LEN 128 -#define NGX_HTTP_CACHE_VERSION 3 +#define NGX_HTTP_CACHE_VERSION 5 typedef struct { @@ -71,6 +71,8 @@ struct ngx_http_cache_s { ngx_file_uniq_t uniq; time_t valid_sec; + time_t updating_sec; + time_t error_sec; time_t last_modified; time_t date; @@ -114,12 +116,18 @@ struct ngx_http_cache_s { unsigned purged:1; unsigned reading:1; unsigned secondary:1; + unsigned background:1; + + unsigned stale_updating:1; + unsigned stale_error:1; }; typedef struct { ngx_uint_t version; time_t valid_sec; + time_t updating_sec; + time_t error_sec; time_t last_modified; time_t date; uint32_t crc32; @@ -151,7 +159,6 @@ struct ngx_http_file_cache_s { ngx_slab_pool_t *shpool; ngx_path_t *path; - ngx_path_t *temp_path; off_t max_size; size_t bsize; @@ -171,6 +178,9 @@ struct ngx_http_file_cache_s { ngx_msec_t manager_threshold; ngx_shm_zone_t *shm_zone; + + ngx_uint_t use_temp_path; + /* unsigned use_temp_path:1 */ }; diff --git a/src/http/ngx_http_copy_filter_module.c b/src/http/ngx_http_copy_filter_module.c index c696fb6f9c1..c8ad5daeea5 100644 --- a/src/http/ngx_http_copy_filter_module.c +++ b/src/http/ngx_http_copy_filter_module.c @@ -187,15 +187,24 @@ static void ngx_http_copy_aio_event_handler(ngx_event_t *ev) { ngx_event_aio_t *aio; + ngx_connection_t *c; ngx_http_request_t *r; aio = ev->data; r = aio->data; + c = r->connection; + + ngx_http_set_log_request(c->log, r); + + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, + "http aio: \"%V?%V\"", &r->uri, &r->args); r->main->blocked--; r->aio = 0; - r->connection->write->handler(r->connection->write); + r->write_event_handler(r); + + ngx_http_run_posted_requests(c); } @@ -300,14 +309,33 @@ ngx_http_copy_thread_handler(ngx_thread_task_t *task, ngx_file_t *file) static void ngx_http_copy_thread_event_handler(ngx_event_t *ev) { + ngx_connection_t *c; ngx_http_request_t *r; r = ev->data; + c = r->connection; + + ngx_http_set_log_request(c->log, r); + + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, + "http thread: \"%V?%V\"", &r->uri, &r->args); r->main->blocked--; r->aio = 0; - r->connection->write->handler(r->connection->write); + if (r->done) { + /* + * trigger connection event handler if the subrequest was + * already finalized; this can happen if the handler is used + * for sendfile() in threads + */ + + c->write->handler(c->write); + + } else { + r->write_event_handler(r); + ngx_http_run_posted_requests(c); + } } #endif diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c index 9da5d109e3c..57a47427f36 100644 --- a/src/http/ngx_http_core_module.c +++ b/src/http/ngx_http_core_module.c @@ -61,8 +61,6 @@ static char *ngx_http_core_directio(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); static char *ngx_http_core_error_page(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); -static char *ngx_http_core_try_files(ngx_conf_t *cf, ngx_command_t *cmd, - void *conf); static char *ngx_http_core_open_file_cache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); static char *ngx_http_core_error_log(ngx_conf_t *cf, ngx_command_t *cmd, @@ -120,6 +118,14 @@ static ngx_conf_enum_t ngx_http_core_lingering_close[] = { }; +static ngx_conf_enum_t ngx_http_core_server_tokens[] = { + { ngx_string("off"), NGX_HTTP_SERVER_TOKENS_OFF }, + { ngx_string("on"), NGX_HTTP_SERVER_TOKENS_ON }, + { ngx_string("build"), NGX_HTTP_SERVER_TOKENS_BUILD }, + { ngx_null_string, 0 } +}; + + static ngx_conf_enum_t ngx_http_core_if_modified_since[] = { { ngx_string("off"), NGX_HTTP_IMS_OFF }, { ngx_string("exact"), NGX_HTTP_IMS_EXACT }, @@ -542,6 +548,13 @@ static ngx_command_t ngx_http_core_commands[] = { offsetof(ngx_http_core_loc_conf_t, reset_timedout_connection), NULL }, + { ngx_string("absolute_redirect"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, + ngx_conf_set_flag_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_core_loc_conf_t, absolute_redirect), + NULL }, + { ngx_string("server_name_in_redirect"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, ngx_conf_set_flag_slot, @@ -592,11 +605,11 @@ static ngx_command_t ngx_http_core_commands[] = { NULL }, { ngx_string("server_tokens"), - NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, - ngx_conf_set_flag_slot, + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_conf_set_enum_slot, NGX_HTTP_LOC_CONF_OFFSET, offsetof(ngx_http_core_loc_conf_t, server_tokens), - NULL }, + &ngx_http_core_server_tokens }, { ngx_string("if_modified_since"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, @@ -634,13 +647,6 @@ static ngx_command_t ngx_http_core_commands[] = { 0, NULL }, - { ngx_string("try_files"), - NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_2MORE, - ngx_http_core_try_files, - NGX_HTTP_LOC_CONF_OFFSET, - 0, - NULL }, - { ngx_string("post_action"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF |NGX_CONF_TAKE1, @@ -976,10 +982,8 @@ ngx_http_core_find_config_phase(ngx_http_request_t *r, return NGX_OK; } - /* - * we do not need to set the r->headers_out.location->hash and - * r->headers_out.location->key fields - */ + r->headers_out.location->hash = 1; + ngx_str_set(&r->headers_out.location->key, "Location"); if (r->args.len == 0) { r->headers_out.location->value = clcf->name; @@ -989,6 +993,7 @@ ngx_http_core_find_config_phase(ngx_http_request_t *r, p = ngx_pnalloc(r->pool, len); if (p == NULL) { + ngx_http_clear_location(r); ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); return NGX_OK; } @@ -1144,217 +1149,6 @@ ngx_http_core_post_access_phase(ngx_http_request_t *r, } -ngx_int_t -ngx_http_core_try_files_phase(ngx_http_request_t *r, - ngx_http_phase_handler_t *ph) -{ - size_t len, root, alias, reserve, allocated; - u_char *p, *name; - ngx_str_t path, args; - ngx_uint_t test_dir; - ngx_http_try_file_t *tf; - ngx_open_file_info_t of; - ngx_http_script_code_pt code; - ngx_http_script_engine_t e; - ngx_http_core_loc_conf_t *clcf; - ngx_http_script_len_code_pt lcode; - - ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "try files phase: %ui", r->phase_handler); - - clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); - - if (clcf->try_files == NULL) { - r->phase_handler++; - return NGX_AGAIN; - } - - allocated = 0; - root = 0; - name = NULL; - /* suppress MSVC warning */ - path.data = NULL; - - tf = clcf->try_files; - - alias = clcf->alias; - - for ( ;; ) { - - if (tf->lengths) { - ngx_memzero(&e, sizeof(ngx_http_script_engine_t)); - - e.ip = tf->lengths->elts; - e.request = r; - - /* 1 is for terminating '\0' as in static names */ - len = 1; - - while (*(uintptr_t *) e.ip) { - lcode = *(ngx_http_script_len_code_pt *) e.ip; - len += lcode(&e); - } - - } else { - len = tf->name.len; - } - - if (!alias) { - reserve = len > r->uri.len ? len - r->uri.len : 0; - - } else if (alias == NGX_MAX_SIZE_T_VALUE) { - reserve = len; - - } else { - reserve = len > r->uri.len - alias ? len - (r->uri.len - alias) : 0; - } - - if (reserve > allocated || !allocated) { - - /* 16 bytes are preallocation */ - allocated = reserve + 16; - - if (ngx_http_map_uri_to_path(r, &path, &root, allocated) == NULL) { - ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); - return NGX_OK; - } - - name = path.data + root; - } - - if (tf->values == NULL) { - - /* tf->name.len includes the terminating '\0' */ - - ngx_memcpy(name, tf->name.data, tf->name.len); - - path.len = (name + tf->name.len - 1) - path.data; - - } else { - e.ip = tf->values->elts; - e.pos = name; - e.flushed = 1; - - while (*(uintptr_t *) e.ip) { - code = *(ngx_http_script_code_pt *) e.ip; - code((ngx_http_script_engine_t *) &e); - } - - path.len = e.pos - path.data; - - *e.pos = '\0'; - - if (alias && alias != NGX_MAX_SIZE_T_VALUE - && ngx_strncmp(name, r->uri.data, alias) == 0) - { - ngx_memmove(name, name + alias, len - alias); - path.len -= alias; - } - } - - test_dir = tf->test_dir; - - tf++; - - ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "trying to use %s: \"%s\" \"%s\"", - test_dir ? "dir" : "file", name, path.data); - - if (tf->lengths == NULL && tf->name.len == 0) { - - if (tf->code) { - ngx_http_finalize_request(r, tf->code); - return NGX_OK; - } - - path.len -= root; - path.data += root; - - if (path.data[0] == '@') { - (void) ngx_http_named_location(r, &path); - - } else { - ngx_http_split_args(r, &path, &args); - - (void) ngx_http_internal_redirect(r, &path, &args); - } - - ngx_http_finalize_request(r, NGX_DONE); - return NGX_OK; - } - - ngx_memzero(&of, sizeof(ngx_open_file_info_t)); - - of.read_ahead = clcf->read_ahead; - of.directio = clcf->directio; - of.valid = clcf->open_file_cache_valid; - of.min_uses = clcf->open_file_cache_min_uses; - of.test_only = 1; - of.errors = clcf->open_file_cache_errors; - of.events = clcf->open_file_cache_events; - - if (ngx_http_set_disable_symlinks(r, clcf, &path, &of) != NGX_OK) { - ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); - return NGX_OK; - } - - if (ngx_open_cached_file(clcf->open_file_cache, &path, &of, r->pool) - != NGX_OK) - { - if (of.err != NGX_ENOENT - && of.err != NGX_ENOTDIR - && of.err != NGX_ENAMETOOLONG) - { - ngx_log_error(NGX_LOG_CRIT, r->connection->log, of.err, - "%s \"%s\" failed", of.failed, path.data); - } - - continue; - } - - if (of.is_dir != test_dir) { - continue; - } - - path.len -= root; - path.data += root; - - if (!alias) { - r->uri = path; - - } else if (alias == NGX_MAX_SIZE_T_VALUE) { - if (!test_dir) { - r->uri = path; - r->add_uri_to_alias = 1; - } - - } else { - name = r->uri.data; - - r->uri.len = alias + path.len; - r->uri.data = ngx_pnalloc(r->pool, r->uri.len); - if (r->uri.data == NULL) { - ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); - return NGX_OK; - } - - p = ngx_copy(r->uri.data, name, alias); - ngx_memcpy(p, path.data, path.len); - } - - ngx_http_set_exten(r); - - ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "try file uri: \"%V\"", &r->uri); - - r->phase_handler++; - return NGX_AGAIN; - } - - /* not reached */ -} - - ngx_int_t ngx_http_core_content_phase(ngx_http_request_t *r, ngx_http_phase_handler_t *ph) @@ -1876,7 +1670,8 @@ ngx_http_send_response(ngx_http_request_t *r, ngx_uint_t status, if (status == NGX_HTTP_MOVED_PERMANENTLY || status == NGX_HTTP_MOVED_TEMPORARILY || status == NGX_HTTP_SEE_OTHER - || status == NGX_HTTP_TEMPORARY_REDIRECT) + || status == NGX_HTTP_TEMPORARY_REDIRECT + || status == NGX_HTTP_PERMANENT_REDIRECT) { ngx_http_clear_location(r); @@ -1908,7 +1703,7 @@ ngx_http_send_response(ngx_http_request_t *r, ngx_uint_t status, return ngx_http_send_header(r); } - b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t)); + b = ngx_calloc_buf(r->pool); if (b == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } @@ -2464,6 +2259,13 @@ ngx_http_subrequest(ngx_http_request_t *r, return NGX_ERROR; } + if (ngx_list_init(&sr->headers_out.trailers, r->pool, 4, + sizeof(ngx_table_elt_t)) + != NGX_OK) + { + return NGX_ERROR; + } + cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module); sr->main_conf = cscf->ctx->main_conf; sr->srv_conf = cscf->ctx->srv_conf; @@ -2498,6 +2300,7 @@ ngx_http_subrequest(ngx_http_request_t *r, sr->subrequest_in_memory = (flags & NGX_HTTP_SUBREQUEST_IN_MEMORY) != 0; sr->waited = (flags & NGX_HTTP_SUBREQUEST_WAITED) != 0; + sr->background = (flags & NGX_HTTP_SUBREQUEST_BACKGROUND) != 0; sr->unparsed_uri = r->unparsed_uri; sr->method_name = ngx_http_core_get_method; @@ -2511,29 +2314,31 @@ ngx_http_subrequest(ngx_http_request_t *r, sr->read_event_handler = ngx_http_request_empty_handler; sr->write_event_handler = ngx_http_handler; - if (c->data == r && r->postponed == NULL) { - c->data = sr; - } - sr->variables = r->variables; sr->log_handler = r->log_handler; - pr = ngx_palloc(r->pool, sizeof(ngx_http_postponed_request_t)); - if (pr == NULL) { - return NGX_ERROR; - } + if (!sr->background) { + if (c->data == r && r->postponed == NULL) { + c->data = sr; + } - pr->request = sr; - pr->out = NULL; - pr->next = NULL; + pr = ngx_palloc(r->pool, sizeof(ngx_http_postponed_request_t)); + if (pr == NULL) { + return NGX_ERROR; + } - if (r->postponed) { - for (p = r->postponed; p->next; p = p->next) { /* void */ } - p->next = pr; + pr->request = sr; + pr->out = NULL; + pr->next = NULL; - } else { - r->postponed = pr; + if (r->postponed) { + for (p = r->postponed; p->next; p = p->next) { /* void */ } + p->next = pr; + + } else { + r->postponed = pr; + } } sr->internal = 1; @@ -2553,6 +2358,18 @@ ngx_http_subrequest(ngx_http_request_t *r, *psr = sr; + if (flags & NGX_HTTP_SUBREQUEST_CLONE) { + sr->method = r->method; + sr->method_name = r->method_name; + sr->loc_conf = r->loc_conf; + sr->valid_location = r->valid_location; + sr->content_handler = r->content_handler; + sr->phase_handler = r->phase_handler; + sr->write_event_handler = ngx_http_core_run_phases; + + ngx_http_update_location_config(sr); + } + return ngx_http_post_request(sr, NULL); } @@ -3518,7 +3335,6 @@ ngx_http_core_create_loc_conf(ngx_conf_t *cf) * clcf->default_type = { 0, NULL }; * clcf->error_log = NULL; * clcf->error_pages = NULL; - * clcf->try_files = NULL; * clcf->client_body_path = NULL; * clcf->regex = NULL; * clcf->exact_match = 0; @@ -3563,6 +3379,7 @@ ngx_http_core_create_loc_conf(ngx_conf_t *cf) clcf->lingering_timeout = NGX_CONF_UNSET_MSEC; clcf->resolver_timeout = NGX_CONF_UNSET_MSEC; clcf->reset_timedout_connection = NGX_CONF_UNSET; + clcf->absolute_redirect = NGX_CONF_UNSET; clcf->server_name_in_redirect = NGX_CONF_UNSET; clcf->port_in_redirect = NGX_CONF_UNSET; clcf->msie_padding = NGX_CONF_UNSET; @@ -3570,9 +3387,9 @@ ngx_http_core_create_loc_conf(ngx_conf_t *cf) clcf->log_not_found = NGX_CONF_UNSET; clcf->log_subrequest = NGX_CONF_UNSET; clcf->recursive_error_pages = NGX_CONF_UNSET; - clcf->server_tokens = NGX_CONF_UNSET; clcf->chunked_transfer_encoding = NGX_CONF_UNSET; clcf->etag = NGX_CONF_UNSET; + clcf->server_tokens = NGX_CONF_UNSET_UINT; clcf->types_hash_max_size = NGX_CONF_UNSET_UINT; clcf->types_hash_bucket_size = NGX_CONF_UNSET_UINT; @@ -3825,6 +3642,8 @@ ngx_http_core_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) ngx_conf_merge_value(conf->reset_timedout_connection, prev->reset_timedout_connection, 0); + ngx_conf_merge_value(conf->absolute_redirect, + prev->absolute_redirect, 1); ngx_conf_merge_value(conf->server_name_in_redirect, prev->server_name_in_redirect, 0); ngx_conf_merge_value(conf->port_in_redirect, prev->port_in_redirect, 1); @@ -3834,11 +3653,13 @@ ngx_http_core_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) ngx_conf_merge_value(conf->log_subrequest, prev->log_subrequest, 0); ngx_conf_merge_value(conf->recursive_error_pages, prev->recursive_error_pages, 0); - ngx_conf_merge_value(conf->server_tokens, prev->server_tokens, 1); ngx_conf_merge_value(conf->chunked_transfer_encoding, prev->chunked_transfer_encoding, 1); ngx_conf_merge_value(conf->etag, prev->etag, 1); + ngx_conf_merge_uint_value(conf->server_tokens, prev->server_tokens, + NGX_HTTP_SERVER_TOKENS_ON); + ngx_conf_merge_ptr_value(conf->open_file_cache, prev->open_file_cache, NULL); @@ -4375,16 +4196,14 @@ ngx_http_core_root(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) if (clcf->root.data) { if ((clcf->alias != 0) == alias) { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "\"%V\" directive is duplicate", - &cmd->name); - } else { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "\"%V\" directive is duplicate, " - "\"%s\" directive was specified earlier", - &cmd->name, clcf->alias ? "alias" : "root"); + return "is duplicate"; } + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "\"%V\" directive is duplicate, " + "\"%s\" directive was specified earlier", + &cmd->name, clcf->alias ? "alias" : "root"); + return NGX_CONF_ERROR; } @@ -4499,7 +4318,7 @@ ngx_http_core_limit_except(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) ngx_http_core_loc_conf_t *clcf; if (pclcf->limit_except) { - return "duplicate"; + return "is duplicate"; } pclcf->limit_except = 0xffffffff; @@ -4827,8 +4646,6 @@ ngx_http_core_error_page(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) case NGX_HTTPS_CERT_ERROR: case NGX_HTTPS_NO_CERT: err->overwrite = NGX_HTTP_BAD_REQUEST; - default: - break; } } @@ -4840,89 +4657,6 @@ ngx_http_core_error_page(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) } -static char * -ngx_http_core_try_files(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) -{ - ngx_http_core_loc_conf_t *clcf = conf; - - ngx_str_t *value; - ngx_int_t code; - ngx_uint_t i, n; - ngx_http_try_file_t *tf; - ngx_http_script_compile_t sc; - ngx_http_core_main_conf_t *cmcf; - - if (clcf->try_files) { - return "is duplicate"; - } - - cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module); - - cmcf->try_files = 1; - - tf = ngx_pcalloc(cf->pool, cf->args->nelts * sizeof(ngx_http_try_file_t)); - if (tf == NULL) { - return NGX_CONF_ERROR; - } - - clcf->try_files = tf; - - value = cf->args->elts; - - for (i = 0; i < cf->args->nelts - 1; i++) { - - tf[i].name = value[i + 1]; - - if (tf[i].name.len > 0 - && tf[i].name.data[tf[i].name.len - 1] == '/' - && i + 2 < cf->args->nelts) - { - tf[i].test_dir = 1; - tf[i].name.len--; - tf[i].name.data[tf[i].name.len] = '\0'; - } - - n = ngx_http_script_variables_count(&tf[i].name); - - if (n) { - ngx_memzero(&sc, sizeof(ngx_http_script_compile_t)); - - sc.cf = cf; - sc.source = &tf[i].name; - sc.lengths = &tf[i].lengths; - sc.values = &tf[i].values; - sc.variables = n; - sc.complete_lengths = 1; - sc.complete_values = 1; - - if (ngx_http_script_compile(&sc) != NGX_OK) { - return NGX_CONF_ERROR; - } - - } else { - /* add trailing '\0' to length */ - tf[i].name.len++; - } - } - - if (tf[i - 1].name.data[0] == '=') { - - code = ngx_atoi(tf[i - 1].name.data + 1, tf[i - 1].name.len - 2); - - if (code == NGX_ERROR || code > 999) { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "invalid code \"%*s\"", - tf[i - 1].name.len - 1, tf[i - 1].name.data); - return NGX_CONF_ERROR; - } - - tf[i].code = code; - } - - return NGX_CONF_OK; -} - - static char * ngx_http_core_open_file_cache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { diff --git a/src/http/ngx_http_core_module.h b/src/http/ngx_http_core_module.h index ade9abbe578..a6128b5410e 100644 --- a/src/http/ngx_http_core_module.h +++ b/src/http/ngx_http_core_module.h @@ -55,6 +55,11 @@ typedef struct ngx_thread_pool_s ngx_thread_pool_t; #define NGX_HTTP_KEEPALIVE_DISABLE_SAFARI 0x0008 +#define NGX_HTTP_SERVER_TOKENS_OFF 0 +#define NGX_HTTP_SERVER_TOKENS_ON 1 +#define NGX_HTTP_SERVER_TOKENS_BUILD 2 + + typedef struct ngx_http_location_tree_node_s ngx_http_location_tree_node_t; typedef struct ngx_http_core_loc_conf_s ngx_http_core_loc_conf_t; @@ -114,7 +119,8 @@ typedef enum { NGX_HTTP_ACCESS_PHASE, NGX_HTTP_POST_ACCESS_PHASE, - NGX_HTTP_TRY_FILES_PHASE, + NGX_HTTP_PRECONTENT_PHASE, + NGX_HTTP_CONTENT_PHASE, NGX_HTTP_LOG_PHASE @@ -153,7 +159,8 @@ typedef struct { ngx_hash_t variables_hash; - ngx_array_t variables; /* ngx_http_variable_t */ + ngx_array_t variables; /* ngx_http_variable_t */ + ngx_array_t prefix_variables; /* ngx_http_variable_t */ ngx_uint_t ncaptures; ngx_uint_t server_names_hash_max_size; @@ -166,8 +173,6 @@ typedef struct { ngx_array_t *ports; - ngx_uint_t try_files; /* unsigned try_files:1 */ - ngx_http_phase_t phases[NGX_HTTP_LOG_PHASE + 1]; } ngx_http_core_main_conf_t; @@ -290,16 +295,6 @@ typedef struct { } ngx_http_err_page_t; -typedef struct { - ngx_array_t *lengths; - ngx_array_t *values; - ngx_str_t name; - - unsigned code:10; - unsigned test_dir:1; -} ngx_http_try_file_t; - - struct ngx_http_core_loc_conf_s { ngx_str_t name; /* location name */ @@ -385,6 +380,7 @@ struct ngx_http_core_loc_conf_s { ngx_flag_t tcp_nopush; /* tcp_nopush */ ngx_flag_t tcp_nodelay; /* tcp_nodelay */ ngx_flag_t reset_timedout_connection; /* reset_timedout_connection */ + ngx_flag_t absolute_redirect; /* absolute_redirect */ ngx_flag_t server_name_in_redirect; /* server_name_in_redirect */ ngx_flag_t port_in_redirect; /* port_in_redirect */ ngx_flag_t msie_padding; /* msie_padding */ @@ -392,7 +388,7 @@ struct ngx_http_core_loc_conf_s { ngx_flag_t log_not_found; /* log_not_found */ ngx_flag_t log_subrequest; /* log_subrequest */ ngx_flag_t recursive_error_pages; /* recursive_error_pages */ - ngx_flag_t server_tokens; /* server_tokens */ + ngx_uint_t server_tokens; /* server_tokens */ ngx_flag_t chunked_transfer_encoding; /* chunked_transfer_encoding */ ngx_flag_t etag; /* etag */ @@ -418,7 +414,6 @@ struct ngx_http_core_loc_conf_s { #endif ngx_array_t *error_pages; /* error_page */ - ngx_http_try_file_t *try_files; /* try_files */ ngx_path_t *client_body_temp_path; /* client_body_temp_path */ @@ -479,8 +474,6 @@ ngx_int_t ngx_http_core_access_phase(ngx_http_request_t *r, ngx_http_phase_handler_t *ph); ngx_int_t ngx_http_core_post_access_phase(ngx_http_request_t *r, ngx_http_phase_handler_t *ph); -ngx_int_t ngx_http_core_try_files_phase(ngx_http_request_t *r, - ngx_http_phase_handler_t *ph); ngx_int_t ngx_http_core_content_phase(ngx_http_request_t *r, ngx_http_phase_handler_t *ph); diff --git a/src/http/ngx_http_file_cache.c b/src/http/ngx_http_file_cache.c index ac5c103745e..3b2b68a2601 100644 --- a/src/http/ngx_http_file_cache.c +++ b/src/http/ngx_http_file_cache.c @@ -129,6 +129,7 @@ ngx_http_file_cache_init(ngx_shm_zone_t *shm_zone, void *data) if (shm_zone->shm.exists) { cache->sh = cache->shpool->data; cache->bsize = ngx_fs_bsize(cache->path->name.data); + cache->max_size /= cache->bsize; return NGX_OK; } @@ -553,7 +554,7 @@ ngx_http_file_cache_read(ngx_http_request_t *r, ngx_http_cache_t *c) return NGX_DECLINED; } - if (h->crc32 != c->crc32 || h->header_start != c->header_start) { + if (h->crc32 != c->crc32 || (size_t) h->header_start != c->header_start) { ngx_log_error(NGX_LOG_CRIT, r->connection->log, 0, "cache file \"%s\" has md5 collision", c->file.name.data); return NGX_DECLINED; @@ -601,6 +602,8 @@ ngx_http_file_cache_read(ngx_http_request_t *r, ngx_http_cache_t *c) c->buf->last += n; c->valid_sec = h->valid_sec; + c->updating_sec = h->updating_sec; + c->error_sec = h->error_sec; c->last_modified = h->last_modified; c->date = h->date; c->valid_msec = h->valid_msec; @@ -632,6 +635,8 @@ ngx_http_file_cache_read(ngx_http_request_t *r, ngx_http_cache_t *c) now = ngx_time(); if (c->valid_sec < now) { + c->stale_updating = c->valid_sec + c->updating_sec >= now; + c->stale_error = c->valid_sec + c->error_sec >= now; ngx_shmtx_lock(&cache->shpool->mutex); @@ -1252,6 +1257,8 @@ ngx_http_file_cache_set_header(ngx_http_request_t *r, u_char *buf) h->version = NGX_HTTP_CACHE_VERSION; h->valid_sec = c->valid_sec; + h->updating_sec = c->updating_sec; + h->error_sec = c->error_sec; h->last_modified = c->last_modified; h->date = c->date; h->crc32 = c->crc32; @@ -1495,8 +1502,8 @@ ngx_http_file_cache_update_header(ngx_http_request_t *r) if (h.version != NGX_HTTP_CACHE_VERSION || h.last_modified != c->last_modified || h.crc32 != c->crc32 - || h.header_start != c->header_start - || h.body_start != c->body_start) + || (size_t) h.header_start != c->header_start + || (size_t) h.body_start != c->body_start) { ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http file cache \"%s\" content changed", @@ -1513,6 +1520,8 @@ ngx_http_file_cache_update_header(ngx_http_request_t *r) h.version = NGX_HTTP_CACHE_VERSION; h.valid_sec = c->valid_sec; + h.updating_sec = c->updating_sec; + h.error_sec = c->error_sec; h.last_modified = c->last_modified; h.date = c->date; h.crc32 = c->crc32; @@ -1569,7 +1578,7 @@ ngx_http_cache_send(ngx_http_request_t *r) /* we need to allocate all before the header would be sent */ - b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t)); + b = ngx_calloc_buf(r->pool); if (b == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } @@ -1680,7 +1689,7 @@ ngx_http_file_cache_cleanup(void *data) ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->file.log, 0, "http file cache cleanup"); - if (c->updating) { + if (c->updating && !c->background) { ngx_log_error(NGX_LOG_ALERT, c->file.log, 0, "stalled cache updating, error:%ui", c->error); } @@ -1692,13 +1701,14 @@ ngx_http_file_cache_cleanup(void *data) static time_t ngx_http_file_cache_forced_expire(ngx_http_file_cache_t *cache) { - u_char *name; + u_char *name, *p; size_t len; time_t wait; ngx_uint_t tries; ngx_path_t *path; - ngx_queue_t *q; + ngx_queue_t *q, *sentinel; ngx_http_file_cache_node_t *fcn; + u_char key[2 * NGX_HTTP_CACHE_KEY_LEN]; ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0, "http file cache forced expire"); @@ -1715,13 +1725,21 @@ ngx_http_file_cache_forced_expire(ngx_http_file_cache_t *cache) wait = 10; tries = 20; + sentinel = NULL; ngx_shmtx_lock(&cache->shpool->mutex); - for (q = ngx_queue_last(&cache->sh->queue); - q != ngx_queue_sentinel(&cache->sh->queue); - q = ngx_queue_prev(q)) - { + for ( ;; ) { + if (ngx_queue_empty(&cache->sh->queue)) { + break; + } + + q = ngx_queue_last(&cache->sh->queue); + + if (q == sentinel) { + break; + } + fcn = ngx_queue_data(q, ngx_http_file_cache_node_t, queue); ngx_log_debug6(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0, @@ -1732,15 +1750,37 @@ ngx_http_file_cache_forced_expire(ngx_http_file_cache_t *cache) if (fcn->count == 0) { ngx_http_file_cache_delete(cache, q, name); wait = 0; + break; + } - } else { - if (--tries) { - continue; - } + p = ngx_hex_dump(key, (u_char *) &fcn->node.key, + sizeof(ngx_rbtree_key_t)); + len = NGX_HTTP_CACHE_KEY_LEN - sizeof(ngx_rbtree_key_t); + (void) ngx_hex_dump(p, fcn->key, len); - wait = 1; + /* + * abnormally exited workers may leave locked cache entries, + * and although it may be safe to remove them completely, + * we prefer to just move them to the top of the inactive queue + */ + + ngx_queue_remove(q); + fcn->expire = ngx_time() + cache->inactive; + ngx_queue_insert_head(&cache->sh->queue, &fcn->queue); + + ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0, + "ignore long locked inactive cache entry %*s, count:%d", + (size_t) 2 * NGX_HTTP_CACHE_KEY_LEN, key, fcn->count); + + if (sentinel == NULL) { + sentinel = q; + } + + if (--tries) { + continue; } + wait = 1; break; } @@ -2112,6 +2152,17 @@ ngx_http_file_cache_add_file(ngx_tree_ctx_t *ctx, ngx_str_t *name) return NGX_ERROR; } + /* + * Temporary files in cache have a suffix consisting of a dot + * followed by 10 digits. + */ + + if (name->len >= 2 * NGX_HTTP_CACHE_KEY_LEN + 1 + 10 + && name->data[name->len - 10 - 1] == '.') + { + return NGX_OK; + } + if (ctx->size < (off_t) sizeof(ngx_http_file_cache_header_t)) { ngx_log_error(NGX_LOG_CRIT, ctx->log, 0, "cache file \"%s\" is too small", name->data); @@ -2256,7 +2307,6 @@ ngx_http_file_cache_set_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) off_t max_size; u_char *last, *p; time_t inactive; - size_t len; ssize_t size; ngx_str_t s, name, *value; ngx_int_t loader_files, manager_files; @@ -2529,37 +2579,6 @@ ngx_http_file_cache_set_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) return NGX_CONF_ERROR; } - if (!use_temp_path) { - cache->temp_path = ngx_pcalloc(cf->pool, sizeof(ngx_path_t)); - if (cache->temp_path == NULL) { - return NGX_CONF_ERROR; - } - - len = cache->path->name.len + sizeof("/temp") - 1; - - p = ngx_pnalloc(cf->pool, len + 1); - if (p == NULL) { - return NGX_CONF_ERROR; - } - - cache->temp_path->name.len = len; - cache->temp_path->name.data = p; - - p = ngx_cpymem(p, cache->path->name.data, cache->path->name.len); - ngx_memcpy(p, "/temp", sizeof("/temp")); - - ngx_memcpy(&cache->temp_path->level, &cache->path->level, - NGX_MAX_PATH_LEVEL * sizeof(size_t)); - - cache->temp_path->len = cache->path->len; - cache->temp_path->conf_file = cf->conf_file->file.name.data; - cache->temp_path->line = cf->conf_file->line; - - if (ngx_add_path(cf, &cache->temp_path) != NGX_OK) { - return NGX_CONF_ERROR; - } - } - cache->shm_zone = ngx_shared_memory_add(cf, &name, size, cmd->post); if (cache->shm_zone == NULL) { return NGX_CONF_ERROR; @@ -2575,6 +2594,8 @@ ngx_http_file_cache_set_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) cache->shm_zone->init = ngx_http_file_cache_init; cache->shm_zone->data = cache; + cache->use_temp_path = use_temp_path; + cache->inactive = inactive; cache->max_size = max_size; diff --git a/src/http/ngx_http_header_filter_module.c b/src/http/ngx_http_header_filter_module.c index f000b2e494e..9b89405904b 100644 --- a/src/http/ngx_http_header_filter_module.c +++ b/src/http/ngx_http_header_filter_module.c @@ -46,8 +46,9 @@ ngx_module_t ngx_http_header_filter_module = { }; -static char ngx_http_server_string[] = "Server: nginx" CRLF; -static char ngx_http_server_full_string[] = "Server: " NGINX_VER CRLF; +static u_char ngx_http_server_string[] = "Server: nginx" CRLF; +static u_char ngx_http_server_full_string[] = "Server: " NGINX_VER CRLF; +static u_char ngx_http_server_build_string[] = "Server: " NGINX_VER_BUILD CRLF; static ngx_str_t ngx_http_status_lines[] = { @@ -74,8 +75,9 @@ static ngx_str_t ngx_http_status_lines[] = { ngx_null_string, /* "305 Use Proxy" */ ngx_null_string, /* "306 unused" */ ngx_string("307 Temporary Redirect"), + ngx_string("308 Permanent Redirect"), -#define NGX_HTTP_LAST_3XX 308 +#define NGX_HTTP_LAST_3XX 309 #define NGX_HTTP_OFF_4XX (NGX_HTTP_LAST_3XX - 301 + NGX_HTTP_OFF_3XX) ngx_string("400 Bad Request"), @@ -100,12 +102,16 @@ static ngx_str_t ngx_http_status_lines[] = { ngx_null_string, /* "419 unused" */ ngx_null_string, /* "420 unused" */ ngx_string("421 Misdirected Request"), - - /* ngx_null_string, */ /* "422 Unprocessable Entity" */ - /* ngx_null_string, */ /* "423 Locked" */ - /* ngx_null_string, */ /* "424 Failed Dependency" */ - -#define NGX_HTTP_LAST_4XX 422 + ngx_null_string, /* "422 Unprocessable Entity" */ + ngx_null_string, /* "423 Locked" */ + ngx_null_string, /* "424 Failed Dependency" */ + ngx_null_string, /* "425 unused" */ + ngx_null_string, /* "426 Upgrade Required" */ + ngx_null_string, /* "427 unused" */ + ngx_null_string, /* "428 Precondition Required" */ + ngx_string("429 Too Many Requests"), + +#define NGX_HTTP_LAST_4XX 430 #define NGX_HTTP_OFF_5XX (NGX_HTTP_LAST_4XX - 400 + NGX_HTTP_OFF_4XX) ngx_string("500 Internal Server Error"), @@ -113,7 +119,7 @@ static ngx_str_t ngx_http_status_lines[] = { ngx_string("502 Bad Gateway"), ngx_string("503 Service Temporarily Unavailable"), ngx_string("504 Gateway Time-out"), - ngx_null_string, /* "505 HTTP Version Not Supported" */ + ngx_string("505 HTTP Version Not Supported"), ngx_null_string, /* "506 Variant Also Negotiates" */ ngx_string("507 Insufficient Storage"), @@ -274,8 +280,15 @@ ngx_http_header_filter(ngx_http_request_t *r) clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); if (r->headers_out.server == NULL) { - len += clcf->server_tokens ? sizeof(ngx_http_server_full_string) - 1: - sizeof(ngx_http_server_string) - 1; + if (clcf->server_tokens == NGX_HTTP_SERVER_TOKENS_ON) { + len += sizeof(ngx_http_server_full_string) - 1; + + } else if (clcf->server_tokens == NGX_HTTP_SERVER_TOKENS_BUILD) { + len += sizeof(ngx_http_server_build_string) - 1; + + } else { + len += sizeof(ngx_http_server_string) - 1; + } } if (r->headers_out.date == NULL) { @@ -309,7 +322,8 @@ ngx_http_header_filter(ngx_http_request_t *r) if (r->headers_out.location && r->headers_out.location->value.len - && r->headers_out.location->value.data[0] == '/') + && r->headers_out.location->value.data[0] == '/' + && clcf->absolute_redirect) { r->headers_out.location->hash = 0; @@ -435,12 +449,16 @@ ngx_http_header_filter(ngx_http_request_t *r) *b->last++ = CR; *b->last++ = LF; if (r->headers_out.server == NULL) { - if (clcf->server_tokens) { - p = (u_char *) ngx_http_server_full_string; + if (clcf->server_tokens == NGX_HTTP_SERVER_TOKENS_ON) { + p = ngx_http_server_full_string; len = sizeof(ngx_http_server_full_string) - 1; + } else if (clcf->server_tokens == NGX_HTTP_SERVER_TOKENS_BUILD) { + p = ngx_http_server_build_string; + len = sizeof(ngx_http_server_build_string) - 1; + } else { - p = (u_char *) ngx_http_server_string; + p = ngx_http_server_string; len = sizeof(ngx_http_server_string) - 1; } diff --git a/src/http/ngx_http_parse.c b/src/http/ngx_http_parse.c index 9f994731611..844054c9dc7 100644 --- a/src/http/ngx_http_parse.c +++ b/src/http/ngx_http_parse.c @@ -723,6 +723,11 @@ ngx_http_parse_request_line(ngx_http_request_t *r, ngx_buf_t *b) } r->http_major = ch - '0'; + + if (r->http_major > 1) { + return NGX_HTTP_PARSE_INVALID_VERSION; + } + state = sw_major_digit; break; @@ -737,11 +742,12 @@ ngx_http_parse_request_line(ngx_http_request_t *r, ngx_buf_t *b) return NGX_HTTP_PARSE_INVALID_REQUEST; } - if (r->http_major > 99) { - return NGX_HTTP_PARSE_INVALID_REQUEST; + r->http_major = r->http_major * 10 + (ch - '0'); + + if (r->http_major > 1) { + return NGX_HTTP_PARSE_INVALID_VERSION; } - r->http_major = r->http_major * 10 + ch - '0'; break; /* first digit of minor HTTP version */ @@ -778,7 +784,7 @@ ngx_http_parse_request_line(ngx_http_request_t *r, ngx_buf_t *b) return NGX_HTTP_PARSE_INVALID_REQUEST; } - r->http_minor = r->http_minor * 10 + ch - '0'; + r->http_minor = r->http_minor * 10 + (ch - '0'); break; case sw_spaces_after_digit: @@ -1390,6 +1396,7 @@ ngx_http_parse_complex_uri(ngx_http_request_t *r, ngx_uint_t merge_slashes) goto done; case '+': r->plus_in_uri = 1; + /* fall through */ default: state = sw_usual; *u++ = ch; @@ -1431,6 +1438,7 @@ ngx_http_parse_complex_uri(ngx_http_request_t *r, ngx_uint_t merge_slashes) goto done; case '+': r->plus_in_uri = 1; + /* fall through */ default: state = sw_usual; *u++ = ch; @@ -1478,6 +1486,7 @@ ngx_http_parse_complex_uri(ngx_http_request_t *r, ngx_uint_t merge_slashes) goto done; case '+': r->plus_in_uri = 1; + /* fall through */ default: state = sw_usual; *u++ = ch; @@ -1509,7 +1518,7 @@ ngx_http_parse_complex_uri(ngx_http_request_t *r, ngx_uint_t merge_slashes) case sw_quoted_second: if (ch >= '0' && ch <= '9') { - ch = (u_char) ((decoded << 4) + ch - '0'); + ch = (u_char) ((decoded << 4) + (ch - '0')); if (ch == '%' || ch == '#') { state = sw_usual; @@ -1527,7 +1536,7 @@ ngx_http_parse_complex_uri(ngx_http_request_t *r, ngx_uint_t merge_slashes) c = (u_char) (ch | 0x20); if (c >= 'a' && c <= 'f') { - ch = (u_char) ((decoded << 4) + c - 'a' + 10); + ch = (u_char) ((decoded << 4) + (c - 'a') + 10); if (ch == '?') { state = sw_usual; @@ -1692,7 +1701,7 @@ ngx_http_parse_status_line(ngx_http_request_t *r, ngx_buf_t *b, return NGX_ERROR; } - r->http_major = r->http_major * 10 + ch - '0'; + r->http_major = r->http_major * 10 + (ch - '0'); break; /* the first digit of minor HTTP version */ @@ -1720,7 +1729,7 @@ ngx_http_parse_status_line(ngx_http_request_t *r, ngx_buf_t *b, return NGX_ERROR; } - r->http_minor = r->http_minor * 10 + ch - '0'; + r->http_minor = r->http_minor * 10 + (ch - '0'); break; /* HTTP status code */ @@ -1733,7 +1742,7 @@ ngx_http_parse_status_line(ngx_http_request_t *r, ngx_buf_t *b, return NGX_ERROR; } - status->code = status->code * 10 + ch - '0'; + status->code = status->code * 10 + (ch - '0'); if (++status->count == 3) { state = sw_space_after_status; diff --git a/src/http/ngx_http_postpone_filter_module.c b/src/http/ngx_http_postpone_filter_module.c index e893b836488..55f2698c5e6 100644 --- a/src/http/ngx_http_postpone_filter_module.c +++ b/src/http/ngx_http_postpone_filter_module.c @@ -63,7 +63,10 @@ ngx_http_postpone_filter(ngx_http_request_t *r, ngx_chain_t *in) if (r != c->data) { if (in) { - ngx_http_postpone_filter_add(r, in); + if (ngx_http_postpone_filter_add(r, in) != NGX_OK) { + return NGX_ERROR; + } + return NGX_OK; } @@ -86,7 +89,9 @@ ngx_http_postpone_filter(ngx_http_request_t *r, ngx_chain_t *in) } if (in) { - ngx_http_postpone_filter_add(r, in); + if (ngx_http_postpone_filter_add(r, in) != NGX_OK) { + return NGX_ERROR; + } } do { diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c index 6ff7903db47..de1b20270a8 100644 --- a/src/http/ngx_http_request.c +++ b/src/http/ngx_http_request.c @@ -72,6 +72,9 @@ static char *ngx_http_client_errors[] = { /* NGX_HTTP_PARSE_INVALID_REQUEST */ "client sent invalid request", + /* NGX_HTTP_PARSE_INVALID_VERSION */ + "client sent invalid version", + /* NGX_HTTP_PARSE_INVALID_09_METHOD */ "client sent invalid method in HTTP/0.9 request" }; @@ -549,7 +552,7 @@ ngx_http_create_request(ngx_connection_t *c) ngx_set_connection_log(r->connection, clcf->error_log); - r->header_in = hc->nbusy ? hc->busy[0] : c->buffer; + r->header_in = hc->busy ? hc->busy->buf : c->buffer; if (ngx_list_init(&r->headers_out.headers, r->pool, 20, sizeof(ngx_table_elt_t)) @@ -559,6 +562,14 @@ ngx_http_create_request(ngx_connection_t *c) return NULL; } + if (ngx_list_init(&r->headers_out.trailers, r->pool, 4, + sizeof(ngx_table_elt_t)) + != NGX_OK) + { + ngx_destroy_pool(r->pool); + return NULL; + } + r->ctx = ngx_pcalloc(r->pool, sizeof(void *) * ngx_http_max_module); if (r->ctx == NULL) { ngx_destroy_pool(r->pool); @@ -620,14 +631,15 @@ ngx_http_create_request(ngx_connection_t *c) static void ngx_http_ssl_handshake(ngx_event_t *rev) { - u_char *p, buf[NGX_PROXY_PROTOCOL_MAX_HEADER + 1]; - size_t size; - ssize_t n; - ngx_err_t err; - ngx_int_t rc; - ngx_connection_t *c; - ngx_http_connection_t *hc; - ngx_http_ssl_srv_conf_t *sscf; + u_char *p, buf[NGX_PROXY_PROTOCOL_MAX_HEADER + 1]; + size_t size; + ssize_t n; + ngx_err_t err; + ngx_int_t rc; + ngx_connection_t *c; + ngx_http_connection_t *hc; + ngx_http_ssl_srv_conf_t *sscf; + ngx_http_core_loc_conf_t *clcf; c = rev->data; hc = c->data; @@ -709,6 +721,14 @@ ngx_http_ssl_handshake(ngx_event_t *rev) ngx_log_debug1(NGX_LOG_DEBUG_HTTP, rev->log, 0, "https ssl handshake: 0x%02Xd", buf[0]); + clcf = ngx_http_get_module_loc_conf(hc->conf_ctx, + ngx_http_core_module); + + if (clcf->tcp_nodelay && ngx_tcp_nodelay(c) != NGX_OK) { + ngx_http_close_connection(c); + return; + } + sscf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_ssl_module); @@ -884,6 +904,8 @@ ngx_http_ssl_servername(ngx_ssl_conn_t *ssl_conn, int *ad, void *arg) sscf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_ssl_module); + c->ssl->buffer_size = sscf->buffer_size; + if (sscf->ssl.ctx) { SSL_set_SSL_CTX(ssl_conn, sscf->ssl.ctx); @@ -1034,7 +1056,14 @@ ngx_http_process_request_line(ngx_event_t *rev) ngx_log_error(NGX_LOG_INFO, c->log, 0, ngx_http_client_errors[rc - NGX_HTTP_CLIENT_ERROR]); - ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST); + + if (rc == NGX_HTTP_PARSE_INVALID_VERSION) { + ngx_http_finalize_request(r, NGX_HTTP_VERSION_NOT_SUPPORTED); + + } else { + ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST); + } + return; } @@ -1429,6 +1458,7 @@ ngx_http_alloc_large_header_buffer(ngx_http_request_t *r, { u_char *old, *new; ngx_buf_t *b; + ngx_chain_t *cl; ngx_http_connection_t *hc; ngx_http_core_srv_conf_t *cscf; @@ -1458,8 +1488,11 @@ ngx_http_alloc_large_header_buffer(ngx_http_request_t *r, hc = r->http_connection; - if (hc->nfree) { - b = hc->free[--hc->nfree]; + if (hc->free) { + cl = hc->free; + hc->free = cl->next; + + b = cl->buf; ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http large header free: %p %uz", @@ -1467,20 +1500,19 @@ ngx_http_alloc_large_header_buffer(ngx_http_request_t *r, } else if (hc->nbusy < cscf->large_client_header_buffers.num) { - if (hc->busy == NULL) { - hc->busy = ngx_palloc(r->connection->pool, - cscf->large_client_header_buffers.num * sizeof(ngx_buf_t *)); - if (hc->busy == NULL) { - return NGX_ERROR; - } - } - b = ngx_create_temp_buf(r->connection->pool, cscf->large_client_header_buffers.size); if (b == NULL) { return NGX_ERROR; } + cl = ngx_alloc_chain_link(r->connection->pool); + if (cl == NULL) { + return NGX_ERROR; + } + + cl->buf = b; + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http large header alloc: %p %uz", b->pos, b->end - b->last); @@ -1489,7 +1521,9 @@ ngx_http_alloc_large_header_buffer(ngx_http_request_t *r, return NGX_DECLINED; } - hc->busy[hc->nbusy++] = b; + cl->next = hc->busy; + hc->busy = cl; + hc->nbusy++; if (r->state == 0) { /* @@ -2191,6 +2225,11 @@ ngx_http_request_handler(ngx_event_t *ev) ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, "http run request: \"%V?%V\"", &r->uri, &r->args); + if (ev->delayed && ev->timedout) { + ev->delayed = 0; + ev->timedout = 0; + } + if (ev->write) { r->write_event_handler(r); @@ -2300,10 +2339,6 @@ ngx_http_finalize_request(ngx_http_request_t *r, ngx_int_t rc) return; } - if (r->main->blocked) { - r->write_event_handler = ngx_http_request_finalizer; - } - ngx_http_terminate_request(r, rc); return; } @@ -2335,6 +2370,26 @@ ngx_http_finalize_request(ngx_http_request_t *r, ngx_int_t rc) } if (r != r->main) { + clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); + + if (r->background) { + if (!r->logged) { + if (clcf->log_subrequest) { + ngx_http_log_request(r); + } + + r->logged = 1; + + } else { + ngx_log_error(NGX_LOG_ALERT, c->log, 0, + "subrequest: \"%V?%V\" logged again", + &r->uri, &r->args); + } + + r->done = 1; + ngx_http_finalize_connection(r); + return; + } if (r->buffered || r->postponed) { @@ -2352,9 +2407,6 @@ ngx_http_finalize_request(ngx_http_request_t *r, ngx_int_t rc) r->main->count--; if (!r->logged) { - - clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); - if (clcf->log_subrequest) { ngx_http_log_request(r); } @@ -2401,7 +2453,7 @@ ngx_http_finalize_request(ngx_http_request_t *r, ngx_int_t rc) return; } - if (r->buffered || c->buffered || r->postponed || r->blocked) { + if (r->buffered || c->buffered || r->postponed) { if (ngx_http_set_write_handler(r) != NGX_OK) { ngx_http_terminate_request(r, 0); @@ -2418,6 +2470,8 @@ ngx_http_finalize_request(ngx_http_request_t *r, ngx_int_t rc) } r->done = 1; + + r->read_event_handler = ngx_http_block_reading; r->write_event_handler = ngx_http_request_empty_handler; if (!r->post_action) { @@ -2480,6 +2534,8 @@ ngx_http_terminate_request(ngx_http_request_t *r, ngx_int_t rc) if (mr->write_event_handler) { if (mr->blocked) { + r->connection->error = 1; + r->write_event_handler = ngx_http_request_finalizer; return; } @@ -2536,6 +2592,8 @@ ngx_http_finalize_connection(ngx_http_request_t *r) return; } + r = r->main; + if (r->reading_body) { r->keepalive = 0; r->lingering_close = 1; @@ -2600,7 +2658,7 @@ ngx_http_set_write_handler(ngx_http_request_t *r) static void ngx_http_writer(ngx_http_request_t *r) { - int rc; + ngx_int_t rc; ngx_event_t *wev; ngx_connection_t *c; ngx_http_core_loc_conf_t *clcf; @@ -2614,34 +2672,22 @@ ngx_http_writer(ngx_http_request_t *r) clcf = ngx_http_get_module_loc_conf(r->main, ngx_http_core_module); if (wev->timedout) { - if (!wev->delayed) { - ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, - "client timed out"); - c->timedout = 1; - - ngx_http_finalize_request(r, NGX_HTTP_REQUEST_TIME_OUT); - return; - } - - wev->timedout = 0; - wev->delayed = 0; - - if (!wev->ready) { - ngx_add_timer(wev, clcf->send_timeout); - - if (ngx_handle_write_event(wev, clcf->send_lowat) != NGX_OK) { - ngx_http_close_request(r, 0); - } - - return; - } + ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, + "client timed out"); + c->timedout = 1; + ngx_http_finalize_request(r, NGX_HTTP_REQUEST_TIME_OUT); + return; } if (wev->delayed || r->aio) { ngx_log_debug0(NGX_LOG_DEBUG_HTTP, wev->log, 0, "http writer delayed"); + if (!wev->delayed) { + ngx_add_timer(wev, clcf->send_timeout); + } + if (ngx_handle_write_event(wev, clcf->send_lowat) != NGX_OK) { ngx_http_close_request(r, 0); } @@ -2652,7 +2698,7 @@ ngx_http_writer(ngx_http_request_t *r) rc = ngx_http_output_filter(r, NULL); ngx_log_debug3(NGX_LOG_DEBUG_HTTP, c->log, 0, - "http writer output filter: %d, \"%V?%V\"", + "http writer output filter: %i, \"%V?%V\"", rc, &r->uri, &r->args); if (rc == NGX_ERROR) { @@ -2833,12 +2879,11 @@ static void ngx_http_set_keepalive(ngx_http_request_t *r) { int tcp_nodelay; - ngx_int_t i; ngx_buf_t *b, *f; + ngx_chain_t *cl, *ln; ngx_event_t *rev, *wev; ngx_connection_t *c; ngx_http_connection_t *hc; - ngx_http_core_srv_conf_t *cscf; ngx_http_core_loc_conf_t *clcf; c = r->connection; @@ -2874,26 +2919,33 @@ ngx_http_set_keepalive(ngx_http_request_t *r) * Now we would move the large header buffers to the free list. */ - cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module); - - if (hc->free == NULL) { - hc->free = ngx_palloc(c->pool, - cscf->large_client_header_buffers.num * sizeof(ngx_buf_t *)); + for (cl = hc->busy; cl; /* void */) { + ln = cl; + cl = cl->next; - if (hc->free == NULL) { - ngx_http_close_request(r, 0); - return; + if (ln->buf == b) { + ngx_free_chain(c->pool, ln); + continue; } - } - for (i = 0; i < hc->nbusy - 1; i++) { - f = hc->busy[i]; - hc->free[hc->nfree++] = f; + f = ln->buf; f->pos = f->start; f->last = f->start; + + ln->next = hc->free; + hc->free = ln; + } + + cl = ngx_alloc_chain_link(c->pool); + if (cl == NULL) { + ngx_http_close_request(r, 0); + return; } - hc->busy[0] = b; + cl->buf = b; + cl->next = NULL; + + hc->busy = cl; hc->nbusy = 1; } } @@ -2964,27 +3016,32 @@ ngx_http_set_keepalive(ngx_http_request_t *r) b->last = b->start; } - ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, "hc free: %p %i", - hc->free, hc->nfree); + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, "hc free: %p", + hc->free); if (hc->free) { - for (i = 0; i < hc->nfree; i++) { - ngx_pfree(c->pool, hc->free[i]->start); - hc->free[i] = NULL; + for (cl = hc->free; cl; /* void */) { + ln = cl; + cl = cl->next; + ngx_pfree(c->pool, ln->buf->start); + ngx_free_chain(c->pool, ln); } - hc->nfree = 0; + hc->free = NULL; } ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, "hc busy: %p %i", hc->busy, hc->nbusy); if (hc->busy) { - for (i = 0; i < hc->nbusy; i++) { - ngx_pfree(c->pool, hc->busy[i]->start); - hc->busy[i] = NULL; + for (cl = hc->busy; cl; /* void */) { + ln = cl; + cl = cl->next; + ngx_pfree(c->pool, ln->buf->start); + ngx_free_chain(c->pool, ln); } + hc->busy = NULL; hc->nbusy = 0; } @@ -3019,30 +3076,9 @@ ngx_http_set_keepalive(ngx_http_request_t *r) tcp_nodelay = 1; } - if (tcp_nodelay - && clcf->tcp_nodelay - && c->tcp_nodelay == NGX_TCP_NODELAY_UNSET) - { - ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "tcp_nodelay"); - - if (setsockopt(c->fd, IPPROTO_TCP, TCP_NODELAY, - (const void *) &tcp_nodelay, sizeof(int)) - == -1) - { -#if (NGX_SOLARIS) - /* Solaris returns EINVAL if a socket has been shut down */ - c->log_error = NGX_ERROR_IGNORE_EINVAL; -#endif - - ngx_connection_error(c, ngx_socket_errno, - "setsockopt(TCP_NODELAY) failed"); - - c->log_error = NGX_ERROR_INFO; - ngx_http_close_connection(c); - return; - } - - c->tcp_nodelay = NGX_TCP_NODELAY_SET; + if (tcp_nodelay && clcf->tcp_nodelay && ngx_tcp_nodelay(c) != NGX_OK) { + ngx_http_close_connection(c); + return; } #if 0 diff --git a/src/http/ngx_http_request.h b/src/http/ngx_http_request.h index cf9ee3c61cc..421004a0d75 100644 --- a/src/http/ngx_http_request.h +++ b/src/http/ngx_http_request.h @@ -54,15 +54,19 @@ #define NGX_HTTP_CLIENT_ERROR 10 #define NGX_HTTP_PARSE_INVALID_METHOD 10 #define NGX_HTTP_PARSE_INVALID_REQUEST 11 -#define NGX_HTTP_PARSE_INVALID_09_METHOD 12 +#define NGX_HTTP_PARSE_INVALID_VERSION 12 +#define NGX_HTTP_PARSE_INVALID_09_METHOD 13 -#define NGX_HTTP_PARSE_INVALID_HEADER 13 +#define NGX_HTTP_PARSE_INVALID_HEADER 14 /* unused 1 */ #define NGX_HTTP_SUBREQUEST_IN_MEMORY 2 #define NGX_HTTP_SUBREQUEST_WAITED 4 -#define NGX_HTTP_LOG_UNSAFE 8 +#define NGX_HTTP_SUBREQUEST_CLONE 8 +#define NGX_HTTP_SUBREQUEST_BACKGROUND 16 + +#define NGX_HTTP_LOG_UNSAFE 1 #define NGX_HTTP_CONTINUE 100 @@ -81,6 +85,7 @@ #define NGX_HTTP_SEE_OTHER 303 #define NGX_HTTP_NOT_MODIFIED 304 #define NGX_HTTP_TEMPORARY_REDIRECT 307 +#define NGX_HTTP_PERMANENT_REDIRECT 308 #define NGX_HTTP_BAD_REQUEST 400 #define NGX_HTTP_UNAUTHORIZED 401 @@ -96,6 +101,7 @@ #define NGX_HTTP_UNSUPPORTED_MEDIA_TYPE 415 #define NGX_HTTP_RANGE_NOT_SATISFIABLE 416 #define NGX_HTTP_MISDIRECTED_REQUEST 421 +#define NGX_HTTP_TOO_MANY_REQUESTS 429 /* Our own HTTP codes */ @@ -132,6 +138,7 @@ #define NGX_HTTP_BAD_GATEWAY 502 #define NGX_HTTP_SERVICE_UNAVAILABLE 503 #define NGX_HTTP_GATEWAY_TIME_OUT 504 +#define NGX_HTTP_VERSION_NOT_SUPPORTED 505 #define NGX_HTTP_INSUFFICIENT_STORAGE 507 @@ -245,6 +252,7 @@ typedef struct { typedef struct { ngx_list_t headers; + ngx_list_t trailers; ngx_uint_t status; ngx_str_t status_line; @@ -307,11 +315,10 @@ typedef struct { #endif #endif - ngx_buf_t **busy; + ngx_chain_t *busy; ngx_int_t nbusy; - ngx_buf_t **free; - ngx_int_t nfree; + ngx_chain_t *free; unsigned ssl:1; unsigned proxy_protocol:1; @@ -508,6 +515,7 @@ struct ngx_http_request_s { unsigned pipeline:1; unsigned chunked:1; unsigned header_only:1; + unsigned expect_trailers:1; unsigned keepalive:1; unsigned lingering_close:1; unsigned discard_body:1; @@ -529,6 +537,7 @@ struct ngx_http_request_s { unsigned main_filter_need_in_memory:1; unsigned filter_need_in_memory:1; unsigned filter_need_temporary:1; + unsigned preserve_body:1; unsigned allow_ranges:1; unsigned subrequest_ranges:1; unsigned single_range:1; @@ -537,6 +546,7 @@ struct ngx_http_request_s { unsigned stat_writing:1; unsigned stat_processing:1; + unsigned background:1; unsigned health_check:1; /* used to parse HTTP headers */ diff --git a/src/http/ngx_http_request_body.c b/src/http/ngx_http_request_body.c index 0641329c532..c4f092e59b1 100644 --- a/src/http/ngx_http_request_body.c +++ b/src/http/ngx_http_request_body.c @@ -46,13 +46,6 @@ ngx_http_read_client_request_body(ngx_http_request_t *r, return NGX_OK; } -#if (NGX_HTTP_V2) - if (r->stream) { - rc = ngx_http_v2_read_request_body(r, post_handler); - goto done; - } -#endif - if (ngx_http_test_expect(r) != NGX_OK) { rc = NGX_HTTP_INTERNAL_SERVER_ERROR; goto done; @@ -85,6 +78,13 @@ ngx_http_read_client_request_body(ngx_http_request_t *r, return NGX_OK; } +#if (NGX_HTTP_V2) + if (r->stream) { + rc = ngx_http_v2_read_request_body(r); + goto done; + } +#endif + preread = r->header_in->last - r->header_in->pos; if (preread) { @@ -805,7 +805,11 @@ ngx_http_test_expect(ngx_http_request_t *r) if (r->expect_tested || r->headers_in.expect == NULL - || r->http_version < NGX_HTTP_VERSION_11) + || r->http_version < NGX_HTTP_VERSION_11 +#if (NGX_HTTP_V2) + || r->stream != NULL +#endif + ) { return NGX_OK; } @@ -835,6 +839,8 @@ ngx_http_test_expect(ngx_http_request_t *r) /* we assume that such small packet should be send successfully */ + r->connection->error = 1; + return NGX_ERROR; } @@ -1085,6 +1091,7 @@ ngx_http_request_body_save_filter(ngx_http_request_t *r, ngx_chain_t *in) #if (NGX_DEBUG) +#if 0 for (cl = rb->bufs; cl; cl = cl->next) { ngx_log_debug7(NGX_LOG_DEBUG_EVENT, r->connection->log, 0, "http body old buf t:%d f:%d %p, pos %p, size: %z " @@ -1095,6 +1102,7 @@ ngx_http_request_body_save_filter(ngx_http_request_t *r, ngx_chain_t *in) cl->buf->file_pos, cl->buf->file_last - cl->buf->file_pos); } +#endif for (cl = in; cl; cl = cl->next) { ngx_log_debug7(NGX_LOG_DEBUG_EVENT, r->connection->log, 0, diff --git a/src/http/ngx_http_script.c b/src/http/ngx_http_script.c index c2b165801a0..96f3ec69651 100644 --- a/src/http/ngx_http_script.c +++ b/src/http/ngx_http_script.c @@ -220,7 +220,7 @@ ngx_http_set_complex_value_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) cv = (ngx_http_complex_value_t **) (p + cmd->offset); if (*cv != NULL) { - return "duplicate"; + return "is duplicate"; } *cv = ngx_palloc(cf->pool, sizeof(ngx_http_complex_value_t)); @@ -356,11 +356,11 @@ ngx_http_script_compile(ngx_http_script_compile_t *sc) n = sc->source->data[i] - '0'; - if (sc->captures_mask & (1 << n)) { + if (sc->captures_mask & ((ngx_uint_t) 1 << n)) { sc->dup_capture = 1; } - sc->captures_mask |= 1 << n; + sc->captures_mask |= (ngx_uint_t) 1 << n; if (ngx_http_script_add_capture_code(sc, n) != NGX_OK) { return NGX_ERROR; @@ -1513,6 +1513,12 @@ ngx_http_script_file_code(ngx_http_script_engine_t *e) if (ngx_open_cached_file(clcf->open_file_cache, &path, &of, r->pool) != NGX_OK) { + if (of.err == 0) { + e->ip = ngx_http_script_exit; + e->status = NGX_HTTP_INTERNAL_SERVER_ERROR; + return; + } + if (of.err != NGX_ENOENT && of.err != NGX_ENOTDIR && of.err != NGX_ENAMETOOLONG) diff --git a/src/http/ngx_http_script.h b/src/http/ngx_http_script.h index 46592ab0155..a5116d74761 100644 --- a/src/http/ngx_http_script.h +++ b/src/http/ngx_http_script.h @@ -121,16 +121,16 @@ typedef struct { uintptr_t status; uintptr_t next; - uintptr_t test:1; - uintptr_t negative_test:1; - uintptr_t uri:1; - uintptr_t args:1; + unsigned test:1; + unsigned negative_test:1; + unsigned uri:1; + unsigned args:1; /* add the r->args to the new arguments */ - uintptr_t add_args:1; + unsigned add_args:1; - uintptr_t redirect:1; - uintptr_t break_cycle:1; + unsigned redirect:1; + unsigned break_cycle:1; ngx_str_t name; } ngx_http_script_regex_code_t; @@ -139,13 +139,13 @@ typedef struct { typedef struct { ngx_http_script_code_pt code; - uintptr_t uri:1; - uintptr_t args:1; + unsigned uri:1; + unsigned args:1; /* add the r->args to the new arguments */ - uintptr_t add_args:1; + unsigned add_args:1; - uintptr_t redirect:1; + unsigned redirect:1; } ngx_http_script_regex_end_code_t; #endif diff --git a/src/http/ngx_http_special_response.c b/src/http/ngx_http_special_response.c index 7692f801f2c..2c1ff17439f 100644 --- a/src/http/ngx_http_special_response.c +++ b/src/http/ngx_http_special_response.c @@ -25,6 +25,13 @@ static u_char ngx_http_error_full_tail[] = ; +static u_char ngx_http_error_build_tail[] = +"
" NGINX_VER_BUILD "
" CRLF +"" CRLF +"" CRLF +; + + static u_char ngx_http_error_tail[] = "
nginx
" CRLF "" CRLF @@ -82,6 +89,14 @@ static char ngx_http_error_307_page[] = ; +static char ngx_http_error_308_page[] = +"" CRLF +"308 Permanent Redirect" CRLF +"" CRLF +"

308 Permanent Redirect

" CRLF +; + + static char ngx_http_error_400_page[] = "" CRLF "400 Bad Request" CRLF @@ -218,6 +233,14 @@ static char ngx_http_error_421_page[] = ; +static char ngx_http_error_429_page[] = +"" CRLF +"429 Too Many Requests" CRLF +"" CRLF +"

429 Too Many Requests

" CRLF +; + + static char ngx_http_error_494_page[] = "" CRLF "400 Request Header Or Cookie Too Large" @@ -298,6 +321,14 @@ static char ngx_http_error_504_page[] = ; +static char ngx_http_error_505_page[] = +"" CRLF +"505 HTTP Version Not Supported" CRLF +"" CRLF +"

505 HTTP Version Not Supported

" CRLF +; + + static char ngx_http_error_507_page[] = "" CRLF "507 Insufficient Storage" CRLF @@ -321,8 +352,9 @@ static ngx_str_t ngx_http_error_pages[] = { ngx_null_string, /* 305 */ ngx_null_string, /* 306 */ ngx_string(ngx_http_error_307_page), + ngx_string(ngx_http_error_308_page), -#define NGX_HTTP_LAST_3XX 308 +#define NGX_HTTP_LAST_3XX 309 #define NGX_HTTP_OFF_4XX (NGX_HTTP_LAST_3XX - 301 + NGX_HTTP_OFF_3XX) ngx_string(ngx_http_error_400_page), @@ -347,8 +379,16 @@ static ngx_str_t ngx_http_error_pages[] = { ngx_null_string, /* 419 */ ngx_null_string, /* 420 */ ngx_string(ngx_http_error_421_page), - -#define NGX_HTTP_LAST_4XX 422 + ngx_null_string, /* 422 */ + ngx_null_string, /* 423 */ + ngx_null_string, /* 424 */ + ngx_null_string, /* 425 */ + ngx_null_string, /* 426 */ + ngx_null_string, /* 427 */ + ngx_null_string, /* 428 */ + ngx_string(ngx_http_error_429_page), + +#define NGX_HTTP_LAST_4XX 430 #define NGX_HTTP_OFF_5XX (NGX_HTTP_LAST_4XX - 400 + NGX_HTTP_OFF_4XX) ngx_string(ngx_http_error_494_page), /* 494, request header too large */ @@ -363,7 +403,7 @@ static ngx_str_t ngx_http_error_pages[] = { ngx_string(ngx_http_error_502_page), ngx_string(ngx_http_error_503_page), ngx_string(ngx_http_error_504_page), - ngx_null_string, /* 505 */ + ngx_string(ngx_http_error_505_page), ngx_null_string, /* 506 */ ngx_string(ngx_http_error_507_page) @@ -473,7 +513,6 @@ ngx_http_special_response_handler(ngx_http_request_t *r, ngx_int_t error) case NGX_HTTPS_NO_CERT: case NGX_HTTP_REQUEST_HEADER_TOO_LARGE: r->err_status = NGX_HTTP_BAD_REQUEST; - break; } } else { @@ -593,7 +632,8 @@ ngx_http_send_error_page(ngx_http_request_t *r, ngx_http_err_page_t *err_page) if (overwrite != NGX_HTTP_MOVED_PERMANENTLY && overwrite != NGX_HTTP_MOVED_TEMPORARILY && overwrite != NGX_HTTP_SEE_OTHER - && overwrite != NGX_HTTP_TEMPORARY_REDIRECT) + && overwrite != NGX_HTTP_TEMPORARY_REDIRECT + && overwrite != NGX_HTTP_PERMANENT_REDIRECT) { r->err_status = NGX_HTTP_MOVED_TEMPORARILY; } @@ -629,10 +669,14 @@ ngx_http_send_special_response(ngx_http_request_t *r, ngx_uint_t msie_padding; ngx_chain_t out[3]; - if (clcf->server_tokens) { + if (clcf->server_tokens == NGX_HTTP_SERVER_TOKENS_ON) { len = sizeof(ngx_http_error_full_tail) - 1; tail = ngx_http_error_full_tail; + } else if (clcf->server_tokens == NGX_HTTP_SERVER_TOKENS_BUILD) { + len = sizeof(ngx_http_error_build_tail) - 1; + tail = ngx_http_error_build_tail; + } else { len = sizeof(ngx_http_error_tail) - 1; tail = ngx_http_error_tail; diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c index addd8075d85..75f463ba799 100644 --- a/src/http/ngx_http_upstream.c +++ b/src/http/ngx_http_upstream.c @@ -17,6 +17,10 @@ static ngx_int_t ngx_http_upstream_cache_get(ngx_http_request_t *r, ngx_http_upstream_t *u, ngx_http_file_cache_t **cache); static ngx_int_t ngx_http_upstream_cache_send(ngx_http_request_t *r, ngx_http_upstream_t *u); +static ngx_int_t ngx_http_upstream_cache_background_update( + ngx_http_request_t *r, ngx_http_upstream_t *u); +static ngx_int_t ngx_http_upstream_cache_check_range(ngx_http_request_t *r, + ngx_http_upstream_t *u); static ngx_int_t ngx_http_upstream_cache_status(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); static ngx_int_t ngx_http_upstream_cache_last_modified(ngx_http_request_t *r, @@ -160,6 +164,10 @@ 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 ngx_int_t ngx_http_upstream_response_length_variable( ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_http_upstream_header_variable(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_http_upstream_cookie_variable(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); static char *ngx_http_upstream(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy); static char *ngx_http_upstream_server(ngx_conf_t *cf, ngx_command_t *cmd, @@ -174,13 +182,15 @@ static char *ngx_http_upstream_init_main_conf(ngx_conf_t *cf, void *conf); #if (NGX_HTTP_SSL) static void ngx_http_upstream_ssl_init_connection(ngx_http_request_t *, ngx_http_upstream_t *u, ngx_connection_t *c); -static void ngx_http_upstream_ssl_handshake(ngx_connection_t *c); +static void ngx_http_upstream_ssl_handshake_handler(ngx_connection_t *c); +static void ngx_http_upstream_ssl_handshake(ngx_http_request_t *, + ngx_http_upstream_t *u, ngx_connection_t *c); static ngx_int_t ngx_http_upstream_ssl_name(ngx_http_request_t *r, ngx_http_upstream_t *u, ngx_connection_t *c); #endif -ngx_http_upstream_header_t ngx_http_upstream_headers_in[] = { +static ngx_http_upstream_header_t ngx_http_upstream_headers_in[] = { { ngx_string("Status"), ngx_http_upstream_process_header_line, @@ -411,7 +421,13 @@ static ngx_http_variable_t ngx_http_upstream_vars[] = { #endif - { ngx_null_string, NULL, NULL, 0, 0, 0 } + { ngx_string("upstream_http_"), NULL, ngx_http_upstream_header_variable, + 0, NGX_HTTP_VAR_NOCACHEABLE|NGX_HTTP_VAR_PREFIX, 0 }, + + { ngx_string("upstream_cookie_"), NULL, ngx_http_upstream_cookie_variable, + 0, NGX_HTTP_VAR_NOCACHEABLE|NGX_HTTP_VAR_PREFIX, 0 }, + + ngx_http_null_variable }; @@ -422,6 +438,7 @@ static ngx_http_upstream_next_t ngx_http_upstream_next_errors[] = { { 504, NGX_HTTP_UPSTREAM_FT_HTTP_504 }, { 403, NGX_HTTP_UPSTREAM_FT_HTTP_403 }, { 404, NGX_HTTP_UPSTREAM_FT_HTTP_404 }, + { 429, NGX_HTTP_UPSTREAM_FT_HTTP_429 }, { 0, 0 } }; @@ -565,6 +582,13 @@ ngx_http_upstream_init_request(ngx_http_request_t *r) if (rc == NGX_HTTP_UPSTREAM_INVALID_HEADER) { rc = NGX_DECLINED; r->cached = 0; + u->buffer.start = NULL; + u->cache_status = NGX_HTTP_CACHE_MISS; + u->request_sent = 1; + } + + if (ngx_http_upstream_cache_background_update(r, u) != NGX_OK) { + rc = NGX_ERROR; } } @@ -857,9 +881,24 @@ ngx_http_upstream_cache(ngx_http_request_t *r, ngx_http_upstream_t *u) switch (rc) { + case NGX_HTTP_CACHE_STALE: + + if (((u->conf->cache_use_stale & NGX_HTTP_UPSTREAM_FT_UPDATING) + || c->stale_updating) && !r->background + && u->conf->cache_background_update) + { + r->cache->background = 1; + u->cache_status = rc; + rc = NGX_OK; + } + + break; + case NGX_HTTP_CACHE_UPDATING: - if (u->conf->cache_use_stale & NGX_HTTP_UPSTREAM_FT_UPDATING) { + if (((u->conf->cache_use_stale & NGX_HTTP_UPSTREAM_FT_UPDATING) + || c->stale_updating) && !r->background) + { u->cache_status = rc; rc = NGX_OK; @@ -882,6 +921,9 @@ ngx_http_upstream_cache(ngx_http_request_t *r, ngx_http_upstream_t *u) case NGX_HTTP_CACHE_STALE: c->valid_sec = 0; + c->updating_sec = 0; + c->error_sec = 0; + u->buffer.start = NULL; u->cache_status = NGX_HTTP_CACHE_EXPIRED; @@ -922,6 +964,10 @@ ngx_http_upstream_cache(ngx_http_request_t *r, ngx_http_upstream_t *u) return rc; } + if (ngx_http_upstream_cache_check_range(r, u) == NGX_DECLINED) { + u->cacheable = 0; + } + r->cached = 0; return NGX_DECLINED; @@ -1016,24 +1062,112 @@ ngx_http_upstream_cache_send(ngx_http_request_t *r, ngx_http_upstream_t *u) return NGX_ERROR; } + if (rc == NGX_AGAIN) { + rc = NGX_HTTP_UPSTREAM_INVALID_HEADER; + } + /* rc == NGX_HTTP_UPSTREAM_INVALID_HEADER */ + ngx_log_error(NGX_LOG_CRIT, r->connection->log, 0, + "cache file \"%s\" contains invalid header", + c->file.name.data); + /* TODO: delete file */ return rc; } + +static ngx_int_t +ngx_http_upstream_cache_background_update(ngx_http_request_t *r, + ngx_http_upstream_t *u) +{ + ngx_http_request_t *sr; + + if (!r->cached || !r->cache->background) { + return NGX_OK; + } + + if (r == r->main) { + r->preserve_body = 1; + } + + if (ngx_http_subrequest(r, &r->uri, &r->args, &sr, NULL, + NGX_HTTP_SUBREQUEST_CLONE + |NGX_HTTP_SUBREQUEST_BACKGROUND) + != NGX_OK) + { + return NGX_ERROR; + } + + sr->header_only = 1; + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_upstream_cache_check_range(ngx_http_request_t *r, + ngx_http_upstream_t *u) +{ + off_t offset; + u_char *p, *start; + ngx_table_elt_t *h; + + h = r->headers_in.range; + + if (h == NULL + || !u->cacheable + || u->conf->cache_max_range_offset == NGX_MAX_OFF_T_VALUE) + { + return NGX_OK; + } + + if (u->conf->cache_max_range_offset == 0) { + return NGX_DECLINED; + } + + if (h->value.len < 7 + || ngx_strncasecmp(h->value.data, (u_char *) "bytes=", 6) != 0) + { + return NGX_OK; + } + + p = h->value.data + 6; + + while (*p == ' ') { p++; } + + if (*p == '-') { + return NGX_DECLINED; + } + + start = p; + + while (*p >= '0' && *p <= '9') { p++; } + + offset = ngx_atoof(start, p - start); + + if (offset >= u->conf->cache_max_range_offset) { + return NGX_DECLINED; + } + + return NGX_OK; +} + #endif static void ngx_http_upstream_resolve_handler(ngx_resolver_ctx_t *ctx) { + ngx_uint_t run_posted; ngx_connection_t *c; ngx_http_request_t *r; ngx_http_upstream_t *u; ngx_http_upstream_resolved_t *ur; + run_posted = ctx->async; + r = ctx->data; c = r->connection; @@ -1097,7 +1231,9 @@ ngx_http_upstream_resolve_handler(ngx_resolver_ctx_t *ctx) failed: - ngx_http_run_posted_requests(c); + if (run_posted) { + ngx_http_run_posted_requests(c); + } } @@ -1119,6 +1255,11 @@ ngx_http_upstream_handler(ngx_event_t *ev) ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, "http upstream request: \"%V?%V\"", &r->uri, &r->args); + if (ev->delayed && ev->timedout) { + ev->delayed = 0; + ev->timedout = 0; + } + if (ev->write) { u->write_event_handler(r, u); @@ -1487,7 +1628,6 @@ static void ngx_http_upstream_ssl_init_connection(ngx_http_request_t *r, ngx_http_upstream_t *u, ngx_connection_t *c) { - int tcp_nodelay; ngx_int_t rc; ngx_http_core_loc_conf_t *clcf; @@ -1527,22 +1667,10 @@ ngx_http_upstream_ssl_init_connection(ngx_http_request_t *r, clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); - if (clcf->tcp_nodelay && c->tcp_nodelay == NGX_TCP_NODELAY_UNSET) { - ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "tcp_nodelay"); - - tcp_nodelay = 1; - - if (setsockopt(c->fd, IPPROTO_TCP, TCP_NODELAY, - (const void *) &tcp_nodelay, sizeof(int)) == -1) - { - ngx_connection_error(c, ngx_socket_errno, - "setsockopt(TCP_NODELAY) failed"); - ngx_http_upstream_finalize_request(r, u, + if (clcf->tcp_nodelay && ngx_tcp_nodelay(c) != NGX_OK) { + ngx_http_upstream_finalize_request(r, u, NGX_HTTP_INTERNAL_SERVER_ERROR); - return; - } - - c->tcp_nodelay = NGX_TCP_NODELAY_SET; + return; } } @@ -1556,26 +1684,43 @@ ngx_http_upstream_ssl_init_connection(ngx_http_request_t *r, ngx_add_timer(c->write, u->conf->connect_timeout); } - c->ssl->handler = ngx_http_upstream_ssl_handshake; + c->ssl->handler = ngx_http_upstream_ssl_handshake_handler; return; } - ngx_http_upstream_ssl_handshake(c); + ngx_http_upstream_ssl_handshake(r, u, c); } static void -ngx_http_upstream_ssl_handshake(ngx_connection_t *c) +ngx_http_upstream_ssl_handshake_handler(ngx_connection_t *c) { - long rc; ngx_http_request_t *r; ngx_http_upstream_t *u; r = c->data; + u = r->upstream; + c = r->connection; ngx_http_set_log_request(c->log, r); + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, + "http upstream ssl handshake: \"%V?%V\"", + &r->uri, &r->args); + + ngx_http_upstream_ssl_handshake(r, u, u->peer.connection); + + ngx_http_run_posted_requests(c); +} + + +static void +ngx_http_upstream_ssl_handshake(ngx_http_request_t *r, ngx_http_upstream_t *u, + ngx_connection_t *c) +{ + long rc; + if (c->ssl->handshaked) { if (u->conf->ssl_verify) { @@ -1603,21 +1748,19 @@ ngx_http_upstream_ssl_handshake(ngx_connection_t *c) c->write->handler = ngx_http_upstream_handler; c->read->handler = ngx_http_upstream_handler; - c = r->connection; - ngx_http_upstream_send_request(r, u, 1); - ngx_http_run_posted_requests(c); return; } -failed: + if (c->write->timedout) { + ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_TIMEOUT); + return; + } - c = r->connection; +failed: ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_ERROR); - - ngx_http_run_posted_requests(c); } @@ -1888,7 +2031,6 @@ static ngx_int_t ngx_http_upstream_send_request_body(ngx_http_request_t *r, ngx_http_upstream_t *u, ngx_uint_t do_write) { - int tcp_nodelay; ngx_int_t rc; ngx_chain_t *out, *cl, *ln; ngx_connection_t *c; @@ -1925,20 +2067,8 @@ ngx_http_upstream_send_request_body(ngx_http_request_t *r, c = u->peer.connection; clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); - if (clcf->tcp_nodelay && c->tcp_nodelay == NGX_TCP_NODELAY_UNSET) { - ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "tcp_nodelay"); - - tcp_nodelay = 1; - - if (setsockopt(c->fd, IPPROTO_TCP, TCP_NODELAY, - (const void *) &tcp_nodelay, sizeof(int)) == -1) - { - ngx_connection_error(c, ngx_socket_errno, - "setsockopt(TCP_NODELAY) failed"); - return NGX_ERROR; - } - - c->tcp_nodelay = NGX_TCP_NODELAY_SET; + if (clcf->tcp_nodelay && ngx_tcp_nodelay(c) != NGX_OK) { + return NGX_ERROR; } r->read_event_handler = ngx_http_upstream_read_request_handler; @@ -2268,15 +2398,26 @@ ngx_http_upstream_test_next(ngx_http_request_t *r, ngx_http_upstream_t *u) #if (NGX_HTTP_CACHE) if (u->cache_status == NGX_HTTP_CACHE_EXPIRED - && (u->conf->cache_use_stale & un->mask)) + && ((u->conf->cache_use_stale & un->mask) || r->cache->stale_error)) { ngx_int_t rc; rc = u->reinit_request(r); - if (rc == NGX_OK) { - u->cache_status = NGX_HTTP_CACHE_STALE; - rc = ngx_http_upstream_cache_send(r, u); + if (rc != NGX_OK) { + ngx_http_upstream_finalize_request(r, u, rc); + return NGX_OK; + } + + u->cache_status = NGX_HTTP_CACHE_STALE; + rc = ngx_http_upstream_cache_send(r, u); + + if (rc == NGX_DONE) { + return NGX_OK; + } + + if (rc == NGX_HTTP_UPSTREAM_INVALID_HEADER) { + rc = NGX_HTTP_INTERNAL_SERVER_ERROR; } ngx_http_upstream_finalize_request(r, u, rc); @@ -2292,14 +2433,17 @@ ngx_http_upstream_test_next(ngx_http_request_t *r, ngx_http_upstream_t *u) && u->cache_status == NGX_HTTP_CACHE_EXPIRED && u->conf->cache_revalidate) { - time_t now, valid; + time_t now, valid, updating, error; ngx_int_t rc; ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http upstream not modified"); now = ngx_time(); + valid = r->cache->valid_sec; + updating = r->cache->updating_sec; + error = r->cache->error_sec; rc = u->reinit_request(r); @@ -2311,8 +2455,18 @@ ngx_http_upstream_test_next(ngx_http_request_t *r, ngx_http_upstream_t *u) u->cache_status = NGX_HTTP_CACHE_REVALIDATED; rc = ngx_http_upstream_cache_send(r, u); + if (rc == NGX_DONE) { + return NGX_OK; + } + + if (rc == NGX_HTTP_UPSTREAM_INVALID_HEADER) { + rc = NGX_HTTP_INTERNAL_SERVER_ERROR; + } + if (valid == 0) { valid = r->cache->valid_sec; + updating = r->cache->updating_sec; + error = r->cache->error_sec; } if (valid == 0) { @@ -2325,6 +2479,9 @@ ngx_http_upstream_test_next(ngx_http_request_t *r, ngx_http_upstream_t *u) if (valid) { r->cache->valid_sec = valid; + r->cache->updating_sec = updating; + r->cache->error_sec = error; + r->cache->date = now; ngx_http_file_cache_update_header(r); @@ -2391,13 +2548,23 @@ ngx_http_upstream_intercept_errors(ngx_http_request_t *r, #if (NGX_HTTP_CACHE) if (r->cache) { - time_t valid; - valid = ngx_http_file_cache_valid(u->conf->cache_valid, status); + if (u->cacheable) { + time_t valid; - if (valid) { - r->cache->valid_sec = ngx_time() + valid; - r->cache->error = status; + valid = r->cache->valid_sec; + + if (valid == 0) { + valid = ngx_http_file_cache_valid(u->conf->cache_valid, + status); + if (valid) { + r->cache->valid_sec = ngx_time() + valid; + } + } + + if (valid) { + r->cache->error = status; + } } ngx_http_file_cache_free(r->cache, u->pipe->temp_file); @@ -2621,7 +2788,7 @@ ngx_http_upstream_process_body_in_memory(ngx_http_request_t *r, rev = c->read; ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, - "http upstream process body on memory"); + "http upstream process body in memory"); if (rev->timedout) { ngx_connection_error(c, NGX_ETIMEDOUT, "upstream timed out"); @@ -2688,7 +2855,6 @@ ngx_http_upstream_process_body_in_memory(ngx_http_request_t *r, static void ngx_http_upstream_send_response(ngx_http_request_t *r, ngx_http_upstream_t *u) { - int tcp_nodelay; ssize_t n; ngx_int_t rc; ngx_event_pipe_t *p; @@ -2705,6 +2871,15 @@ ngx_http_upstream_send_response(ngx_http_request_t *r, ngx_http_upstream_t *u) u->header_sent = 1; if (u->upgrade) { + +#if (NGX_HTTP_CACHE) + + if (r->cache) { + ngx_http_file_cache_free(r->cache, u->pipe->temp_file); + } + +#endif + ngx_http_upstream_upgrade(r, u); return; } @@ -2726,7 +2901,9 @@ ngx_http_upstream_send_response(ngx_http_request_t *r, ngx_http_upstream_t *u) u->pipe->downstream_error = 1; } - if (r->request_body && r->request_body->temp_file) { + if (r->request_body && r->request_body->temp_file + && r == r->main && !r->preserve_body) + { ngx_pool_run_cleanup_file(r->pool, r->request_body->temp_file->file.fd); r->request_body->temp_file->file.fd = NGX_INVALID_FILE; } @@ -2735,6 +2912,14 @@ ngx_http_upstream_send_response(ngx_http_request_t *r, ngx_http_upstream_t *u) if (!u->buffering) { +#if (NGX_HTTP_CACHE) + + if (r->cache) { + ngx_http_file_cache_free(r->cache, u->pipe->temp_file); + } + +#endif + if (u->input_filter == NULL) { u->input_filter_init = ngx_http_upstream_non_buffered_filter_init; u->input_filter = ngx_http_upstream_non_buffered_filter; @@ -2752,21 +2937,9 @@ ngx_http_upstream_send_response(ngx_http_request_t *r, ngx_http_upstream_t *u) return; } - if (clcf->tcp_nodelay && c->tcp_nodelay == NGX_TCP_NODELAY_UNSET) { - ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "tcp_nodelay"); - - tcp_nodelay = 1; - - if (setsockopt(c->fd, IPPROTO_TCP, TCP_NODELAY, - (const void *) &tcp_nodelay, sizeof(int)) == -1) - { - ngx_connection_error(c, ngx_socket_errno, - "setsockopt(TCP_NODELAY) failed"); - ngx_http_upstream_finalize_request(r, u, NGX_ERROR); - return; - } - - c->tcp_nodelay = NGX_TCP_NODELAY_SET; + if (clcf->tcp_nodelay && ngx_tcp_nodelay(c) != NGX_OK) { + ngx_http_upstream_finalize_request(r, u, NGX_ERROR); + return; } n = u->buffer.last - u->buffer.pos; @@ -2925,8 +3098,9 @@ ngx_http_upstream_send_response(ngx_http_request_t *r, ngx_http_upstream_t *u) p->temp_file->persistent = 1; #if (NGX_HTTP_CACHE) - if (r->cache && r->cache->file_cache->temp_path) { - p->temp_file->path = r->cache->file_cache->temp_path; + if (r->cache && !r->cache->file_cache->use_temp_path) { + p->temp_file->path = r->cache->file_cache->path; + p->temp_file->file.name = r->cache->file.name; } #endif @@ -3024,7 +3198,6 @@ ngx_http_upstream_send_response(ngx_http_request_t *r, ngx_http_upstream_t *u) static void ngx_http_upstream_upgrade(ngx_http_request_t *r, ngx_http_upstream_t *u) { - int tcp_nodelay; ngx_connection_t *c; ngx_http_core_loc_conf_t *clcf; @@ -3033,6 +3206,13 @@ ngx_http_upstream_upgrade(ngx_http_request_t *r, ngx_http_upstream_t *u) /* TODO: prevent upgrade if not requested or not possible */ + if (r != r->main) { + ngx_log_error(NGX_LOG_ERR, c->log, 0, + "connection upgrade in subrequest"); + ngx_http_upstream_finalize_request(r, u, NGX_ERROR); + return; + } + r->keepalive = 0; c->log->action = "proxying upgraded connection"; @@ -3042,37 +3222,15 @@ ngx_http_upstream_upgrade(ngx_http_request_t *r, ngx_http_upstream_t *u) r->write_event_handler = ngx_http_upstream_upgraded_write_downstream; if (clcf->tcp_nodelay) { - tcp_nodelay = 1; - - if (c->tcp_nodelay == NGX_TCP_NODELAY_UNSET) { - ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "tcp_nodelay"); - if (setsockopt(c->fd, IPPROTO_TCP, TCP_NODELAY, - (const void *) &tcp_nodelay, sizeof(int)) == -1) - { - ngx_connection_error(c, ngx_socket_errno, - "setsockopt(TCP_NODELAY) failed"); - ngx_http_upstream_finalize_request(r, u, NGX_ERROR); - return; - } - - c->tcp_nodelay = NGX_TCP_NODELAY_SET; + if (ngx_tcp_nodelay(c) != NGX_OK) { + ngx_http_upstream_finalize_request(r, u, NGX_ERROR); + return; } - if (u->peer.connection->tcp_nodelay == NGX_TCP_NODELAY_UNSET) { - ngx_log_debug0(NGX_LOG_DEBUG_HTTP, u->peer.connection->log, 0, - "tcp_nodelay"); - - if (setsockopt(u->peer.connection->fd, IPPROTO_TCP, TCP_NODELAY, - (const void *) &tcp_nodelay, sizeof(int)) == -1) - { - ngx_connection_error(u->peer.connection, ngx_socket_errno, - "setsockopt(TCP_NODELAY) failed"); - ngx_http_upstream_finalize_request(r, u, NGX_ERROR); - return; - } - - u->peer.connection->tcp_nodelay = NGX_TCP_NODELAY_SET; + if (ngx_tcp_nodelay(u->peer.connection) != NGX_OK) { + ngx_http_upstream_finalize_request(r, u, NGX_ERROR); + return; } } @@ -3590,9 +3748,19 @@ ngx_http_upstream_thread_event_handler(ngx_event_t *ev) r->main->blocked--; r->aio = 0; - r->write_event_handler(r); + if (r->done) { + /* + * trigger connection event handler if the subrequest was + * already finalized; this can happen if the handler is used + * for sendfile() in threads + */ + + c->write->handler(c->write); - ngx_http_run_posted_requests(c); + } else { + r->write_event_handler(r); + ngx_http_run_posted_requests(c); + } } #endif @@ -3640,31 +3808,9 @@ ngx_http_upstream_process_downstream(ngx_http_request_t *r) if (wev->timedout) { - if (wev->delayed) { - - wev->timedout = 0; - wev->delayed = 0; - - if (!wev->ready) { - ngx_add_timer(wev, p->send_timeout); - - if (ngx_handle_write_event(wev, p->send_lowat) != NGX_OK) { - ngx_http_upstream_finalize_request(r, u, NGX_ERROR); - } - - return; - } - - if (ngx_event_pipe(p, wev->write) == NGX_ABORT) { - ngx_http_upstream_finalize_request(r, u, NGX_ERROR); - return; - } - - } else { - p->downstream_error = 1; - c->timedout = 1; - ngx_connection_error(c, NGX_ETIMEDOUT, "client timed out"); - } + p->downstream_error = 1; + c->timedout = 1; + ngx_connection_error(c, NGX_ETIMEDOUT, "client timed out"); } else { @@ -3709,30 +3855,8 @@ ngx_http_upstream_process_upstream(ngx_http_request_t *r, if (rev->timedout) { - if (rev->delayed) { - - rev->timedout = 0; - rev->delayed = 0; - - if (!rev->ready) { - ngx_add_timer(rev, p->read_timeout); - - if (ngx_handle_read_event(rev, 0) != NGX_OK) { - ngx_http_upstream_finalize_request(r, u, NGX_ERROR); - } - - return; - } - - if (ngx_event_pipe(p, 0) == NGX_ABORT) { - ngx_http_upstream_finalize_request(r, u, NGX_ERROR); - return; - } - - } else { - p->upstream_error = 1; - ngx_connection_error(c, NGX_ETIMEDOUT, "upstream timed out"); - } + p->upstream_error = 1; + ngx_connection_error(c, NGX_ETIMEDOUT, "upstream timed out"); } else { @@ -3768,9 +3892,24 @@ ngx_http_upstream_process_request(ngx_http_request_t *r, p = u->pipe; #if (NGX_THREADS) + + if (p->writing && !p->aio) { + + /* + * make sure to call ngx_event_pipe() + * if there is an incomplete aio write + */ + + if (ngx_event_pipe(p, 1) == NGX_ABORT) { + ngx_http_upstream_finalize_request(r, u, NGX_ERROR); + return; + } + } + if (p->writing) { return; } + #endif if (u->peer.connection) { @@ -3979,6 +4118,7 @@ ngx_http_upstream_next(ngx_http_request_t *r, ngx_http_upstream_t *u, switch (ft_type) { case NGX_HTTP_UPSTREAM_FT_TIMEOUT: + case NGX_HTTP_UPSTREAM_FT_HTTP_504: status = NGX_HTTP_GATEWAY_TIME_OUT; break; @@ -3986,6 +4126,10 @@ ngx_http_upstream_next(ngx_http_request_t *r, ngx_http_upstream_t *u, status = NGX_HTTP_INTERNAL_SERVER_ERROR; break; + case NGX_HTTP_UPSTREAM_FT_HTTP_503: + status = NGX_HTTP_SERVICE_UNAVAILABLE; + break; + case NGX_HTTP_UPSTREAM_FT_HTTP_403: status = NGX_HTTP_FORBIDDEN; break; @@ -3994,6 +4138,10 @@ ngx_http_upstream_next(ngx_http_request_t *r, ngx_http_upstream_t *u, status = NGX_HTTP_NOT_FOUND; break; + case NGX_HTTP_UPSTREAM_FT_HTTP_429: + status = NGX_HTTP_TOO_MANY_REQUESTS; + break; + /* * NGX_HTTP_UPSTREAM_FT_BUSY_LOCK and NGX_HTTP_UPSTREAM_FT_MAX_WAITING * never reach here @@ -4027,15 +4175,26 @@ ngx_http_upstream_next(ngx_http_request_t *r, ngx_http_upstream_t *u, #if (NGX_HTTP_CACHE) if (u->cache_status == NGX_HTTP_CACHE_EXPIRED - && (u->conf->cache_use_stale & ft_type)) + && ((u->conf->cache_use_stale & ft_type) || r->cache->stale_error)) { ngx_int_t rc; rc = u->reinit_request(r); - if (rc == NGX_OK) { - u->cache_status = NGX_HTTP_CACHE_STALE; - rc = ngx_http_upstream_cache_send(r, u); + if (rc != NGX_OK) { + ngx_http_upstream_finalize_request(r, u, rc); + return; + } + + u->cache_status = NGX_HTTP_CACHE_STALE; + rc = ngx_http_upstream_cache_send(r, u); + + if (rc == NGX_DONE) { + return; + } + + if (rc == NGX_HTTP_UPSTREAM_INVALID_HEADER) { + rc = NGX_HTTP_INTERNAL_SERVER_ERROR; } ngx_http_upstream_finalize_request(r, u, rc); @@ -4205,6 +4364,8 @@ ngx_http_upstream_finalize_request(ngx_http_request_t *r, u->buffer.last = u->buffer.pos; } + r->read_event_handler = ngx_http_block_reading; + if (rc == NGX_DECLINED) { return; } @@ -4292,15 +4453,8 @@ ngx_http_upstream_process_last_modified(ngx_http_request_t *r, u = r->upstream; u->headers_in.last_modified = h; - -#if (NGX_HTTP_CACHE) - - if (u->cacheable) { - u->headers_in.last_modified_time = ngx_parse_http_time(h->value.data, - h->value.len); - } - -#endif + u->headers_in.last_modified_time = ngx_parse_http_time(h->value.data, + h->value.len); return NGX_OK; } @@ -4402,32 +4556,76 @@ ngx_http_upstream_process_cache_control(ngx_http_request_t *r, offset = 8; } - if (p == NULL) { - return NGX_OK; - } + if (p) { + n = 0; - n = 0; + for (p += offset; p < last; p++) { + if (*p == ',' || *p == ';' || *p == ' ') { + break; + } - for (p += offset; p < last; p++) { - if (*p == ',' || *p == ';' || *p == ' ') { - break; + if (*p >= '0' && *p <= '9') { + n = n * 10 + (*p - '0'); + continue; + } + + u->cacheable = 0; + return NGX_OK; } - if (*p >= '0' && *p <= '9') { - n = n * 10 + *p - '0'; - continue; + if (n == 0) { + u->cacheable = 0; + return NGX_OK; } - u->cacheable = 0; - return NGX_OK; + r->cache->valid_sec = ngx_time() + n; } - if (n == 0) { - u->cacheable = 0; - return NGX_OK; + p = ngx_strlcasestrn(start, last, (u_char *) "stale-while-revalidate=", + 23 - 1); + + if (p) { + n = 0; + + for (p += 23; p < last; p++) { + if (*p == ',' || *p == ';' || *p == ' ') { + break; + } + + if (*p >= '0' && *p <= '9') { + n = n * 10 + (*p - '0'); + continue; + } + + u->cacheable = 0; + return NGX_OK; + } + + r->cache->updating_sec = n; + r->cache->error_sec = n; } - r->cache->valid_sec = ngx_time() + n; + p = ngx_strlcasestrn(start, last, (u_char *) "stale-if-error=", 15 - 1); + + if (p) { + n = 0; + + for (p += 15; p < last; p++) { + if (*p == ',' || *p == ';' || *p == ' ') { + break; + } + + if (*p >= '0' && *p <= '9') { + n = n * 10 + (*p - '0'); + continue; + } + + u->cacheable = 0; + return NGX_OK; + } + + r->cache->error_sec = n; + } } #endif @@ -4714,17 +4912,18 @@ ngx_http_upstream_copy_multi_header_lines(ngx_http_request_t *r, } } - ph = ngx_array_push(pa); - if (ph == NULL) { - return NGX_ERROR; - } - ho = ngx_list_push(&r->headers_out.headers); if (ho == NULL) { return NGX_ERROR; } *ho = *h; + + ph = ngx_array_push(pa); + if (ph == NULL) { + return NGX_ERROR; + } + *ph = ho; return NGX_OK; @@ -4797,15 +4996,8 @@ ngx_http_upstream_copy_last_modified(ngx_http_request_t *r, ngx_table_elt_t *h, *ho = *h; r->headers_out.last_modified = ho; - -#if (NGX_HTTP_CACHE) - - if (r->upstream->cacheable) { - r->headers_out.last_modified_time = + r->headers_out.last_modified_time = r->upstream->headers_in.last_modified_time; - } - -#endif return NGX_OK; } @@ -4847,8 +5039,8 @@ ngx_http_upstream_rewrite_location(ngx_http_request_t *r, ngx_table_elt_t *h, } /* - * we do not set r->headers_out.location here to avoid the handling - * the local redirects without a host name by ngx_http_header_filter() + * we do not set r->headers_out.location here to avoid handling + * relative redirects in ngx_http_header_filter() */ return NGX_OK; @@ -5296,7 +5488,7 @@ ngx_http_upstream_response_length_variable(ngx_http_request_t *r, } -ngx_int_t +static ngx_int_t ngx_http_upstream_header_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data) { @@ -5311,7 +5503,7 @@ ngx_http_upstream_header_variable(ngx_http_request_t *r, } -ngx_int_t +static ngx_int_t ngx_http_upstream_cookie_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data) { @@ -5347,7 +5539,7 @@ ngx_http_upstream_cookie_variable(ngx_http_request_t *r, #if (NGX_HTTP_CACHE) -ngx_int_t +static ngx_int_t ngx_http_upstream_cache_status(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data) { diff --git a/src/http/ngx_http_upstream.h b/src/http/ngx_http_upstream.h index 23d4726a168..3e714e5b195 100644 --- a/src/http/ngx_http_upstream.h +++ b/src/http/ngx_http_upstream.h @@ -26,10 +26,11 @@ #define NGX_HTTP_UPSTREAM_FT_HTTP_504 0x00000080 #define NGX_HTTP_UPSTREAM_FT_HTTP_403 0x00000100 #define NGX_HTTP_UPSTREAM_FT_HTTP_404 0x00000200 -#define NGX_HTTP_UPSTREAM_FT_UPDATING 0x00000400 -#define NGX_HTTP_UPSTREAM_FT_BUSY_LOCK 0x00000800 -#define NGX_HTTP_UPSTREAM_FT_MAX_WAITING 0x00001000 -#define NGX_HTTP_UPSTREAM_FT_NON_IDEMPOTENT 0x00002000 +#define NGX_HTTP_UPSTREAM_FT_HTTP_429 0x00000400 +#define NGX_HTTP_UPSTREAM_FT_UPDATING 0x00000800 +#define NGX_HTTP_UPSTREAM_FT_BUSY_LOCK 0x00001000 +#define NGX_HTTP_UPSTREAM_FT_MAX_WAITING 0x00002000 +#define NGX_HTTP_UPSTREAM_FT_NON_IDEMPOTENT 0x00004000 #define NGX_HTTP_UPSTREAM_FT_NOLIVE 0x40000000 #define NGX_HTTP_UPSTREAM_FT_OFF 0x80000000 @@ -38,7 +39,8 @@ |NGX_HTTP_UPSTREAM_FT_HTTP_503 \ |NGX_HTTP_UPSTREAM_FT_HTTP_504 \ |NGX_HTTP_UPSTREAM_FT_HTTP_403 \ - |NGX_HTTP_UPSTREAM_FT_HTTP_404) + |NGX_HTTP_UPSTREAM_FT_HTTP_404 \ + |NGX_HTTP_UPSTREAM_FT_HTTP_429) #define NGX_HTTP_UPSTREAM_INVALID_HEADER 40 @@ -55,9 +57,6 @@ typedef struct { - ngx_msec_t bl_time; - ngx_uint_t bl_state; - ngx_uint_t status; ngx_msec_t response_time; ngx_msec_t connect_time; @@ -99,8 +98,8 @@ typedef struct { ngx_uint_t max_fails; time_t fail_timeout; ngx_msec_t slow_start; + ngx_uint_t down; - unsigned down:1; unsigned backup:1; NGX_COMPAT_BEGIN(6) @@ -151,7 +150,6 @@ typedef struct { ngx_msec_t connect_timeout; ngx_msec_t send_timeout; ngx_msec_t read_timeout; - ngx_msec_t timeout; ngx_msec_t next_upstream_timeout; size_t send_lowat; @@ -198,12 +196,15 @@ typedef struct { ngx_uint_t cache_use_stale; ngx_uint_t cache_methods; + off_t cache_max_range_offset; + ngx_flag_t cache_lock; ngx_msec_t cache_lock_timeout; ngx_msec_t cache_lock_age; ngx_flag_t cache_revalidate; ngx_flag_t cache_convert_head; + ngx_flag_t cache_background_update; ngx_array_t *cache_valid; ngx_array_t *cache_bypass; @@ -388,9 +389,6 @@ struct ngx_http_upstream_s { unsigned request_sent:1; unsigned request_body_sent:1; unsigned header_sent:1; - - NGX_COMPAT_BEGIN(1) - NGX_COMPAT_END }; @@ -407,11 +405,6 @@ typedef struct { } ngx_http_upstream_param_t; -ngx_int_t ngx_http_upstream_cookie_variable(ngx_http_request_t *r, - ngx_http_variable_value_t *v, uintptr_t data); -ngx_int_t ngx_http_upstream_header_variable(ngx_http_request_t *r, - ngx_http_variable_value_t *v, uintptr_t data); - ngx_int_t ngx_http_upstream_create(ngx_http_request_t *r); void ngx_http_upstream_init(ngx_http_request_t *r); ngx_http_upstream_srv_conf_t *ngx_http_upstream_add(ngx_conf_t *cf, diff --git a/src/http/ngx_http_variables.c b/src/http/ngx_http_variables.c index 7e65b2e507e..ab82177caea 100644 --- a/src/http/ngx_http_variables.c +++ b/src/http/ngx_http_variables.c @@ -11,6 +11,9 @@ #include +static ngx_http_variable_t *ngx_http_add_prefix_variable(ngx_conf_t *cf, + ngx_str_t *name, ngx_uint_t flags); + static ngx_int_t ngx_http_variable_request(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); #if 0 @@ -35,6 +38,8 @@ static ngx_int_t ngx_http_variable_unknown_header_in(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); static ngx_int_t ngx_http_variable_unknown_header_out(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_http_variable_unknown_trailer_out(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); static ngx_int_t ngx_http_variable_request_line(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); static ngx_int_t ngx_http_variable_cookie(ngx_http_request_t *r, @@ -356,7 +361,22 @@ static ngx_http_variable_t ngx_http_core_variables[] = { 3, NGX_HTTP_VAR_NOCACHEABLE, 0 }, #endif - { ngx_null_string, NULL, NULL, 0, 0, 0 } + { ngx_string("http_"), NULL, ngx_http_variable_unknown_header_in, + 0, NGX_HTTP_VAR_PREFIX, 0 }, + + { ngx_string("sent_http_"), NULL, ngx_http_variable_unknown_header_out, + 0, NGX_HTTP_VAR_PREFIX, 0 }, + + { ngx_string("sent_trailer_"), NULL, ngx_http_variable_unknown_trailer_out, + 0, NGX_HTTP_VAR_PREFIX, 0 }, + + { ngx_string("cookie_"), NULL, ngx_http_variable_cookie, + 0, NGX_HTTP_VAR_PREFIX, 0 }, + + { ngx_string("arg_"), NULL, ngx_http_variable_argument, + 0, NGX_HTTP_VAR_NOCACHEABLE|NGX_HTTP_VAR_PREFIX, 0 }, + + ngx_http_null_variable }; @@ -366,6 +386,9 @@ ngx_http_variable_value_t ngx_http_variable_true_value = ngx_http_variable("1"); +static ngx_uint_t ngx_http_variable_depth = 100; + + ngx_http_variable_t * ngx_http_add_variable(ngx_conf_t *cf, ngx_str_t *name, ngx_uint_t flags) { @@ -381,6 +404,10 @@ ngx_http_add_variable(ngx_conf_t *cf, ngx_str_t *name, ngx_uint_t flags) return NULL; } + if (flags & NGX_HTTP_VAR_PREFIX) { + return ngx_http_add_prefix_variable(cf, name, flags); + } + cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module); key = cmcf->variables_keys->keys.elts; @@ -399,6 +426,8 @@ ngx_http_add_variable(ngx_conf_t *cf, ngx_str_t *name, ngx_uint_t flags) return NULL; } + v->flags &= flags | ~NGX_HTTP_VAR_WEAK; + return v; } @@ -437,6 +466,59 @@ ngx_http_add_variable(ngx_conf_t *cf, ngx_str_t *name, ngx_uint_t flags) } +static ngx_http_variable_t * +ngx_http_add_prefix_variable(ngx_conf_t *cf, ngx_str_t *name, ngx_uint_t flags) +{ + ngx_uint_t i; + ngx_http_variable_t *v; + ngx_http_core_main_conf_t *cmcf; + + cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module); + + v = cmcf->prefix_variables.elts; + for (i = 0; i < cmcf->prefix_variables.nelts; i++) { + if (name->len != v[i].name.len + || ngx_strncasecmp(name->data, v[i].name.data, name->len) != 0) + { + continue; + } + + v = &v[i]; + + if (!(v->flags & NGX_HTTP_VAR_CHANGEABLE)) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "the duplicate \"%V\" variable", name); + return NULL; + } + + v->flags &= flags | ~NGX_HTTP_VAR_WEAK; + + return v; + } + + v = ngx_array_push(&cmcf->prefix_variables); + if (v == NULL) { + return NULL; + } + + v->name.len = name->len; + v->name.data = ngx_pnalloc(cf->pool, name->len); + if (v->name.data == NULL) { + return NULL; + } + + ngx_strlow(v->name.data, name->data, name->len); + + v->set_handler = NULL; + v->get_handler = NULL; + v->data = 0; + v->flags = flags; + v->index = 0; + + return v; +} + + ngx_int_t ngx_http_get_variable_index(ngx_conf_t *cf, ngx_str_t *name) { @@ -517,9 +599,20 @@ ngx_http_get_indexed_variable(ngx_http_request_t *r, ngx_uint_t index) v = cmcf->variables.elts; + if (ngx_http_variable_depth == 0) { + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "cycle while evaluating variable \"%V\"", + &v[index].name); + return NULL; + } + + ngx_http_variable_depth--; + if (v[index].get_handler(r, &r->variables[index], v[index].data) == NGX_OK) { + ngx_http_variable_depth++; + if (v[index].flags & NGX_HTTP_VAR_NOCACHEABLE) { r->variables[index].no_cacheable = 1; } @@ -527,6 +620,8 @@ ngx_http_get_indexed_variable(ngx_http_request_t *r, ngx_uint_t index) return &r->variables[index]; } + ngx_http_variable_depth++; + r->variables[index].valid = 0; r->variables[index].not_found = 1; @@ -557,6 +652,8 @@ 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, ngx_uint_t key) { + size_t len; + ngx_uint_t i, n; ngx_http_variable_t *v; ngx_http_variable_value_t *vv; ngx_http_core_main_conf_t *cmcf; @@ -568,82 +665,48 @@ ngx_http_get_variable(ngx_http_request_t *r, ngx_str_t *name, ngx_uint_t key) if (v) { if (v->flags & NGX_HTTP_VAR_INDEXED) { return ngx_http_get_flushed_variable(r, v->index); - - } else { - - vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t)); - - if (vv && v->get_handler(r, vv, v->data) == NGX_OK) { - return vv; - } - - return NULL; } - } - vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t)); - if (vv == NULL) { - return NULL; - } - - if (name->len >= 5 && ngx_strncmp(name->data, "http_", 5) == 0) { - - if (ngx_http_variable_unknown_header_in(r, vv, (uintptr_t) name) - == NGX_OK) - { - return vv; + if (ngx_http_variable_depth == 0) { + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "cycle while evaluating variable \"%V\"", name); + return NULL; } - return NULL; - } + ngx_http_variable_depth--; - if (name->len >= 10 && ngx_strncmp(name->data, "sent_http_", 10) == 0) { + vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t)); - if (ngx_http_variable_unknown_header_out(r, vv, (uintptr_t) name) - == NGX_OK) - { + if (vv && v->get_handler(r, vv, v->data) == NGX_OK) { + ngx_http_variable_depth++; return vv; } + ngx_http_variable_depth++; return NULL; } - if (name->len >= 14 && ngx_strncmp(name->data, "upstream_http_", 14) == 0) { - - if (ngx_http_upstream_header_variable(r, vv, (uintptr_t) name) - == NGX_OK) - { - return vv; - } - + vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t)); + if (vv == NULL) { return NULL; } - if (name->len >= 7 && ngx_strncmp(name->data, "cookie_", 7) == 0) { - - if (ngx_http_variable_cookie(r, vv, (uintptr_t) name) == NGX_OK) { - return vv; - } - - return NULL; - } + len = 0; - if (name->len >= 16 - && ngx_strncmp(name->data, "upstream_cookie_", 16) == 0) - { + v = cmcf->prefix_variables.elts; + n = cmcf->prefix_variables.nelts; - if (ngx_http_upstream_cookie_variable(r, vv, (uintptr_t) name) - == NGX_OK) + for (i = 0; i < cmcf->prefix_variables.nelts; i++) { + if (name->len >= v[i].name.len && name->len > len + && ngx_strncmp(name->data, v[i].name.data, v[i].name.len) == 0) { - return vv; + len = v[i].name.len; + n = i; } - - return NULL; } - if (name->len >= 4 && ngx_strncmp(name->data, "arg_", 4) == 0) { - - if (ngx_http_variable_argument(r, vv, (uintptr_t) name) == NGX_OK) { + if (n != cmcf->prefix_variables.nelts) { + if (v[n].get_handler(r, vv, (uintptr_t) name) == NGX_OK) { return vv; } @@ -876,6 +939,16 @@ ngx_http_variable_unknown_header_out(ngx_http_request_t *r, } +static ngx_int_t +ngx_http_variable_unknown_trailer_out(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ + return ngx_http_variable_unknown_header(v, (ngx_str_t *) data, + &r->headers_out.trailers.part, + sizeof("sent_trailer_") - 1); +} + + ngx_int_t ngx_http_variable_unknown_header(ngx_http_variable_value_t *v, ngx_str_t *var, ngx_list_part_t *part, size_t prefix) @@ -1167,6 +1240,18 @@ ngx_http_variable_binary_remote_addr(ngx_http_request_t *r, break; #endif +#if (NGX_HAVE_UNIX_DOMAIN) + case AF_UNIX: + + v->len = r->connection->addr_text.len; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + v->data = r->connection->addr_text.data; + + break; +#endif + default: /* AF_INET */ sin = (struct sockaddr_in *) r->connection->sockaddr; @@ -1390,17 +1475,15 @@ static ngx_int_t ngx_http_variable_is_args(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data) { - v->valid = 1; - v->no_cacheable = 0; - v->not_found = 0; - if (r->args.len == 0) { - v->len = 0; - v->data = NULL; + *v = ngx_http_variable_null_value; return NGX_OK; } v->len = 1; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; v->data = (u_char *) "?"; return NGX_OK; @@ -1917,11 +2000,7 @@ ngx_http_variable_request_completion(ngx_http_request_t *r, return NGX_OK; } - v->len = 0; - v->valid = 1; - v->no_cacheable = 0; - v->not_found = 0; - v->data = (u_char *) ""; + *v = ngx_http_variable_null_value; return NGX_OK; } @@ -2478,7 +2557,6 @@ ngx_http_regex_exec(ngx_http_request_t *r, ngx_http_regex_t *re, ngx_str_t *s) ngx_int_t ngx_http_variables_add_core_vars(ngx_conf_t *cf) { - ngx_int_t rc; ngx_http_variable_t *cv, *v; ngx_http_core_main_conf_t *cmcf; @@ -2499,27 +2577,20 @@ ngx_http_variables_add_core_vars(ngx_conf_t *cf) return NGX_ERROR; } + if (ngx_array_init(&cmcf->prefix_variables, cf->pool, 8, + sizeof(ngx_http_variable_t)) + != NGX_OK) + { + return NGX_ERROR; + } + for (cv = ngx_http_core_variables; cv->name.len; cv++) { - v = ngx_palloc(cf->pool, sizeof(ngx_http_variable_t)); + v = ngx_http_add_variable(cf, &cv->name, cv->flags); if (v == NULL) { return NGX_ERROR; } *v = *cv; - - rc = ngx_hash_add_key(cmcf->variables_keys, &v->name, v, - NGX_HASH_READONLY_KEY); - - if (rc == NGX_OK) { - continue; - } - - if (rc == NGX_BUSY) { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "conflicting variable name \"%V\"", &v->name); - } - - return NGX_ERROR; } return NGX_OK; @@ -2529,10 +2600,11 @@ ngx_http_variables_add_core_vars(ngx_conf_t *cf) ngx_int_t ngx_http_variables_init_vars(ngx_conf_t *cf) { + size_t len; ngx_uint_t i, n; ngx_hash_key_t *key; ngx_hash_init_t hash; - ngx_http_variable_t *v, *av; + ngx_http_variable_t *v, *av, *pv; ngx_http_core_main_conf_t *cmcf; /* set the handlers for the indexed http variables */ @@ -2540,6 +2612,7 @@ ngx_http_variables_init_vars(ngx_conf_t *cf) cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module); v = cmcf->variables.elts; + pv = cmcf->prefix_variables.elts; key = cmcf->variables_keys->keys.elts; for (i = 0; i < cmcf->variables.nelts; i++) { @@ -2560,7 +2633,9 @@ ngx_http_variables_init_vars(ngx_conf_t *cf) av->index = i; - if (av->get_handler == NULL) { + if (av->get_handler == NULL + || (av->flags & NGX_HTTP_VAR_WEAK)) + { break; } @@ -2568,68 +2643,34 @@ ngx_http_variables_init_vars(ngx_conf_t *cf) } } - if (v[i].name.len >= 5 - && ngx_strncmp(v[i].name.data, "http_", 5) == 0) - { - v[i].get_handler = ngx_http_variable_unknown_header_in; - v[i].data = (uintptr_t) &v[i].name; - - continue; - } - - if (v[i].name.len >= 10 - && ngx_strncmp(v[i].name.data, "sent_http_", 10) == 0) - { - v[i].get_handler = ngx_http_variable_unknown_header_out; - v[i].data = (uintptr_t) &v[i].name; - - continue; - } - - if (v[i].name.len >= 14 - && ngx_strncmp(v[i].name.data, "upstream_http_", 14) == 0) - { - v[i].get_handler = ngx_http_upstream_header_variable; - v[i].data = (uintptr_t) &v[i].name; - v[i].flags = NGX_HTTP_VAR_NOCACHEABLE; - - continue; - } - - if (v[i].name.len >= 7 - && ngx_strncmp(v[i].name.data, "cookie_", 7) == 0) - { - v[i].get_handler = ngx_http_variable_cookie; - v[i].data = (uintptr_t) &v[i].name; + len = 0; + av = NULL; - continue; + for (n = 0; n < cmcf->prefix_variables.nelts; n++) { + if (v[i].name.len >= pv[n].name.len && v[i].name.len > len + && ngx_strncmp(v[i].name.data, pv[n].name.data, pv[n].name.len) + == 0) + { + av = &pv[n]; + len = pv[n].name.len; + } } - if (v[i].name.len >= 16 - && ngx_strncmp(v[i].name.data, "upstream_cookie_", 16) == 0) - { - v[i].get_handler = ngx_http_upstream_cookie_variable; + if (av) { + v[i].get_handler = av->get_handler; v[i].data = (uintptr_t) &v[i].name; - v[i].flags = NGX_HTTP_VAR_NOCACHEABLE; + v[i].flags = av->flags; - continue; + goto next; } - if (v[i].name.len >= 4 - && ngx_strncmp(v[i].name.data, "arg_", 4) == 0) - { - v[i].get_handler = ngx_http_variable_argument; - v[i].data = (uintptr_t) &v[i].name; - v[i].flags = NGX_HTTP_VAR_NOCACHEABLE; + if (v[i].get_handler == NULL) { + ngx_log_error(NGX_LOG_EMERG, cf->log, 0, + "unknown \"%V\" variable", &v[i].name); - continue; + return NGX_ERROR; } - ngx_log_error(NGX_LOG_EMERG, cf->log, 0, - "unknown \"%V\" variable", &v[i].name); - - return NGX_ERROR; - next: continue; } diff --git a/src/http/ngx_http_variables.h b/src/http/ngx_http_variables.h index 829fab31e64..f3f7f3c1cee 100644 --- a/src/http/ngx_http_variables.h +++ b/src/http/ngx_http_variables.h @@ -30,6 +30,8 @@ typedef ngx_int_t (*ngx_http_get_variable_pt) (ngx_http_request_t *r, #define NGX_HTTP_VAR_NOCACHEABLE 2 #define NGX_HTTP_VAR_INDEXED 4 #define NGX_HTTP_VAR_NOHASH 8 +#define NGX_HTTP_VAR_WEAK 16 +#define NGX_HTTP_VAR_PREFIX 32 struct ngx_http_variable_s { @@ -41,6 +43,8 @@ struct ngx_http_variable_s { ngx_uint_t index; }; +#define ngx_http_null_variable { ngx_null_string, NULL, NULL, 0, 0, 0 } + ngx_http_variable_t *ngx_http_add_variable(ngx_conf_t *cf, ngx_str_t *name, ngx_uint_t flags); diff --git a/src/http/v2/ngx_http_v2.c b/src/http/v2/ngx_http_v2.c index 83016304a46..2c621907b7e 100644 --- a/src/http/v2/ngx_http_v2.c +++ b/src/http/v2/ngx_http_v2.c @@ -28,6 +28,7 @@ #define NGX_HTTP_V2_HTTP_1_1_REQUIRED 0xd /* frame sizes */ +#define NGX_HTTP_V2_SETTINGS_ACK_SIZE 0 #define NGX_HTTP_V2_RST_STREAM_SIZE 4 #define NGX_HTTP_V2_PRIORITY_SIZE 5 #define NGX_HTTP_V2_PING_SIZE 8 @@ -128,8 +129,7 @@ static ngx_http_v2_node_t *ngx_http_v2_get_closed_node( #define ngx_http_v2_index_size(h2scf) (h2scf->streams_index_mask + 1) #define ngx_http_v2_index(h2scf, sid) ((sid >> 1) & h2scf->streams_index_mask) -static ngx_int_t ngx_http_v2_send_settings(ngx_http_v2_connection_t *h2c, - ngx_uint_t ack); +static ngx_int_t ngx_http_v2_send_settings(ngx_http_v2_connection_t *h2c); static ngx_int_t ngx_http_v2_settings_frame_handler( ngx_http_v2_connection_t *h2c, ngx_http_v2_out_frame_t *frame); static ngx_int_t ngx_http_v2_send_window_update(ngx_http_v2_connection_t *h2c, @@ -245,6 +245,8 @@ ngx_http_v2_init(ngx_event_t *rev) h2c->frame_size = NGX_HTTP_V2_DEFAULT_FRAME_SIZE; + h2c->table_update = 1; + h2scf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_v2_module); h2c->pool = ngx_create_pool(h2scf->pool_size, h2c->connection->log); @@ -269,7 +271,7 @@ ngx_http_v2_init(ngx_event_t *rev) return; } - if (ngx_http_v2_send_settings(h2c, 0) == NGX_ERROR) { + if (ngx_http_v2_send_settings(h2c) == NGX_ERROR) { ngx_http_close_connection(c); return; } @@ -286,7 +288,6 @@ ngx_http_v2_init(ngx_event_t *rev) : ngx_http_v2_state_preface; ngx_queue_init(&h2c->waiting); - ngx_queue_init(&h2c->posted); ngx_queue_init(&h2c->dependencies); ngx_queue_init(&h2c->closed); @@ -420,9 +421,7 @@ static void ngx_http_v2_write_handler(ngx_event_t *wev) { ngx_int_t rc; - ngx_queue_t *q; ngx_connection_t *c; - ngx_http_v2_stream_t *stream; ngx_http_v2_connection_t *h2c; c = wev->data; @@ -457,26 +456,6 @@ ngx_http_v2_write_handler(ngx_event_t *wev) return; } - while (!ngx_queue_empty(&h2c->posted)) { - q = ngx_queue_head(&h2c->posted); - - ngx_queue_remove(q); - - stream = ngx_queue_data(q, ngx_http_v2_stream_t, queue); - - stream->handled = 0; - - ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, - "run http2 stream %ui", stream->node->id); - - wev = stream->request->connection->write; - - wev->active = 0; - wev->ready = 1; - - wev->handler(wev); - } - h2c->blocked = 0; if (rc == NGX_AGAIN) { @@ -552,29 +531,8 @@ ngx_http_v2_send_output_queue(ngx_http_v2_connection_t *h2c) tcp_nodelay = 1; } - if (tcp_nodelay - && clcf->tcp_nodelay - && c->tcp_nodelay == NGX_TCP_NODELAY_UNSET) - { - ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "tcp_nodelay"); - - if (setsockopt(c->fd, IPPROTO_TCP, TCP_NODELAY, - (const void *) &tcp_nodelay, sizeof(int)) - == -1) - { -#if (NGX_SOLARIS) - /* Solaris returns EINVAL if a socket has been shut down */ - c->log_error = NGX_ERROR_IGNORE_EINVAL; -#endif - - ngx_connection_error(c, ngx_socket_errno, - "setsockopt(TCP_NODELAY) failed"); - - c->log_error = NGX_ERROR_INFO; - goto error; - } - - c->tcp_nodelay = NGX_TCP_NODELAY_SET; + if (tcp_nodelay && clcf->tcp_nodelay && ngx_tcp_nodelay(c) != NGX_OK) { + goto error; } for ( /* void */ ; out; out = fn) { @@ -790,7 +748,7 @@ ngx_http_v2_state_head(ngx_http_v2_connection_t *h2c, u_char *pos, u_char *end) type = ngx_http_v2_parse_type(head); ngx_log_debug4(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, - "process http2 frame type:%ui f:%Xd l:%uz sid:%ui", + "http2 frame type:%ui f:%Xd l:%uz sid:%ui", type, h2c->state.flags, h2c->state.length, h2c->state.sid); if (type >= NGX_HTTP_V2_FRAME_STATES) { @@ -806,9 +764,12 @@ ngx_http_v2_state_head(ngx_http_v2_connection_t *h2c, u_char *pos, u_char *end) static u_char * ngx_http_v2_state_data(ngx_http_v2_connection_t *h2c, u_char *pos, u_char *end) { + size_t size; ngx_http_v2_node_t *node; ngx_http_v2_stream_t *stream; + size = h2c->state.length; + if (h2c->state.flags & NGX_HTTP_V2_PADDED_FLAG) { if (h2c->state.length == 0) { @@ -825,33 +786,33 @@ ngx_http_v2_state_data(ngx_http_v2_connection_t *h2c, u_char *pos, u_char *end) } h2c->state.padding = *pos++; - h2c->state.length--; - if (h2c->state.padding > h2c->state.length) { + if (h2c->state.padding >= size) { ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0, "client sent padded DATA frame " "with incorrect length: %uz, padding: %uz", - h2c->state.length, h2c->state.padding); + size, h2c->state.padding); - return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_SIZE_ERROR); + return ngx_http_v2_connection_error(h2c, + NGX_HTTP_V2_PROTOCOL_ERROR); } - h2c->state.length -= h2c->state.padding; + h2c->state.length -= 1 + h2c->state.padding; } ngx_log_debug0(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, "http2 DATA frame"); - if (h2c->state.length > h2c->recv_window) { + if (size > h2c->recv_window) { ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0, "client violated connection flow control: " "received DATA frame length %uz, available window %uz", - h2c->state.length, h2c->recv_window); + size, h2c->recv_window); return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_FLOW_CTRL_ERROR); } - h2c->recv_window -= h2c->state.length; + h2c->recv_window -= size; if (h2c->recv_window < NGX_HTTP_V2_MAX_WINDOW / 4) { @@ -877,11 +838,11 @@ ngx_http_v2_state_data(ngx_http_v2_connection_t *h2c, u_char *pos, u_char *end) stream = node->stream; - if (h2c->state.length > stream->recv_window) { + if (size > stream->recv_window) { ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0, "client violated flow control for stream %ui: " "received DATA frame length %uz, available window %uz", - node->id, h2c->state.length, stream->recv_window); + node->id, size, stream->recv_window); if (ngx_http_v2_terminate_stream(h2c, stream, NGX_HTTP_V2_FLOW_CTRL_ERROR) @@ -894,7 +855,7 @@ ngx_http_v2_state_data(ngx_http_v2_connection_t *h2c, u_char *pos, u_char *end) return ngx_http_v2_state_skip_padded(h2c, pos, end); } - stream->recv_window -= h2c->state.length; + stream->recv_window -= size; if (stream->no_flow_control && stream->recv_window < NGX_HTTP_V2_MAX_WINDOW / 4) @@ -961,7 +922,7 @@ ngx_http_v2_state_read_data(ngx_http_v2_connection_t *h2c, u_char *pos, if (size >= h2c->state.length) { size = h2c->state.length; - stream->in_closed = h2c->state.flags & NGX_HTTP_V2_END_STREAM_FLAG; + stream->in_closed = h2c->state.flags & NGX_HTTP_V2_END_STREAM_FLAG; } r = stream->request; @@ -1076,7 +1037,8 @@ ngx_http_v2_state_headers(ngx_http_v2_connection_t *h2c, u_char *pos, "with incorrect length: %uz, padding: %uz", h2c->state.length, h2c->state.padding); - return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_SIZE_ERROR); + return ngx_http_v2_connection_error(h2c, + NGX_HTTP_V2_PROTOCOL_ERROR); } h2c->state.length -= h2c->state.padding; @@ -1354,7 +1316,7 @@ ngx_http_v2_state_field_len(ngx_http_v2_connection_t *h2c, u_char *pos, } ngx_log_debug2(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, - "http2 hpack %s string length: %i", + "http2 %s string, len:%i", huff ? "encoded" : "raw", len); h2scf = ngx_http_get_module_srv_conf(h2c->http_connection->conf_ctx, @@ -1608,6 +1570,10 @@ ngx_http_v2_state_process_header(ngx_http_v2_connection_t *h2c, u_char *pos, rc = ngx_http_v2_pseudo_header(r, header); if (rc == NGX_OK) { + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "http2 header: \":%V: %V\"", + &header->name, &header->value); + return ngx_http_v2_state_header_complete(h2c, pos, end); } @@ -1649,36 +1615,40 @@ ngx_http_v2_state_process_header(ngx_http_v2_connection_t *h2c, u_char *pos, NGX_HTTP_V2_INTERNAL_ERROR); } - return ngx_http_v2_state_header_complete(h2c, pos, end); - } - - h = ngx_list_push(&r->headers_in.headers); - if (h == NULL) { - return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_INTERNAL_ERROR); - } + } else { + h = ngx_list_push(&r->headers_in.headers); + if (h == NULL) { + return ngx_http_v2_connection_error(h2c, + NGX_HTTP_V2_INTERNAL_ERROR); + } - h->key.len = header->name.len; - h->key.data = header->name.data; + h->key.len = header->name.len; + h->key.data = header->name.data; - /* TODO Optimization: precalculate hash and handler for indexed headers. */ - h->hash = ngx_hash_key(h->key.data, h->key.len); + /* + * TODO Optimization: precalculate hash + * and handler for indexed headers. + */ + h->hash = ngx_hash_key(h->key.data, h->key.len); - h->value.len = header->value.len; - h->value.data = header->value.data; + h->value.len = header->value.len; + h->value.data = header->value.data; - h->lowcase_key = h->key.data; + h->lowcase_key = h->key.data; - cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module); + cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module); - hh = ngx_hash_find(&cmcf->headers_in_hash, h->hash, - h->lowcase_key, h->key.len); + hh = ngx_hash_find(&cmcf->headers_in_hash, h->hash, + h->lowcase_key, h->key.len); - if (hh && hh->handler(r, h, hh->offset) != NGX_OK) { - goto error; + if (hh && hh->handler(r, h, hh->offset) != NGX_OK) { + goto error; + } } ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "http2 http header: \"%V: %V\"", &h->key, &h->value); + "http2 header: \"%V: %V\"", + &header->name, &header->value); return ngx_http_v2_state_header_complete(h2c, pos, end); @@ -1924,7 +1894,7 @@ ngx_http_v2_state_rst_stream(ngx_http_v2_connection_t *h2c, u_char *pos, if (node == NULL || node->stream == NULL) { ngx_log_debug0(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, - "unknown http2 stream"); + "unknown http2 stream"); return ngx_http_v2_state_complete(h2c, pos, end); } @@ -1991,8 +1961,6 @@ ngx_http_v2_state_settings(ngx_http_v2_connection_t *h2c, u_char *pos, return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_SIZE_ERROR); } - ngx_http_v2_send_settings(h2c, 1); - return ngx_http_v2_state_settings_params(h2c, pos, end); } @@ -2001,7 +1969,11 @@ static u_char * ngx_http_v2_state_settings_params(ngx_http_v2_connection_t *h2c, u_char *pos, u_char *end) { - ngx_uint_t id, value; + ssize_t window_delta; + ngx_uint_t id, value; + ngx_http_v2_out_frame_t *frame; + + window_delta = 0; while (h2c->state.length) { if (end - pos < NGX_HTTP_V2_SETTINGS_PARAM_SIZE) { @@ -2027,17 +1999,13 @@ ngx_http_v2_state_settings_params(ngx_http_v2_connection_t *h2c, u_char *pos, NGX_HTTP_V2_FLOW_CTRL_ERROR); } - if (ngx_http_v2_adjust_windows(h2c, value - h2c->init_window) - != NGX_OK) - { - return ngx_http_v2_connection_error(h2c, - NGX_HTTP_V2_INTERNAL_ERROR); - } + window_delta = value - h2c->init_window; h2c->init_window = value; break; case NGX_HTTP_V2_MAX_FRAME_SIZE_SETTING: + if (value > NGX_HTTP_V2_MAX_FRAME_SIZE || value < NGX_HTTP_V2_DEFAULT_FRAME_SIZE) { @@ -2059,6 +2027,22 @@ ngx_http_v2_state_settings_params(ngx_http_v2_connection_t *h2c, u_char *pos, pos += NGX_HTTP_V2_SETTINGS_PARAM_SIZE; } + frame = ngx_http_v2_get_frame(h2c, NGX_HTTP_V2_SETTINGS_ACK_SIZE, + NGX_HTTP_V2_SETTINGS_FRAME, + NGX_HTTP_V2_ACK_FLAG, 0); + if (frame == NULL) { + return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_INTERNAL_ERROR); + } + + ngx_http_v2_queue_ordered_frame(h2c, frame); + + if (window_delta) { + if (ngx_http_v2_adjust_windows(h2c, window_delta) != NGX_OK) { + return ngx_http_v2_connection_error(h2c, + NGX_HTTP_V2_INTERNAL_ERROR); + } + } + return ngx_http_v2_state_complete(h2c, pos, end); } @@ -2184,6 +2168,44 @@ ngx_http_v2_state_window_update(ngx_http_v2_connection_t *h2c, u_char *pos, "http2 WINDOW_UPDATE frame sid:%ui window:%uz", h2c->state.sid, window); + if (window == 0) { + if (h2c->state.sid == 0) { + ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0, + "client sent WINDOW_UPDATE frame " + "with incorrect window increment 0"); + + return ngx_http_v2_connection_error(h2c, + NGX_HTTP_V2_PROTOCOL_ERROR); + } + + ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0, + "client sent WINDOW_UPDATE frame for stream %ui " + "with incorrect window increment 0", h2c->state.sid); + + node = ngx_http_v2_get_node_by_id(h2c, h2c->state.sid, 0); + + if (node && node->stream) { + if (ngx_http_v2_terminate_stream(h2c, node->stream, + NGX_HTTP_V2_PROTOCOL_ERROR) + == NGX_ERROR) + { + return ngx_http_v2_connection_error(h2c, + NGX_HTTP_V2_INTERNAL_ERROR); + } + + } else { + if (ngx_http_v2_send_rst_stream(h2c, h2c->state.sid, + NGX_HTTP_V2_PROTOCOL_ERROR) + == NGX_ERROR) + { + return ngx_http_v2_connection_error(h2c, + NGX_HTTP_V2_INTERNAL_ERROR); + } + } + + return ngx_http_v2_state_complete(h2c, pos, end); + } + if (h2c->state.sid) { node = ngx_http_v2_get_node_by_id(h2c, h2c->state.sid, 0); @@ -2254,7 +2276,7 @@ ngx_http_v2_state_window_update(ngx_http_v2_connection_t *h2c, u_char *pos, stream = ngx_queue_data(q, ngx_http_v2_stream_t, queue); - stream->handled = 0; + stream->waiting = 0; wev = stream->request->connection->write; @@ -2464,7 +2486,7 @@ ngx_http_v2_parse_int(ngx_http_v2_connection_t *h2c, u_char **pos, u_char *end, static ngx_int_t -ngx_http_v2_send_settings(ngx_http_v2_connection_t *h2c, ngx_uint_t ack) +ngx_http_v2_send_settings(ngx_http_v2_connection_t *h2c) { size_t len; ngx_buf_t *buf; @@ -2472,8 +2494,8 @@ ngx_http_v2_send_settings(ngx_http_v2_connection_t *h2c, ngx_uint_t ack) ngx_http_v2_srv_conf_t *h2scf; ngx_http_v2_out_frame_t *frame; - ngx_log_debug1(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, - "http2 send SETTINGS frame ack:%ui", ack); + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, + "http2 send SETTINGS frame"); frame = ngx_palloc(h2c->pool, sizeof(ngx_http_v2_out_frame_t)); if (frame == NULL) { @@ -2485,7 +2507,7 @@ ngx_http_v2_send_settings(ngx_http_v2_connection_t *h2c, ngx_uint_t ack) return NGX_ERROR; } - len = ack ? 0 : (sizeof(uint16_t) + sizeof(uint32_t)) * 3; + len = NGX_HTTP_V2_SETTINGS_PARAM_SIZE * 3; buf = ngx_create_temp_buf(h2c->pool, NGX_HTTP_V2_FRAME_HEADER_SIZE + len); if (buf == NULL) { @@ -2509,28 +2531,26 @@ ngx_http_v2_send_settings(ngx_http_v2_connection_t *h2c, ngx_uint_t ack) buf->last = ngx_http_v2_write_len_and_type(buf->last, len, NGX_HTTP_V2_SETTINGS_FRAME); - *buf->last++ = ack ? NGX_HTTP_V2_ACK_FLAG : NGX_HTTP_V2_NO_FLAG; + *buf->last++ = NGX_HTTP_V2_NO_FLAG; buf->last = ngx_http_v2_write_sid(buf->last, 0); - if (!ack) { - h2scf = ngx_http_get_module_srv_conf(h2c->http_connection->conf_ctx, - ngx_http_v2_module); + h2scf = ngx_http_get_module_srv_conf(h2c->http_connection->conf_ctx, + ngx_http_v2_module); - buf->last = ngx_http_v2_write_uint16(buf->last, - NGX_HTTP_V2_MAX_STREAMS_SETTING); - buf->last = ngx_http_v2_write_uint32(buf->last, - h2scf->concurrent_streams); + buf->last = ngx_http_v2_write_uint16(buf->last, + NGX_HTTP_V2_MAX_STREAMS_SETTING); + buf->last = ngx_http_v2_write_uint32(buf->last, + h2scf->concurrent_streams); - buf->last = ngx_http_v2_write_uint16(buf->last, + buf->last = ngx_http_v2_write_uint16(buf->last, NGX_HTTP_V2_INIT_WINDOW_SIZE_SETTING); - buf->last = ngx_http_v2_write_uint32(buf->last, h2scf->preread_size); + buf->last = ngx_http_v2_write_uint32(buf->last, h2scf->preread_size); - buf->last = ngx_http_v2_write_uint16(buf->last, - NGX_HTTP_V2_MAX_FRAME_SIZE_SETTING); - buf->last = ngx_http_v2_write_uint32(buf->last, - NGX_HTTP_V2_MAX_FRAME_SIZE); - } + buf->last = ngx_http_v2_write_uint16(buf->last, + NGX_HTTP_V2_MAX_FRAME_SIZE_SETTING); + buf->last = ngx_http_v2_write_uint32(buf->last, + NGX_HTTP_V2_MAX_FRAME_SIZE); ngx_http_v2_queue_blocked_frame(h2c, frame); @@ -3095,7 +3115,7 @@ ngx_http_v2_pseudo_header(ngx_http_request_t *r, ngx_http_v2_header_t *header) } ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, - "client sent unknown pseudo header \"%V\"", + "client sent unknown pseudo-header \":%V\"", &header->name); return NGX_DECLINED; @@ -3242,14 +3262,14 @@ ngx_http_v2_parse_scheme(ngx_http_request_t *r, ngx_http_v2_header_t *header) { if (r->schema_start) { ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, - "client sent duplicate :schema header"); + "client sent duplicate :scheme header"); return NGX_DECLINED; } if (header->value.len == 0) { ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, - "client sent empty :schema header"); + "client sent empty :scheme header"); return NGX_DECLINED; } @@ -3314,8 +3334,22 @@ ngx_http_v2_construct_request_line(ngx_http_request_t *r) static const u_char ending[] = " HTTP/2.0"; if (r->method_name.len == 0 + || r->schema_start == NULL || r->unparsed_uri.len == 0) { + if (r->method_name.len == 0) { + ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, + "client sent no :method header"); + + } else if (r->schema_start == NULL) { + ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, + "client sent no :schema header"); + + } else { + ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, + "client sent no :path header"); + } + ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST); return NGX_ERROR; } @@ -3341,7 +3375,7 @@ ngx_http_v2_construct_request_line(ngx_http_request_t *r) ngx_memcpy(p, ending, sizeof(ending)); ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "http2 http request line: \"%V\"", &r->request_line); + "http2 request line: \"%V\"", &r->request_line); return NGX_OK; } @@ -3502,8 +3536,7 @@ ngx_http_v2_run_request(ngx_http_request_t *r) ngx_int_t -ngx_http_v2_read_request_body(ngx_http_request_t *r, - ngx_http_client_body_handler_pt post_handler) +ngx_http_v2_read_request_body(ngx_http_request_t *r) { off_t len; size_t size; @@ -3516,33 +3549,14 @@ ngx_http_v2_read_request_body(ngx_http_request_t *r, ngx_http_v2_connection_t *h2c; stream = r->stream; + rb = r->request_body; if (stream->skip_data) { r->request_body_no_buffering = 0; - post_handler(r); + rb->post_handler(r); return NGX_OK; } - rb = ngx_pcalloc(r->pool, sizeof(ngx_http_request_body_t)); - if (rb == NULL) { - return NGX_HTTP_INTERNAL_SERVER_ERROR; - } - - /* - * set by ngx_pcalloc(): - * - * rb->bufs = NULL; - * rb->buf = NULL; - * rb->received = 0; - * rb->free = NULL; - * rb->busy = NULL; - */ - - rb->rest = 1; - rb->post_handler = post_handler; - - r->request_body = rb; - h2scf = ngx_http_get_module_srv_conf(r, ngx_http_v2_module); clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); @@ -3587,6 +3601,8 @@ ngx_http_v2_read_request_body(ngx_http_request_t *r, return NGX_HTTP_INTERNAL_SERVER_ERROR; } + rb->rest = 1; + buf = stream->preread; if (stream->in_closed) { @@ -3673,6 +3689,8 @@ ngx_http_v2_process_request_body(ngx_http_request_t *r, u_char *pos, buf->pos = buf->start = pos; buf->last = buf->end = pos + size; + r->request_body_in_file_only = 1; + } else { if (size > (size_t) (buf->end - buf->last)) { ngx_log_error(NGX_LOG_INFO, fc->log, 0, @@ -4148,6 +4166,14 @@ ngx_http_v2_handle_connection_handler(ngx_event_t *rev) ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0, "http2 handle connection handler"); + c = rev->data; + h2c = c->data; + + if (c->error) { + ngx_http_v2_finalize_connection(h2c, 0); + return; + } + rev->handler = ngx_http_v2_read_handler; if (rev->ready) { @@ -4155,9 +4181,6 @@ ngx_http_v2_handle_connection_handler(ngx_event_t *rev) return; } - c = rev->data; - h2c = c->data; - if (h2c->last_out && ngx_http_v2_send_output_queue(h2c) == NGX_ERROR) { ngx_http_v2_finalize_connection(h2c, 0); return; @@ -4271,7 +4294,7 @@ ngx_http_v2_finalize_connection(ngx_http_v2_connection_t *h2c, continue; } - stream->handled = 0; + stream->waiting = 0; r = stream->request; fc = r->connection; @@ -4280,7 +4303,10 @@ ngx_http_v2_finalize_connection(ngx_http_v2_connection_t *h2c, if (stream->queued) { stream->queued = 0; + ev = fc->write; + ev->active = 0; + ev->ready = 1; } else { ev = fc->read; diff --git a/src/http/v2/ngx_http_v2.h b/src/http/v2/ngx_http_v2.h index 63bbdad5485..42e0eb13251 100644 --- a/src/http/v2/ngx_http_v2.h +++ b/src/http/v2/ngx_http_v2.h @@ -137,7 +137,6 @@ struct ngx_http_v2_connection_s { ngx_http_v2_out_frame_t *last_out; - ngx_queue_t posted; ngx_queue_t dependencies; ngx_queue_t closed; @@ -145,6 +144,7 @@ struct ngx_http_v2_connection_s { unsigned closed_nodes:8; unsigned settings_ack:1; + unsigned table_update:1; unsigned blocked:1; unsigned goaway:1; }; @@ -192,7 +192,7 @@ struct ngx_http_v2_stream_s { ngx_pool_t *pool; - unsigned handled:1; + unsigned waiting:1; unsigned blocked:1; unsigned exhausted:1; unsigned in_closed:1; @@ -250,8 +250,8 @@ ngx_http_v2_queue_blocked_frame(ngx_http_v2_connection_t *h2c, { ngx_http_v2_out_frame_t **out; - for (out = &h2c->last_out; *out; out = &(*out)->next) - { + for (out = &h2c->last_out; *out; out = &(*out)->next) { + if ((*out)->blocked || (*out)->stream == NULL) { break; } @@ -262,11 +262,19 @@ ngx_http_v2_queue_blocked_frame(ngx_http_v2_connection_t *h2c, } +static ngx_inline void +ngx_http_v2_queue_ordered_frame(ngx_http_v2_connection_t *h2c, + ngx_http_v2_out_frame_t *frame) +{ + frame->next = h2c->last_out; + h2c->last_out = frame; +} + + void ngx_http_v2_init(ngx_event_t *rev); void ngx_http_v2_request_headers_init(void); -ngx_int_t ngx_http_v2_read_request_body(ngx_http_request_t *r, - ngx_http_client_body_handler_pt post_handler); +ngx_int_t ngx_http_v2_read_request_body(ngx_http_request_t *r); ngx_int_t ngx_http_v2_read_unbuffered_request_body(ngx_http_request_t *r); void ngx_http_v2_close_stream(ngx_http_v2_stream_t *stream, ngx_int_t rc); diff --git a/src/http/v2/ngx_http_v2_filter_module.c b/src/http/v2/ngx_http_v2_filter_module.c index 4ab77912183..90707850656 100644 --- a/src/http/v2/ngx_http_v2_filter_module.c +++ b/src/http/v2/ngx_http_v2_filter_module.c @@ -50,13 +50,17 @@ #define NGX_HTTP_V2_SERVER_INDEX 54 #define NGX_HTTP_V2_VARY_INDEX 59 +#define NGX_HTTP_V2_NO_TRAILERS (ngx_http_v2_out_frame_t *) -1 + static u_char *ngx_http_v2_string_encode(u_char *dst, u_char *src, size_t len, u_char *tmp, ngx_uint_t lower); static u_char *ngx_http_v2_write_int(u_char *pos, ngx_uint_t prefix, ngx_uint_t value); static ngx_http_v2_out_frame_t *ngx_http_v2_create_headers_frame( - ngx_http_request_t *r, u_char *pos, u_char *end); + ngx_http_request_t *r, u_char *pos, u_char *end, ngx_uint_t fin); +static ngx_http_v2_out_frame_t *ngx_http_v2_create_trailers_frame( + ngx_http_request_t *r); static ngx_chain_t *ngx_http_v2_send_chain(ngx_connection_t *fc, ngx_chain_t *in, off_t limit); @@ -135,6 +139,7 @@ ngx_http_v2_header_filter(ngx_http_request_t *r) ngx_connection_t *fc; ngx_http_cleanup_t *cln; ngx_http_v2_out_frame_t *frame; + ngx_http_v2_connection_t *h2c; ngx_http_core_loc_conf_t *clcf; ngx_http_core_srv_conf_t *cscf; u_char addr[NGX_SOCKADDR_STRLEN]; @@ -148,6 +153,10 @@ ngx_http_v2_header_filter(ngx_http_request_t *r) static size_t nginx_ver_len = ngx_http_v2_literal_size(NGINX_VER); static u_char nginx_ver[ngx_http_v2_literal_size(NGINX_VER)]; + static size_t nginx_ver_build_len = + ngx_http_v2_literal_size(NGINX_VER_BUILD); + static u_char nginx_ver_build[ngx_http_v2_literal_size(NGINX_VER_BUILD)]; + if (!r->stream) { return ngx_http_next_header_filter(r); } @@ -227,12 +236,25 @@ ngx_http_v2_header_filter(ngx_http_request_t *r) } } - len = status ? 1 : 1 + ngx_http_v2_literal_size("418"); + h2c = r->stream->connection; + + len = h2c->table_update ? 1 : 0; + + len += status ? 1 : 1 + ngx_http_v2_literal_size("418"); clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); if (r->headers_out.server == NULL) { - len += 1 + (clcf->server_tokens ? nginx_ver_len : sizeof(nginx)); + + if (clcf->server_tokens == NGX_HTTP_SERVER_TOKENS_ON) { + len += 1 + nginx_ver_len; + + } else if (clcf->server_tokens == NGX_HTTP_SERVER_TOKENS_BUILD) { + len += 1 + nginx_ver_build_len; + + } else { + len += 1 + sizeof(nginx); + } } if (r->headers_out.date == NULL) { @@ -263,7 +285,9 @@ ngx_http_v2_header_filter(ngx_http_request_t *r) if (r->headers_out.location && r->headers_out.location->value.len) { - if (r->headers_out.location->value.data[0] == '/') { + if (r->headers_out.location->value.data[0] == '/' + && clcf->absolute_redirect) + { if (clcf->server_name_in_redirect) { cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module); host = cscf->server_name; @@ -404,6 +428,13 @@ ngx_http_v2_header_filter(ngx_http_request_t *r) start = pos; + if (h2c->table_update) { + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, fc->log, 0, + "http2 table size update: 0"); + *pos++ = (1 << 5) | 0; + h2c->table_update = 0; + } + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, fc->log, 0, "http2 output header: \":status: %03ui\"", r->headers_out.status); @@ -418,13 +449,25 @@ ngx_http_v2_header_filter(ngx_http_request_t *r) } if (r->headers_out.server == NULL) { - ngx_log_debug1(NGX_LOG_DEBUG_HTTP, fc->log, 0, - "http2 output header: \"server: %s\"", - clcf->server_tokens ? NGINX_VER : "nginx"); + + if (clcf->server_tokens == NGX_HTTP_SERVER_TOKENS_ON) { + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, fc->log, 0, + "http2 output header: \"server: %s\"", + NGINX_VER); + + } else if (clcf->server_tokens == NGX_HTTP_SERVER_TOKENS_BUILD) { + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, fc->log, 0, + "http2 output header: \"server: %s\"", + NGINX_VER_BUILD); + + } else { + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, fc->log, 0, + "http2 output header: \"server: nginx\""); + } *pos++ = ngx_http_v2_inc_indexed(NGX_HTTP_V2_SERVER_INDEX); - if (clcf->server_tokens) { + if (clcf->server_tokens == NGX_HTTP_SERVER_TOKENS_ON) { if (nginx_ver[0] == '\0') { p = ngx_http_v2_write_value(nginx_ver, (u_char *) NGINX_VER, sizeof(NGINX_VER) - 1, tmp); @@ -433,6 +476,16 @@ ngx_http_v2_header_filter(ngx_http_request_t *r) pos = ngx_cpymem(pos, nginx_ver, nginx_ver_len); + } else if (clcf->server_tokens == NGX_HTTP_SERVER_TOKENS_BUILD) { + if (nginx_ver_build[0] == '\0') { + p = ngx_http_v2_write_value(nginx_ver_build, + (u_char *) NGINX_VER_BUILD, + sizeof(NGINX_VER_BUILD) - 1, tmp); + nginx_ver_build_len = p - nginx_ver_build; + } + + pos = ngx_cpymem(pos, nginx_ver_build, nginx_ver_build_len); + } else { pos = ngx_cpymem(pos, nginx, sizeof(nginx)); } @@ -575,13 +628,15 @@ ngx_http_v2_header_filter(ngx_http_request_t *r) header[i].value.len, tmp); } - frame = ngx_http_v2_create_headers_frame(r, start, pos); + frame = ngx_http_v2_create_headers_frame(r, start, pos, r->header_only); if (frame == NULL) { return NGX_ERROR; } ngx_http_v2_queue_blocked_frame(r->stream->connection, frame); + r->stream->queued = 1; + cln = ngx_http_cleanup_add(r, 0); if (cln == NULL) { return NGX_ERROR; @@ -590,8 +645,6 @@ ngx_http_v2_header_filter(ngx_http_request_t *r) cln->handler = ngx_http_v2_filter_cleanup; cln->data = r->stream; - r->stream->queued = 1; - fc->send_chain = ngx_http_v2_send_chain; fc->need_last_buf = 1; @@ -599,6 +652,118 @@ ngx_http_v2_header_filter(ngx_http_request_t *r) } +static ngx_http_v2_out_frame_t * +ngx_http_v2_create_trailers_frame(ngx_http_request_t *r) +{ + u_char *pos, *start, *tmp; + size_t len, tmp_len; + ngx_uint_t i; + ngx_list_part_t *part; + ngx_table_elt_t *header; + + len = 0; + tmp_len = 0; + + part = &r->headers_out.trailers.part; + header = part->elts; + + for (i = 0; /* void */; i++) { + + if (i >= part->nelts) { + if (part->next == NULL) { + break; + } + + part = part->next; + header = part->elts; + i = 0; + } + + if (header[i].hash == 0) { + continue; + } + + if (header[i].key.len > NGX_HTTP_V2_MAX_FIELD) { + ngx_log_error(NGX_LOG_CRIT, r->connection->log, 0, + "too long response trailer name: \"%V\"", + &header[i].key); + return NULL; + } + + if (header[i].value.len > NGX_HTTP_V2_MAX_FIELD) { + ngx_log_error(NGX_LOG_CRIT, r->connection->log, 0, + "too long response trailer value: \"%V: %V\"", + &header[i].key, &header[i].value); + return NULL; + } + + len += 1 + NGX_HTTP_V2_INT_OCTETS + header[i].key.len + + NGX_HTTP_V2_INT_OCTETS + header[i].value.len; + + if (header[i].key.len > tmp_len) { + tmp_len = header[i].key.len; + } + + if (header[i].value.len > tmp_len) { + tmp_len = header[i].value.len; + } + } + + if (len == 0) { + return NGX_HTTP_V2_NO_TRAILERS; + } + + tmp = ngx_palloc(r->pool, tmp_len); + pos = ngx_pnalloc(r->pool, len); + + if (pos == NULL || tmp == NULL) { + return NULL; + } + + start = pos; + + part = &r->headers_out.trailers.part; + header = part->elts; + + for (i = 0; /* void */; i++) { + + if (i >= part->nelts) { + if (part->next == NULL) { + break; + } + + part = part->next; + header = part->elts; + i = 0; + } + + if (header[i].hash == 0) { + continue; + } + +#if (NGX_DEBUG) + if (r->connection->log->log_level & NGX_LOG_DEBUG_HTTP) { + ngx_strlow(tmp, header[i].key.data, header[i].key.len); + + ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "http2 output trailer: \"%*s: %V\"", + header[i].key.len, tmp, &header[i].value); + } +#endif + + *pos++ = 0; + + pos = ngx_http_v2_write_name(pos, header[i].key.data, + header[i].key.len, tmp); + + pos = ngx_http_v2_write_value(pos, header[i].value.data, + header[i].value.len, tmp); + } + + return ngx_http_v2_create_headers_frame(r, start, pos, 1); +} + + static u_char * ngx_http_v2_string_encode(u_char *dst, u_char *src, size_t len, u_char *tmp, ngx_uint_t lower) @@ -649,7 +814,7 @@ ngx_http_v2_write_int(u_char *pos, ngx_uint_t prefix, ngx_uint_t value) static ngx_http_v2_out_frame_t * ngx_http_v2_create_headers_frame(ngx_http_request_t *r, u_char *pos, - u_char *end) + u_char *end, ngx_uint_t fin) { u_char type, flags; size_t rest, frame_size; @@ -670,12 +835,12 @@ ngx_http_v2_create_headers_frame(ngx_http_request_t *r, u_char *pos, frame->stream = stream; frame->length = rest; frame->blocked = 1; - frame->fin = r->header_only; + frame->fin = fin; ll = &frame->first; type = NGX_HTTP_V2_HEADERS_FRAME; - flags = r->header_only ? NGX_HTTP_V2_END_STREAM_FLAG : NGX_HTTP_V2_NO_FLAG; + flags = fin ? NGX_HTTP_V2_END_STREAM_FLAG : NGX_HTTP_V2_NO_FLAG; frame_size = stream->connection->frame_size; for ( ;; ) { @@ -732,12 +897,14 @@ ngx_http_v2_create_headers_frame(ngx_http_request_t *r, u_char *pos, rest -= frame_size; if (rest) { + frame->length += NGX_HTTP_V2_FRAME_HEADER_SIZE; + type = NGX_HTTP_V2_CONTINUATION_FRAME; flags = NGX_HTTP_V2_NO_FLAG; continue; } - b->last_buf = r->header_only; + b->last_buf = fin; cl->next = NULL; frame->last = cl; @@ -759,7 +926,7 @@ ngx_http_v2_send_chain(ngx_connection_t *fc, ngx_chain_t *in, off_t limit) ngx_http_request_t *r; ngx_http_v2_stream_t *stream; ngx_http_v2_loc_conf_t *h2lcf; - ngx_http_v2_out_frame_t *frame; + ngx_http_v2_out_frame_t *frame, *trailers; ngx_http_v2_connection_t *h2c; r = fc->data; @@ -833,6 +1000,8 @@ ngx_http_v2_send_chain(ngx_connection_t *fc, ngx_chain_t *in, off_t limit) frame_size = (h2lcf->chunk_size < h2c->frame_size) ? h2lcf->chunk_size : h2c->frame_size; + trailers = NGX_HTTP_V2_NO_TRAILERS; + #if (NGX_SUPPRESS_WARN) cl = NULL; #endif @@ -895,19 +1064,39 @@ ngx_http_v2_send_chain(ngx_connection_t *fc, ngx_chain_t *in, off_t limit) size -= rest; } - frame = ngx_http_v2_filter_get_data_frame(stream, frame_size, out, cl); - if (frame == NULL) { - return NGX_CHAIN_ERROR; + if (cl->buf->last_buf) { + trailers = ngx_http_v2_create_trailers_frame(r); + if (trailers == NULL) { + return NGX_CHAIN_ERROR; + } + + if (trailers != NGX_HTTP_V2_NO_TRAILERS) { + cl->buf->last_buf = 0; + } } - ngx_http_v2_queue_frame(h2c, frame); + if (frame_size || cl->buf->last_buf) { + frame = ngx_http_v2_filter_get_data_frame(stream, frame_size, + out, cl); + if (frame == NULL) { + return NGX_CHAIN_ERROR; + } + + ngx_http_v2_queue_frame(h2c, frame); - h2c->send_window -= frame_size; + h2c->send_window -= frame_size; - stream->send_window -= frame_size; - stream->queued++; + stream->send_window -= frame_size; + stream->queued++; + } if (in == NULL) { + + if (trailers != NGX_HTTP_V2_NO_TRAILERS) { + ngx_http_v2_queue_frame(h2c, trailers); + stream->queued++; + } + break; } @@ -1079,6 +1268,10 @@ static ngx_inline ngx_int_t ngx_http_v2_flow_control(ngx_http_v2_connection_t *h2c, ngx_http_v2_stream_t *stream) { + ngx_log_debug3(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, + "http2:%ui windows: conn:%uz stream:%z", + stream->node->id, h2c->send_window, stream->send_window); + if (stream->send_window <= 0) { stream->exhausted = 1; return NGX_DECLINED; @@ -1100,11 +1293,11 @@ ngx_http_v2_waiting_queue(ngx_http_v2_connection_t *h2c, ngx_queue_t *q; ngx_http_v2_stream_t *s; - if (stream->handled) { + if (stream->waiting) { return; } - stream->handled = 1; + stream->waiting = 1; for (q = ngx_queue_last(&h2c->waiting); q != ngx_queue_sentinel(&h2c->waiting); @@ -1168,6 +1361,9 @@ ngx_http_v2_headers_frame_handler(ngx_http_v2_connection_t *h2c, "http2:%ui HEADERS frame %p was sent", stream->node->id, frame); + stream->request->header_size += NGX_HTTP_V2_FRAME_HEADER_SIZE + + frame->length; + ngx_http_v2_handle_frame(stream, frame); ngx_http_v2_handle_stream(h2c, stream); @@ -1294,20 +1490,29 @@ static ngx_inline void ngx_http_v2_handle_stream(ngx_http_v2_connection_t *h2c, ngx_http_v2_stream_t *stream) { + ngx_event_t *wev; ngx_connection_t *fc; - if (stream->handled || stream->blocked) { + if (stream->waiting || stream->blocked) { return; } fc = stream->request->connection; - if (!fc->error && (stream->exhausted || fc->write->delayed)) { + if (!fc->error && stream->exhausted) { + return; + } + + wev = fc->write; + + wev->active = 0; + wev->ready = 1; + + if (!fc->error && wev->delayed) { return; } - stream->handled = 1; - ngx_queue_insert_tail(&h2c->posted, &stream->queue); + ngx_post_event(wev, &ngx_posted_events); } @@ -1317,11 +1522,13 @@ ngx_http_v2_filter_cleanup(void *data) ngx_http_v2_stream_t *stream = data; size_t window; + ngx_event_t *wev; + ngx_queue_t *q; ngx_http_v2_out_frame_t *frame, **fn; ngx_http_v2_connection_t *h2c; - if (stream->handled) { - stream->handled = 0; + if (stream->waiting) { + stream->waiting = 0; ngx_queue_remove(&stream->queue); } @@ -1355,9 +1562,26 @@ ngx_http_v2_filter_cleanup(void *data) fn = &frame->next; } - if (h2c->send_window == 0 && window && !ngx_queue_empty(&h2c->waiting)) { - ngx_queue_add(&h2c->posted, &h2c->waiting); - ngx_queue_init(&h2c->waiting); + if (h2c->send_window == 0 && window) { + + while (!ngx_queue_empty(&h2c->waiting)) { + q = ngx_queue_head(&h2c->waiting); + + ngx_queue_remove(q); + + stream = ngx_queue_data(q, ngx_http_v2_stream_t, queue); + + stream->waiting = 0; + + wev = stream->request->connection->write; + + wev->active = 0; + wev->ready = 1; + + if (!wev->delayed) { + ngx_post_event(wev, &ngx_posted_events); + } + } } h2c->send_window += window; diff --git a/src/http/v2/ngx_http_v2_module.c b/src/http/v2/ngx_http_v2_module.c index 032abcb64c7..7f7dab29e51 100644 --- a/src/http/v2/ngx_http_v2_module.c +++ b/src/http/v2/ngx_http_v2_module.c @@ -225,7 +225,7 @@ static ngx_http_variable_t ngx_http_v2_vars[] = { { ngx_string("http2"), NULL, ngx_http_v2_variable, 0, 0, 0 }, - { ngx_null_string, NULL, NULL, 0, 0, 0 } + ngx_http_null_variable }; diff --git a/src/http/v2/ngx_http_v2_table.c b/src/http/v2/ngx_http_v2_table.c index a73748a9878..62025c426d4 100644 --- a/src/http/v2/ngx_http_v2_table.c +++ b/src/http/v2/ngx_http_v2_table.c @@ -102,7 +102,7 @@ ngx_http_v2_get_indexed_header(ngx_http_v2_connection_t *h2c, ngx_uint_t index, ngx_log_debug2(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, "http2 get indexed %s: %ui", - name_only ? "header" : "header name", index); + name_only ? "name" : "header", index); index--; @@ -180,7 +180,7 @@ ngx_http_v2_add_header(ngx_http_v2_connection_t *h2c, ngx_http_v2_header_t *entry, **entries; ngx_log_debug2(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, - "http2 add header to hpack table: \"%V: %V\"", + "http2 table add: \"%V: %V\"", &header->name, &header->value); if (h2c->hpack.entries == NULL) { @@ -293,7 +293,7 @@ ngx_http_v2_table_account(ngx_http_v2_connection_t *h2c, size_t size) size += 32; ngx_log_debug2(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, - "http2 hpack table account: %uz free:%uz", + "http2 table account: %uz free:%uz", size, h2c->hpack.free); if (size <= h2c->hpack.free) { diff --git a/src/mail/ngx_mail.c b/src/mail/ngx_mail.c index 9e560bb7c95..5fd5fa00c7d 100644 --- a/src/mail/ngx_mail.c +++ b/src/mail/ngx_mail.c @@ -333,6 +333,8 @@ ngx_mail_optimize_servers(ngx_conf_t *cf, ngx_array_t *ports) ls->log.handler = ngx_accept_log_error; ls->backlog = addr[i].opt.backlog; + ls->rcvbuf = addr[i].opt.rcvbuf; + ls->sndbuf = addr[i].opt.sndbuf; ls->keepalive = addr[i].opt.so_keepalive; #if (NGX_HAVE_KEEPALIVE_TUNABLE) diff --git a/src/mail/ngx_mail.h b/src/mail/ngx_mail.h index 60025082009..6ecfefc98fb 100644 --- a/src/mail/ngx_mail.h +++ b/src/mail/ngx_mail.h @@ -46,6 +46,8 @@ typedef struct { int tcp_keepcnt; #endif int backlog; + int rcvbuf; + int sndbuf; } ngx_mail_listen_t; diff --git a/src/mail/ngx_mail_core_module.c b/src/mail/ngx_mail_core_module.c index b974d905c00..276b8eeb1f1 100644 --- a/src/mail/ngx_mail_core_module.c +++ b/src/mail/ngx_mail_core_module.c @@ -295,7 +295,7 @@ ngx_mail_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { ngx_mail_core_srv_conf_t *cscf = conf; - ngx_str_t *value; + ngx_str_t *value, size; ngx_url_t u; ngx_uint_t i, m; ngx_mail_listen_t *ls; @@ -350,6 +350,8 @@ ngx_mail_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) ls->socklen = u.socklen; ls->backlog = NGX_LISTEN_BACKLOG; + ls->rcvbuf = -1; + ls->sndbuf = -1; ls->wildcard = u.wildcard; ls->ctx = cf->ctx; @@ -398,6 +400,38 @@ ngx_mail_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) continue; } + if (ngx_strncmp(value[i].data, "rcvbuf=", 7) == 0) { + size.len = value[i].len - 7; + size.data = value[i].data + 7; + + ls->rcvbuf = ngx_parse_size(&size); + ls->bind = 1; + + if (ls->rcvbuf == NGX_ERROR) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "invalid rcvbuf \"%V\"", &value[i]); + return NGX_CONF_ERROR; + } + + continue; + } + + if (ngx_strncmp(value[i].data, "sndbuf=", 7) == 0) { + size.len = value[i].len - 7; + size.data = value[i].data + 7; + + ls->sndbuf = ngx_parse_size(&size); + ls->bind = 1; + + if (ls->sndbuf == NGX_ERROR) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "invalid sndbuf \"%V\"", &value[i]); + return NGX_CONF_ERROR; + } + + continue; + } + if (ngx_strncmp(value[i].data, "ipv6only=o", 10) == 0) { #if (NGX_HAVE_INET6 && defined IPV6_V6ONLY) size_t len; diff --git a/src/mail/ngx_mail_handler.c b/src/mail/ngx_mail_handler.c index 9d4ef561b79..f6b26ede03c 100644 --- a/src/mail/ngx_mail_handler.c +++ b/src/mail/ngx_mail_handler.c @@ -222,7 +222,7 @@ ngx_mail_ssl_init_connection(ngx_ssl_t *ssl, ngx_connection_t *c) ngx_mail_session_t *s; ngx_mail_core_srv_conf_t *cscf; - if (ngx_ssl_create_connection(ssl, c, 0) == NGX_ERROR) { + if (ngx_ssl_create_connection(ssl, c, 0) != NGX_OK) { ngx_mail_close_connection(c); return; } diff --git a/src/mail/ngx_mail_imap_handler.c b/src/mail/ngx_mail_imap_handler.c index 1c54457853e..3bf09ec3c9f 100644 --- a/src/mail/ngx_mail_imap_handler.c +++ b/src/mail/ngx_mail_imap_handler.c @@ -356,6 +356,8 @@ ngx_mail_imap_authenticate(ngx_mail_session_t *s, ngx_connection_t *c) } #endif + iscf = ngx_mail_get_module_srv_conf(s, ngx_mail_imap_module); + rc = ngx_mail_auth_parse(s, c); switch (rc) { @@ -383,8 +385,6 @@ ngx_mail_imap_authenticate(ngx_mail_session_t *s, ngx_connection_t *c) case NGX_MAIL_AUTH_CRAM_MD5: - iscf = ngx_mail_get_module_srv_conf(s, ngx_mail_imap_module); - if (!(iscf->auth_methods & NGX_MAIL_AUTH_CRAM_MD5_ENABLED)) { return NGX_MAIL_PARSE_INVALID_COMMAND; } @@ -406,6 +406,10 @@ ngx_mail_imap_authenticate(ngx_mail_session_t *s, ngx_connection_t *c) case NGX_MAIL_AUTH_EXTERNAL: + if (!(iscf->auth_methods & NGX_MAIL_AUTH_EXTERNAL_ENABLED)) { + return NGX_MAIL_PARSE_INVALID_COMMAND; + } + ngx_str_set(&s->out, imap_username); s->mail_state = ngx_imap_auth_external; diff --git a/src/mail/ngx_mail_pop3_handler.c b/src/mail/ngx_mail_pop3_handler.c index a2d565804f9..9310c2750f4 100644 --- a/src/mail/ngx_mail_pop3_handler.c +++ b/src/mail/ngx_mail_pop3_handler.c @@ -501,6 +501,10 @@ ngx_mail_pop3_auth(ngx_mail_session_t *s, ngx_connection_t *c) case NGX_MAIL_AUTH_EXTERNAL: + if (!(pscf->auth_methods & NGX_MAIL_AUTH_EXTERNAL_ENABLED)) { + return NGX_MAIL_PARSE_INVALID_COMMAND; + } + ngx_str_set(&s->out, pop3_username); s->mail_state = ngx_pop3_auth_external; diff --git a/src/mail/ngx_mail_pop3_module.c b/src/mail/ngx_mail_pop3_module.c index bd60e0a6733..a673070736a 100644 --- a/src/mail/ngx_mail_pop3_module.c +++ b/src/mail/ngx_mail_pop3_module.c @@ -185,6 +185,10 @@ ngx_mail_pop3_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) m <= NGX_MAIL_AUTH_EXTERNAL_ENABLED; m <<= 1, i++) { + if (ngx_mail_pop3_auth_methods_names[i].len == 0) { + continue; + } + if (m & conf->auth_methods) { size += 1 + ngx_mail_pop3_auth_methods_names[i].len; } @@ -212,6 +216,10 @@ ngx_mail_pop3_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) m <= NGX_MAIL_AUTH_EXTERNAL_ENABLED; m <<= 1, i++) { + if (ngx_mail_pop3_auth_methods_names[i].len == 0) { + continue; + } + if (m & conf->auth_methods) { *p++ = ' '; p = ngx_cpymem(p, ngx_mail_pop3_auth_methods_names[i].data, @@ -248,6 +256,10 @@ ngx_mail_pop3_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) m <= NGX_MAIL_AUTH_EXTERNAL_ENABLED; m <<= 1, i++) { + if (ngx_mail_pop3_auth_methods_names[i].len == 0) { + continue; + } + if (m & conf->auth_methods) { size += ngx_mail_pop3_auth_methods_names[i].len + sizeof(CRLF) - 1; @@ -269,6 +281,10 @@ ngx_mail_pop3_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) m <= NGX_MAIL_AUTH_EXTERNAL_ENABLED; m <<= 1, i++) { + if (ngx_mail_pop3_auth_methods_names[i].len == 0) { + continue; + } + if (m & conf->auth_methods) { p = ngx_cpymem(p, ngx_mail_pop3_auth_methods_names[i].data, ngx_mail_pop3_auth_methods_names[i].len); diff --git a/src/mail/ngx_mail_smtp_handler.c b/src/mail/ngx_mail_smtp_handler.c index 47756c31156..939fb1a5190 100644 --- a/src/mail/ngx_mail_smtp_handler.c +++ b/src/mail/ngx_mail_smtp_handler.c @@ -609,6 +609,8 @@ ngx_mail_smtp_auth(ngx_mail_session_t *s, ngx_connection_t *c) return NGX_OK; } + sscf = ngx_mail_get_module_srv_conf(s, ngx_mail_smtp_module); + rc = ngx_mail_auth_parse(s, c); switch (rc) { @@ -636,8 +638,6 @@ ngx_mail_smtp_auth(ngx_mail_session_t *s, ngx_connection_t *c) case NGX_MAIL_AUTH_CRAM_MD5: - sscf = ngx_mail_get_module_srv_conf(s, ngx_mail_smtp_module); - if (!(sscf->auth_methods & NGX_MAIL_AUTH_CRAM_MD5_ENABLED)) { return NGX_MAIL_PARSE_INVALID_COMMAND; } @@ -659,6 +659,10 @@ ngx_mail_smtp_auth(ngx_mail_session_t *s, ngx_connection_t *c) case NGX_MAIL_AUTH_EXTERNAL: + if (!(sscf->auth_methods & NGX_MAIL_AUTH_EXTERNAL_ENABLED)) { + return NGX_MAIL_PARSE_INVALID_COMMAND; + } + ngx_str_set(&s->out, smtp_username); s->mail_state = ngx_smtp_auth_external; diff --git a/src/mail/ngx_mail_smtp_module.c b/src/mail/ngx_mail_smtp_module.c index f03bd907e9b..3b5a2d8f315 100644 --- a/src/mail/ngx_mail_smtp_module.c +++ b/src/mail/ngx_mail_smtp_module.c @@ -280,7 +280,7 @@ ngx_mail_smtp_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) p = ngx_cpymem(p, conf->capability.data, conf->capability.len); - p = ngx_cpymem(p, "250 STARTTLS" CRLF, sizeof("250 STARTTLS" CRLF) - 1); + ngx_memcpy(p, "250 STARTTLS" CRLF, sizeof("250 STARTTLS" CRLF) - 1); p = conf->starttls_capability.data + (last - conf->capability.data) + 3; diff --git a/src/mail/ngx_mail_ssl_module.c b/src/mail/ngx_mail_ssl_module.c index fbc9bc74b12..aebd179d0cc 100644 --- a/src/mail/ngx_mail_ssl_module.c +++ b/src/mail/ngx_mail_ssl_module.c @@ -42,6 +42,7 @@ static ngx_conf_bitmask_t ngx_mail_ssl_protocols[] = { { ngx_string("TLSv1"), NGX_SSL_TLSv1 }, { ngx_string("TLSv1.1"), NGX_SSL_TLSv1_1 }, { ngx_string("TLSv1.2"), NGX_SSL_TLSv1_2 }, + { ngx_string("TLSv1.3"), NGX_SSL_TLSv1_3 }, { ngx_null_string, 0 } }; diff --git a/src/misc/ngx_google_perftools_module.c b/src/misc/ngx_google_perftools_module.c index f2f8221b560..381f3d105fa 100644 --- a/src/misc/ngx_google_perftools_module.c +++ b/src/misc/ngx_google_perftools_module.c @@ -36,7 +36,7 @@ static ngx_command_t ngx_google_perftools_commands[] = { offsetof(ngx_google_perftools_conf_t, profiles), NULL }, - ngx_null_command + ngx_null_command }; diff --git a/src/os/unix/ngx_darwin_config.h b/src/os/unix/ngx_darwin_config.h index cfe3ce22380..0dfe6337416 100644 --- a/src/os/unix/ngx_darwin_config.h +++ b/src/os/unix/ngx_darwin_config.h @@ -9,6 +9,9 @@ #define _NGX_DARWIN_CONFIG_H_INCLUDED_ +#define __APPLE_USE_RFC_3542 /* IPV6_PKTINFO */ + + #include #include #include diff --git a/src/os/unix/ngx_darwin_sendfile_chain.c b/src/os/unix/ngx_darwin_sendfile_chain.c index c802e9f9a16..2a76c154dd2 100644 --- a/src/os/unix/ngx_darwin_sendfile_chain.c +++ b/src/os/unix/ngx_darwin_sendfile_chain.c @@ -98,7 +98,7 @@ ngx_darwin_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit) send += file_size; - if (header.count == 0) { + if (header.count == 0 && send < limit) { /* * create the trailer iovec and coalesce the neighbouring bufs diff --git a/src/os/unix/ngx_files.c b/src/os/unix/ngx_files.c index 7fbb7c9a795..482d327637e 100644 --- a/src/os/unix/ngx_files.c +++ b/src/os/unix/ngx_files.c @@ -620,6 +620,7 @@ ngx_create_file_mapping(ngx_file_mapping_t *fm) { fm->fd = ngx_open_file(fm->name, NGX_FILE_RDWR, NGX_FILE_TRUNCATE, NGX_FILE_DEFAULT_ACCESS); + if (fm->fd == NGX_INVALID_FILE) { ngx_log_error(NGX_LOG_CRIT, fm->log, ngx_errno, ngx_open_file_n " \"%s\" failed", fm->name); diff --git a/src/os/unix/ngx_freebsd_sendfile_chain.c b/src/os/unix/ngx_freebsd_sendfile_chain.c index d0299f54fa9..4822e72bb82 100644 --- a/src/os/unix/ngx_freebsd_sendfile_chain.c +++ b/src/os/unix/ngx_freebsd_sendfile_chain.c @@ -114,15 +114,23 @@ ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit) send += file_size; - /* create the trailer iovec and coalesce the neighbouring bufs */ + if (send < limit) { - cl = ngx_output_chain_to_iovec(&trailer, cl, limit - send, c->log); + /* + * create the trailer iovec and coalesce the neighbouring bufs + */ - if (cl == NGX_CHAIN_ERROR) { - return NGX_CHAIN_ERROR; - } + cl = ngx_output_chain_to_iovec(&trailer, cl, limit - send, + c->log); + if (cl == NGX_CHAIN_ERROR) { + return NGX_CHAIN_ERROR; + } + + send += trailer.size; - send += trailer.size; + } else { + trailer.count = 0; + } if (ngx_freebsd_use_tcp_nopush && c->tcp_nopush == NGX_TCP_NOPUSH_UNSET) diff --git a/src/os/unix/ngx_linux_sendfile_chain.c b/src/os/unix/ngx_linux_sendfile_chain.c index 3c0696a025f..b44724cdd61 100644 --- a/src/os/unix/ngx_linux_sendfile_chain.c +++ b/src/os/unix/ngx_linux_sendfile_chain.c @@ -20,8 +20,8 @@ static ssize_t ngx_linux_sendfile(ngx_connection_t *c, ngx_buf_t *file, #error sendfile64() is required! #endif -static ngx_int_t ngx_linux_sendfile_thread(ngx_connection_t *c, ngx_buf_t *file, - size_t size, size_t *sent); +static ssize_t ngx_linux_sendfile_thread(ngx_connection_t *c, ngx_buf_t *file, + size_t size); static void ngx_linux_sendfile_thread_handler(void *data, ngx_log_t *log); #endif @@ -56,10 +56,6 @@ ngx_linux_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit) ngx_chain_t *cl; ngx_iovec_t header; struct iovec headers[NGX_IOVS_PREALLOCATE]; -#if (NGX_THREADS) - ngx_int_t rc; - ngx_uint_t thread_handled, thread_complete; -#endif wev = c->write; @@ -82,10 +78,6 @@ ngx_linux_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit) for ( ;; ) { prev_send = send; -#if (NGX_THREADS) - thread_handled = 0; - thread_complete = 0; -#endif /* create the iovec and coalesce the neighbouring bufs */ @@ -179,38 +171,19 @@ ngx_linux_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit) } #endif -#if (NGX_THREADS) - if (file->file->thread_handler) { - rc = ngx_linux_sendfile_thread(c, file, file_size, &sent); - - switch (rc) { - case NGX_OK: - thread_handled = 1; - break; - - case NGX_DONE: - thread_complete = 1; - break; - - case NGX_AGAIN: - break; - - default: /* NGX_ERROR */ - return NGX_CHAIN_ERROR; - } - - } else -#endif - { - n = ngx_linux_sendfile(c, file, file_size); + n = ngx_linux_sendfile(c, file, file_size); - if (n == NGX_ERROR) { - return NGX_CHAIN_ERROR; - } + if (n == NGX_ERROR) { + return NGX_CHAIN_ERROR; + } - sent = (n == NGX_AGAIN) ? 0 : n; + if (n == NGX_DONE) { + /* thread task posted */ + return in; } + sent = (n == NGX_AGAIN) ? 0 : n; + } else { n = ngx_writev(c, &header); @@ -225,21 +198,27 @@ ngx_linux_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit) in = ngx_chain_update_sent(in, sent); - if ((size_t) (send - prev_send) != sent) { -#if (NGX_THREADS) - if (thread_handled) { - return in; - } - - if (thread_complete) { - send = prev_send + sent; - continue; - } -#endif + if (n == NGX_AGAIN) { wev->ready = 0; return in; } + if ((size_t) (send - prev_send) != sent) { + + /* + * sendfile() on Linux 4.3+ might be interrupted at any time, + * and provides no indication if it was interrupted or not, + * so we have to retry till an explicit EAGAIN + * + * sendfile() in threads can also report less bytes written + * than we are prepared to send now, since it was started in + * some point in the past, so we again have to retry + */ + + send = prev_send + sent; + continue; + } + if (send >= limit || in == NULL) { return in; } @@ -258,6 +237,14 @@ ngx_linux_sendfile(ngx_connection_t *c, ngx_buf_t *file, size_t size) ssize_t n; ngx_err_t err; +#if (NGX_THREADS) + + if (file->file->thread_handler) { + return ngx_linux_sendfile_thread(c, file, size); + } + +#endif + #if (NGX_HAVE_SENDFILE64) offset = file->file_pos; #else @@ -324,9 +311,8 @@ typedef struct { } ngx_linux_sendfile_ctx_t; -static ngx_int_t -ngx_linux_sendfile_thread(ngx_connection_t *c, ngx_buf_t *file, size_t size, - size_t *sent) +static ssize_t +ngx_linux_sendfile_thread(ngx_connection_t *c, ngx_buf_t *file, size_t size) { ngx_event_t *wev; ngx_thread_task_t *task; @@ -356,10 +342,14 @@ ngx_linux_sendfile_thread(ngx_connection_t *c, ngx_buf_t *file, size_t size, task->event.complete = 0; if (ctx->err == NGX_EAGAIN) { - *sent = 0; + /* + * if wev->complete is set, this means that a write event + * happened while we were waiting for the thread task, so + * we have to retry sending even on EAGAIN + */ if (wev->complete) { - return NGX_DONE; + return 0; } return NGX_AGAIN; @@ -384,13 +374,7 @@ ngx_linux_sendfile_thread(ngx_connection_t *c, ngx_buf_t *file, size_t size, return NGX_ERROR; } - *sent = ctx->sent; - - if (ctx->sent == ctx->size || wev->complete) { - return NGX_DONE; - } - - return NGX_AGAIN; + return ctx->sent; } if (task->event.active && ctx->file == file) { @@ -399,9 +383,7 @@ ngx_linux_sendfile_thread(ngx_connection_t *c, ngx_buf_t *file, size_t size, * or multiple calls of the next body filter from a filter */ - *sent = 0; - - return NGX_OK; + return NGX_DONE; } ctx->file = file; @@ -414,9 +396,7 @@ ngx_linux_sendfile_thread(ngx_connection_t *c, ngx_buf_t *file, size_t size, return NGX_ERROR; } - *sent = 0; - - return NGX_OK; + return NGX_DONE; } diff --git a/src/os/unix/ngx_process.c b/src/os/unix/ngx_process.c index 24a63fbf580..993c032ae19 100644 --- a/src/os/unix/ngx_process.c +++ b/src/os/unix/ngx_process.c @@ -15,13 +15,13 @@ typedef struct { int signo; char *signame; char *name; - void (*handler)(int signo); + void (*handler)(int signo, siginfo_t *siginfo, void *ucontext); } ngx_signal_t; static void ngx_execute_proc(ngx_cycle_t *cycle, void *data); -static void ngx_signal_handler(int signo); +static void ngx_signal_handler(int signo, siginfo_t *siginfo, void *ucontext); static void ngx_process_get_status(void); static void ngx_unlock_mutexes(ngx_pid_t pid); @@ -75,9 +75,9 @@ ngx_signal_t signals[] = { { SIGCHLD, "SIGCHLD", "", ngx_signal_handler }, - { SIGSYS, "SIGSYS, SIG_IGN", "", SIG_IGN }, + { SIGSYS, "SIGSYS, SIG_IGN", "", NULL }, - { SIGPIPE, "SIGPIPE, SIG_IGN", "", SIG_IGN }, + { SIGPIPE, "SIGPIPE, SIG_IGN", "", NULL }, { 0, NULL, "", NULL } }; @@ -288,7 +288,15 @@ ngx_init_signals(ngx_log_t *log) for (sig = signals; sig->signo != 0; sig++) { ngx_memzero(&sa, sizeof(struct sigaction)); - sa.sa_handler = sig->handler; + + if (sig->handler) { + sa.sa_sigaction = sig->handler; + sa.sa_flags = SA_SIGINFO; + + } else { + sa.sa_handler = SIG_IGN; + } + sigemptyset(&sa.sa_mask); if (sigaction(sig->signo, &sa, NULL) == -1) { #if (NGX_VALGRIND) @@ -306,8 +314,8 @@ ngx_init_signals(ngx_log_t *log) } -void -ngx_signal_handler(int signo) +static void +ngx_signal_handler(int signo, siginfo_t *siginfo, void *ucontext) { char *action; ngx_int_t ignore; @@ -405,6 +413,7 @@ ngx_signal_handler(int signo) break; } ngx_debug_quit = 1; + /* fall through */ case ngx_signal_value(NGX_SHUTDOWN_SIGNAL): ngx_quit = 1; action = ", shutting down"; @@ -431,8 +440,16 @@ ngx_signal_handler(int signo) break; } - ngx_log_error(NGX_LOG_NOTICE, ngx_cycle->log, 0, - "signal %d (%s) received%s", signo, sig->signame, action); + if (siginfo && siginfo->si_pid) { + ngx_log_error(NGX_LOG_NOTICE, ngx_cycle->log, 0, + "signal %d (%s) received from %P%s", + signo, sig->signame, siginfo->si_pid, action); + + } else { + ngx_log_error(NGX_LOG_NOTICE, ngx_cycle->log, 0, + "signal %d (%s) received%s", + signo, sig->signame, action); + } if (ignore) { ngx_log_error(NGX_LOG_CRIT, ngx_cycle->log, 0, diff --git a/src/os/unix/ngx_process_cycle.c b/src/os/unix/ngx_process_cycle.c index 5c4e21dfd9e..1710ea81201 100644 --- a/src/os/unix/ngx_process_cycle.c +++ b/src/os/unix/ngx_process_cycle.c @@ -738,12 +738,8 @@ ngx_worker_process_cycle(ngx_cycle_t *cycle, void *data) for ( ;; ) { if (ngx_exiting) { - ngx_event_cancel_timers(); - - if (ngx_event_timer_rbtree.root == ngx_event_timer_rbtree.sentinel) - { + if (ngx_event_no_timers_left() == NGX_OK) { ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "exiting"); - ngx_worker_process_exit(cycle); } } @@ -754,7 +750,6 @@ ngx_worker_process_cycle(ngx_cycle_t *cycle, void *data) if (ngx_terminate) { ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "exiting"); - ngx_worker_process_exit(cycle); } @@ -766,6 +761,7 @@ ngx_worker_process_cycle(ngx_cycle_t *cycle, void *data) if (!ngx_exiting) { ngx_exiting = 1; + ngx_set_shutdown_timer(cycle); ngx_close_listening_sockets(cycle); ngx_close_idle_connections(cycle); } diff --git a/src/os/unix/ngx_thread_cond.c b/src/os/unix/ngx_thread_cond.c index f5246966a67..2ad51b809e1 100644 --- a/src/os/unix/ngx_thread_cond.c +++ b/src/os/unix/ngx_thread_cond.c @@ -16,8 +16,6 @@ ngx_thread_cond_create(ngx_thread_cond_t *cond, ngx_log_t *log) err = pthread_cond_init(cond, NULL); if (err == 0) { - ngx_log_debug1(NGX_LOG_DEBUG_CORE, log, 0, - "pthread_cond_init(%p)", cond); return NGX_OK; } @@ -33,8 +31,6 @@ ngx_thread_cond_destroy(ngx_thread_cond_t *cond, ngx_log_t *log) err = pthread_cond_destroy(cond); if (err == 0) { - ngx_log_debug1(NGX_LOG_DEBUG_CORE, log, 0, - "pthread_cond_destroy(%p)", cond); return NGX_OK; } @@ -50,8 +46,6 @@ ngx_thread_cond_signal(ngx_thread_cond_t *cond, ngx_log_t *log) err = pthread_cond_signal(cond); if (err == 0) { - ngx_log_debug1(NGX_LOG_DEBUG_CORE, log, 0, - "pthread_cond_signal(%p)", cond); return NGX_OK; } @@ -66,9 +60,6 @@ ngx_thread_cond_wait(ngx_thread_cond_t *cond, ngx_thread_mutex_t *mtx, { ngx_err_t err; - ngx_log_debug1(NGX_LOG_DEBUG_CORE, log, 0, - "pthread_cond_wait(%p) enter", cond); - err = pthread_cond_wait(cond, mtx); #if 0 @@ -76,8 +67,6 @@ ngx_thread_cond_wait(ngx_thread_cond_t *cond, ngx_thread_mutex_t *mtx, #endif if (err == 0) { - ngx_log_debug1(NGX_LOG_DEBUG_CORE, log, 0, - "pthread_cond_wait(%p) exit", cond); return NGX_OK; } diff --git a/src/os/unix/ngx_thread_mutex.c b/src/os/unix/ngx_thread_mutex.c index a0ef693e72a..4886f49d7d8 100644 --- a/src/os/unix/ngx_thread_mutex.c +++ b/src/os/unix/ngx_thread_mutex.c @@ -108,8 +108,6 @@ ngx_thread_mutex_create(ngx_thread_mutex_t *mtx, ngx_log_t *log) "pthread_mutexattr_destroy() failed"); } - ngx_log_debug1(NGX_LOG_DEBUG_CORE, log, 0, - "pthread_mutex_init(%p)", mtx); return NGX_OK; } @@ -126,8 +124,6 @@ ngx_thread_mutex_destroy(ngx_thread_mutex_t *mtx, ngx_log_t *log) return NGX_ERROR; } - ngx_log_debug1(NGX_LOG_DEBUG_CORE, log, 0, - "pthread_mutex_destroy(%p)", mtx); return NGX_OK; } @@ -137,9 +133,6 @@ ngx_thread_mutex_lock(ngx_thread_mutex_t *mtx, ngx_log_t *log) { ngx_err_t err; - ngx_log_debug1(NGX_LOG_DEBUG_CORE, log, 0, - "pthread_mutex_lock(%p) enter", mtx); - err = pthread_mutex_lock(mtx); if (err == 0) { return NGX_OK; @@ -163,8 +156,6 @@ ngx_thread_mutex_unlock(ngx_thread_mutex_t *mtx, ngx_log_t *log) #endif if (err == 0) { - ngx_log_debug1(NGX_LOG_DEBUG_CORE, log, 0, - "pthread_mutex_unlock(%p) exit", mtx); return NGX_OK; } diff --git a/src/os/unix/ngx_udp_sendmsg_chain.c b/src/os/unix/ngx_udp_sendmsg_chain.c index 65bde6f97fc..5399c7916a9 100644 --- a/src/os/unix/ngx_udp_sendmsg_chain.c +++ b/src/os/unix/ngx_udp_sendmsg_chain.c @@ -203,6 +203,20 @@ ngx_sendmsg(ngx_connection_t *c, ngx_iovec_t *vec) ngx_err_t err; struct msghdr msg; +#if (NGX_HAVE_MSGHDR_MSG_CONTROL) + +#if (NGX_HAVE_IP_SENDSRCADDR) + u_char msg_control[CMSG_SPACE(sizeof(struct in_addr))]; +#elif (NGX_HAVE_IP_PKTINFO) + u_char msg_control[CMSG_SPACE(sizeof(struct in_pktinfo))]; +#endif + +#if (NGX_HAVE_INET6 && NGX_HAVE_IPV6_RECVPKTINFO) + u_char msg_control6[CMSG_SPACE(sizeof(struct in6_pktinfo))]; +#endif + +#endif + ngx_memzero(&msg, sizeof(struct msghdr)); if (c->socklen) { @@ -213,6 +227,82 @@ ngx_sendmsg(ngx_connection_t *c, ngx_iovec_t *vec) msg.msg_iov = vec->iovs; msg.msg_iovlen = vec->count; +#if (NGX_HAVE_MSGHDR_MSG_CONTROL) + + if (c->listening && c->listening->wildcard && c->local_sockaddr) { + +#if (NGX_HAVE_IP_SENDSRCADDR) + + if (c->local_sockaddr->sa_family == AF_INET) { + struct cmsghdr *cmsg; + struct in_addr *addr; + struct sockaddr_in *sin; + + msg.msg_control = &msg_control; + msg.msg_controllen = sizeof(msg_control); + + cmsg = CMSG_FIRSTHDR(&msg); + cmsg->cmsg_level = IPPROTO_IP; + cmsg->cmsg_type = IP_SENDSRCADDR; + cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_addr)); + + sin = (struct sockaddr_in *) c->local_sockaddr; + + addr = (struct in_addr *) CMSG_DATA(cmsg); + *addr = sin->sin_addr; + } + +#elif (NGX_HAVE_IP_PKTINFO) + + if (c->local_sockaddr->sa_family == AF_INET) { + struct cmsghdr *cmsg; + struct in_pktinfo *pkt; + struct sockaddr_in *sin; + + msg.msg_control = &msg_control; + msg.msg_controllen = sizeof(msg_control); + + cmsg = CMSG_FIRSTHDR(&msg); + cmsg->cmsg_level = IPPROTO_IP; + cmsg->cmsg_type = IP_PKTINFO; + cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo)); + + sin = (struct sockaddr_in *) c->local_sockaddr; + + pkt = (struct in_pktinfo *) CMSG_DATA(cmsg); + ngx_memzero(pkt, sizeof(struct in_pktinfo)); + pkt->ipi_spec_dst = sin->sin_addr; + } + +#endif + +#if (NGX_HAVE_INET6 && NGX_HAVE_IPV6_RECVPKTINFO) + + if (c->local_sockaddr->sa_family == AF_INET6) { + struct cmsghdr *cmsg; + struct in6_pktinfo *pkt6; + struct sockaddr_in6 *sin6; + + msg.msg_control = &msg_control6; + msg.msg_controllen = sizeof(msg_control6); + + cmsg = CMSG_FIRSTHDR(&msg); + cmsg->cmsg_level = IPPROTO_IPV6; + cmsg->cmsg_type = IPV6_PKTINFO; + cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo)); + + sin6 = (struct sockaddr_in6 *) c->local_sockaddr; + + pkt6 = (struct in6_pktinfo *) CMSG_DATA(cmsg); + ngx_memzero(pkt6, sizeof(struct in6_pktinfo)); + pkt6->ipi6_addr = sin6->sin6_addr; + } + +#endif + } + +#endif + eintr: n = sendmsg(c->fd, &msg, 0); diff --git a/src/os/unix/ngx_user.c b/src/os/unix/ngx_user.c index 27c76ef80a5..7ebe2b576c1 100644 --- a/src/os/unix/ngx_user.c +++ b/src/os/unix/ngx_user.c @@ -9,16 +9,6 @@ #include -/* - * Solaris has thread-safe crypt() - * Linux has crypt_r(); "struct crypt_data" is more than 128K - * FreeBSD needs the mutex to protect crypt() - * - * TODO: - * ngx_crypt_init() to init mutex - */ - - #if (NGX_CRYPT) #if (NGX_HAVE_GNU_CRYPT_R) diff --git a/src/os/win32/ngx_files.c b/src/os/win32/ngx_files.c index 9ef22a56c89..55d7f7696c8 100644 --- a/src/os/win32/ngx_files.c +++ b/src/os/win32/ngx_files.c @@ -330,6 +330,7 @@ ngx_create_file_mapping(ngx_file_mapping_t *fm) fm->fd = ngx_open_file(fm->name, NGX_FILE_RDWR, NGX_FILE_TRUNCATE, NGX_FILE_DEFAULT_ACCESS); + if (fm->fd == NGX_INVALID_FILE) { ngx_log_error(NGX_LOG_CRIT, fm->log, ngx_errno, ngx_open_file_n " \"%s\" failed", fm->name); diff --git a/src/os/win32/ngx_process_cycle.c b/src/os/win32/ngx_process_cycle.c index 99fec54e36a..293b967ec45 100644 --- a/src/os/win32/ngx_process_cycle.c +++ b/src/os/win32/ngx_process_cycle.c @@ -782,11 +782,7 @@ ngx_worker_thread(void *data) while (!ngx_quit) { if (ngx_exiting) { - ngx_event_cancel_timers(); - - if (ngx_event_timer_rbtree.root - == ngx_event_timer_rbtree.sentinel) - { + if (ngx_event_no_timers_left() == NGX_OK) { break; } } @@ -804,6 +800,7 @@ ngx_worker_thread(void *data) if (!ngx_exiting) { ngx_exiting = 1; + ngx_set_shutdown_timer(cycle); ngx_close_listening_sockets(cycle); ngx_close_idle_connections(cycle); } diff --git a/src/os/win32/ngx_win32_config.h b/src/os/win32/ngx_win32_config.h index f5b5950bb20..4824d05a875 100644 --- a/src/os/win32/ngx_win32_config.h +++ b/src/os/win32/ngx_win32_config.h @@ -51,13 +51,14 @@ /* GCC MinGW's stdio.h includes sys/types.h */ #define _OFF_T_ +#define __have_typedef_off_t #endif #include #include #include -#ifdef __MINGW64_VERSION_MAJOR +#ifdef __GNUC__ #include #endif #include @@ -87,12 +88,21 @@ typedef long time_t; /* 'type cast': from data pointer to function pointer */ #pragma warning(disable:4055) +/* 'function' : different 'const' qualifiers */ +#pragma warning(disable:4090) + /* unreferenced formal parameter */ #pragma warning(disable:4100) /* FD_SET() and FD_CLR(): conditional expression is constant */ #pragma warning(disable:4127) +/* conversion from 'type1' to 'type2', possible loss of data */ +#pragma warning(disable:4244) + +/* conversion from 'size_t' to 'type', possible loss of data */ +#pragma warning(disable:4267) + /* array is too small to include a terminating null character */ #pragma warning(disable:4295) @@ -118,6 +128,9 @@ typedef long time_t; /* unreferenced formal parameter */ #pragma warn -8057 +/* suspicious pointer arithmetic */ +#pragma warn -8072 + #endif @@ -151,7 +164,7 @@ typedef unsigned short int uint16_t; typedef __int64 int64_t; typedef unsigned __int64 uint64_t; -#if !defined(__WATCOMC__) && !defined(__MINGW64_VERSION_MAJOR) +#if __BORLANDC__ typedef int intptr_t; typedef u_int uintptr_t; #endif @@ -184,9 +197,13 @@ typedef unsigned int ino_t; #endif -#ifndef __MINGW64_VERSION_MAJOR +#ifndef __GNUC__ +#ifdef _WIN64 +typedef __int64 ssize_t; +#else typedef int ssize_t; #endif +#endif typedef uint32_t in_addr_t; diff --git a/src/stream/ngx_stream.c b/src/stream/ngx_stream.c index 4a394d75ea0..0efbda89efe 100644 --- a/src/stream/ngx_stream.c +++ b/src/stream/ngx_stream.c @@ -494,6 +494,8 @@ ngx_stream_optimize_servers(ngx_conf_t *cf, ngx_array_t *ports) ls->log.handler = ngx_accept_log_error; ls->backlog = addr[i].opt.backlog; + ls->rcvbuf = addr[i].opt.rcvbuf; + ls->sndbuf = addr[i].opt.sndbuf; ls->wildcard = addr[i].opt.wildcard; diff --git a/src/stream/ngx_stream.h b/src/stream/ngx_stream.h index 9e4169c3818..09d24593982 100644 --- a/src/stream/ngx_stream.h +++ b/src/stream/ngx_stream.h @@ -62,6 +62,8 @@ typedef struct { int tcp_keepcnt; #endif int backlog; + int rcvbuf; + int sndbuf; int type; } ngx_stream_listen_t; @@ -153,7 +155,8 @@ typedef struct { ngx_hash_t variables_hash; - ngx_array_t variables; /* ngx_stream_variable_t */ + ngx_array_t variables; /* ngx_stream_variable_t */ + ngx_array_t prefix_variables; /* ngx_stream_variable_t */ ngx_uint_t ncaptures; ngx_uint_t variables_hash_max_size; diff --git a/src/stream/ngx_stream_access_module.c b/src/stream/ngx_stream_access_module.c index 1745cdf0e5f..a3020d4fbd6 100644 --- a/src/stream/ngx_stream_access_module.c +++ b/src/stream/ngx_stream_access_module.c @@ -299,27 +299,21 @@ ngx_stream_access_rule(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) ngx_stream_access_rule_un_t *rule_un; #endif + all = 0; ngx_memzero(&cidr, sizeof(ngx_cidr_t)); value = cf->args->elts; - all = (value[1].len == 3 && ngx_strcmp(value[1].data, "all") == 0); - - if (!all) { + if (value[1].len == 3 && ngx_strcmp(value[1].data, "all") == 0) { + all = 1; #if (NGX_HAVE_UNIX_DOMAIN) + } else if (value[1].len == 5 && ngx_strcmp(value[1].data, "unix:") == 0) { + cidr.family = AF_UNIX; +#endif - if (value[1].len == 5 && ngx_strcmp(value[1].data, "unix:") == 0) { - cidr.family = AF_UNIX; - rc = NGX_OK; - - } else { - rc = ngx_ptocidr(&value[1], &cidr); - } - -#else + } else { rc = ngx_ptocidr(&value[1], &cidr); -#endif if (rc == NGX_ERROR) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, diff --git a/src/stream/ngx_stream_core_module.c b/src/stream/ngx_stream_core_module.c index f7870eed501..272708d62a7 100644 --- a/src/stream/ngx_stream_core_module.c +++ b/src/stream/ngx_stream_core_module.c @@ -309,7 +309,6 @@ ngx_int_t ngx_stream_core_content_phase(ngx_stream_session_t *s, ngx_stream_phase_handler_t *ph) { - int tcp_nodelay; ngx_connection_t *c; ngx_stream_core_srv_conf_t *cscf; @@ -321,22 +320,10 @@ ngx_stream_core_content_phase(ngx_stream_session_t *s, if (c->type == SOCK_STREAM && cscf->tcp_nodelay - && c->tcp_nodelay == NGX_TCP_NODELAY_UNSET) + && ngx_tcp_nodelay(c) != NGX_OK) { - ngx_log_debug0(NGX_LOG_DEBUG_STREAM, c->log, 0, "tcp_nodelay"); - - tcp_nodelay = 1; - - if (setsockopt(c->fd, IPPROTO_TCP, TCP_NODELAY, - (const void *) &tcp_nodelay, sizeof(int)) == -1) - { - ngx_connection_error(c, ngx_socket_errno, - "setsockopt(TCP_NODELAY) failed"); - ngx_stream_finalize_session(s, NGX_STREAM_INTERNAL_SERVER_ERROR); - return NGX_OK; - } - - c->tcp_nodelay = NGX_TCP_NODELAY_SET; + ngx_stream_finalize_session(s, NGX_STREAM_INTERNAL_SERVER_ERROR); + return NGX_OK; } cscf->handler(s); @@ -582,7 +569,7 @@ ngx_stream_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { ngx_stream_core_srv_conf_t *cscf = conf; - ngx_str_t *value; + ngx_str_t *value, size; ngx_url_t u; ngx_uint_t i, backlog; ngx_stream_listen_t *ls, *als; @@ -620,6 +607,8 @@ ngx_stream_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) ls->socklen = u.socklen; ls->backlog = NGX_LISTEN_BACKLOG; + ls->rcvbuf = -1; + ls->sndbuf = -1; ls->type = SOCK_STREAM; ls->wildcard = u.wildcard; ls->ctx = cf->ctx; @@ -659,6 +648,38 @@ ngx_stream_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) continue; } + if (ngx_strncmp(value[i].data, "rcvbuf=", 7) == 0) { + size.len = value[i].len - 7; + size.data = value[i].data + 7; + + ls->rcvbuf = ngx_parse_size(&size); + ls->bind = 1; + + if (ls->rcvbuf == NGX_ERROR) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "invalid rcvbuf \"%V\"", &value[i]); + return NGX_CONF_ERROR; + } + + continue; + } + + if (ngx_strncmp(value[i].data, "sndbuf=", 7) == 0) { + size.len = value[i].len - 7; + size.data = value[i].data + 7; + + ls->sndbuf = ngx_parse_size(&size); + ls->bind = 1; + + if (ls->sndbuf == NGX_ERROR) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "invalid sndbuf \"%V\"", &value[i]); + return NGX_CONF_ERROR; + } + + continue; + } + if (ngx_strncmp(value[i].data, "ipv6only=o", 10) == 0) { #if (NGX_HAVE_INET6 && defined IPV6_V6ONLY) size_t len; diff --git a/src/stream/ngx_stream_geo_module.c b/src/stream/ngx_stream_geo_module.c index 220454631ae..632fa5a5a63 100644 --- a/src/stream/ngx_stream_geo_module.c +++ b/src/stream/ngx_stream_geo_module.c @@ -1326,7 +1326,8 @@ ngx_stream_geo_include_binary_base(ngx_conf_t *cf, file.name = *name; file.log = cf->log; - file.fd = ngx_open_file(name->data, NGX_FILE_RDONLY, 0, 0); + file.fd = ngx_open_file(name->data, NGX_FILE_RDONLY, NGX_FILE_OPEN, 0); + if (file.fd == NGX_INVALID_FILE) { err = ngx_errno; if (err != NGX_ENOENT) { diff --git a/src/stream/ngx_stream_geoip_module.c b/src/stream/ngx_stream_geoip_module.c index f694033cb4f..6507b716ec1 100644 --- a/src/stream/ngx_stream_geoip_module.c +++ b/src/stream/ngx_stream_geoip_module.c @@ -210,7 +210,7 @@ static ngx_stream_variable_t ngx_stream_geoip_vars[] = { ngx_stream_geoip_city_int_variable, offsetof(GeoIPRecord, area_code), 0, 0 }, - { ngx_null_string, NULL, NULL, 0, 0, 0 } + ngx_stream_null_variable }; diff --git a/src/stream/ngx_stream_log_module.c b/src/stream/ngx_stream_log_module.c index 26e6d229841..466bdda514f 100644 --- a/src/stream/ngx_stream_log_module.c +++ b/src/stream/ngx_stream_log_module.c @@ -106,12 +106,16 @@ static void ngx_stream_log_flush(ngx_open_file_t *file, ngx_log_t *log); static void ngx_stream_log_flush_handler(ngx_event_t *ev); static ngx_int_t ngx_stream_log_variable_compile(ngx_conf_t *cf, - ngx_stream_log_op_t *op, ngx_str_t *value); + ngx_stream_log_op_t *op, ngx_str_t *value, ngx_uint_t json); static size_t ngx_stream_log_variable_getlen(ngx_stream_session_t *s, uintptr_t data); static u_char *ngx_stream_log_variable(ngx_stream_session_t *s, u_char *buf, ngx_stream_log_op_t *op); static uintptr_t ngx_stream_log_escape(u_char *dst, u_char *src, size_t size); +static size_t ngx_stream_log_json_variable_getlen(ngx_stream_session_t *s, + uintptr_t data); +static u_char *ngx_stream_log_json_variable(ngx_stream_session_t *s, + u_char *buf, ngx_stream_log_op_t *op); static void *ngx_stream_log_create_main_conf(ngx_conf_t *cf); @@ -439,6 +443,11 @@ ngx_stream_log_script_write(ngx_stream_session_t *s, s->connection->pool) != NGX_OK) { + if (of.err == 0) { + /* simulate successful logging */ + return len; + } + ngx_log_error(NGX_LOG_CRIT, s->connection->log, ngx_errno, "%s \"%s\" failed", of.failed, log.data); /* simulate successful logging */ @@ -637,23 +646,10 @@ ngx_stream_log_flush(ngx_open_file_t *file, ngx_log_t *log) static void ngx_stream_log_flush_handler(ngx_event_t *ev) { - ngx_open_file_t *file; - ngx_stream_log_buf_t *buffer; - ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ev->log, 0, "stream log buffer flush handler"); - if (ev->timedout) { - ngx_stream_log_flush(ev->data, ev->log); - return; - } - - /* cancel the flush timer for graceful shutdown */ - - file = ev->data; - buffer = file->data; - - buffer->event = NULL; + ngx_stream_log_flush(ev->data, ev->log); } @@ -686,7 +682,7 @@ ngx_stream_log_copy_long(ngx_stream_session_t *s, u_char *buf, static ngx_int_t ngx_stream_log_variable_compile(ngx_conf_t *cf, ngx_stream_log_op_t *op, - ngx_str_t *value) + ngx_str_t *value, ngx_uint_t json) { ngx_int_t index; @@ -696,8 +692,16 @@ ngx_stream_log_variable_compile(ngx_conf_t *cf, ngx_stream_log_op_t *op, } op->len = 0; - op->getlen = ngx_stream_log_variable_getlen; - op->run = ngx_stream_log_variable; + + if (json) { + op->getlen = ngx_stream_log_json_variable_getlen; + op->run = ngx_stream_log_json_variable; + + } else { + op->getlen = ngx_stream_log_variable_getlen; + op->run = ngx_stream_log_variable; + } + op->data = index; return NGX_OK; @@ -806,6 +810,47 @@ ngx_stream_log_escape(u_char *dst, u_char *src, size_t size) } +static size_t +ngx_stream_log_json_variable_getlen(ngx_stream_session_t *s, uintptr_t data) +{ + uintptr_t len; + ngx_stream_variable_value_t *value; + + value = ngx_stream_get_indexed_variable(s, data); + + if (value == NULL || value->not_found) { + return 0; + } + + len = ngx_escape_json(NULL, value->data, value->len); + + value->escape = len ? 1 : 0; + + return value->len + len; +} + + +static u_char * +ngx_stream_log_json_variable(ngx_stream_session_t *s, u_char *buf, + ngx_stream_log_op_t *op) +{ + ngx_stream_variable_value_t *value; + + value = ngx_stream_get_indexed_variable(s, op->data); + + if (value == NULL || value->not_found) { + return buf; + } + + if (value->escape == 0) { + return ngx_cpymem(buf, value->data, value->len); + + } else { + return (u_char *) ngx_escape_json(buf, value->data, value->len); + } +} + + static void * ngx_stream_log_create_main_conf(ngx_conf_t *cf) { @@ -1220,11 +1265,27 @@ ngx_stream_log_compile_format(ngx_conf_t *cf, ngx_array_t *flushes, size_t i, len; ngx_str_t *value, var; ngx_int_t *flush; - ngx_uint_t bracket; + ngx_uint_t bracket, json; ngx_stream_log_op_t *op; + json = 0; value = args->elts; + if (s < args->nelts && ngx_strncmp(value[s].data, "escape=", 7) == 0) { + data = value[s].data + 7; + + if (ngx_strcmp(data, "json") == 0) { + json = 1; + + } else if (ngx_strcmp(data, "default") != 0) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "unknown log format escaping \"%s\"", data); + return NGX_CONF_ERROR; + } + + s++; + } + for ( /* void */ ; s < args->nelts; s++) { i = 0; @@ -1289,7 +1350,9 @@ ngx_stream_log_compile_format(ngx_conf_t *cf, ngx_array_t *flushes, goto invalid; } - if (ngx_stream_log_variable_compile(cf, op, &var) != NGX_OK) { + if (ngx_stream_log_variable_compile(cf, op, &var, json) + != NGX_OK) + { return NGX_CONF_ERROR; } diff --git a/src/stream/ngx_stream_map_module.c b/src/stream/ngx_stream_map_module.c index 47a15bef7a6..ef06b2de872 100644 --- a/src/stream/ngx_stream_map_module.c +++ b/src/stream/ngx_stream_map_module.c @@ -26,7 +26,8 @@ typedef struct { ngx_stream_variable_value_t *default_value; ngx_conf_t *cf; - ngx_uint_t hostnames; /* unsigned hostnames:1 */ + unsigned hostnames:1; + unsigned no_cacheable:1; } ngx_stream_map_conf_ctx_t; @@ -264,6 +265,7 @@ ngx_stream_map_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) ctx.default_value = NULL; ctx.cf = &save; ctx.hostnames = 0; + ctx.no_cacheable = 0; save = *cf; cf->pool = pool; @@ -280,6 +282,10 @@ ngx_stream_map_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) return rv; } + if (ctx.no_cacheable) { + var->flags |= NGX_STREAM_VAR_NOCACHEABLE; + } + map->default_value = ctx.default_value ? ctx.default_value: &ngx_stream_variable_null_value; @@ -392,8 +398,16 @@ ngx_stream_map(ngx_conf_t *cf, ngx_command_t *dummy, void *conf) { ctx->hostnames = 1; return NGX_CONF_OK; + } + + if (cf->args->nelts == 1 + && ngx_strcmp(value[0].data, "volatile") == 0) + { + ctx->no_cacheable = 1; + return NGX_CONF_OK; + } - } else if (cf->args->nelts != 2) { + if (cf->args->nelts != 2) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid number of the map parameters"); return NGX_CONF_ERROR; diff --git a/src/stream/ngx_stream_proxy_module.c b/src/stream/ngx_stream_proxy_module.c index c03b515057d..9d4b075fb22 100644 --- a/src/stream/ngx_stream_proxy_module.c +++ b/src/stream/ngx_stream_proxy_module.c @@ -103,6 +103,7 @@ static ngx_conf_bitmask_t ngx_stream_proxy_ssl_protocols[] = { { ngx_string("TLSv1"), NGX_SSL_TLSv1 }, { ngx_string("TLSv1.1"), NGX_SSL_TLSv1_1 }, { ngx_string("TLSv1.2"), NGX_SSL_TLSv1_2 }, + { ngx_string("TLSv1.3"), NGX_SSL_TLSv1_3 }, { ngx_null_string, 0 } }; @@ -728,7 +729,6 @@ ngx_stream_proxy_connect(ngx_stream_session_t *s) static void ngx_stream_proxy_init_upstream(ngx_stream_session_t *s) { - int tcp_nodelay; u_char *p; ngx_chain_t *cl; ngx_connection_t *c, *pc; @@ -744,22 +744,10 @@ ngx_stream_proxy_init_upstream(ngx_stream_session_t *s) if (pc->type == SOCK_STREAM && cscf->tcp_nodelay - && pc->tcp_nodelay == NGX_TCP_NODELAY_UNSET) + && ngx_tcp_nodelay(pc) != NGX_OK) { - ngx_log_debug0(NGX_LOG_DEBUG_STREAM, pc->log, 0, "tcp_nodelay"); - - tcp_nodelay = 1; - - if (setsockopt(pc->fd, IPPROTO_TCP, TCP_NODELAY, - (const void *) &tcp_nodelay, sizeof(int)) == -1) - { - ngx_connection_error(pc, ngx_socket_errno, - "setsockopt(TCP_NODELAY) failed"); - ngx_stream_proxy_next_upstream(s); - return; - } - - pc->tcp_nodelay = NGX_TCP_NODELAY_SET; + ngx_stream_proxy_next_upstream(s); + return; } pscf = ngx_stream_get_module_srv_conf(s, ngx_stream_proxy_module); @@ -808,6 +796,11 @@ ngx_stream_proxy_init_upstream(ngx_stream_session_t *s) u->state->connect_time = ngx_current_msec - u->state->response_time; + if (u->peer.notify) { + u->peer.notify(&u->peer, u->peer.data, + NGX_STREAM_UPSTREAM_NOTIFY_CONNECT); + } + c->log->action = "proxying connection"; if (u->upstream_buf.start == NULL) { @@ -1338,13 +1331,17 @@ ngx_stream_proxy_process_connection(ngx_event_t *ev, ngx_uint_t from_upstream) return; } + ngx_connection_error(pc, NGX_ETIMEDOUT, "upstream timed out"); + if (u->received == 0) { ngx_stream_proxy_next_upstream(s); return; } + + } else { + ngx_connection_error(c, NGX_ETIMEDOUT, "connection timed out"); } - ngx_connection_error(c, NGX_ETIMEDOUT, "connection timed out"); ngx_stream_proxy_finalize(s, NGX_STREAM_OK); return; } @@ -1529,8 +1526,9 @@ ngx_stream_proxy_process(ngx_stream_session_t *s, ngx_uint_t from_upstream, size = b->end - b->last; - if (size && src->read->ready && !src->read->delayed) { - + if (size && src->read->ready && !src->read->delayed + && !src->read->error) + { if (limit_rate) { limit = (off_t) limit_rate * (ngx_time() - u->start_sec + 1) - *received; @@ -1671,13 +1669,17 @@ ngx_stream_proxy_next_upstream(ngx_stream_session_t *s) u = s->upstream; pc = u->peer.connection; - if (u->upstream_out || u->upstream_busy || (pc && pc->buffered)) { + if (pc && pc->buffered) { ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, - "pending buffers on next upstream"); + "buffered data on next upstream"); ngx_stream_proxy_finalize(s, NGX_STREAM_INTERNAL_SERVER_ERROR); return; } + if (s->connection->type == SOCK_DGRAM) { + u->upstream_out = NULL; + } + if (u->peer.sockaddr) { u->peer.free(&u->peer, u->peer.data, NGX_PEER_FAILED); u->peer.sockaddr = NULL; diff --git a/src/stream/ngx_stream_realip_module.c b/src/stream/ngx_stream_realip_module.c index 0740431e3a8..57b1ac21e18 100644 --- a/src/stream/ngx_stream_realip_module.c +++ b/src/stream/ngx_stream_realip_module.c @@ -89,7 +89,7 @@ static ngx_stream_variable_t ngx_stream_realip_vars[] = { { ngx_string("realip_remote_port"), NULL, ngx_stream_realip_remote_port_variable, 0, 0, 0 }, - { ngx_null_string, NULL, NULL, 0, 0, 0 } + ngx_stream_null_variable }; @@ -178,9 +178,15 @@ ngx_stream_realip_from(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { ngx_stream_realip_srv_conf_t *rscf = conf; - ngx_int_t rc; - ngx_str_t *value; - ngx_cidr_t *cidr; + ngx_int_t rc; + ngx_str_t *value; + ngx_url_t u; + ngx_cidr_t c, *cidr; + ngx_uint_t i; + struct sockaddr_in *sin; +#if (NGX_HAVE_INET6) + struct sockaddr_in6 *sin6; +#endif value = cf->args->elts; @@ -192,31 +198,78 @@ ngx_stream_realip_from(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) } } - cidr = ngx_array_push(rscf->from); - if (cidr == NULL) { - return NGX_CONF_ERROR; - } - #if (NGX_HAVE_UNIX_DOMAIN) if (ngx_strcmp(value[1].data, "unix:") == 0) { + cidr = ngx_array_push(rscf->from); + if (cidr == NULL) { + return NGX_CONF_ERROR; + } + cidr->family = AF_UNIX; return NGX_CONF_OK; } #endif - rc = ngx_ptocidr(&value[1], cidr); + rc = ngx_ptocidr(&value[1], &c); + + if (rc != NGX_ERROR) { + if (rc == NGX_DONE) { + ngx_conf_log_error(NGX_LOG_WARN, cf, 0, + "low address bits of %V are meaningless", + &value[1]); + } + + cidr = ngx_array_push(rscf->from); + if (cidr == NULL) { + return NGX_CONF_ERROR; + } + + *cidr = c; + + return NGX_CONF_OK; + } + + ngx_memzero(&u, sizeof(ngx_url_t)); + u.host = value[1]; + + if (ngx_inet_resolve_host(cf->pool, &u) != NGX_OK) { + if (u.err) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "%s in set_real_ip_from \"%V\"", + u.err, &u.host); + } - if (rc == NGX_ERROR) { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid parameter \"%V\"", - &value[1]); return NGX_CONF_ERROR; } - if (rc == NGX_DONE) { - ngx_conf_log_error(NGX_LOG_WARN, cf, 0, - "low address bits of %V are meaningless", &value[1]); + cidr = ngx_array_push_n(rscf->from, u.naddrs); + if (cidr == NULL) { + return NGX_CONF_ERROR; + } + + ngx_memzero(cidr, u.naddrs * sizeof(ngx_cidr_t)); + + for (i = 0; i < u.naddrs; i++) { + cidr[i].family = u.addrs[i].sockaddr->sa_family; + + switch (cidr[i].family) { + +#if (NGX_HAVE_INET6) + case AF_INET6: + sin6 = (struct sockaddr_in6 *) u.addrs[i].sockaddr; + cidr[i].u.in6.addr = sin6->sin6_addr; + ngx_memset(cidr[i].u.in6.mask.s6_addr, 0xff, 16); + break; +#endif + + default: /* AF_INET */ + sin = (struct sockaddr_in *) u.addrs[i].sockaddr; + cidr[i].u.in.addr = sin->sin_addr.s_addr; + cidr[i].u.in.mask = 0xffffffff; + break; + } } return NGX_CONF_OK; diff --git a/src/stream/ngx_stream_script.c b/src/stream/ngx_stream_script.c index ff8e655a652..aa555ca2c10 100644 --- a/src/stream/ngx_stream_script.c +++ b/src/stream/ngx_stream_script.c @@ -222,7 +222,7 @@ ngx_stream_set_complex_value_slot(ngx_conf_t *cf, ngx_command_t *cmd, cv = (ngx_stream_complex_value_t **) (p + cmd->offset); if (*cv != NULL) { - return "duplicate"; + return "is duplicate"; } *cv = ngx_palloc(cf->pool, sizeof(ngx_stream_complex_value_t)); diff --git a/src/stream/ngx_stream_ssl_module.c b/src/stream/ngx_stream_ssl_module.c index d00718b11ec..1e9973feea0 100644 --- a/src/stream/ngx_stream_ssl_module.c +++ b/src/stream/ngx_stream_ssl_module.c @@ -45,6 +45,16 @@ static ngx_conf_bitmask_t ngx_stream_ssl_protocols[] = { { ngx_string("TLSv1"), NGX_SSL_TLSv1 }, { ngx_string("TLSv1.1"), NGX_SSL_TLSv1_1 }, { ngx_string("TLSv1.2"), NGX_SSL_TLSv1_2 }, + { ngx_string("TLSv1.3"), NGX_SSL_TLSv1_3 }, + { ngx_null_string, 0 } +}; + + +static ngx_conf_enum_t ngx_stream_ssl_verify[] = { + { ngx_string("off"), 0 }, + { ngx_string("on"), 1 }, + { ngx_string("optional"), 2 }, + { ngx_string("optional_no_ca"), 3 }, { ngx_null_string, 0 } }; @@ -107,6 +117,34 @@ static ngx_command_t ngx_stream_ssl_commands[] = { offsetof(ngx_stream_ssl_conf_t, ciphers), NULL }, + { ngx_string("ssl_verify_client"), + NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1, + ngx_conf_set_enum_slot, + NGX_STREAM_SRV_CONF_OFFSET, + offsetof(ngx_stream_ssl_conf_t, verify), + &ngx_stream_ssl_verify }, + + { ngx_string("ssl_verify_depth"), + NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1, + ngx_conf_set_num_slot, + NGX_STREAM_SRV_CONF_OFFSET, + offsetof(ngx_stream_ssl_conf_t, verify_depth), + NULL }, + + { ngx_string("ssl_client_certificate"), + NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1, + ngx_conf_set_str_slot, + NGX_STREAM_SRV_CONF_OFFSET, + offsetof(ngx_stream_ssl_conf_t, client_certificate), + NULL }, + + { ngx_string("ssl_trusted_certificate"), + NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1, + ngx_conf_set_str_slot, + NGX_STREAM_SRV_CONF_OFFSET, + offsetof(ngx_stream_ssl_conf_t, trusted_certificate), + NULL }, + { ngx_string("ssl_prefer_server_ciphers"), NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_FLAG, ngx_conf_set_flag_slot, @@ -142,6 +180,13 @@ static ngx_command_t ngx_stream_ssl_commands[] = { offsetof(ngx_stream_ssl_conf_t, session_timeout), NULL }, + { ngx_string("ssl_crl"), + NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1, + ngx_conf_set_str_slot, + NGX_STREAM_SRV_CONF_OFFSET, + offsetof(ngx_stream_ssl_conf_t, crl), + NULL }, + ngx_null_command }; @@ -182,6 +227,12 @@ static ngx_stream_variable_t ngx_stream_ssl_vars[] = { { ngx_string("ssl_cipher"), NULL, ngx_stream_ssl_static_variable, (uintptr_t) ngx_ssl_get_cipher_name, NGX_STREAM_VAR_CHANGEABLE, 0 }, + { ngx_string("ssl_ciphers"), NULL, ngx_stream_ssl_variable, + (uintptr_t) ngx_ssl_get_ciphers, NGX_STREAM_VAR_CHANGEABLE, 0 }, + + { ngx_string("ssl_curves"), NULL, ngx_stream_ssl_variable, + (uintptr_t) ngx_ssl_get_curves, NGX_STREAM_VAR_CHANGEABLE, 0 }, + { ngx_string("ssl_session_id"), NULL, ngx_stream_ssl_variable, (uintptr_t) ngx_ssl_get_session_id, NGX_STREAM_VAR_CHANGEABLE, 0 }, @@ -191,7 +242,42 @@ static ngx_stream_variable_t ngx_stream_ssl_vars[] = { { ngx_string("ssl_server_name"), NULL, ngx_stream_ssl_variable, (uintptr_t) ngx_ssl_get_server_name, NGX_STREAM_VAR_CHANGEABLE, 0 }, - { ngx_null_string, NULL, NULL, 0, 0, 0 } + { ngx_string("ssl_client_cert"), NULL, ngx_stream_ssl_variable, + (uintptr_t) ngx_ssl_get_certificate, NGX_STREAM_VAR_CHANGEABLE, 0 }, + + { ngx_string("ssl_client_raw_cert"), NULL, ngx_stream_ssl_variable, + (uintptr_t) ngx_ssl_get_raw_certificate, + NGX_STREAM_VAR_CHANGEABLE, 0 }, + + { ngx_string("ssl_client_escaped_cert"), NULL, ngx_stream_ssl_variable, + (uintptr_t) ngx_ssl_get_escaped_certificate, + NGX_STREAM_VAR_CHANGEABLE, 0 }, + + { ngx_string("ssl_client_s_dn"), NULL, ngx_stream_ssl_variable, + (uintptr_t) ngx_ssl_get_subject_dn, NGX_STREAM_VAR_CHANGEABLE, 0 }, + + { ngx_string("ssl_client_i_dn"), NULL, ngx_stream_ssl_variable, + (uintptr_t) ngx_ssl_get_issuer_dn, NGX_STREAM_VAR_CHANGEABLE, 0 }, + + { ngx_string("ssl_client_serial"), NULL, ngx_stream_ssl_variable, + (uintptr_t) ngx_ssl_get_serial_number, NGX_STREAM_VAR_CHANGEABLE, 0 }, + + { ngx_string("ssl_client_fingerprint"), NULL, ngx_stream_ssl_variable, + (uintptr_t) ngx_ssl_get_fingerprint, NGX_STREAM_VAR_CHANGEABLE, 0 }, + + { ngx_string("ssl_client_verify"), NULL, ngx_stream_ssl_variable, + (uintptr_t) ngx_ssl_get_client_verify, NGX_STREAM_VAR_CHANGEABLE, 0 }, + + { ngx_string("ssl_client_v_start"), NULL, ngx_stream_ssl_variable, + (uintptr_t) ngx_ssl_get_client_v_start, NGX_STREAM_VAR_CHANGEABLE, 0 }, + + { ngx_string("ssl_client_v_end"), NULL, ngx_stream_ssl_variable, + (uintptr_t) ngx_ssl_get_client_v_end, NGX_STREAM_VAR_CHANGEABLE, 0 }, + + { ngx_string("ssl_client_v_remain"), NULL, ngx_stream_ssl_variable, + (uintptr_t) ngx_ssl_get_client_v_remain, NGX_STREAM_VAR_CHANGEABLE, 0 }, + + ngx_stream_null_variable }; @@ -201,14 +287,21 @@ static ngx_str_t ngx_stream_ssl_sess_id_ctx = ngx_string("STREAM"); static ngx_int_t ngx_stream_ssl_handler(ngx_stream_session_t *s) { + long rc; + X509 *cert; + ngx_int_t rv; ngx_connection_t *c; ngx_stream_ssl_conf_t *sslcf; + if (!s->ssl) { + return NGX_OK; + } + c = s->connection; sslcf = ngx_stream_get_module_srv_conf(s, ngx_stream_ssl_module); - if (s->ssl && c->ssl == NULL) { + if (c->ssl == NULL) { c->log->action = "SSL handshaking"; if (sslcf->ssl.ctx == NULL) { @@ -218,7 +311,42 @@ ngx_stream_ssl_handler(ngx_stream_session_t *s) return NGX_ERROR; } - return ngx_stream_ssl_init_connection(&sslcf->ssl, c); + rv = ngx_stream_ssl_init_connection(&sslcf->ssl, c); + + if (rv != NGX_OK) { + return rv; + } + } + + if (sslcf->verify) { + rc = SSL_get_verify_result(c->ssl->connection); + + if (rc != X509_V_OK + && (sslcf->verify != 3 || !ngx_ssl_verify_error_optional(rc))) + { + ngx_log_error(NGX_LOG_INFO, c->log, 0, + "client SSL certificate verify error: (%l:%s)", + rc, X509_verify_cert_error_string(rc)); + + ngx_ssl_remove_cached_session(sslcf->ssl.ctx, + (SSL_get0_session(c->ssl->connection))); + return NGX_ERROR; + } + + if (sslcf->verify == 1) { + cert = SSL_get_peer_certificate(c->ssl->connection); + + if (cert == NULL) { + ngx_log_error(NGX_LOG_INFO, c->log, 0, + "client sent no required SSL certificate"); + + ngx_ssl_remove_cached_session(sslcf->ssl.ctx, + (SSL_get0_session(c->ssl->connection))); + return NGX_ERROR; + } + + X509_free(cert); + } } return NGX_OK; @@ -228,13 +356,20 @@ ngx_stream_ssl_handler(ngx_stream_session_t *s) static ngx_int_t ngx_stream_ssl_init_connection(ngx_ssl_t *ssl, ngx_connection_t *c) { - ngx_int_t rc; - ngx_stream_session_t *s; - ngx_stream_ssl_conf_t *sslcf; + ngx_int_t rc; + ngx_stream_session_t *s; + ngx_stream_ssl_conf_t *sslcf; + ngx_stream_core_srv_conf_t *cscf; s = c->data; - if (ngx_ssl_create_connection(ssl, c, 0) == NGX_ERROR) { + cscf = ngx_stream_get_module_srv_conf(s, ngx_stream_core_module); + + if (cscf->tcp_nodelay && ngx_tcp_nodelay(c) != NGX_OK) { + return NGX_ERROR; + } + + if (ngx_ssl_create_connection(ssl, c, 0) != NGX_OK) { return NGX_ERROR; } @@ -378,6 +513,9 @@ ngx_stream_ssl_create_conf(ngx_conf_t *cf) * scf->protocols = 0; * scf->dhparam = { 0, NULL }; * scf->ecdh_curve = { 0, NULL }; + * scf->client_certificate = { 0, NULL }; + * scf->trusted_certificate = { 0, NULL }; + * scf->crl = { 0, NULL }; * scf->ciphers = { 0, NULL }; * scf->shm_zone = NULL; */ @@ -387,6 +525,8 @@ ngx_stream_ssl_create_conf(ngx_conf_t *cf) scf->certificate_keys = NGX_CONF_UNSET_PTR; scf->passwords = NGX_CONF_UNSET_PTR; scf->prefer_server_ciphers = NGX_CONF_UNSET; + scf->verify = NGX_CONF_UNSET_UINT; + scf->verify_depth = NGX_CONF_UNSET_UINT; scf->builtin_session_cache = NGX_CONF_UNSET; scf->session_timeout = NGX_CONF_UNSET; scf->session_tickets = NGX_CONF_UNSET; @@ -417,6 +557,9 @@ ngx_stream_ssl_merge_conf(ngx_conf_t *cf, void *parent, void *child) (NGX_CONF_BITMASK_SET|NGX_SSL_TLSv1 |NGX_SSL_TLSv1_1|NGX_SSL_TLSv1_2)); + ngx_conf_merge_uint_value(conf->verify, prev->verify, 0); + ngx_conf_merge_uint_value(conf->verify_depth, prev->verify_depth, 1); + ngx_conf_merge_ptr_value(conf->certificates, prev->certificates, NULL); ngx_conf_merge_ptr_value(conf->certificate_keys, prev->certificate_keys, NULL); @@ -425,6 +568,12 @@ ngx_stream_ssl_merge_conf(ngx_conf_t *cf, void *parent, void *child) ngx_conf_merge_str_value(conf->dhparam, prev->dhparam, ""); + ngx_conf_merge_str_value(conf->client_certificate, prev->client_certificate, + ""); + ngx_conf_merge_str_value(conf->trusted_certificate, + prev->trusted_certificate, ""); + ngx_conf_merge_str_value(conf->crl, prev->crl, ""); + ngx_conf_merge_str_value(conf->ecdh_curve, prev->ecdh_curve, NGX_DEFAULT_ECDH_CURVE); @@ -474,6 +623,35 @@ ngx_stream_ssl_merge_conf(ngx_conf_t *cf, void *parent, void *child) return NGX_CONF_ERROR; } + if (conf->verify) { + + if (conf->client_certificate.len == 0 && conf->verify != 3) { + ngx_log_error(NGX_LOG_EMERG, cf->log, 0, + "no ssl_client_certificate for ssl_client_verify"); + return NGX_CONF_ERROR; + } + + if (ngx_ssl_client_certificate(cf, &conf->ssl, + &conf->client_certificate, + conf->verify_depth) + != NGX_OK) + { + return NGX_CONF_ERROR; + } + + if (ngx_ssl_trusted_certificate(cf, &conf->ssl, + &conf->trusted_certificate, + conf->verify_depth) + != NGX_OK) + { + return NGX_CONF_ERROR; + } + + if (ngx_ssl_crl(cf, &conf->ssl, &conf->crl) != NGX_OK) { + return NGX_CONF_ERROR; + } + } + if (ngx_ssl_dhparam(cf, &conf->ssl, &conf->dhparam) != NGX_OK) { return NGX_CONF_ERROR; } diff --git a/src/stream/ngx_stream_ssl_module.h b/src/stream/ngx_stream_ssl_module.h index 9b1c41a138c..65f5d456e1f 100644 --- a/src/stream/ngx_stream_ssl_module.h +++ b/src/stream/ngx_stream_ssl_module.h @@ -23,6 +23,9 @@ typedef struct { ngx_uint_t protocols; + ngx_uint_t verify; + ngx_uint_t verify_depth; + ssize_t builtin_session_cache; time_t session_timeout; @@ -32,6 +35,9 @@ typedef struct { ngx_str_t dhparam; ngx_str_t ecdh_curve; + ngx_str_t client_certificate; + ngx_str_t trusted_certificate; + ngx_str_t crl; ngx_str_t ciphers; diff --git a/src/stream/ngx_stream_ssl_preread_module.c b/src/stream/ngx_stream_ssl_preread_module.c index e26c51891ef..e3d11fd931e 100644 --- a/src/stream/ngx_stream_ssl_preread_module.c +++ b/src/stream/ngx_stream_ssl_preread_module.c @@ -85,7 +85,7 @@ static ngx_stream_variable_t ngx_stream_ssl_preread_vars[] = { { ngx_string("ssl_preread_server_name"), NULL, ngx_stream_ssl_preread_server_name_variable, 0, 0, 0 }, - { ngx_null_string, NULL, NULL, 0, 0, 0 } + ngx_stream_null_variable }; @@ -142,7 +142,7 @@ ngx_stream_ssl_preread_handler(ngx_stream_session_t *s) return NGX_DECLINED; } - if (p[1] != 3 || p[2] == 0) { + if (p[1] != 3) { ngx_log_debug0(NGX_LOG_DEBUG_STREAM, ctx->log, 0, "ssl preread: unsupported SSL version"); return NGX_DECLINED; diff --git a/src/stream/ngx_stream_upstream.c b/src/stream/ngx_stream_upstream.c index c9e17845e5b..7feac4381db 100644 --- a/src/stream/ngx_stream_upstream.c +++ b/src/stream/ngx_stream_upstream.c @@ -100,7 +100,7 @@ static ngx_stream_variable_t ngx_stream_upstream_vars[] = { ngx_stream_upstream_bytes_variable, 1, NGX_STREAM_VAR_NOCACHEABLE, 0 }, - { ngx_null_string, NULL, NULL, 0, 0, 0 } + ngx_stream_null_variable }; diff --git a/src/stream/ngx_stream_upstream.h b/src/stream/ngx_stream_upstream.h index ec75768f8dd..73947f465c5 100644 --- a/src/stream/ngx_stream_upstream.h +++ b/src/stream/ngx_stream_upstream.h @@ -24,6 +24,9 @@ #define NGX_STREAM_UPSTREAM_MAX_CONNS 0x0100 +#define NGX_STREAM_UPSTREAM_NOTIFY_CONNECT 0x1 + + typedef struct { ngx_array_t upstreams; /* ngx_stream_upstream_srv_conf_t */ @@ -55,8 +58,8 @@ typedef struct { ngx_uint_t max_fails; time_t fail_timeout; ngx_msec_t slow_start; + ngx_uint_t down; - unsigned down:1; unsigned backup:1; NGX_COMPAT_BEGIN(4) diff --git a/src/stream/ngx_stream_upstream_hash_module.c b/src/stream/ngx_stream_upstream_hash_module.c index cb44fcdad6f..79ad742cf92 100644 --- a/src/stream/ngx_stream_upstream_hash_module.c +++ b/src/stream/ngx_stream_upstream_hash_module.c @@ -505,6 +505,11 @@ ngx_stream_upstream_get_chash_peer(ngx_peer_connection_t *pc, void *data) ngx_stream_upstream_rr_peers_wlock(hp->rrp.peers); + if (hp->tries > 20 || hp->rrp.peers->single) { + ngx_stream_upstream_rr_peers_unlock(hp->rrp.peers); + return hp->get_rr_peer(pc, &hp->rrp); + } + pc->connection = NULL; now = ngx_time(); @@ -539,13 +544,6 @@ ngx_stream_upstream_get_chash_peer(ngx_peer_connection_t *pc, void *data) continue; } - if (peer->server.len != server->len - || ngx_strncmp(peer->server.data, server->data, server->len) - != 0) - { - continue; - } - if (peer->max_fails && peer->fails >= peer->max_fails && now - peer->checked <= peer->fail_timeout) @@ -557,6 +555,13 @@ ngx_stream_upstream_get_chash_peer(ngx_peer_connection_t *pc, void *data) continue; } + if (peer->server.len != server->len + || ngx_strncmp(peer->server.data, server->data, server->len) + != 0) + { + continue; + } + peer->current_weight += peer->effective_weight; total += peer->effective_weight; @@ -578,10 +583,9 @@ ngx_stream_upstream_get_chash_peer(ngx_peer_connection_t *pc, void *data) hp->hash++; hp->tries++; - if (hp->tries >= points->number) { - pc->name = hp->rrp.peers->name; + if (hp->tries > 20) { ngx_stream_upstream_rr_peers_unlock(hp->rrp.peers); - return NGX_BUSY; + return hp->get_rr_peer(pc, &hp->rrp); } } diff --git a/src/stream/ngx_stream_upstream_round_robin.c b/src/stream/ngx_stream_upstream_round_robin.c index db620ef9ebe..526de3a8059 100644 --- a/src/stream/ngx_stream_upstream_round_robin.c +++ b/src/stream/ngx_stream_upstream_round_robin.c @@ -16,6 +16,8 @@ static ngx_stream_upstream_rr_peer_t *ngx_stream_upstream_get_peer( ngx_stream_upstream_rr_peer_data_t *rrp); +static void ngx_stream_upstream_notify_round_robin_peer( + ngx_peer_connection_t *pc, void *data, ngx_uint_t state); #if (NGX_STREAM_SSL) @@ -288,6 +290,7 @@ ngx_stream_upstream_init_round_robin_peer(ngx_stream_session_t *s, s->upstream->peer.get = ngx_stream_upstream_get_round_robin_peer; s->upstream->peer.free = ngx_stream_upstream_free_round_robin_peer; + s->upstream->peer.notify = ngx_stream_upstream_notify_round_robin_peer; s->upstream->peer.tries = ngx_stream_upstream_tries(rrp->peers); #if (NGX_STREAM_SSL) s->upstream->peer.set_session = @@ -659,6 +662,32 @@ ngx_stream_upstream_free_round_robin_peer(ngx_peer_connection_t *pc, void *data, } +static void +ngx_stream_upstream_notify_round_robin_peer(ngx_peer_connection_t *pc, + void *data, ngx_uint_t type) +{ + ngx_stream_upstream_rr_peer_data_t *rrp = data; + + ngx_stream_upstream_rr_peer_t *peer; + + peer = rrp->current; + + if (type == NGX_STREAM_UPSTREAM_NOTIFY_CONNECT + && pc->connection->type == SOCK_STREAM) + { + ngx_stream_upstream_rr_peers_rlock(rrp->peers); + ngx_stream_upstream_rr_peer_lock(rrp->peers, peer); + + if (peer->accessed < peer->checked) { + peer->fails = 0; + } + + ngx_stream_upstream_rr_peer_unlock(rrp->peers, peer); + ngx_stream_upstream_rr_peers_unlock(rrp->peers); + } +} + + #if (NGX_STREAM_SSL) static ngx_int_t diff --git a/src/stream/ngx_stream_upstream_zone_module.c b/src/stream/ngx_stream_upstream_zone_module.c index 07ab88dfa89..80d42fa0018 100644 --- a/src/stream/ngx_stream_upstream_zone_module.c +++ b/src/stream/ngx_stream_upstream_zone_module.c @@ -16,6 +16,8 @@ static ngx_int_t ngx_stream_upstream_init_zone(ngx_shm_zone_t *shm_zone, void *data); static ngx_stream_upstream_rr_peers_t *ngx_stream_upstream_zone_copy_peers( ngx_slab_pool_t *shpool, ngx_stream_upstream_srv_conf_t *uscf); +static ngx_stream_upstream_rr_peer_t *ngx_stream_upstream_zone_copy_peer( + ngx_stream_upstream_rr_peers_t *peers, ngx_stream_upstream_rr_peer_t *src); static ngx_command_t ngx_stream_upstream_zone_commands[] = { @@ -182,6 +184,7 @@ static ngx_stream_upstream_rr_peers_t * ngx_stream_upstream_zone_copy_peers(ngx_slab_pool_t *shpool, ngx_stream_upstream_srv_conf_t *uscf) { + ngx_str_t *name; ngx_stream_upstream_rr_peer_t *peer, **peerp; ngx_stream_upstream_rr_peers_t *peers, *backup; @@ -192,18 +195,30 @@ ngx_stream_upstream_zone_copy_peers(ngx_slab_pool_t *shpool, ngx_memcpy(peers, uscf->peer.data, sizeof(ngx_stream_upstream_rr_peers_t)); + name = ngx_slab_alloc(shpool, sizeof(ngx_str_t)); + if (name == NULL) { + return NULL; + } + + name->data = ngx_slab_alloc(shpool, peers->name->len); + if (name->data == NULL) { + return NULL; + } + + ngx_memcpy(name->data, peers->name->data, peers->name->len); + name->len = peers->name->len; + + peers->name = name; + peers->shpool = shpool; for (peerp = &peers->peer; *peerp; peerp = &peer->next) { /* pool is unlocked */ - peer = ngx_slab_calloc_locked(shpool, - sizeof(ngx_stream_upstream_rr_peer_t)); + peer = ngx_stream_upstream_zone_copy_peer(peers, *peerp); if (peer == NULL) { return NULL; } - ngx_memcpy(peer, *peerp, sizeof(ngx_stream_upstream_rr_peer_t)); - *peerp = peer; } @@ -218,18 +233,17 @@ ngx_stream_upstream_zone_copy_peers(ngx_slab_pool_t *shpool, ngx_memcpy(backup, peers->next, sizeof(ngx_stream_upstream_rr_peers_t)); + backup->name = name; + backup->shpool = shpool; for (peerp = &backup->peer; *peerp; peerp = &peer->next) { /* pool is unlocked */ - peer = ngx_slab_calloc_locked(shpool, - sizeof(ngx_stream_upstream_rr_peer_t)); + peer = ngx_stream_upstream_zone_copy_peer(backup, *peerp); if (peer == NULL) { return NULL; } - ngx_memcpy(peer, *peerp, sizeof(ngx_stream_upstream_rr_peer_t)); - *peerp = peer; } @@ -241,3 +255,68 @@ ngx_stream_upstream_zone_copy_peers(ngx_slab_pool_t *shpool, return peers; } + + +static ngx_stream_upstream_rr_peer_t * +ngx_stream_upstream_zone_copy_peer(ngx_stream_upstream_rr_peers_t *peers, + ngx_stream_upstream_rr_peer_t *src) +{ + ngx_slab_pool_t *pool; + ngx_stream_upstream_rr_peer_t *dst; + + pool = peers->shpool; + + dst = ngx_slab_calloc_locked(pool, sizeof(ngx_stream_upstream_rr_peer_t)); + if (dst == NULL) { + return NULL; + } + + if (src) { + ngx_memcpy(dst, src, sizeof(ngx_stream_upstream_rr_peer_t)); + dst->sockaddr = NULL; + dst->name.data = NULL; + dst->server.data = NULL; + } + + dst->sockaddr = ngx_slab_calloc_locked(pool, sizeof(ngx_sockaddr_t)); + if (dst->sockaddr == NULL) { + goto failed; + } + + dst->name.data = ngx_slab_calloc_locked(pool, NGX_SOCKADDR_STRLEN); + if (dst->name.data == NULL) { + goto failed; + } + + if (src) { + ngx_memcpy(dst->sockaddr, src->sockaddr, src->socklen); + ngx_memcpy(dst->name.data, src->name.data, src->name.len); + + dst->server.data = ngx_slab_alloc_locked(pool, src->server.len); + if (dst->server.data == NULL) { + goto failed; + } + + ngx_memcpy(dst->server.data, src->server.data, src->server.len); + } + + return dst; + +failed: + + if (dst->server.data) { + ngx_slab_free_locked(pool, dst->server.data); + } + + if (dst->name.data) { + ngx_slab_free_locked(pool, dst->name.data); + } + + if (dst->sockaddr) { + ngx_slab_free_locked(pool, dst->sockaddr); + } + + ngx_slab_free_locked(pool, dst); + + return NULL; +} diff --git a/src/stream/ngx_stream_variables.c b/src/stream/ngx_stream_variables.c index aa5361d18b0..95ae12b1fff 100644 --- a/src/stream/ngx_stream_variables.c +++ b/src/stream/ngx_stream_variables.c @@ -10,6 +10,8 @@ #include #include +static ngx_stream_variable_t *ngx_stream_add_prefix_variable(ngx_conf_t *cf, + ngx_str_t *name, ngx_uint_t flags); static ngx_int_t ngx_stream_variable_binary_remote_addr( ngx_stream_session_t *s, ngx_stream_variable_value_t *v, uintptr_t data); @@ -109,7 +111,7 @@ static ngx_stream_variable_t ngx_stream_core_variables[] = { { ngx_string("protocol"), NULL, ngx_stream_variable_protocol, 0, 0, 0 }, - { ngx_null_string, NULL, NULL, 0, 0, 0 } + ngx_stream_null_variable }; @@ -119,6 +121,9 @@ ngx_stream_variable_value_t ngx_stream_variable_true_value = ngx_stream_variable("1"); +static ngx_uint_t ngx_stream_variable_depth = 100; + + ngx_stream_variable_t * ngx_stream_add_variable(ngx_conf_t *cf, ngx_str_t *name, ngx_uint_t flags) { @@ -134,6 +139,10 @@ ngx_stream_add_variable(ngx_conf_t *cf, ngx_str_t *name, ngx_uint_t flags) return NULL; } + if (flags & NGX_STREAM_VAR_PREFIX) { + return ngx_stream_add_prefix_variable(cf, name, flags); + } + cmcf = ngx_stream_conf_get_module_main_conf(cf, ngx_stream_core_module); key = cmcf->variables_keys->keys.elts; @@ -152,6 +161,8 @@ ngx_stream_add_variable(ngx_conf_t *cf, ngx_str_t *name, ngx_uint_t flags) return NULL; } + v->flags &= flags | ~NGX_STREAM_VAR_WEAK; + return v; } @@ -190,6 +201,60 @@ ngx_stream_add_variable(ngx_conf_t *cf, ngx_str_t *name, ngx_uint_t flags) } +static ngx_stream_variable_t * +ngx_stream_add_prefix_variable(ngx_conf_t *cf, ngx_str_t *name, + ngx_uint_t flags) +{ + ngx_uint_t i; + ngx_stream_variable_t *v; + ngx_stream_core_main_conf_t *cmcf; + + cmcf = ngx_stream_conf_get_module_main_conf(cf, ngx_stream_core_module); + + v = cmcf->prefix_variables.elts; + for (i = 0; i < cmcf->prefix_variables.nelts; i++) { + if (name->len != v[i].name.len + || ngx_strncasecmp(name->data, v[i].name.data, name->len) != 0) + { + continue; + } + + v = &v[i]; + + if (!(v->flags & NGX_STREAM_VAR_CHANGEABLE)) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "the duplicate \"%V\" variable", name); + return NULL; + } + + v->flags &= flags | ~NGX_STREAM_VAR_WEAK; + + return v; + } + + v = ngx_array_push(&cmcf->prefix_variables); + if (v == NULL) { + return NULL; + } + + v->name.len = name->len; + v->name.data = ngx_pnalloc(cf->pool, name->len); + if (v->name.data == NULL) { + return NULL; + } + + ngx_strlow(v->name.data, name->data, name->len); + + v->set_handler = NULL; + v->get_handler = NULL; + v->data = 0; + v->flags = flags; + v->index = 0; + + return v; +} + + ngx_int_t ngx_stream_get_variable_index(ngx_conf_t *cf, ngx_str_t *name) { @@ -270,9 +335,20 @@ ngx_stream_get_indexed_variable(ngx_stream_session_t *s, ngx_uint_t index) v = cmcf->variables.elts; + if (ngx_stream_variable_depth == 0) { + ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, + "cycle while evaluating variable \"%V\"", + &v[index].name); + return NULL; + } + + ngx_stream_variable_depth--; + if (v[index].get_handler(s, &s->variables[index], v[index].data) == NGX_OK) { + ngx_stream_variable_depth++; + if (v[index].flags & NGX_STREAM_VAR_NOCACHEABLE) { s->variables[index].no_cacheable = 1; } @@ -280,6 +356,8 @@ ngx_stream_get_indexed_variable(ngx_stream_session_t *s, ngx_uint_t index) return &s->variables[index]; } + ngx_stream_variable_depth++; + s->variables[index].valid = 0; s->variables[index].not_found = 1; @@ -311,6 +389,8 @@ ngx_stream_variable_value_t * ngx_stream_get_variable(ngx_stream_session_t *s, ngx_str_t *name, ngx_uint_t key) { + size_t len; + ngx_uint_t i, n; ngx_stream_variable_t *v; ngx_stream_variable_value_t *vv; ngx_stream_core_main_conf_t *cmcf; @@ -322,18 +402,26 @@ ngx_stream_get_variable(ngx_stream_session_t *s, ngx_str_t *name, if (v) { if (v->flags & NGX_STREAM_VAR_INDEXED) { return ngx_stream_get_flushed_variable(s, v->index); + } - } else { + if (ngx_stream_variable_depth == 0) { + ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, + "cycle while evaluating variable \"%V\"", name); + return NULL; + } - vv = ngx_palloc(s->connection->pool, - sizeof(ngx_stream_variable_value_t)); + ngx_stream_variable_depth--; - if (vv && v->get_handler(s, vv, v->data) == NGX_OK) { - return vv; - } + vv = ngx_palloc(s->connection->pool, + sizeof(ngx_stream_variable_value_t)); - return NULL; + if (vv && v->get_handler(s, vv, v->data) == NGX_OK) { + ngx_stream_variable_depth++; + return vv; } + + ngx_stream_variable_depth++; + return NULL; } vv = ngx_palloc(s->connection->pool, sizeof(ngx_stream_variable_value_t)); @@ -341,6 +429,28 @@ ngx_stream_get_variable(ngx_stream_session_t *s, ngx_str_t *name, return NULL; } + len = 0; + + v = cmcf->prefix_variables.elts; + n = cmcf->prefix_variables.nelts; + + for (i = 0; i < cmcf->prefix_variables.nelts; i++) { + if (name->len >= v[i].name.len && name->len > len + && ngx_strncmp(name->data, v[i].name.data, v[i].name.len) == 0) + { + len = v[i].name.len; + n = i; + } + } + + if (n != cmcf->prefix_variables.nelts) { + if (v[n].get_handler(s, vv, (uintptr_t) name) == NGX_OK) { + return vv; + } + + return NULL; + } + vv->not_found = 1; return vv; @@ -350,7 +460,7 @@ ngx_stream_get_variable(ngx_stream_session_t *s, ngx_str_t *name, static ngx_int_t ngx_stream_variable_binary_remote_addr(ngx_stream_session_t *s, ngx_stream_variable_value_t *v, uintptr_t data) - { +{ struct sockaddr_in *sin; #if (NGX_HAVE_INET6) struct sockaddr_in6 *sin6; @@ -371,6 +481,18 @@ ngx_stream_variable_binary_remote_addr(ngx_stream_session_t *s, break; #endif +#if (NGX_HAVE_UNIX_DOMAIN) + case AF_UNIX: + + v->len = s->connection->addr_text.len; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + v->data = s->connection->addr_text.data; + + break; +#endif + default: /* AF_INET */ sin = (struct sockaddr_in *) s->connection->sockaddr; @@ -976,7 +1098,6 @@ ngx_stream_regex_exec(ngx_stream_session_t *s, ngx_stream_regex_t *re, ngx_int_t ngx_stream_variables_add_core_vars(ngx_conf_t *cf) { - ngx_int_t rc; ngx_stream_variable_t *cv, *v; ngx_stream_core_main_conf_t *cmcf; @@ -997,27 +1118,20 @@ ngx_stream_variables_add_core_vars(ngx_conf_t *cf) return NGX_ERROR; } + if (ngx_array_init(&cmcf->prefix_variables, cf->pool, 8, + sizeof(ngx_stream_variable_t)) + != NGX_OK) + { + return NGX_ERROR; + } + for (cv = ngx_stream_core_variables; cv->name.len; cv++) { - v = ngx_palloc(cf->pool, sizeof(ngx_stream_variable_t)); + v = ngx_stream_add_variable(cf, &cv->name, cv->flags); if (v == NULL) { return NGX_ERROR; } *v = *cv; - - rc = ngx_hash_add_key(cmcf->variables_keys, &v->name, v, - NGX_HASH_READONLY_KEY); - - if (rc == NGX_OK) { - continue; - } - - if (rc == NGX_BUSY) { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "conflicting variable name \"%V\"", &v->name); - } - - return NGX_ERROR; } return NGX_OK; @@ -1027,10 +1141,11 @@ ngx_stream_variables_add_core_vars(ngx_conf_t *cf) ngx_int_t ngx_stream_variables_init_vars(ngx_conf_t *cf) { + size_t len; ngx_uint_t i, n; ngx_hash_key_t *key; ngx_hash_init_t hash; - ngx_stream_variable_t *v, *av; + ngx_stream_variable_t *v, *av, *pv; ngx_stream_core_main_conf_t *cmcf; /* set the handlers for the indexed stream variables */ @@ -1038,6 +1153,7 @@ ngx_stream_variables_init_vars(ngx_conf_t *cf) cmcf = ngx_stream_conf_get_module_main_conf(cf, ngx_stream_core_module); v = cmcf->variables.elts; + pv = cmcf->prefix_variables.elts; key = cmcf->variables_keys->keys.elts; for (i = 0; i < cmcf->variables.nelts; i++) { @@ -1058,7 +1174,9 @@ ngx_stream_variables_init_vars(ngx_conf_t *cf) av->index = i; - if (av->get_handler == NULL) { + if (av->get_handler == NULL + || (av->flags & NGX_STREAM_VAR_WEAK)) + { break; } @@ -1066,10 +1184,32 @@ ngx_stream_variables_init_vars(ngx_conf_t *cf) } } - ngx_log_error(NGX_LOG_EMERG, cf->log, 0, - "unknown \"%V\" variable", &v[i].name); + len = 0; + av = NULL; - return NGX_ERROR; + for (n = 0; n < cmcf->prefix_variables.nelts; n++) { + if (v[i].name.len >= pv[n].name.len && v[i].name.len > len + && ngx_strncmp(v[i].name.data, pv[n].name.data, pv[n].name.len) + == 0) + { + av = &pv[n]; + len = pv[n].name.len; + } + } + + if (av) { + v[i].get_handler = av->get_handler; + v[i].data = (uintptr_t) &v[i].name; + v[i].flags = av->flags; + + goto next; + } + + if (v[i].get_handler == NULL) { + ngx_log_error(NGX_LOG_EMERG, cf->log, 0, + "unknown \"%V\" variable", &v[i].name); + return NGX_ERROR; + } next: continue; diff --git a/src/stream/ngx_stream_variables.h b/src/stream/ngx_stream_variables.h index e4151e224fe..4ead2a6240d 100644 --- a/src/stream/ngx_stream_variables.h +++ b/src/stream/ngx_stream_variables.h @@ -30,6 +30,8 @@ typedef ngx_int_t (*ngx_stream_get_variable_pt) (ngx_stream_session_t *s, #define NGX_STREAM_VAR_NOCACHEABLE 2 #define NGX_STREAM_VAR_INDEXED 4 #define NGX_STREAM_VAR_NOHASH 8 +#define NGX_STREAM_VAR_WEAK 16 +#define NGX_STREAM_VAR_PREFIX 32 struct ngx_stream_variable_s { @@ -41,6 +43,8 @@ struct ngx_stream_variable_s { ngx_uint_t index; }; +#define ngx_stream_null_variable { ngx_null_string, NULL, NULL, 0, 0, 0 } + ngx_stream_variable_t *ngx_stream_add_variable(ngx_conf_t *cf, ngx_str_t *name, ngx_uint_t flags);