summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIgor Sysoev <igor@sysoev.ru>2005-05-12 14:58:06 +0000
committerIgor Sysoev <igor@sysoev.ru>2005-05-12 14:58:06 +0000
commit899b44eab259f32af5c6e3da342f430c654528ce (patch)
tree23fb5dfbc9219030f9e102db5a2ce44e98c0a9d0
parent22157ce9d570452b2d77f0fe7e510e6b0e4d05c2 (diff)
downloadnginx-release-0.1.29.tar.gz
nginx-0.1.29-RELEASE importrelease-0.1.29
*) Feature: the ngx_http_ssi_module supports "include virtual" command. *) Feature: the ngx_http_ssi_module supports the condition command like 'if expr="$NAME"' and "else" and "endif" commands. Only one nested level is supported. *) Feature: the ngx_http_ssi_module supports the DATE_LOCAL and DATE_GMT variables and "config timefmt" command. *) Feature: the "ssi_ignore_recycled_buffers" directive. *) Bugfix: the "echo" command did not show the default value for the empty QUERY_STRING variable. *) Change: the ngx_http_proxy_module was rewritten. *) Feature: the "proxy_redirect", "proxy_pass_request_headers", "proxy_pass_request_body", and "proxy_method" directives. *) Feature: the "proxy_set_header" directive. The "proxy_x_var" was canceled and must be replaced with the proxy_set_header directive. *) Change: the "proxy_preserve_host" is canceled and must be replaced with the "proxy_set_header Host $host" and the "proxy_redirect off" directives, the "proxy_set_header Host $host:$proxy_port" directive and the appropriate proxy_redirect directives. *) Change: the "proxy_set_x_real_ip" is canceled and must be replaced with the "proxy_set_header X-Real-IP $remote_addr" directive. *) Change: the "proxy_add_x_forwarded_for" is canceled and must be replaced with the "proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for" directive. *) Change: the "proxy_set_x_url" is canceled and must be replaced with the "proxy_set_header X-URL http://$host:$server_port$request_uri" directive. *) Feature: the "fastcgi_param" directive. *) Change: the "fastcgi_root", "fastcgi_set_var" and "fastcgi_params" directive are canceled and must be replaced with the fastcgi_param directives. *) Feature: the "index" directive can use the variables. *) Feature: the "index" directive can be used at http and server levels. *) Change: the last index only in the "index" directive can be absolute. *) Feature: the "rewrite" directive can use the variables. *) Feature: the "internal" directive. *) Feature: the CONTENT_LENGTH, CONTENT_TYPE, REMOTE_PORT, SERVER_ADDR, SERVER_PORT, SERVER_PROTOCOL, DOCUMENT_ROOT, SERVER_NAME, REQUEST_METHOD, REQUEST_URI, and REMOTE_USER variables. *) Change: nginx now passes the invalid lines in a client request headers or a backend response header. *) Bugfix: if the backend did not transfer response for a long time and the "send_timeout" was less than "proxy_read_timeout", then nginx returned the 408 response. *) Bugfix: the segmentation fault was occurred if the backend sent an invalid line in response header; the bug had appeared in 0.1.26. *) Bugfix: the segmentation fault may occurred in FastCGI fault tolerance configuration. *) Bugfix: the "expires" directive did not remove the previous "Expires" and "Cache-Control" headers. *) Bugfix: nginx did not take into account trailing dot in "Host" header line. *) Bugfix: the ngx_http_auth_module did not work under Linux. *) Bugfix: the rewrite directive worked incorrectly, if the arguments were in a request. *) Bugfix: nginx could not be built on MacOS X.
-rw-r--r--auto/cc/gcc5
-rw-r--r--auto/cc/msvc27
-rw-r--r--auto/have_headers11
-rw-r--r--auto/include9
-rw-r--r--auto/modules10
-rw-r--r--auto/options1
-rw-r--r--auto/os/conf17
-rw-r--r--auto/os/freebsd10
-rw-r--r--auto/os/linux8
-rw-r--r--auto/os/solaris8
-rw-r--r--auto/os/win329
-rw-r--r--auto/sources19
-rwxr-xr-xauto/unix2
-rw-r--r--conf/mime.types1
-rw-r--r--docs/xml/nginx/changes.xml315
-rw-r--r--src/core/nginx.c2
-rw-r--r--src/core/nginx.h2
-rw-r--r--src/core/ngx_array.h13
-rw-r--r--src/core/ngx_buf.c3
-rw-r--r--src/core/ngx_buf.h5
-rw-r--r--src/core/ngx_conf_file.c55
-rw-r--r--src/core/ngx_conf_file.h8
-rw-r--r--src/core/ngx_cycle.c2
-rw-r--r--src/core/ngx_file.c20
-rw-r--r--src/core/ngx_hash.c51
-rw-r--r--src/core/ngx_hash.h3
-rw-r--r--src/core/ngx_inet.c19
-rw-r--r--src/core/ngx_log.c2
-rw-r--r--src/core/ngx_output_chain.c9
-rw-r--r--src/core/ngx_palloc.c45
-rw-r--r--src/core/ngx_palloc.h41
-rw-r--r--src/core/ngx_times.c3
-rw-r--r--src/core/ngx_times.h1
-rw-r--r--src/core/ngx_unix_domain.c4
-rw-r--r--src/event/modules/ngx_aio_module.c2
-rw-r--r--src/event/modules/ngx_devpoll_module.c8
-rw-r--r--src/event/modules/ngx_epoll_module.c8
-rw-r--r--src/event/modules/ngx_iocp_module.c6
-rw-r--r--src/event/modules/ngx_kqueue_module.c12
-rw-r--r--src/event/modules/ngx_poll_module.c6
-rw-r--r--src/event/modules/ngx_rtsig_module.c20
-rw-r--r--src/event/modules/ngx_select_module.c6
-rw-r--r--src/event/ngx_event.c181
-rw-r--r--src/event/ngx_event.h161
-rw-r--r--src/event/ngx_event_accept.c4
-rw-r--r--src/event/ngx_event_acceptex.c2
-rw-r--r--src/event/ngx_event_busy_lock.c6
-rw-r--r--src/event/ngx_event_connect.c3
-rw-r--r--src/event/ngx_event_openssl.c25
-rw-r--r--src/event/ngx_event_openssl.h1
-rw-r--r--src/event/ngx_event_pipe.c26
-rw-r--r--src/event/ngx_event_posted.c4
-rw-r--r--src/event/ngx_event_timer.c2
-rw-r--r--src/http/modules/ngx_http_access_module.c5
-rw-r--r--src/http/modules/ngx_http_auth_basic_module.c6
-rw-r--r--src/http/modules/ngx_http_autoindex_module.c21
-rw-r--r--src/http/modules/ngx_http_charset_filter_module.c16
-rw-r--r--src/http/modules/ngx_http_chunked_filter_module.c7
-rw-r--r--src/http/modules/ngx_http_fastcgi_module.c1636
-rw-r--r--src/http/modules/ngx_http_geo_module.c7
-rw-r--r--src/http/modules/ngx_http_gzip_filter_module.c40
-rw-r--r--src/http/modules/ngx_http_headers_filter_module.c51
-rw-r--r--src/http/modules/ngx_http_index_module.c507
-rw-r--r--src/http/modules/ngx_http_not_modified_filter_module.c11
-rw-r--r--src/http/modules/ngx_http_proxy_module.c1567
-rw-r--r--src/http/modules/ngx_http_range_filter_module.c36
-rw-r--r--src/http/modules/ngx_http_rewrite_module.c972
-rw-r--r--src/http/modules/ngx_http_ssi_filter_module.c604
-rw-r--r--src/http/modules/ngx_http_ssl_module.c12
-rw-r--r--src/http/modules/ngx_http_static_module.c290
-rw-r--r--src/http/modules/ngx_http_stub_status_module.c22
-rw-r--r--src/http/modules/ngx_http_userid_filter_module.c117
-rw-r--r--src/http/modules/proxy/ngx_http_proxy_handler.c31
-rw-r--r--src/http/modules/proxy/ngx_http_proxy_handler.h7
-rw-r--r--src/http/modules/proxy/ngx_http_proxy_upstream.c38
-rw-r--r--src/http/ngx_http.c67
-rw-r--r--src/http/ngx_http.h27
-rw-r--r--src/http/ngx_http_busy_lock.c4
-rw-r--r--src/http/ngx_http_config.h3
-rw-r--r--src/http/ngx_http_copy_filter_module.c22
-rw-r--r--src/http/ngx_http_core_module.c252
-rw-r--r--src/http/ngx_http_core_module.h5
-rw-r--r--src/http/ngx_http_header_filter_module.c128
-rw-r--r--src/http/ngx_http_log_module.c27
-rw-r--r--src/http/ngx_http_parse.c137
-rw-r--r--src/http/ngx_http_postpone_filter_module.c126
-rw-r--r--src/http/ngx_http_request.c578
-rw-r--r--src/http/ngx_http_request.h69
-rw-r--r--src/http/ngx_http_request_body.c47
-rw-r--r--src/http/ngx_http_script.c771
-rw-r--r--src/http/ngx_http_script.h138
-rw-r--r--src/http/ngx_http_special_response.c19
-rw-r--r--src/http/ngx_http_upstream.c707
-rw-r--r--src/http/ngx_http_upstream.h151
-rw-r--r--src/http/ngx_http_variables.c506
-rw-r--r--src/http/ngx_http_variables.h30
-rw-r--r--src/http/ngx_http_write_filter_module.c63
-rw-r--r--src/imap/ngx_imap.c2
-rw-r--r--src/imap/ngx_imap_handler.c4
-rw-r--r--src/imap/ngx_imap_proxy.c14
-rw-r--r--src/os/unix/ngx_channel.c4
-rw-r--r--src/os/unix/ngx_freebsd_config.h3
-rw-r--r--src/os/unix/ngx_linux_config.h5
-rw-r--r--src/os/unix/ngx_linux_init.c2
-rw-r--r--src/os/unix/ngx_posix_config.h7
-rw-r--r--src/os/unix/ngx_posix_init.c3
-rw-r--r--src/os/unix/ngx_process.h6
-rw-r--r--src/os/unix/ngx_process_cycle.c1
-rw-r--r--src/os/unix/ngx_send.c2
-rw-r--r--src/os/unix/ngx_setproctitle.c18
-rw-r--r--src/os/unix/ngx_setproctitle.h45
-rw-r--r--src/os/unix/ngx_solaris_config.h6
-rw-r--r--src/os/unix/ngx_solaris_init.c2
-rw-r--r--src/os/unix/ngx_time.c40
-rw-r--r--src/os/unix/ngx_time.h2
-rw-r--r--src/os/unix/ngx_user.c27
-rw-r--r--src/os/win32/ngx_gui.c3
-rw-r--r--src/os/win32/ngx_process_cycle.c21
-rw-r--r--src/os/win32/ngx_time.c22
-rw-r--r--src/os/win32/ngx_time.h2
-rw-r--r--src/os/win32/ngx_win32_config.h19
121 files changed, 6959 insertions, 4404 deletions
diff --git a/auto/cc/gcc b/auto/cc/gcc
index 46b0aabb9..2e5906a75 100644
--- a/auto/cc/gcc
+++ b/auto/cc/gcc
@@ -57,6 +57,11 @@ case $CPU in
CPU_OPT="-march=pentium4"
;;
+ opteron)
+ # optimize for Opteron, gcc 3.x
+ CPU_OPT="-march=opteron"
+ ;;
+
sparc64)
# build 64-bit UltraSparc binary
CPU_OPT="-m64"
diff --git a/auto/cc/msvc b/auto/cc/msvc
index d920ed0c9..0fa5df9d7 100644
--- a/auto/cc/msvc
+++ b/auto/cc/msvc
@@ -6,18 +6,31 @@
# optimizations
-# maximize speed
+# maximize speed, equivalent to -Og -Oi -Ot -Oy -Ob2 -Gs -GF -Gy
CFLAGS="$CFLAGS -O2"
+
# enable global optimization
-CFLAGS="$CFLAGS -Og"
+#CFLAGS="$CFLAGS -Og"
# enable intrinsic functions
-CFLAGS="$CFLAGS -Oi"
-# inline expansion
-CFLAGS="$CFLAGS -Ob1"
+#CFLAGS="$CFLAGS -Oi"
+
+# disable inline expansion
+#CFLAGS="$CFLAGS -Ob0"
+# explicit inline expansion
+#CFLAGS="$CFLAGS -Ob1"
+# explicit and implicit inline expansion
+#CFLAGS="$CFLAGS -Ob2"
+
# enable frame pointer omission
-CFLAGS="$CFLAGS -Oy"
+#CFLAGS="$CFLAGS -Oy"
# disable stack checking calls
-CFLAGS="$CFLAGS -Gs"
+#CFLAGS="$CFLAGS -Gs"
+
+# pools strings as read/write
+#CFLAGS="$CFLAGS -Gf"
+# pools strings as read-only
+#CFLAGS="$CFLAGS -GF"
+
case $CPU in
pentium)
diff --git a/auto/have_headers b/auto/have_headers
new file mode 100644
index 000000000..526ac47d4
--- /dev/null
+++ b/auto/have_headers
@@ -0,0 +1,11 @@
+
+# Copyright (C) Igor Sysoev
+
+
+cat << END >> $NGX_AUTO_HEADERS_H
+
+#ifndef $have
+#define $have 1
+#endif
+
+END
diff --git a/auto/include b/auto/include
index b36916947..7ed3086fd 100644
--- a/auto/include
+++ b/auto/include
@@ -39,14 +39,7 @@ if [ -x $NGX_AUTOTEST ]; then
| tr '[a-z]' '[A-Z]'`
- cat << END >> $NGX_AUTO_HEADERS_H
-
-#ifndef NGX_HAVE_$ngx_name
-#define NGX_HAVE_$ngx_name 1
-#endif
-
-END
-
+ have=NGX_HAVE_$ngx_name . auto/have_headers
eval "NGX_INCLUDE_$ngx_name='#include <$ngx_include>'"
diff --git a/auto/modules b/auto/modules
index 4ab272ed8..b032f05cd 100644
--- a/auto/modules
+++ b/auto/modules
@@ -51,6 +51,10 @@ if [ $NGX_TEST_BUILD_SOLARIS_SENDFILEV = YES ]; then
fi
+if [ $HTTP_SSI = YES ]; then
+ HTTP_POSTPONE=YES
+fi
+
# the filter order is important
# ngx_http_write_filter
# ngx_http_header_filter
@@ -58,6 +62,7 @@ fi
# ngx_http_range_header_filter
# ngx_http_ssl_filter
# ngx_http_gzip_filter
+# ngx_http_postpone_filter
# ngx_http_charset_filter
# ngx_http_ssi_filter
# ngx_http_headers_filter
@@ -77,6 +82,11 @@ if [ $HTTP_GZIP = YES ]; then
HTTP_SRCS="$HTTP_SRCS $HTTP_GZIP_SRCS"
fi
+if [ $HTTP_POSTPONE = YES ]; then
+ HTTP_FILTER_MODULES="$HTTP_FILTER_MODULES $HTTP_POSTPONE_FILTER_MODULE"
+ HTTP_SRCS="$HTTP_SRCS $HTPP_POSTPONE_FILTER_SRCS"
+fi
+
if [ $HTTP_CHARSET = YES ]; then
have=NGX_HTTP_CHARSET . auto/have
HTTP_FILTER_MODULES="$HTTP_FILTER_MODULES $HTTP_CHARSET_FILTER_MODULE"
diff --git a/auto/options b/auto/options
index 2bdb5dfa3..a56bc4271 100644
--- a/auto/options
+++ b/auto/options
@@ -49,6 +49,7 @@ HTTP_CHARSET=YES
HTTP_GZIP=YES
HTTP_SSL=NO
HTTP_SSI=YES
+HTTP_POSTPONE=NO
HTTP_ACCESS=YES
HTTP_AUTH_BASIC=YES
HTTP_USERID=YES
diff --git a/auto/os/conf b/auto/os/conf
index b48b6404d..f2a49cee5 100644
--- a/auto/os/conf
+++ b/auto/os/conf
@@ -23,6 +23,15 @@ case "$NGX_PLATFORM" in
. auto/os/freebsd
;;
+ Darwin:*)
+ have=NGX_DARWIN . auto/have_headers
+ have=NGX_HAVE_INHERITED_NONBLOCK . auto/have
+ CORE_INCS="$UNIX_INCS"
+ CORE_DEPS="$UNIX_DEPS $POSIX_DEPS"
+ CORE_SRCS="$UNIX_SRCS"
+ CRYPT_LIB=
+ ;;
+
Linux:*)
. auto/os/linux
;;
@@ -47,16 +56,16 @@ esac
case "$NGX_MACHINE" in
- i386|i686|i86pc|amd64)
- have=NGX_HAVE_NONALIGNED . auto/have
- ;;
+ i386|i686|i86pc|amd64)
+ have=NGX_HAVE_NONALIGNED . auto/have
+ ;;
esac
if [ "$NGX_PLATFORM" != win32 ]; then
- NGX_USER=${NGX_USER:-nobody}
+ NGX_USER=${NGX_USER:-nobody}
if [ -z "$NGX_GROUP" -a $NGX_USER = nobody ] ; then
if grep nobody /etc/group 2>&1 >/dev/null; then
diff --git a/auto/os/freebsd b/auto/os/freebsd
index 133f5f55b..f916860d9 100644
--- a/auto/os/freebsd
+++ b/auto/os/freebsd
@@ -2,14 +2,7 @@
# Copyright (C) Igor Sysoev
-cat << END >> $NGX_AUTO_HEADERS_H
-
-#ifndef NGX_FREEBSD
-#define NGX_FREEBSD 1
-#endif
-
-END
-
+have=NGX_FREEBSD . auto/have_headers
CORE_INCS="$UNIX_INCS"
CORE_DEPS="$UNIX_DEPS $FREEBSD_DEPS"
@@ -39,6 +32,7 @@ then
echo " + setproctitle() in libutil"
CORE_LIBS="$CORE_LIBS -lutil"
+ NGX_SETPROCTITLE_LIB="-lutil"
fi
# sendfile
diff --git a/auto/os/linux b/auto/os/linux
index 84e4f6667..5926211a4 100644
--- a/auto/os/linux
+++ b/auto/os/linux
@@ -2,13 +2,7 @@
# Copyright (C) Igor Sysoev
-cat << END >> $NGX_AUTO_HEADERS_H
-
-#ifndef NGX_LINUX
-#define NGX_LINUX 1
-#endif
-
-END
+have=NGX_LINUX . auto/have_headers
CORE_INCS="$UNIX_INCS"
CORE_DEPS="$UNIX_DEPS $LINUX_DEPS"
diff --git a/auto/os/solaris b/auto/os/solaris
index 67e0a8e6b..cf7fc6c84 100644
--- a/auto/os/solaris
+++ b/auto/os/solaris
@@ -2,13 +2,7 @@
# Copyright (C) Igor Sysoev
-cat << END >> $NGX_AUTO_HEADERS_H
-
-#ifndef NGX_SOLARIS
-#define NGX_SOLARIS 1
-#endif
-
-END
+have=NGX_SOLARIS . auto/have_headers
CORE_INCS="$UNIX_INCS"
CORE_DEPS="$UNIX_DEPS $SOLARIS_DEPS"
diff --git a/auto/os/win32 b/auto/os/win32
index 5567535c2..f65f2c9a4 100644
--- a/auto/os/win32
+++ b/auto/os/win32
@@ -2,14 +2,7 @@
# Copyright (C) Igor Sysoev
-cat << END >> $NGX_AUTO_HEADERS_H
-
-#ifndef NGX_WIN32
-#define NGX_WIN32 1
-#endif
-
-END
-
+have=NGX_WIN32 . auto/have_headers
CORE_INCS="$WIN32_INCS"
CORE_DEPS="$WIN32_DEPS"
diff --git a/auto/sources b/auto/sources
index 1a2abad13..e597f9732 100644
--- a/auto/sources
+++ b/auto/sources
@@ -120,6 +120,7 @@ UNIX_DEPS="$CORE_DEPS $EVENT_DEPS \
src/os/unix/ngx_channel.h \
src/os/unix/ngx_shared.h \
src/os/unix/ngx_process.h \
+ src/os/unix/ngx_setproctitle.h \
src/os/unix/ngx_atomic.h \
src/os/unix/ngx_thread.h \
src/os/unix/ngx_socket.h \
@@ -224,9 +225,11 @@ HTTP_CACHE_MODULE=ngx_http_cache_module
HTTP_WRITE_FILTER_MODULE="ngx_http_write_filter_module"
HTTP_HEADER_FILTER_MODULE="ngx_http_header_filter_module"
+HTTP_POSTPONE_FILTER_MODULE=ngx_http_postpone_filter_module
+HTTP_COPY_FILTER_MODULE=ngx_http_copy_filter_module
+
HTTP_CHUNKED_FILTER_MODULE=ngx_http_chunked_filter_module
HTTP_HEADERS_FILTER_MODULE=ngx_http_headers_filter_module
-HTTP_COPY_FILTER_MODULE=ngx_http_copy_filter_module
HTTP_RANGE_HEADER_FILTER_MODULE=ngx_http_range_header_filter_module
HTTP_RANGE_BODY_FILTER_MODULE=ngx_http_range_body_filter_module
@@ -273,6 +276,8 @@ HTTP_SRCS="src/http/ngx_http.c \
# STUB
HTTP_SRCS="$HTTP_SRCS src/http/ngx_http_busy_lock.c"
+HTPP_POSTPONE_FILTER_SRCS=src/http/ngx_http_postpone_filter_module.c
+
HTPP_CACHE_SRCS=src/http/ngx_http_cache.c
HTPP_FILE_CACHE_SRCS=src/http/ngx_http_file_cache.c
@@ -323,17 +328,7 @@ HTTP_SSL_SRCS=src/http/modules/ngx_http_ssl_module.c
HTTP_PROXY_MODULE=ngx_http_proxy_module
-#HTTP_PROXY_SRCS=src/http/modules/ngx_http_proxy_module.c
-
-HTTP_PROXY_INCS="src/http/modules/proxy"
-HTTP_PROXY_DEPS=src/http/modules/proxy/ngx_http_proxy_handler.h
-HTTP_PROXY_SRCS="src/http/modules/proxy/ngx_http_proxy_handler.c \
- src/http/modules/proxy/ngx_http_proxy_upstream.c \
- src/http/modules/proxy/ngx_http_proxy_parse.c \
- src/http/modules/proxy/ngx_http_proxy_header.c"
-
-# STUB
-# src/http/modules/proxy/ngx_http_proxy_cache.c \
+HTTP_PROXY_SRCS=src/http/modules/ngx_http_proxy_module.c
HTTP_FASTCGI_MODULE=ngx_http_fastcgi_module
diff --git a/auto/unix b/auto/unix
index 112626d2f..e9e0c7ae0 100755
--- a/auto/unix
+++ b/auto/unix
@@ -64,7 +64,7 @@ ngx_feature="setproctitle()"
ngx_feature_name="NGX_HAVE_SETPROCTITLE"
ngx_feature_run=no
ngx_feature_incs=
-ngx_feature_libs=
+ngx_feature_libs=$NGX_SETPROCTITLE_LIB
ngx_feature_test="setproctitle(\"test\");"
. auto/feature
diff --git a/conf/mime.types b/conf/mime.types
index 3785e5388..6ef277763 100644
--- a/conf/mime.types
+++ b/conf/mime.types
@@ -17,6 +17,7 @@ types {
application/x-javascript js;
application/x-rar-compressed rar;
application/x-xpinstall xpi;
+ application/x-x509-ca-cert der pem crt;
audio/mpeg mp3;
audio/x-realaudio ra;
diff --git a/docs/xml/nginx/changes.xml b/docs/xml/nginx/changes.xml
index 9444bac88..909b4cbfe 100644
--- a/docs/xml/nginx/changes.xml
+++ b/docs/xml/nginx/changes.xml
@@ -9,6 +9,319 @@
<title lang="en">nginx changelog</title>
+<changes ver="0.1.29" date="12.05.2005">
+
+<change type="feature">
+<para lang="ru">
+ÍÏÄÕÌØ ngx_http_ssi_module ÐÏÄÄÅÒÖÉ×ÁÅÔ ËÏÍÁÎÄÕ include virtual.
+</para>
+<para lang="en">
+the ngx_http_ssi_module supports "include virtual" command.
+</para>
+</change>
+
+<change type="feature">
+<para lang="ru">
+ÍÏÄÕÌØ ngx_http_ssi_module ÐÏÄÄÅÒÖÉ×ÁÅÔ ÕÓÌÏ×ÎÕÀ ËÏÍÁÎÄÕ ×ÉÄÁ
+'if expr="$NAME"' É ËÏÍÁÎÄÙ else É endif.
+äÏÐÕÓËÁÅÔÓÑ ÔÏÌØËÏ ÏÄÉÎ ÕÒÏ×ÅÎØ ×ÌÏÖÅÎÎÏÓÔÉ.
+</para>
+<para lang="en">
+the ngx_http_ssi_module supports the condition command like
+'if expr="$NAME"' and "else" and "endif" commands.
+Only one nested level is supported.
+</para>
+</change>
+
+<change type="feature">
+<para lang="ru">
+ÍÏÄÕÌØ ngx_http_ssi_module ÐÏÄÄÅÒÖÉ×ÁÅÔ Ä×Å ÐÅÒÅÍÅÎÎÙÅ DATE_LOCAL É DATE_GMT
+É ËÏÍÁÎÄÕ config timefmt.
+</para>
+<para lang="en">
+the ngx_http_ssi_module supports the DATE_LOCAL and DATE_GMT variables
+and "config timefmt" command.
+</para>
+</change>
+
+<change type="feature">
+<para lang="ru">
+ÄÉÒÅËÔÉ×Á ssi_ignore_recycled_buffers.
+</para>
+<para lang="en">
+the "ssi_ignore_recycled_buffers" directive.
+</para>
+</change>
+
+<change type="bugfix">
+<para lang="ru">
+ÅÓÌÉ ÐÅÒÅÍÅÎÎÁÑ QUERY_STRING ÎÅ ÂÙÌÁ ÏÐÒÅÄÅÌÅÎÁ, ÔÏ × ËÏÍÁÎÄÅ echo
+ÎÅ ÓÔÁ×ÉÌÏÓØ ÚÎÁÞÅÎÉÅ ÐÏ ÕÍÏÌÞÁÎÉÀ.
+</para>
+<para lang="en">
+the "echo" command did not show the default value for the empty QUERY_STRING
+variable.
+</para>
+</change>
+
+<change type="change">
+<para lang="ru">
+ÍÏÄÕÌØ ngx_http_proxy_module ÐÏÌÎÏÓÔØÀ ÐÅÒÅÐÉÓÁÎ.
+</para>
+<para lang="en">
+the ngx_http_proxy_module was rewritten.
+</para>
+</change>
+
+<change type="feature">
+<para lang="ru">
+ÄÉÒÅËÔÉ×Ù proxy_redirect, proxy_pass_request_headers,
+proxy_pass_request_body É proxy_method.
+</para>
+<para lang="en">
+the "proxy_redirect", "proxy_pass_request_headers",
+"proxy_pass_request_body", and "proxy_method" directives.
+</para>
+</change>
+
+<change type="feature">
+<para lang="ru">
+ÄÉÒÅËÔÉ×Á proxy_set_header.
+äÉÒÅËÔÉ×Á proxy_x_var ÕÐÒÁÚÄÎÅÎÁ É ÄÏÌÖÎÁ ÂÙÔØ ÚÁÍÅÎÅÎÁ ÄÉÒÅËÔÉ×ÏÊ
+proxy_set_header.
+</para>
+<para lang="en">
+the "proxy_set_header" directive.
+The "proxy_x_var" is canceled and must be replaced with the proxy_set_header
+directive.
+</para>
+</change>
+
+<change type="change">
+<para lang="ru">
+ÄÉÒÅËÔÉ×Á proxy_preserve_host ÕÐÒÁÚÄÎÅÎÁ É ÄÏÌÖÎÁ ÂÙÔØ ÚÁÍÅÎÅÎÁ ÄÉÒÅËÔÉ×ÁÍÉ
+"proxy_set_header Host $host" É "proxy_redirect off"
+ÉÌÉ ÄÉÒÅËÔÉ×ÏÊ <nobr>"proxy_set_header Host $host:$proxy_port"</nobr>
+É ÓÏÏÔ×ÅÔÓÔ×ÕÀÝÉÍÉ ÅÊ ÄÉÒÅËÔÉ×ÁÍÉ proxy_redirect.
+</para>
+<para lang="en">
+the "proxy_preserve_host" is canceled and must be replaced with
+the "proxy_set_header Host $host" and the "proxy_redirect off" directives,
+the <nobr>"proxy_set_header Host $host:$proxy_port" directive</nobr>
+and the appropriate proxy_redirect directives.
+</para>
+</change>
+
+<change type="change">
+<para lang="ru">
+ÄÉÒÅËÔÉ×Á proxy_set_x_real_ip ÕÐÒÁÚÄÎÅÎÁ É ÄÏÌÖÎÁ ÂÙÔØ ÚÁÍÅÎÅÎÁ ÄÉÒÅËÔÉ×ÏÊ
+"proxy_set_header X-Real-IP $remote_addr".
+</para>
+<para lang="en">
+the "proxy_set_x_real_ip" is canceled and must be replaced with
+the "proxy_set_header X-Real-IP $remote_addr" directive.
+</para>
+</change>
+
+<change type="change">
+<para lang="ru">
+ÄÉÒÅËÔÉ×Á proxy_add_x_forwarded_for ÕÐÒÁÚÄÎÅÎÁ É ÄÏÌÖÎÁ ÂÙÔØ ÚÁÍÅÎÅÎÁ
+ÄÉÒÅËÔÉ×ÏÊ
+<nobr>"proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for".</nobr>
+</para>
+<para lang="en">
+the "proxy_add_x_forwarded_for" is canceled and must be replaced with
+<nobr>the "proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for"</nobr>
+directive.
+</para>
+</change>
+
+<change type="change">
+<para lang="ru">
+ÄÉÒÅËÔÉ×Á proxy_set_x_url ÕÐÒÁÚÄÎÅÎÁ É ÄÏÌÖÎÁ ÂÙÔØ ÚÁÍÅÎÅÎÁ ÄÉÒÅËÔÉ×ÏÊ
+<nobr>"proxy_set_header X-URL http://$host:$server_port$request_uri".</nobr>
+</para>
+<para lang="en">
+the "proxy_set_x_url" is canceled and must be replaced with
+the "proxy_set_header X-URL http://$host:$server_port$request_uri"
+directive.
+</para>
+</change>
+
+<change type="feature">
+<para lang="ru">
+ÄÉÒÅËÔÉ×Á fastcgi_param.
+</para>
+<para lang="en">
+the "fastcgi_param" directive.
+</para>
+</change>
+
+<change type="change">
+<para lang="ru">
+ÄÉÒÅËÔÉ×Ù fastcgi_set_var É fastcgi_params ÕÐÒÁÚÄÎÅÎÙ É ÄÏÌÖÎÙ ÂÙÔØ
+ÚÁÍÅÎÙ ÄÉÒÅËÔÉ×ÁÍÉ fastcgi_param.
+</para>
+<para lang="en">
+the "fastcgi_set_var" and "fastcgi_params" directive are canceled and
+must be replaced with the fastcgi_param directives.
+</para>
+</change>
+
+<change type="feature">
+<para lang="ru">
+ÄÉÒÅËÔÉ×Á index ÍÏÖÅÔ ÉÓÐÏÌØÚÏ×ÁÔØ ÐÅÒÅÍÅÎÎÙÅ.
+</para>
+<para lang="en">
+the "index" directive can use the variables.
+</para>
+</change>
+
+<change type="feature">
+<para lang="ru">
+ÄÉÒÅËÔÉ×Á index ÍÏÖÅÔ ÂÙÔØ ÕËÁÚÁÎÁ ÎÁ ÕÒÏ×ÎÅ http É server.
+</para>
+<para lang="en">
+the "index" directive can be used at http and server levels.
+</para>
+</change>
+
+<change type="change">
+<para lang="ru">
+ÔÏÌØËÏ ÐÏÓÌÅÄÎÉÊ ÐÁÒÁÍÅÔÒ × ÄÉÒÅËÔÉ×Å index ÍÏÖÅÔ ÂÙÔØ ÁÂÓÏÌÀÔÎÙÍ.
+</para>
+<para lang="en">
+the last index only in the "index" directive can be absolute.
+</para>
+</change>
+
+<change type="feature">
+<para lang="ru">
+× ÄÉÒÅËÔÉ×Å rewrite ÍÏÇÕÔ ÉÓÐÏÌØÚÏ×ÁÔØÓÑ ÐÅÒÅÍÅÎÎÙÅ.
+</para>
+<para lang="en">
+the "rewrite" directive can use the variables.
+</para>
+</change>
+
+<change type="feature">
+<para lang="ru">
+ÄÉÒÅËÔÉ×Á internal.
+</para>
+<para lang="en">
+the "internal" directive.
+</para>
+</change>
+
+<change type="feature">
+<para lang="ru">
+ÐÅÒÅÍÅÎÎÙÅ CONTENT_LENGTH, CONTENT_TYPE, REMOTE_PORT, SERVER_ADDR,
+SERVER_PORT, SERVER_PROTOCOL, DOCUMENT_ROOT, SERVER_NAME,
+REQUEST_METHOD, REQUEST_URI É REMOTE_USER.
+</para>
+<para lang="en">
+the CONTENT_LENGTH, CONTENT_TYPE, REMOTE_PORT, SERVER_ADDR,
+SERVER_PORT, SERVER_PROTOCOL, DOCUMENT_ROOT, SERVER_NAME,
+REQUEST_METHOD, REQUEST_URI, and REMOTE_USER variables.
+</para>
+</change>
+
+<change type="change">
+<para lang="ru">
+nginx ÔÅÐÅÒØ ÐÅÒÅÄÁ£Ô ÎÅ×ÅÒÎÙÅ ÓÔÒÏËÉ × ÚÁÇÏÌÏ×ËÁÈ ÚÁÐÒÏÓÁ ËÌÉÅÎÔÁ É
+ÏÔ×ÅÔÁ ÂÜËÅÎÄÁ.
+</para>
+<para lang="en">
+nginx now passes the invalid lines in a client request headers
+or a backend response header.
+</para>
+</change>
+
+<change type="bugfix">
+<para lang="ru">
+ÅÓÌÉ ÂÜËÅÎÄ ÄÏÌÇÏ ÎÅ ÐÅÒÅÄÁ×ÁÌ ÏÔ×ÅÔ É send_timeout ÂÙÌ ÍÅÎØÛÅ, ÞÅÍ
+proxy_read_timeout, ÔÏ ËÌÉÅÎÔÕ ×ÏÚ×ÒÁÝÁÌÓÑ ÏÔ×ÅÔ 408.
+</para>
+<para lang="en">
+if the backend did not transfer response for a long time and
+the "send_timeout" was less than "proxy_read_timeout", then nginx
+returned the 408 response.
+</para>
+</change>
+
+<change type="bugfix">
+<para lang="ru">
+ÅÓÌÉ ÂÜËÅÎÄ ÐÅÒÅÄÁ×ÁÌ ÎÅ×ÅÒÎÕÀ ÓÔÒÏËÕ × ÚÁÇÏÌÏ×ËÅ ÏÔ×ÅÔÁ, ÔÏ ÐÒÏÉÓÈÏÄÉÌ
+segmentation fault;
+ÏÛÉÂËÁ ÐÏÑ×ÉÌÁÓØ × 0.1.26.
+</para>
+<para lang="en">
+the segmentation fault was occurred if the backend sent an invalid line
+in response header;
+bug appeared in 0.1.26.
+</para>
+</change>
+
+<change type="bugfix">
+<para lang="ru">
+ÐÒÉ ÉÓÐÏÌØÚÏ×ÁÎÉÉ ÏÔËÁÚÏÕÓÔÏÊÞÉ×ÏÊ ËÏÎÆÉÇÕÒÁÃÉÉ × FastCGI ÍÏÇ
+ÐÒÏÉÓÈÏÄÉÔØ segmentation fault.
+</para>
+<para lang="en">
+the segmentation fault may occurred in FastCGI fault tolerance configuration.
+</para>
+</change>
+
+<change type="bugfix">
+<para lang="ru">
+ÄÉÒÅËÔÉ×Á expires ÎÅ ÕÄÁÌÑÌÁ ÕÖÅ ÕÓÔÁÎÏ×ÌÅÎÎÙÅ ÓÔÒÏËÉ ÚÁÇÏÌÏ×ËÁ
+"Expires" É "Cache-Control".
+</para>
+<para lang="en">
+the "expires" directive did not remove the previous "Expires" and
+"Cache-Control" headers.
+</para>
+</change>
+
+<change type="bugfix">
+<para lang="ru">
+nginx ÎÅ ÕÞÉÔÙ×ÁÌ ÚÁ×ÅÒÛÁÀÝÕÀ ÔÏÞËÕ × ÓÔÒÏËÅ ÚÁÇÏÌÏ×ËÁ ÚÁÐÒÏÓÁ "Host".
+</para>
+<para lang="en">
+nginx did not take into account trailing dot in "Host" header line.
+</para>
+</change>
+
+<change type="bugfix">
+<para lang="ru">
+ÍÏÄÕÌØ ngx_http_auth_module ÎÅ ÒÁÂÏÔÁÌ ÎÁ Linux.
+</para>
+<para lang="en">
+the ngx_http_auth_module did not work under Linux.
+</para>
+</change>
+
+<change type="bugfix">
+<para lang="ru">
+ÄÉÒÅËÔÉ×Á rewrite ÎÅ×ÅÒÎÏ ÒÁÂÏÔÁÌÁ, ÅÓÌÉ × ÚÁÐÒÏÓÅ ÐÒÉÓÕÔÓÔ×Ï×ÁÌÉ ÁÒÇÕÍÅÎÔÙ.
+</para>
+<para lang="en">
+the rewrite directive worked incorrectly, if the arguments were in a request.
+</para>
+</change>
+
+<change type="bugfix">
+<para lang="ru">
+nginx ÎÅ ÓÏÂÉÒÁÌÓÑ ÎÁ MacOS X.
+</para>
+<para lang="en">
+nginx could not be built on MacOS X.
+</para>
+</change>
+
+</changes>
+
+
<changes ver="0.1.28" date="08.04.2005">
<change type="bugfix">
@@ -586,7 +899,7 @@ the rewrite/location cycle and sets the current configuration to the request.
<changes ver="0.1.17" date="03.02.2005">
-<change type="feature">
+<change type="change">
<para lang="ru">
ÍÏÄÕÌØ ngx_http_rewrite_module ÐÏÌÎÏÓÔØÀ ÐÅÒÅÐÉÓÁÎ.
ôÅÐÅÒØ ÍÏÖÎÏ ÄÅÌÁÔØ ÒÅÄÉÒÅËÔÙ, ×ÏÚ×ÒÁÝÁÔØ ËÏÄÙ ÏÛÉÂÏË
diff --git a/src/core/nginx.c b/src/core/nginx.c
index 9f2211291..bb6f093e4 100644
--- a/src/core/nginx.c
+++ b/src/core/nginx.c
@@ -107,7 +107,7 @@ static ngx_core_module_t ngx_core_module_ctx = {
ngx_module_t ngx_core_module = {
- NGX_MODULE,
+ NGX_MODULE_V1,
&ngx_core_module_ctx, /* module context */
ngx_core_commands, /* module directives */
NGX_CORE_MODULE, /* module type */
diff --git a/src/core/nginx.h b/src/core/nginx.h
index 9fa141ab7..4d27a875f 100644
--- a/src/core/nginx.h
+++ b/src/core/nginx.h
@@ -8,7 +8,7 @@
#define _NGINX_H_INCLUDED_
-#define NGINX_VER "nginx/0.1.28"
+#define NGINX_VER "nginx/0.1.29"
#define NGINX_VAR "NGINX"
#define NGX_NEWPID_EXT ".newbin"
diff --git a/src/core/ngx_array.h b/src/core/ngx_array.h
index 5f97451aa..00206cb1b 100644
--- a/src/core/ngx_array.h
+++ b/src/core/ngx_array.h
@@ -30,16 +30,21 @@ void *ngx_array_push_n(ngx_array_t *a, ngx_uint_t n);
static ngx_inline ngx_int_t
ngx_array_init(ngx_array_t *array, ngx_pool_t *pool, ngx_uint_t n, size_t size)
{
- array->elts = ngx_palloc(pool, n * size);
- if (array->elts == NULL) {
- return NGX_ERROR;
- }
+ /*
+ * set "array->nelts" before "array->elts", otherwise MSVC thinks
+ * that "array->nelts" may be used without having been initialized
+ */
array->nelts = 0;
array->size = size;
array->nalloc = n;
array->pool = pool;
+ array->elts = ngx_palloc(pool, n * size);
+ if (array->elts == NULL) {
+ return NGX_ERROR;
+ }
+
return NGX_OK;
}
diff --git a/src/core/ngx_buf.c b/src/core/ngx_buf.c
index 4c1b1d5ac..b7f597d39 100644
--- a/src/core/ngx_buf.c
+++ b/src/core/ngx_buf.c
@@ -31,7 +31,7 @@ ngx_create_temp_buf(ngx_pool_t *pool, size_t size)
* b->file = NULL;
* b->shadow = NULL;
* b->tag = 0;
- *
+ * and flags
*/
b->pos = b->start;
@@ -94,6 +94,7 @@ ngx_create_chain_of_bufs(ngx_pool_t *pool, ngx_bufs_t *bufs)
* b->file = NULL;
* b->shadow = NULL;
* b->tag = 0;
+ * and flags
*
*/
diff --git a/src/core/ngx_buf.h b/src/core/ngx_buf.h
index 96394f9f6..471ab190c 100644
--- a/src/core/ngx_buf.h
+++ b/src/core/ngx_buf.h
@@ -44,7 +44,9 @@ struct ngx_buf_s {
unsigned recycled:1;
unsigned in_file:1;
unsigned flush:1;
+ unsigned sync:1;
unsigned last_buf:1;
+ unsigned last_in_chain:1;
unsigned last_shadow:1;
unsigned temp_file:1;
@@ -104,7 +106,8 @@ typedef struct {
#define ngx_buf_in_memory(b) (b->temporary || b->memory || b->mmap)
#define ngx_buf_in_memory_only(b) (ngx_buf_in_memory(b) && !b->in_file)
#define ngx_buf_special(b) \
- ((b->flush || b->last_buf) && !ngx_buf_in_memory(b) && !b->in_file)
+ ((b->flush || b->last_buf || b->sync) \
+ && !ngx_buf_in_memory(b) && !b->in_file)
#define ngx_buf_size(b) \
(ngx_buf_in_memory(b) ? (off_t) (b->last - b->pos): \
diff --git a/src/core/ngx_conf_file.c b/src/core/ngx_conf_file.c
index 35ee8b8e0..b9b2200bf 100644
--- a/src/core/ngx_conf_file.c
+++ b/src/core/ngx_conf_file.c
@@ -27,7 +27,7 @@ static ngx_command_t ngx_conf_commands[] = {
ngx_module_t ngx_conf_module = {
- NGX_MODULE,
+ NGX_MODULE_V1,
NULL, /* module context */
ngx_conf_commands, /* module directives */
NGX_CONF_MODULE, /* module type */
@@ -336,7 +336,7 @@ ngx_conf_read_token(ngx_conf_t *cf)
{
u_char *start, ch, *src, *dst;
int len;
- int found, need_space, last_space, sharp_comment;
+ int found, need_space, last_space, sharp_comment, variable;
int quoted, s_quoted, d_quoted;
ssize_t n;
ngx_str_t *word;
@@ -346,6 +346,7 @@ ngx_conf_read_token(ngx_conf_t *cf)
need_space = 0;
last_space = 1;
sharp_comment = 0;
+ variable = 0;
quoted = s_quoted = d_quoted = 0;
cf->args->nelts = 0;
@@ -492,11 +493,22 @@ ngx_conf_read_token(ngx_conf_t *cf)
}
} else {
+ if (ch == '{' && variable) {
+ continue;
+ }
+
+ variable = 0;
+
if (ch == '\\') {
quoted = 1;
continue;
}
+ if (ch == '$') {
+ variable = 1;
+ continue;
+ }
+
if (d_quoted) {
if (ch == '"') {
d_quoted = 0;
@@ -802,6 +814,45 @@ ngx_conf_set_str_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
char *
+ngx_conf_set_table_elt_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
+{
+ char *p = conf;
+
+ ngx_str_t *value;
+ ngx_array_t **a;
+ ngx_table_elt_t *elt;
+ ngx_conf_post_t *post;
+
+ a = (ngx_array_t **) (p + cmd->offset);
+
+ if (*a == NULL) {
+ *a = ngx_array_create(cf->pool, 4, sizeof(ngx_table_elt_t));
+ if (*a == NULL) {
+ return NGX_CONF_ERROR;
+ }
+ }
+
+ elt = ngx_array_push(*a);
+ if (elt == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ value = cf->args->elts;
+
+ elt->hash = 0;
+ elt->key = value[1];
+ elt->value = value[2];
+
+ if (cmd->post) {
+ post = cmd->post;
+ return post->post_handler(cf, post, elt);
+ }
+
+ return NGX_CONF_OK;
+}
+
+
+char *
ngx_conf_set_num_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
char *p = conf;
diff --git a/src/core/ngx_conf_file.h b/src/core/ngx_conf_file.h
index 4fab8c10c..899f046e8 100644
--- a/src/core/ngx_conf_file.h
+++ b/src/core/ngx_conf_file.h
@@ -63,7 +63,7 @@
#define NGX_CONF_BLOCK_DONE 2
#define NGX_CONF_FILE_DONE 3
-#define NGX_MODULE 0, 0
+#define NGX_MODULE_V1 0, 0, 1, 0, 0
#define NGX_CORE_MODULE 0x45524F43 /* "CORE" */
#define NGX_CONF_MODULE 0x464E4F43 /* "CONF" */
@@ -100,6 +100,10 @@ struct ngx_open_file_s {
struct ngx_module_s {
ngx_uint_t ctx_index;
ngx_uint_t index;
+ ngx_uint_t version;
+ ngx_uint_t spare0;
+ ngx_uint_t spare1;
+
void *ctx;
ngx_command_t *commands;
ngx_uint_t type;
@@ -280,6 +284,8 @@ void ngx_cdecl ngx_conf_log_error(ngx_uint_t level, ngx_conf_t *cf,
char *ngx_conf_set_flag_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
char *ngx_conf_set_str_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
+char *ngx_conf_set_table_elt_slot(ngx_conf_t *cf, ngx_command_t *cmd,
+ void *conf);
char *ngx_conf_set_num_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
char *ngx_conf_set_size_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
char *ngx_conf_set_msec_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
diff --git a/src/core/ngx_cycle.c b/src/core/ngx_cycle.c
index 51042058a..eaebdb0bf 100644
--- a/src/core/ngx_cycle.c
+++ b/src/core/ngx_cycle.c
@@ -517,7 +517,7 @@ ngx_cycle_t *ngx_init_cycle(ngx_cycle_t *old_cycle)
ngx_old_cycles.nalloc = n;
ngx_old_cycles.pool = ngx_temp_pool;
- ngx_cleaner_event.event_handler = ngx_clean_old_cycles;
+ ngx_cleaner_event.handler = ngx_clean_old_cycles;
ngx_cleaner_event.log = cycle->log;
ngx_cleaner_event.data = &dumb;
dumb.fd = (ngx_socket_t) -1;
diff --git a/src/core/ngx_file.c b/src/core/ngx_file.c
index 6fe04e70d..46d2e0acb 100644
--- a/src/core/ngx_file.c
+++ b/src/core/ngx_file.c
@@ -38,8 +38,10 @@ ngx_int_t
ngx_create_temp_file(ngx_file_t *file, ngx_path_t *path, ngx_pool_t *pool,
int persistent)
{
- ngx_err_t err;
- ngx_atomic_uint_t n;
+ ngx_err_t err;
+ ngx_atomic_uint_t n;
+ ngx_pool_cleanup_file_t *cln;
+
file->name.len = path->name.len + 1 + path->len + NGX_ATOMIC_T_LEN;
@@ -74,6 +76,20 @@ ngx_create_temp_file(ngx_file_t *file, ngx_path_t *path, ngx_pool_t *pool,
"temp fd:%d", file->fd);
if (file->fd != NGX_INVALID_FILE) {
+ cln = ngx_palloc(pool, sizeof(ngx_pool_cleanup_file_t));
+ if (cln == NULL) {
+ return NGX_ERROR;
+ }
+
+ cln->fd = file->fd;
+ cln->name = file->name.data;
+ cln->log = pool->log;
+
+ if (ngx_pool_cleanup_add(pool, ngx_pool_cleanup_file, cln) == NULL)
+ {
+ return NGX_ERROR;
+ }
+
return NGX_OK;
}
diff --git a/src/core/ngx_hash.c b/src/core/ngx_hash.c
index 2c062b709..6b75fa598 100644
--- a/src/core/ngx_hash.c
+++ b/src/core/ngx_hash.c
@@ -9,11 +9,20 @@
ngx_int_t
-ngx_hash_init(ngx_hash_t *hash, ngx_pool_t *pool, void *names)
+ngx_hash_init(ngx_hash_t *hash, ngx_pool_t *pool, void *names, ngx_uint_t nelts)
{
u_char *p;
- ngx_str_t *n, *bucket;
- ngx_uint_t i, key, size, best, *test, buckets, min_buckets;
+ ngx_str_t *name, *bucket;
+ ngx_uint_t i, n, key, size, best, *test, buckets, min_buckets;
+
+ if (nelts == 0) {
+ for (name = (ngx_str_t *) names;
+ name->len;
+ name = (ngx_str_t *) ((char *) name + hash->bucket_size))
+ {
+ nelts++;
+ }
+ }
test = ngx_alloc(hash->max_size * sizeof(ngx_uint_t), pool->log);
if (test == NULL) {
@@ -34,14 +43,14 @@ ngx_hash_init(ngx_hash_t *hash, ngx_pool_t *pool, void *names)
test[i] = 0;
}
- for (n = (ngx_str_t *) names;
- n->len;
- n = (ngx_str_t *) ((char *) n + hash->bucket_size))
+ for (n = 0, name = (ngx_str_t *) names;
+ n < nelts;
+ n++, name = (ngx_str_t *) ((char *) name + hash->bucket_size))
{
key = 0;
- for (i = 0; i < n->len; i++) {
- key += ngx_tolower(n->data[i]);
+ for (i = 0; i < name->len; i++) {
+ key += ngx_tolower(name->data[i]);
}
key %= size;
@@ -57,7 +66,7 @@ ngx_hash_init(ngx_hash_t *hash, ngx_pool_t *pool, void *names)
}
}
- if (n->len == 0) {
+ if (n == nelts) {
if (min_buckets > buckets) {
min_buckets = buckets;
best = size;
@@ -91,14 +100,14 @@ ngx_hash_init(ngx_hash_t *hash, ngx_pool_t *pool, void *names)
test[i] = 0;
}
- for (n = (ngx_str_t *) names;
- n->len;
- n = (ngx_str_t *) ((char *) n + hash->bucket_size))
+ for (n = 0, name = (ngx_str_t *) names;
+ n < nelts;
+ n++, name = (ngx_str_t *) ((char *) name + hash->bucket_size))
{
key = 0;
- for (i = 0; i < n->len; i++) {
- key += ngx_tolower(n->data[i]);
+ for (i = 0; i < name->len; i++) {
+ key += ngx_tolower(name->data[i]);
}
key %= best;
@@ -122,21 +131,21 @@ ngx_hash_init(ngx_hash_t *hash, ngx_pool_t *pool, void *names)
}
}
- for (n = (ngx_str_t *) names;
- n->len;
- n = (ngx_str_t *) ((char *) n + hash->bucket_size))
+ for (n = 0, name = (ngx_str_t *) names;
+ n < nelts;
+ n++, name = (ngx_str_t *) ((char *) name + hash->bucket_size))
{
key = 0;
- for (i = 0; i < n->len; i++) {
- key += ngx_tolower(n->data[i]);
+ for (i = 0; i < name->len; i++) {
+ key += ngx_tolower(name->data[i]);
}
key %= best;
if (hash->bucket_limit == 1) {
p = (u_char *) hash->buckets + key * hash->bucket_size;
- ngx_memcpy(p, n, hash->bucket_size);
+ ngx_memcpy(p, name, hash->bucket_size);
continue;
}
@@ -147,7 +156,7 @@ ngx_hash_init(ngx_hash_t *hash, ngx_pool_t *pool, void *names)
bucket->len &= 0x7fffffff;
}
- ngx_memcpy(bucket, n, hash->bucket_size);
+ ngx_memcpy(bucket, name, hash->bucket_size);
bucket->len |= 0x80000000;
}
diff --git a/src/core/ngx_hash.h b/src/core/ngx_hash.h
index 5a4bf5fbc..e9912579a 100644
--- a/src/core/ngx_hash.h
+++ b/src/core/ngx_hash.h
@@ -31,7 +31,8 @@ typedef struct {
} ngx_table_elt_t;
-ngx_int_t ngx_hash_init(ngx_hash_t *hash, ngx_pool_t *pool, void *names);
+ngx_int_t ngx_hash_init(ngx_hash_t *hash, ngx_pool_t *pool, void *names,
+ ngx_uint_t nelts);
#endif /* _NGX_HASH_H_INCLUDED_ */
diff --git a/src/core/ngx_inet.c b/src/core/ngx_inet.c
index 6cad053b7..1ae7829fa 100644
--- a/src/core/ngx_inet.c
+++ b/src/core/ngx_inet.c
@@ -21,7 +21,8 @@
*/
-static ngx_inline size_t ngx_sprint_uchar(u_char *text, u_char c, size_t len)
+static
+ngx_inline size_t ngx_sprint_uchar(u_char *text, u_char c, size_t len)
{
size_t n;
ngx_uint_t c1, c2;
@@ -65,8 +66,8 @@ static ngx_inline size_t ngx_sprint_uchar(u_char *text, u_char c, size_t len)
/* AF_INET only */
-size_t ngx_sock_ntop(int family, struct sockaddr *sa, u_char *text,
- size_t len)
+size_t
+ngx_sock_ntop(int family, struct sockaddr *sa, u_char *text, size_t len)
{
u_char *p;
size_t n;
@@ -119,7 +120,8 @@ size_t ngx_sock_ntop(int family, struct sockaddr *sa, u_char *text,
return n;
}
-size_t ngx_inet_ntop(int family, void *addr, u_char *text, size_t len)
+size_t
+ngx_inet_ntop(int family, void *addr, u_char *text, size_t len)
{
u_char *p;
size_t n;
@@ -173,7 +175,8 @@ size_t ngx_inet_ntop(int family, void *addr, u_char *text, size_t len)
/* AF_INET only */
-ngx_int_t ngx_ptocidr(ngx_str_t *text, void *cidr)
+ngx_int_t
+ngx_ptocidr(ngx_str_t *text, void *cidr)
{
ngx_int_t m;
ngx_uint_t i;
@@ -217,7 +220,8 @@ ngx_int_t ngx_ptocidr(ngx_str_t *text, void *cidr)
}
-ngx_peers_t *ngx_inet_upstream_parse(ngx_conf_t *cf, ngx_inet_upstream_t *u)
+ngx_peers_t *
+ngx_inet_upstream_parse(ngx_conf_t *cf, ngx_inet_upstream_t *u)
{
char *err;
u_char *host;
@@ -392,7 +396,8 @@ ngx_peers_t *ngx_inet_upstream_parse(ngx_conf_t *cf, ngx_inet_upstream_t *u)
}
-char *ngx_inet_parse_host_port(ngx_inet_upstream_t *u)
+char *
+ngx_inet_parse_host_port(ngx_inet_upstream_t *u)
{
size_t i;
ngx_int_t port;
diff --git a/src/core/ngx_log.c b/src/core/ngx_log.c
index 181d05928..278258262 100644
--- a/src/core/ngx_log.c
+++ b/src/core/ngx_log.c
@@ -33,7 +33,7 @@ static ngx_core_module_t ngx_errlog_module_ctx = {
ngx_module_t ngx_errlog_module = {
- NGX_MODULE,
+ NGX_MODULE_V1,
&ngx_errlog_module_ctx, /* module context */
ngx_errlog_commands, /* module directives */
NGX_CORE_MODULE, /* module type */
diff --git a/src/core/ngx_output_chain.c b/src/core/ngx_output_chain.c
index fc8a0bf2a..e4a8723b2 100644
--- a/src/core/ngx_output_chain.c
+++ b/src/core/ngx_output_chain.c
@@ -49,7 +49,7 @@ ngx_output_chain(ngx_output_chain_ctx_t *ctx, ngx_chain_t *in)
#if (NGX_SENDFILE_LIMIT)
&& !(in->buf->in_file && in->buf->file_last > NGX_SENDFILE_LIMIT)
#endif
- && (!ngx_output_chain_need_to_copy(ctx, in->buf)))
+ && !ngx_output_chain_need_to_copy(ctx, in->buf))
{
return ctx->output_filter(ctx->filter_ctx, in);
}
@@ -132,7 +132,7 @@ ngx_output_chain(ngx_output_chain_ctx_t *ctx, ngx_chain_t *in)
size = ctx->bufs.size;
- if (ctx->in->buf->last_buf) {
+ if (ctx->in->buf->last_in_chain) {
if (bsize < (off_t) ctx->bufs.size) {
@@ -202,6 +202,11 @@ ngx_output_chain(ngx_output_chain_ctx_t *ctx, ngx_chain_t *in)
}
if (out == NULL && last != NGX_NONE) {
+
+ if (ctx->in) {
+ return NGX_AGAIN;
+ }
+
return last;
}
diff --git a/src/core/ngx_palloc.c b/src/core/ngx_palloc.c
index 2804dd0ba..e7c888285 100644
--- a/src/core/ngx_palloc.c
+++ b/src/core/ngx_palloc.c
@@ -23,6 +23,7 @@ ngx_create_pool(size_t size, ngx_log_t *log)
p->next = NULL;
p->large = NULL;
p->chain = NULL;
+ p->cleanup = NULL;
p->log = log;
return p;
@@ -32,8 +33,15 @@ ngx_create_pool(size_t size, ngx_log_t *log)
void
ngx_destroy_pool(ngx_pool_t *pool)
{
- ngx_pool_t *p, *n;
- ngx_pool_large_t *l;
+ ngx_pool_t *p, *n;
+ ngx_pool_large_t *l;
+ ngx_pool_cleanup_t *c;
+
+ for (c = pool->cleanup; c; c = c->next) {
+ if (c->handler) {
+ c->handler(c->data);
+ }
+ }
for (l = pool->large; l; l = l->next) {
@@ -197,6 +205,39 @@ ngx_pcalloc(ngx_pool_t *pool, size_t size)
return p;
}
+
+ngx_pool_cleanup_t *
+ngx_pool_cleanup_add(ngx_pool_t *p, ngx_pool_cleanup_pt handler, void *data)
+{
+ ngx_pool_cleanup_t *c;
+
+ c = ngx_palloc(p, sizeof(ngx_pool_cleanup_t));
+ if (c == NULL) {
+ return NULL;
+ }
+
+ c->handler = handler;
+ c->data = data;
+ c->next = p->cleanup;
+
+ p->cleanup = c;
+
+ return c;
+}
+
+
+void
+ngx_pool_cleanup_file(void *data)
+{
+ ngx_pool_cleanup_file_t *c = data;
+
+ if (ngx_close_file(c->fd) == NGX_FILE_ERROR) {
+ ngx_log_error(NGX_LOG_ALERT, c->log, ngx_errno,
+ ngx_close_file_n " \"%s\" failed", c->name);
+ }
+}
+
+
#if 0
static void *
diff --git a/src/core/ngx_palloc.h b/src/core/ngx_palloc.h
index bd256e8a9..62a571818 100644
--- a/src/core/ngx_palloc.h
+++ b/src/core/ngx_palloc.h
@@ -22,24 +22,44 @@
#define NGX_DEFAULT_POOL_SIZE (16 * 1024)
+typedef void (*ngx_pool_cleanup_pt)(void *data);
+
+typedef struct ngx_pool_cleanup_s ngx_pool_cleanup_t;
+
+struct ngx_pool_cleanup_s {
+ ngx_pool_cleanup_pt handler;
+ void *data;
+ ngx_pool_cleanup_t *next;
+};
+
+
typedef struct ngx_pool_large_s ngx_pool_large_t;
struct ngx_pool_large_s {
- ngx_pool_large_t *next;
- void *alloc;
+ ngx_pool_large_t *next;
+ void *alloc;
};
struct ngx_pool_s {
- u_char *last;
- u_char *end;
- ngx_chain_t *chain;
- ngx_pool_t *next;
- ngx_pool_large_t *large;
- ngx_log_t *log;
+ u_char *last;
+ u_char *end;
+ ngx_chain_t *chain;
+ ngx_pool_t *next;
+ ngx_pool_large_t *large;
+ ngx_pool_cleanup_t *cleanup;
+ ngx_log_t *log;
};
+typedef struct {
+ ngx_fd_t fd;
+ u_char *name;
+ ngx_log_t *log;
+} 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);
@@ -51,4 +71,9 @@ void *ngx_pcalloc(ngx_pool_t *pool, size_t size);
ngx_int_t ngx_pfree(ngx_pool_t *pool, void *p);
+ngx_pool_cleanup_t *ngx_pool_cleanup_add(ngx_pool_t *p,
+ ngx_pool_cleanup_pt handler, void *data);
+void ngx_pool_cleanup_file(void *data);
+
+
#endif /* _NGX_PALLOC_H_INCLUDED_ */
diff --git a/src/core/ngx_times.c b/src/core/ngx_times.c
index e4fa69d7f..30938a174 100644
--- a/src/core/ngx_times.c
+++ b/src/core/ngx_times.c
@@ -12,8 +12,9 @@ ngx_epoch_msec_t ngx_elapsed_msec;
ngx_epoch_msec_t ngx_old_elapsed_msec;
ngx_epoch_msec_t ngx_start_msec;
+ngx_int_t ngx_gmtoff;
+
static ngx_tm_t ngx_cached_gmtime;
-static ngx_int_t ngx_gmtoff;
/*
diff --git a/src/core/ngx_times.h b/src/core/ngx_times.h
index f9c4d3e3d..2959cc4b6 100644
--- a/src/core/ngx_times.h
+++ b/src/core/ngx_times.h
@@ -53,6 +53,7 @@ extern ngx_epoch_msec_t ngx_elapsed_msec;
*/
extern ngx_epoch_msec_t ngx_old_elapsed_msec;
+extern ngx_int_t ngx_gmtoff;
#endif /* _NGX_TIMES_H_INCLUDED_ */
diff --git a/src/core/ngx_unix_domain.c b/src/core/ngx_unix_domain.c
index 3df83bb3e..a7fdd6357 100644
--- a/src/core/ngx_unix_domain.c
+++ b/src/core/ngx_unix_domain.c
@@ -14,8 +14,8 @@
#undef sun
-ngx_peers_t *ngx_unix_upstream_parse(ngx_conf_t *cf,
- ngx_unix_domain_upstream_t *u)
+ngx_peers_t *
+ngx_unix_upstream_parse(ngx_conf_t *cf, ngx_unix_domain_upstream_t *u)
{
size_t len;
ngx_uint_t i;
diff --git a/src/event/modules/ngx_aio_module.c b/src/event/modules/ngx_aio_module.c
index 37a3a4499..37d520a96 100644
--- a/src/event/modules/ngx_aio_module.c
+++ b/src/event/modules/ngx_aio_module.c
@@ -54,7 +54,7 @@ ngx_event_module_t ngx_aio_module_ctx = {
};
ngx_module_t ngx_aio_module = {
- NGX_MODULE,
+ NGX_MODULE_V1,
&ngx_aio_module_ctx, /* module context */
NULL, /* module directives */
NGX_EVENT_MODULE, /* module type */
diff --git a/src/event/modules/ngx_devpoll_module.c b/src/event/modules/ngx_devpoll_module.c
index 57b6b1239..cab5af074 100644
--- a/src/event/modules/ngx_devpoll_module.c
+++ b/src/event/modules/ngx_devpoll_module.c
@@ -91,7 +91,7 @@ ngx_event_module_t ngx_devpoll_module_ctx = {
};
ngx_module_t ngx_devpoll_module = {
- NGX_MODULE,
+ NGX_MODULE_V1,
&ngx_devpoll_module_ctx, /* module context */
ngx_devpoll_commands, /* module directives */
NGX_EVENT_MODULE, /* module type */
@@ -511,7 +511,7 @@ ngx_devpoll_process_events(ngx_cycle_t *cycle)
wev->ready = 1;
if (!ngx_threaded && !ngx_accept_mutex_held) {
- wev->event_handler(wev);
+ wev->handler(wev);
} else {
ngx_post_event(wev);
@@ -530,7 +530,7 @@ ngx_devpoll_process_events(ngx_cycle_t *cycle)
rev->ready = 1;
if (!ngx_threaded && !ngx_accept_mutex_held) {
- rev->event_handler(rev);
+ rev->handler(rev);
} else if (!rev->accept) {
ngx_post_event(rev);
@@ -538,7 +538,7 @@ ngx_devpoll_process_events(ngx_cycle_t *cycle)
} else if (ngx_accept_disabled <= 0) {
ngx_mutex_unlock(ngx_posted_events_mutex);
- c->read->event_handler(rev);
+ c->read->handler(rev);
if (ngx_accept_disabled > 0) {
ngx_accept_mutex_unlock();
diff --git a/src/event/modules/ngx_epoll_module.c b/src/event/modules/ngx_epoll_module.c
index 14b77508c..9847e0fe4 100644
--- a/src/event/modules/ngx_epoll_module.c
+++ b/src/event/modules/ngx_epoll_module.c
@@ -121,7 +121,7 @@ ngx_event_module_t ngx_epoll_module_ctx = {
};
ngx_module_t ngx_epoll_module = {
- NGX_MODULE,
+ NGX_MODULE_V1,
&ngx_epoll_module_ctx, /* module context */
ngx_epoll_commands, /* module directives */
NGX_EVENT_MODULE, /* module type */
@@ -573,7 +573,7 @@ ngx_epoll_process_events(ngx_cycle_t *cycle)
wev->ready = 1;
if (!ngx_accept_mutex_held) {
- wev->event_handler(wev);
+ wev->handler(wev);
} else {
ngx_post_event(wev);
@@ -600,7 +600,7 @@ ngx_epoll_process_events(ngx_cycle_t *cycle)
rev->ready = 1;
if (!ngx_threaded && !ngx_accept_mutex_held) {
- rev->event_handler(rev);
+ rev->handler(rev);
} else if (!rev->accept) {
ngx_post_event(rev);
@@ -609,7 +609,7 @@ ngx_epoll_process_events(ngx_cycle_t *cycle)
ngx_mutex_unlock(ngx_posted_events_mutex);
- rev->event_handler(rev);
+ rev->handler(rev);
if (ngx_accept_disabled > 0) {
ngx_accept_mutex_unlock();
diff --git a/src/event/modules/ngx_iocp_module.c b/src/event/modules/ngx_iocp_module.c
index 0a04a209a..1bb677c63 100644
--- a/src/event/modules/ngx_iocp_module.c
+++ b/src/event/modules/ngx_iocp_module.c
@@ -69,7 +69,7 @@ ngx_event_module_t ngx_iocp_module_ctx = {
};
ngx_module_t ngx_iocp_module = {
- NGX_MODULE,
+ NGX_MODULE_V1,
&ngx_iocp_module_ctx, /* module context */
ngx_iocp_commands, /* module directives */
NGX_EVENT_MODULE, /* module type */
@@ -294,9 +294,9 @@ ngx_int_t ngx_iocp_process_events(ngx_cycle_t *cycle)
ev->available = bytes;
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
- "iocp event handler: %p", ev->event_handler);
+ "iocp event handler: %p", ev->handler);
- ev->event_handler(ev);
+ ev->handler(ev);
if (timer != INFINITE && delta) {
ngx_event_expire_timers((ngx_msec_t) delta);
diff --git a/src/event/modules/ngx_kqueue_module.c b/src/event/modules/ngx_kqueue_module.c
index 14bbfaf27..713ea1a07 100644
--- a/src/event/modules/ngx_kqueue_module.c
+++ b/src/event/modules/ngx_kqueue_module.c
@@ -94,7 +94,7 @@ ngx_event_module_t ngx_kqueue_module_ctx = {
};
ngx_module_t ngx_kqueue_module = {
- NGX_MODULE,
+ NGX_MODULE_V1,
&ngx_kqueue_module_ctx, /* module context */
ngx_kqueue_commands, /* module directives */
NGX_EVENT_MODULE, /* module type */
@@ -192,11 +192,13 @@ ngx_kqueue_init(ngx_cycle_t *cycle)
ngx_event_actions = ngx_kqueue_module_ctx.actions;
ngx_event_flags = NGX_USE_ONESHOT_EVENT
+#if 1
#if (NGX_HAVE_CLEAR_EVENT)
|NGX_USE_CLEAR_EVENT
#else
|NGX_USE_LEVEL_EVENT
#endif
+#endif
#if (NGX_HAVE_LOWAT_EVENT)
|NGX_USE_LOWAT_EVENT
#endif
@@ -615,6 +617,10 @@ ngx_kqueue_process_events(ngx_cycle_t *cycle)
ngx_kqueue_dump_event(ev->log, &event_list[i]);
}
+ if (ev->oneshot) {
+ ev->active = 0;
+ }
+
#if (NGX_THREADS)
if (ngx_threaded && !ev->accept) {
@@ -663,7 +669,7 @@ ngx_kqueue_process_events(ngx_cycle_t *cycle)
}
if (!ngx_threaded && !ngx_accept_mutex_held) {
- ev->event_handler(ev);
+ ev->handler(ev);
continue;
}
@@ -678,7 +684,7 @@ ngx_kqueue_process_events(ngx_cycle_t *cycle)
ngx_mutex_unlock(ngx_posted_events_mutex);
- ev->event_handler(ev);
+ ev->handler(ev);
if (ngx_accept_disabled > 0) {
ngx_accept_mutex_unlock();
diff --git a/src/event/modules/ngx_poll_module.c b/src/event/modules/ngx_poll_module.c
index c25a5611c..97ac7ccc4 100644
--- a/src/event/modules/ngx_poll_module.c
+++ b/src/event/modules/ngx_poll_module.c
@@ -50,7 +50,7 @@ ngx_event_module_t ngx_poll_module_ctx = {
};
ngx_module_t ngx_poll_module = {
- NGX_MODULE,
+ NGX_MODULE_V1,
&ngx_poll_module_ctx, /* module context */
NULL, /* module directives */
NGX_EVENT_MODULE, /* module type */
@@ -536,7 +536,7 @@ ngx_poll_process_events(ngx_cycle_t *cycle)
}
}
- ev->event_handler(ev);
+ ev->handler(ev);
}
#endif
@@ -553,7 +553,7 @@ ngx_poll_process_events(ngx_cycle_t *cycle)
ngx_mutex_unlock(ngx_posted_events_mutex);
- ev->event_handler(ev);
+ ev->handler(ev);
if (ngx_accept_disabled > 0) {
lock = 0;
diff --git a/src/event/modules/ngx_rtsig_module.c b/src/event/modules/ngx_rtsig_module.c
index 6c94977db..122b0918d 100644
--- a/src/event/modules/ngx_rtsig_module.c
+++ b/src/event/modules/ngx_rtsig_module.c
@@ -118,7 +118,7 @@ ngx_event_module_t ngx_rtsig_module_ctx = {
};
ngx_module_t ngx_rtsig_module = {
- NGX_MODULE,
+ NGX_MODULE_V1,
&ngx_rtsig_module_ctx, /* module context */
ngx_rtsig_commands, /* module directives */
NGX_EVENT_MODULE, /* module type */
@@ -461,11 +461,11 @@ ngx_rtsig_process_events(ngx_cycle_t *cycle)
rev->ready = 1;
if (!ngx_threaded && !ngx_accept_mutex_held) {
- rev->event_handler(rev);
+ rev->handler(rev);
} else if (rev->accept) {
if (ngx_accept_disabled <= 0) {
- rev->event_handler(rev);
+ rev->handler(rev);
}
} else {
@@ -495,7 +495,7 @@ ngx_rtsig_process_events(ngx_cycle_t *cycle)
wev->ready = 1;
if (!ngx_threaded && !ngx_accept_mutex_held) {
- wev->event_handler(wev);
+ wev->handler(wev);
} else {
ngx_post_event(wev);
@@ -598,11 +598,11 @@ ngx_rtsig_process_overflow(ngx_cycle_t *cycle)
events = 0;
- if (c->read->active && c->read->event_handler) {
+ if (c->read->active && c->read->handler) {
events |= POLLIN;
}
- if (c->write->active && c->write->event_handler) {
+ if (c->write->active && c->write->handler) {
events |= POLLOUT;
}
@@ -652,7 +652,7 @@ ngx_rtsig_process_overflow(ngx_cycle_t *cycle)
if (rev->active
&& !rev->closed
- && rev->event_handler
+ && rev->handler
&& (overflow_list[i].revents
& (POLLIN|POLLERR|POLLHUP|POLLNVAL)))
{
@@ -664,7 +664,7 @@ ngx_rtsig_process_overflow(ngx_cycle_t *cycle)
} else {
rev->ready = 1;
- rev->event_handler(rev);
+ rev->handler(rev);
}
}
@@ -672,7 +672,7 @@ ngx_rtsig_process_overflow(ngx_cycle_t *cycle)
if (wev->active
&& !wev->closed
- && wev->event_handler
+ && wev->handler
&& (overflow_list[i].revents
& (POLLOUT|POLLERR|POLLHUP|POLLNVAL)))
{
@@ -684,7 +684,7 @@ ngx_rtsig_process_overflow(ngx_cycle_t *cycle)
} else {
wev->ready = 1;
- wev->event_handler(wev);
+ wev->handler(wev);
}
}
}
diff --git a/src/event/modules/ngx_select_module.c b/src/event/modules/ngx_select_module.c
index 6edc2840a..4cf88400c 100644
--- a/src/event/modules/ngx_select_module.c
+++ b/src/event/modules/ngx_select_module.c
@@ -63,7 +63,7 @@ ngx_event_module_t ngx_select_module_ctx = {
};
ngx_module_t ngx_select_module = {
- NGX_MODULE,
+ NGX_MODULE_V1,
&ngx_select_module_ctx, /* module context */
NULL, /* module directives */
NGX_EVENT_MODULE, /* module type */
@@ -540,7 +540,7 @@ ngx_select_process_events(ngx_cycle_t *cycle)
}
}
- ev->event_handler(ev);
+ ev->handler(ev);
}
#endif
@@ -557,7 +557,7 @@ ngx_select_process_events(ngx_cycle_t *cycle)
ngx_mutex_unlock(ngx_posted_events_mutex);
- ev->event_handler(ev);
+ ev->handler(ev);
if (ngx_accept_disabled > 0) {
lock = 0;
diff --git a/src/event/ngx_event.c b/src/event/ngx_event.c
index 0d10c4b56..274be6c52 100644
--- a/src/event/ngx_event.c
+++ b/src/event/ngx_event.c
@@ -24,10 +24,10 @@ static ngx_int_t ngx_event_process_init(ngx_cycle_t *cycle);
static char *ngx_events_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
static char *ngx_event_connections(ngx_conf_t *cf, ngx_command_t *cmd,
- void *conf);
+ void *conf);
static char *ngx_event_use(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
static char *ngx_event_debug_connection(ngx_conf_t *cf, ngx_command_t *cmd,
- void *conf);
+ void *conf);
static void *ngx_event_create_conf(ngx_cycle_t *cycle);
static char *ngx_event_init_conf(ngx_cycle_t *cycle, void *conf);
@@ -91,7 +91,7 @@ static ngx_core_module_t ngx_events_module_ctx = {
ngx_module_t ngx_events_module = {
- NGX_MODULE,
+ NGX_MODULE_V1,
&ngx_events_module_ctx, /* module context */
ngx_events_commands, /* module directives */
NGX_CORE_MODULE, /* module type */
@@ -163,7 +163,7 @@ ngx_event_module_t ngx_event_core_module_ctx = {
ngx_module_t ngx_event_core_module = {
- NGX_MODULE,
+ NGX_MODULE_V1,
&ngx_event_core_module_ctx, /* module context */
ngx_event_core_commands, /* module directives */
NGX_EVENT_MODULE, /* module type */
@@ -172,7 +172,143 @@ ngx_module_t ngx_event_core_module = {
};
-static ngx_int_t ngx_event_module_init(ngx_cycle_t *cycle)
+ngx_int_t
+ngx_handle_read_event(ngx_event_t *rev, u_int flags)
+{
+ if (ngx_event_flags & NGX_USE_CLEAR_EVENT) {
+
+ /* kqueue, epoll */
+
+ if (!rev->active && !rev->ready) {
+ if (ngx_add_event(rev, NGX_READ_EVENT, NGX_CLEAR_EVENT)
+ == NGX_ERROR)
+ {
+ return NGX_ERROR;
+ }
+ }
+
+ return NGX_OK;
+
+ } else if (ngx_event_flags & NGX_USE_LEVEL_EVENT) {
+
+ /* select, poll, /dev/poll */
+
+ if (!rev->active && !rev->ready) {
+ if (ngx_add_event(rev, NGX_READ_EVENT, NGX_LEVEL_EVENT)
+ == NGX_ERROR)
+ {
+ return NGX_ERROR;
+ }
+
+ return NGX_OK;
+ }
+
+ if (rev->active && (rev->ready || (flags & NGX_CLOSE_EVENT))) {
+ if (ngx_del_event(rev, NGX_READ_EVENT, NGX_LEVEL_EVENT | flags)
+ == NGX_ERROR)
+ {
+ return NGX_ERROR;
+ }
+
+ return NGX_OK;
+ }
+
+ } else if (ngx_event_flags & NGX_USE_ONESHOT_EVENT) {
+
+ /* event ports */
+
+ if (!rev->active) {
+ if (ngx_add_event(rev, NGX_READ_EVENT, NGX_ONESHOT_EVENT)
+ == NGX_ERROR)
+ {
+ return NGX_ERROR;
+ }
+ }
+
+ return NGX_OK;
+ }
+
+ /* aio, iocp, rtsig */
+
+ return NGX_OK;
+}
+
+
+ngx_int_t
+ngx_handle_write_event(ngx_event_t *wev, size_t lowat)
+{
+ ngx_connection_t *c;
+
+ if (lowat) {
+ c = (ngx_connection_t *) wev->data;
+
+ if (ngx_send_lowat(c, lowat) == NGX_ERROR) {
+ return NGX_ERROR;
+ }
+ }
+
+ if (ngx_event_flags & NGX_USE_CLEAR_EVENT) {
+
+ /* kqueue, epoll */
+
+ if (!wev->active && !wev->ready) {
+ if (ngx_add_event(wev, NGX_WRITE_EVENT,
+ NGX_CLEAR_EVENT | (lowat ? NGX_LOWAT_EVENT : 0))
+ == NGX_ERROR)
+ {
+ return NGX_ERROR;
+ }
+ }
+
+ return NGX_OK;
+
+ } else if (ngx_event_flags & NGX_USE_LEVEL_EVENT) {
+
+ /* select, poll, /dev/poll */
+
+ if (!wev->active && !wev->ready) {
+ if (ngx_add_event(wev, NGX_WRITE_EVENT, NGX_LEVEL_EVENT)
+ == NGX_ERROR)
+ {
+ return NGX_ERROR;
+ }
+
+ return NGX_OK;
+ }
+
+ if (wev->active && wev->ready) {
+ if (ngx_del_event(wev, NGX_WRITE_EVENT, NGX_LEVEL_EVENT)
+ == NGX_ERROR)
+ {
+ return NGX_ERROR;
+ }
+
+ return NGX_OK;
+ }
+
+ } else if (ngx_event_flags & NGX_USE_ONESHOT_EVENT) {
+
+ /* event ports */
+
+ if (!wev->active) {
+ if (ngx_add_event(wev, NGX_WRITE_EVENT, NGX_ONESHOT_EVENT)
+ == NGX_ERROR)
+ {
+ return NGX_ERROR;
+ }
+ }
+
+ return NGX_OK;
+ }
+
+ /* aio, iocp, rtsig */
+
+ return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_event_module_init(ngx_cycle_t *cycle)
{
#if !(NGX_WIN32)
@@ -248,7 +384,8 @@ static ngx_int_t ngx_event_module_init(ngx_cycle_t *cycle)
}
-static ngx_int_t ngx_event_process_init(ngx_cycle_t *cycle)
+static ngx_int_t
+ngx_event_process_init(ngx_cycle_t *cycle)
{
ngx_uint_t m, i;
ngx_socket_t fd;
@@ -417,7 +554,7 @@ static ngx_int_t ngx_event_process_init(ngx_cycle_t *cycle)
#if (NGX_WIN32)
if (ngx_event_flags & NGX_USE_IOCP_EVENT) {
- rev->event_handler = ngx_event_acceptex;
+ rev->handler = ngx_event_acceptex;
if (ngx_add_event(rev, 0, NGX_IOCP_ACCEPT) == NGX_ERROR) {
return NGX_ERROR;
@@ -431,7 +568,7 @@ static ngx_int_t ngx_event_process_init(ngx_cycle_t *cycle)
}
} else {
- rev->event_handler = ngx_event_accept;
+ rev->handler = ngx_event_accept;
if (ngx_add_event(rev, NGX_READ_EVENT, 0) == NGX_ERROR) {
return NGX_ERROR;
@@ -440,7 +577,7 @@ static ngx_int_t ngx_event_process_init(ngx_cycle_t *cycle)
#else
- rev->event_handler = ngx_event_accept;
+ rev->handler = ngx_event_accept;
if (ngx_accept_mutex) {
continue;
@@ -464,7 +601,8 @@ static ngx_int_t ngx_event_process_init(ngx_cycle_t *cycle)
}
-ngx_int_t ngx_send_lowat(ngx_connection_t *c, size_t lowat)
+ngx_int_t
+ngx_send_lowat(ngx_connection_t *c, size_t lowat)
{
int sndlowat;
@@ -497,7 +635,8 @@ ngx_int_t ngx_send_lowat(ngx_connection_t *c, size_t lowat)
}
-static char *ngx_events_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
+static char *
+ngx_events_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
char *rv;
void ***ctx;
@@ -574,8 +713,8 @@ static char *ngx_events_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
}
-static char *ngx_event_connections(ngx_conf_t *cf, ngx_command_t *cmd,
- void *conf)
+static char *
+ngx_event_connections(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
ngx_event_conf_t *ecf = conf;
@@ -600,7 +739,8 @@ static char *ngx_event_connections(ngx_conf_t *cf, ngx_command_t *cmd,
}
-static char *ngx_event_use(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
+static char *
+ngx_event_use(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
ngx_event_conf_t *ecf = conf;
@@ -662,8 +802,8 @@ static char *ngx_event_use(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
}
-static char *ngx_event_debug_connection(ngx_conf_t *cf, ngx_command_t *cmd,
- void *conf)
+static char *
+ngx_event_debug_connection(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
#if (NGX_DEBUG)
ngx_event_conf_t *ecf = conf;
@@ -709,7 +849,8 @@ static char *ngx_event_debug_connection(ngx_conf_t *cf, ngx_command_t *cmd,
}
-static void *ngx_event_create_conf(ngx_cycle_t *cycle)
+static void *
+ngx_event_create_conf(ngx_cycle_t *cycle)
{
ngx_event_conf_t *ecf;
@@ -739,7 +880,8 @@ static void *ngx_event_create_conf(ngx_cycle_t *cycle)
}
-static char *ngx_event_init_conf(ngx_cycle_t *cycle, void *conf)
+static char *
+ngx_event_init_conf(ngx_cycle_t *cycle, void *conf)
{
ngx_event_conf_t *ecf = conf;
@@ -874,7 +1016,8 @@ static char *ngx_event_init_conf(ngx_cycle_t *cycle, void *conf)
}
-static char *ngx_accept_mutex_check(ngx_conf_t *cf, void *post, void *data)
+static char *
+ngx_accept_mutex_check(ngx_conf_t *cf, void *post, void *data)
{
#if !(NGX_HAVE_ATOMIC_OPS)
diff --git a/src/event/ngx_event.h b/src/event/ngx_event.h
index 6dfd70986..3e93bf778 100644
--- a/src/event/ngx_event.h
+++ b/src/event/ngx_event.h
@@ -113,8 +113,7 @@ struct ngx_event_s {
unsigned available:1;
#endif
- /* TODO rename to handler */
- ngx_event_handler_pt event_handler;
+ ngx_event_handler_pt handler;
#if (NGX_HAVE_AIO)
@@ -474,6 +473,10 @@ ngx_int_t ngx_disable_accept_events(ngx_cycle_t *cycle);
ngx_int_t ngx_enable_accept_events(ngx_cycle_t *cycle);
+ngx_int_t ngx_handle_read_event(ngx_event_t *rev, u_int flags);
+ngx_int_t ngx_handle_write_event(ngx_event_t *wev, size_t lowat);
+
+
#if (NGX_WIN32)
void ngx_event_acceptex(ngx_event_t *ev);
int ngx_event_post_acceptex(ngx_listening_t *ls, int n);
@@ -496,158 +499,4 @@ ngx_int_t ngx_send_lowat(ngx_connection_t *c, size_t lowat);
#endif
-
-static ngx_inline ngx_int_t ngx_handle_read_event(ngx_event_t *rev, u_int flags)
-{
- if (ngx_event_flags & NGX_USE_CLEAR_EVENT) {
-
- /* kqueue, epoll */
-
- if (!rev->active && !rev->ready) {
- if (ngx_add_event(rev, NGX_READ_EVENT, NGX_CLEAR_EVENT)
- == NGX_ERROR) {
- return NGX_ERROR;
- }
- }
-
- return NGX_OK;
-
- } else if (ngx_event_flags & NGX_USE_LEVEL_EVENT) {
-
- /* select, poll, /dev/poll */
-
- if (!rev->active && !rev->ready) {
- if (ngx_add_event(rev, NGX_READ_EVENT, NGX_LEVEL_EVENT)
- == NGX_ERROR)
- {
- return NGX_ERROR;
- }
-
- return NGX_OK;
- }
-
- if (rev->active && (rev->ready || (flags & NGX_CLOSE_EVENT))) {
- if (ngx_del_event(rev, NGX_READ_EVENT, flags) == NGX_ERROR) {
- return NGX_ERROR;
- }
-
- return NGX_OK;
- }
- }
-
- /* aio, iocp, rtsig */
-
- return NGX_OK;
-}
-
-
-static ngx_inline ngx_int_t ngx_handle_level_read_event(ngx_event_t *rev)
-{
- if (ngx_event_flags & NGX_USE_LEVEL_EVENT) {
- if (!rev->active && !rev->ready) {
- if (ngx_add_event(rev, NGX_READ_EVENT, NGX_LEVEL_EVENT)
- == NGX_ERROR)
- {
- return NGX_ERROR;
- }
-
- return NGX_OK;
- }
-
- if (rev->active && rev->ready) {
- if (ngx_del_event(rev, NGX_READ_EVENT, 0) == NGX_ERROR) {
- return NGX_ERROR;
- }
-
- return NGX_OK;
- }
- }
-
- return NGX_OK;
-}
-
-
-static ngx_inline ngx_int_t ngx_handle_write_event(ngx_event_t *wev,
- size_t lowat)
-{
- ngx_connection_t *c;
-
- if (lowat) {
- c = (ngx_connection_t *) wev->data;
-
- if (ngx_send_lowat(c, lowat) == NGX_ERROR) {
- return NGX_ERROR;
- }
- }
-
- if (ngx_event_flags & NGX_USE_CLEAR_EVENT) {
-
- /* kqueue, epoll */
-
- if (!wev->active && !wev->ready) {
- if (ngx_add_event(wev, NGX_WRITE_EVENT,
- NGX_CLEAR_EVENT | (lowat ? NGX_LOWAT_EVENT : 0))
- == NGX_ERROR)
- {
- return NGX_ERROR;
- }
- }
-
- return NGX_OK;
-
- } else if (ngx_event_flags & NGX_USE_LEVEL_EVENT) {
-
- /* select, poll, /dev/poll */
-
- if (!wev->active && !wev->ready) {
- if (ngx_add_event(wev, NGX_WRITE_EVENT, NGX_LEVEL_EVENT)
- == NGX_ERROR)
- {
- return NGX_ERROR;
- }
-
- return NGX_OK;
- }
-
- if (wev->active && wev->ready) {
- if (ngx_del_event(wev, NGX_WRITE_EVENT, 0) == NGX_ERROR) {
- return NGX_ERROR;
- }
-
- return NGX_OK;
- }
- }
-
- /* aio, iocp, rtsig */
-
- return NGX_OK;
-}
-
-
-static ngx_inline ngx_int_t ngx_handle_level_write_event(ngx_event_t *wev)
-{
- if (ngx_event_flags & NGX_USE_LEVEL_EVENT) {
- if (!wev->active && !wev->ready) {
- if (ngx_add_event(wev, NGX_WRITE_EVENT, NGX_LEVEL_EVENT)
- == NGX_ERROR)
- {
- return NGX_ERROR;
- }
-
- return NGX_OK;
- }
-
- if (wev->active && wev->ready) {
- if (ngx_del_event(wev, NGX_WRITE_EVENT, 0) == NGX_ERROR) {
- return NGX_ERROR;
- }
-
- return NGX_OK;
- }
- }
-
- return NGX_OK;
-}
-
-
#endif /* _NGX_EVENT_H_INCLUDED_ */
diff --git a/src/event/ngx_event_accept.c b/src/event/ngx_event_accept.c
index 9441c82a6..e31253367 100644
--- a/src/event/ngx_event_accept.c
+++ b/src/event/ngx_event_accept.c
@@ -106,7 +106,9 @@ ngx_event_accept(ngx_event_t *ev)
return;
}
- ngx_log_error(NGX_LOG_ALERT, ev->log, err,
+ ngx_log_error((err == NGX_ECONNABORTED) ? NGX_LOG_CRIT:
+ NGX_LOG_ALERT,
+ ev->log, err,
"accept() on %V failed", &ls->listening->addr_text);
if (err == NGX_ECONNABORTED) {
diff --git a/src/event/ngx_event_acceptex.c b/src/event/ngx_event_acceptex.c
index b02dfd0d5..50cd21df3 100644
--- a/src/event/ngx_event_acceptex.c
+++ b/src/event/ngx_event_acceptex.c
@@ -132,7 +132,7 @@ int ngx_event_post_acceptex(ngx_listening_t *ls, int n)
rev->ovlp.event = rev;
wev->ovlp.event = wev;
- rev->event_handler = ngx_event_acceptex;
+ rev->handler = ngx_event_acceptex;
rev->data = c;
wev->data = c;
diff --git a/src/event/ngx_event_busy_lock.c b/src/event/ngx_event_busy_lock.c
index 56a8d921c..4d499a3ae 100644
--- a/src/event/ngx_event_busy_lock.c
+++ b/src/event/ngx_event_busy_lock.c
@@ -43,7 +43,7 @@ ngx_int_t ngx_event_busy_lock(ngx_event_busy_lock_t *bl,
} else if (ctx->timer && bl->waiting < bl->max_waiting) {
bl->waiting++;
ngx_add_timer(ctx->event, ctx->timer);
- ctx->event->event_handler = ngx_event_busy_lock_handler;
+ ctx->event->handler = ngx_event_busy_lock_handler;
if (bl->events) {
bl->last->next = ctx;
@@ -92,7 +92,7 @@ ngx_int_t ngx_event_busy_lock_cachable(ngx_event_busy_lock_t *bl,
if (ctx->timer && bl->waiting < bl->max_waiting) {
bl->waiting++;
ngx_add_timer(ctx->event, ctx->timer);
- ctx->event->event_handler = ngx_event_busy_lock_handler;
+ ctx->event->handler = ngx_event_busy_lock_handler;
if (bl->events == NULL) {
bl->events = ctx;
@@ -296,7 +296,7 @@ static void ngx_event_busy_lock_handler(ngx_event_t *ev)
ngx_mutex_unlock(ngx_posted_events_mutex);
- ev->event_handler = ngx_event_busy_lock_posted_handler;
+ ev->handler = ngx_event_busy_lock_posted_handler;
}
diff --git a/src/event/ngx_event_connect.c b/src/event/ngx_event_connect.c
index 81798d315..2f559a34d 100644
--- a/src/event/ngx_event_connect.c
+++ b/src/event/ngx_event_connect.c
@@ -114,6 +114,9 @@ ngx_event_connect_peer(ngx_peer_connection_t *pc)
s = ngx_socket(peer->sockaddr->sa_family, SOCK_STREAM, 0);
+ ngx_log_debug1(NGX_LOG_DEBUG_EVENT, pc->log, 0,
+ "socket %d", s);
+
if (s == -1) {
ngx_log_error(NGX_LOG_ALERT, pc->log, ngx_socket_errno,
ngx_socket_n " failed");
diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c
index d213eb158..afdf4631c 100644
--- a/src/event/ngx_event_openssl.c
+++ b/src/event/ngx_event_openssl.c
@@ -170,7 +170,7 @@ ngx_ssl_handle_recv(ngx_connection_t *c, int n)
if (c->ssl->saved_write_handler) {
- c->write->event_handler = c->ssl->saved_write_handler;
+ c->write->handler = c->ssl->saved_write_handler;
c->ssl->saved_write_handler = NULL;
c->write->ready = 1;
@@ -223,8 +223,8 @@ ngx_ssl_handle_recv(ngx_connection_t *c, int n)
*/
if (c->ssl->saved_write_handler == NULL) {
- c->ssl->saved_write_handler = c->write->event_handler;
- c->write->event_handler = ngx_ssl_write_handler;
+ c->ssl->saved_write_handler = c->write->handler;
+ c->write->handler = ngx_ssl_write_handler;
}
return NGX_AGAIN;
@@ -253,7 +253,7 @@ ngx_ssl_write_handler(ngx_event_t *wev)
ngx_connection_t *c;
c = wev->data;
- c->read->event_handler(c->read);
+ c->read->handler(c->read);
}
@@ -405,7 +405,7 @@ ngx_ssl_write(ngx_connection_t *c, u_char *data, size_t size)
if (n > 0) {
if (c->ssl->saved_read_handler) {
- c->read->event_handler = c->ssl->saved_read_handler;
+ c->read->handler = c->ssl->saved_read_handler;
c->ssl->saved_read_handler = NULL;
c->read->ready = 1;
@@ -460,8 +460,8 @@ ngx_ssl_write(ngx_connection_t *c, u_char *data, size_t size)
*/
if (c->ssl->saved_read_handler == NULL) {
- c->ssl->saved_read_handler = c->read->event_handler;
- c->read->event_handler = ngx_ssl_read_handler;
+ c->ssl->saved_read_handler = c->read->handler;
+ c->read->handler = ngx_ssl_read_handler;
}
return NGX_AGAIN;
@@ -482,7 +482,7 @@ ngx_ssl_read_handler(ngx_event_t *rev)
ngx_connection_t *c;
c = rev->data;
- c->write->event_handler(c->write);
+ c->write->handler(c->write);
}
@@ -592,3 +592,12 @@ ngx_ssl_error(ngx_uint_t level, ngx_log_t *log, ngx_err_t err, char *fmt, ...)
ngx_log_error(level, log, err, "%s)", errstr);
}
+
+
+void
+ngx_ssl_cleanup_ctx(void *data)
+{
+ SSL_CTX *ctx = data;
+
+ SSL_CTX_free(ctx);
+}
diff --git a/src/event/ngx_event_openssl.h b/src/event/ngx_event_openssl.h
index afebde694..8797fcd0f 100644
--- a/src/event/ngx_event_openssl.h
+++ b/src/event/ngx_event_openssl.h
@@ -54,6 +54,7 @@ ngx_chain_t *ngx_ssl_send_chain(ngx_connection_t *c, ngx_chain_t *in,
ngx_int_t ngx_ssl_shutdown(ngx_connection_t *c);
void ngx_ssl_error(ngx_uint_t level, ngx_log_t *log, ngx_err_t err,
char *fmt, ...);
+void ngx_ssl_cleanup_ctx(void *data);
#endif /* _NGX_EVENT_OPENSSL_H_INCLUDED_ */
diff --git a/src/event/ngx_event_pipe.c b/src/event/ngx_event_pipe.c
index 5f9d7c090..5d26405e2 100644
--- a/src/event/ngx_event_pipe.c
+++ b/src/event/ngx_event_pipe.c
@@ -64,13 +64,13 @@ ngx_int_t ngx_event_pipe(ngx_event_pipe_t *p, int do_write)
}
}
- if (p->downstream->fd != -1) {
+ if (p->downstream->fd != -1 && p->downstream->data == p->output_ctx) {
wev = p->downstream->write;
if (ngx_handle_write_event(wev, p->send_lowat) == NGX_ERROR) {
return NGX_ABORT;
}
- if (wev->active) {
+ if (wev->active && !wev->ready && !wev->delayed) {
ngx_add_timer(wev, p->send_timeout);
}
}
@@ -180,8 +180,10 @@ static ngx_int_t ngx_event_pipe_read_upstream(ngx_event_pipe_t *p)
chain->buf = b;
chain->next = NULL;
- } else if (!p->cachable && p->downstream->write->ready) {
-
+ } else if (!p->cachable
+ && p->downstream->data == p->output_ctx
+ && p->downstream->write->ready)
+ {
/*
* if the bufs are not needed to be saved in a cache and
* a downstream is ready then write the bufs to a downstream
@@ -409,10 +411,18 @@ static ngx_int_t ngx_event_pipe_write_to_downstream(ngx_event_pipe_t *p)
/* pass the p->out and p->in chains to the output filter */
+ for (cl = p->busy; cl; cl = cl->next) {
+ cl->buf->recycled = 0;
+ }
+
if (p->out) {
ngx_log_debug0(NGX_LOG_DEBUG_EVENT, p->log, 0,
"pipe write downstream flush out");
+ for (cl = p->out; cl; cl = cl->next) {
+ cl->buf->recycled = 0;
+ }
+
if (p->output_filter(p->output_ctx, p->out) == NGX_ERROR) {
p->downstream_error = 1;
return ngx_event_pipe_drain_chains(p);
@@ -425,6 +435,10 @@ static ngx_int_t ngx_event_pipe_write_to_downstream(ngx_event_pipe_t *p)
ngx_log_debug0(NGX_LOG_DEBUG_EVENT, p->log, 0,
"pipe write downstream flush in");
+ for (cl = p->in; cl; cl = cl->next) {
+ cl->buf->recycled = 0;
+ }
+
if (p->output_filter(p->output_ctx, p->in) == NGX_ERROR) {
p->downstream_error = 1;
return ngx_event_pipe_drain_chains(p);
@@ -442,7 +456,9 @@ static ngx_int_t ngx_event_pipe_write_to_downstream(ngx_event_pipe_t *p)
break;
}
- if (!p->downstream->write->ready) {
+ if (p->downstream->data != p->output_ctx
+ || !p->downstream->write->ready)
+ {
break;
}
diff --git a/src/event/ngx_event_posted.c b/src/event/ngx_event_posted.c
index 8050c326f..181ab4cb4 100644
--- a/src/event/ngx_event_posted.c
+++ b/src/event/ngx_event_posted.c
@@ -33,7 +33,7 @@ void ngx_event_process_posted(ngx_cycle_t *cycle)
ngx_delete_posted_event(ev);
- ev->event_handler(ev);
+ ev->handler(ev);
}
}
@@ -137,7 +137,7 @@ ngx_int_t ngx_event_thread_process_posted(ngx_cycle_t *cycle)
ngx_mutex_unlock(ngx_posted_events_mutex);
- ev->event_handler(ev);
+ ev->handler(ev);
if (ngx_mutex_lock(ngx_posted_events_mutex) == NGX_ERROR) {
return NGX_ERROR;
diff --git a/src/event/ngx_event_timer.c b/src/event/ngx_event_timer.c
index 7655c4fd8..fdec446c4 100644
--- a/src/event/ngx_event_timer.c
+++ b/src/event/ngx_event_timer.c
@@ -156,7 +156,7 @@ ngx_event_expire_timers(ngx_msec_t timer)
ev->timedout = 1;
- ev->event_handler(ev);
+ ev->handler(ev);
continue;
}
diff --git a/src/http/modules/ngx_http_access_module.c b/src/http/modules/ngx_http_access_module.c
index 685d15d57..47f9944b0 100644
--- a/src/http/modules/ngx_http_access_module.c
+++ b/src/http/modules/ngx_http_access_module.c
@@ -54,7 +54,8 @@ static ngx_command_t ngx_http_access_commands[] = {
ngx_http_module_t ngx_http_access_module_ctx = {
- NULL, /* pre conf */
+ NULL, /* preconfiguration */
+ NULL, /* postconfiguration */
NULL, /* create main configuration */
NULL, /* init main configuration */
@@ -68,7 +69,7 @@ ngx_http_module_t ngx_http_access_module_ctx = {
ngx_module_t ngx_http_access_module = {
- NGX_MODULE,
+ NGX_MODULE_V1,
&ngx_http_access_module_ctx, /* module context */
ngx_http_access_commands, /* module directives */
NGX_HTTP_MODULE, /* module type */
diff --git a/src/http/modules/ngx_http_auth_basic_module.c b/src/http/modules/ngx_http_auth_basic_module.c
index 03314b5cf..98c47bd64 100644
--- a/src/http/modules/ngx_http_auth_basic_module.c
+++ b/src/http/modules/ngx_http_auth_basic_module.c
@@ -60,7 +60,8 @@ static ngx_command_t ngx_http_auth_basic_commands[] = {
ngx_http_module_t ngx_http_auth_basic_module_ctx = {
- NULL, /* pre conf */
+ NULL, /* preconfiguration */
+ NULL, /* postconfiguration */
NULL, /* create main configuration */
NULL, /* init main configuration */
@@ -74,7 +75,7 @@ ngx_http_module_t ngx_http_auth_basic_module_ctx = {
ngx_module_t ngx_http_auth_basic_module = {
- NGX_MODULE,
+ NGX_MODULE_V1,
&ngx_http_auth_basic_module_ctx, /* module context */
ngx_http_auth_basic_commands, /* module directives */
NGX_HTTP_MODULE, /* module type */
@@ -327,6 +328,7 @@ ngx_http_auth_basic_set_realm(ngx_http_request_t *r, ngx_str_t *realm)
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
+ r->headers_out.www_authenticate->hash = 1;
r->headers_out.www_authenticate->key.len = sizeof("WWW-Authenticate") - 1;
r->headers_out.www_authenticate->key.data = (u_char *) "WWW-Authenticate";
r->headers_out.www_authenticate->value = *realm;
diff --git a/src/http/modules/ngx_http_autoindex_module.c b/src/http/modules/ngx_http_autoindex_module.c
index ff163ed3c..76c5b0314 100644
--- a/src/http/modules/ngx_http_autoindex_module.c
+++ b/src/http/modules/ngx_http_autoindex_module.c
@@ -63,7 +63,8 @@ static ngx_command_t ngx_http_autoindex_commands[] = {
ngx_http_module_t ngx_http_autoindex_module_ctx = {
- NULL, /* pre conf */
+ NULL, /* preconfiguration */
+ NULL, /* postconfiguration */
NULL, /* create main configuration */
NULL, /* init main configuration */
@@ -77,7 +78,7 @@ ngx_http_module_t ngx_http_autoindex_module_ctx = {
ngx_module_t ngx_http_autoindex_module = {
- NGX_MODULE,
+ NGX_MODULE_V1,
&ngx_http_autoindex_module_ctx, /* module context */
ngx_http_autoindex_commands, /* module directives */
NGX_HTTP_MODULE, /* module type */
@@ -419,16 +420,8 @@ ngx_http_autoindex_handler(ngx_http_request_t *r)
r->headers_out.status = NGX_HTTP_OK;
r->headers_out.content_length_n = b->last - b->pos;
-
- r->headers_out.content_type = ngx_list_push(&r->headers_out.headers);
- if (r->headers_out.content_type == NULL) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- r->headers_out.content_type->key.len = 0;
- r->headers_out.content_type->key.data = NULL;
- r->headers_out.content_type->value.len = sizeof("text/html") - 1;
- r->headers_out.content_type->value.data = (u_char *) "text/html";
+ r->headers_out.content_type.len = sizeof("text/html") - 1;
+ r->headers_out.content_type.data = (u_char *) "text/html";
rc = ngx_http_send_header(r);
@@ -436,10 +429,12 @@ ngx_http_autoindex_handler(ngx_http_request_t *r)
return rc;
}
- if (!r->main) {
+ if (r->main == NULL) {
b->last_buf = 1;
}
+ b->last_in_chain = 1;
+
out.buf = b;
out.next = NULL;
diff --git a/src/http/modules/ngx_http_charset_filter_module.c b/src/http/modules/ngx_http_charset_filter_module.c
index dad26ba91..0c76a5f43 100644
--- a/src/http/modules/ngx_http_charset_filter_module.c
+++ b/src/http/modules/ngx_http_charset_filter_module.c
@@ -106,7 +106,8 @@ static ngx_command_t ngx_http_charset_filter_commands[] = {
static ngx_http_module_t ngx_http_charset_filter_module_ctx = {
- NULL, /* pre conf */
+ NULL, /* preconfiguration */
+ NULL, /* postconfiguration */
ngx_http_charset_create_main_conf, /* create main configuration */
ngx_http_charset_init_main_conf, /* init main configuration */
@@ -120,7 +121,7 @@ static ngx_http_module_t ngx_http_charset_filter_module_ctx = {
ngx_module_t ngx_http_charset_filter_module = {
- NGX_MODULE,
+ NGX_MODULE_V1,
&ngx_http_charset_filter_module_ctx, /* module context */
ngx_http_charset_filter_commands, /* module directives */
NGX_HTTP_MODULE, /* module type */
@@ -148,19 +149,18 @@ ngx_http_charset_header_filter(ngx_http_request_t *r)
return ngx_http_next_header_filter(r);
}
- if (r->headers_out.content_type == NULL) {
+ if (r->headers_out.content_type.len == 0) {
return ngx_http_next_header_filter(r);
}
- if (ngx_strncasecmp(r->headers_out.content_type->value.data,
- "text/", 5) != 0
- && ngx_strncasecmp(r->headers_out.content_type->value.data,
- "application/x-javascript", 24) != 0)
+ if (ngx_strncasecmp(r->headers_out.content_type.data, "text/", 5) != 0
+ && ngx_strncasecmp(r->headers_out.content_type.data,
+ "application/x-javascript", 24) != 0)
{
return ngx_http_next_header_filter(r);
}
- if (ngx_strstr(r->headers_out.content_type->value.data, "charset") != NULL)
+ if (ngx_strstr(r->headers_out.content_type.data, "charset") != NULL)
{
return ngx_http_next_header_filter(r);
}
diff --git a/src/http/modules/ngx_http_chunked_filter_module.c b/src/http/modules/ngx_http_chunked_filter_module.c
index b742dbb7c..4136613e0 100644
--- a/src/http/modules/ngx_http_chunked_filter_module.c
+++ b/src/http/modules/ngx_http_chunked_filter_module.c
@@ -13,7 +13,8 @@ static ngx_int_t ngx_http_chunked_filter_init(ngx_cycle_t *cycle);
static ngx_http_module_t ngx_http_chunked_filter_module_ctx = {
- NULL, /* pre conf */
+ NULL, /* preconfiguration */
+ NULL, /* postconfiguration */
NULL, /* create main configuration */
NULL, /* init main configuration */
@@ -27,7 +28,7 @@ static ngx_http_module_t ngx_http_chunked_filter_module_ctx = {
ngx_module_t ngx_http_chunked_filter_module = {
- NGX_MODULE,
+ NGX_MODULE_V1,
&ngx_http_chunked_filter_module_ctx, /* module context */
NULL, /* module directives */
NGX_HTTP_MODULE, /* module type */
@@ -43,7 +44,7 @@ static ngx_http_output_body_filter_pt ngx_http_next_body_filter;
static ngx_int_t
ngx_http_chunked_header_filter(ngx_http_request_t *r)
{
- if (r->headers_out.status == NGX_HTTP_NOT_MODIFIED) {
+ if (r->headers_out.status == NGX_HTTP_NOT_MODIFIED || r->main) {
return ngx_http_next_header_filter(r);
}
diff --git a/src/http/modules/ngx_http_fastcgi_module.c b/src/http/modules/ngx_http_fastcgi_module.c
index 4b92cd46f..cf9d008a5 100644
--- a/src/http/modules/ngx_http_fastcgi_module.c
+++ b/src/http/modules/ngx_http_fastcgi_module.c
@@ -15,37 +15,14 @@ typedef struct {
ngx_peers_t *peers;
- ngx_uint_t params;
-
- ngx_str_t root;
ngx_str_t index;
- ngx_array_t *vars;
-
- ngx_str_t *location;
+ ngx_array_t *params_len;
+ ngx_array_t *params;
+ ngx_array_t *params_source;
} ngx_http_fastcgi_loc_conf_t;
-typedef struct {
- ngx_list_t headers;
-
- ngx_table_elt_t *status;
-
- ngx_table_elt_t *content_type;
- ngx_table_elt_t *content_length;
- ngx_table_elt_t *x_powered_by;
-
-#if (NGX_HTTP_GZIP)
- ngx_table_elt_t *content_encoding;
-#endif
-} ngx_http_fastcgi_headers_in_t;
-
-
-typedef struct {
- ngx_http_fastcgi_headers_in_t headers_in;
-} ngx_http_fastcgi_upstream_t;
-
-
typedef enum {
ngx_http_fastcgi_st_version = 0,
ngx_http_fastcgi_st_type,
@@ -69,28 +46,9 @@ typedef struct {
size_t padding;
ngx_uint_t header;
-
- ngx_http_fastcgi_upstream_t *upstream;
} ngx_http_fastcgi_ctx_t;
-#define NGX_HTTP_FASTCGI_REMOTE_ADDR 0x00000002
-#define NGX_HTTP_FASTCGI_REMOTE_USER 0x00000004
-#define NGX_HTTP_FASTCGI_SERVER_NAME 0x00000008
-#define NGX_HTTP_FASTCGI_SERVER_ADDR 0x00000010
-#define NGX_HTTP_FASTCGI_SERVER_PORT 0x00000020
-#define NGX_HTTP_FASTCGI_SCRIPT_NAME 0x00000040
-#define NGX_HTTP_FASTCGI_AUTH_TYPE 0x00000080
-#define NGX_HTTP_FASTCGI_SERVER_PROTOCOL 0x00000100
-#define NGX_HTTP_FASTCGI_SERVER_SOFTWARE 0x00000200
-#define NGX_HTTP_FASTCGI_GATEWAY_INTERFACE 0x00000400
-#define NGX_HTTP_FASTCGI_REQUEST_URI 0x00000800
-#define NGX_HTTP_FASTCGI_REDIRECT_STATUS 0x00001000
-#define NGX_HTTP_FASTCGI_DOCUMENT_ROOT 0x00002000
-#define NGX_HTTP_FASTCGI_SCRIPT_FILENAME 0x00004000
-#define NGX_HTTP_FASTCGI_REMOTE_PORT 0x00008000
-
-
#define NGX_HTTP_FASTCGI_RESPONDER 1
#define NGX_HTTP_FASTCGI_BEGIN_REQUEST 1
@@ -123,10 +81,24 @@ typedef struct {
} ngx_http_fastcgi_begin_request_t;
+typedef struct {
+ u_char version;
+ u_char type;
+ u_char request_id_hi;
+ u_char request_id_lo;
+} ngx_http_fastcgi_header_small_t;
+
+
+typedef struct {
+ ngx_http_fastcgi_header_t h0;
+ ngx_http_fastcgi_begin_request_t br;
+ ngx_http_fastcgi_header_small_t h1;
+} ngx_http_fastcgi_request_start_t;
+
+
static ngx_int_t ngx_http_fastcgi_create_request(ngx_http_request_t *r);
static ngx_int_t ngx_http_fastcgi_reinit_request(ngx_http_request_t *r);
static ngx_int_t ngx_http_fastcgi_process_header(ngx_http_request_t *r);
-static ngx_int_t ngx_http_fastcgi_send_header(ngx_http_request_t *r);
static ngx_int_t ngx_http_fastcgi_input_filter(ngx_event_pipe_t *p,
ngx_buf_t *buf);
static ngx_int_t ngx_http_fastcgi_process_record(ngx_http_request_t *r,
@@ -135,53 +107,69 @@ static void ngx_http_fastcgi_abort_request(ngx_http_request_t *r);
static void ngx_http_fastcgi_finalize_request(ngx_http_request_t *r,
ngx_int_t rc);
+static ngx_int_t ngx_http_fastcgi_add_variables(ngx_conf_t *cf);
+static void *ngx_http_fastcgi_create_loc_conf(ngx_conf_t *cf);
+static char *ngx_http_fastcgi_merge_loc_conf(ngx_conf_t *cf,
+ void *parent, void *child);
+static ngx_http_variable_value_t *
+ ngx_http_fastcgi_script_name_variable(ngx_http_request_t *r,
+ uintptr_t data);
+
static char *ngx_http_fastcgi_pass(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
-static char *ngx_http_fastcgi_set_var(ngx_conf_t *cf, ngx_command_t *cmd,
- void *conf);
static char *ngx_http_fastcgi_lowat_check(ngx_conf_t *cf, void *post,
void *data);
-static void *ngx_http_fastcgi_create_loc_conf(ngx_conf_t *cf);
-static char *ngx_http_fastcgi_merge_loc_conf(ngx_conf_t *cf,
- void *parent, void *child);
+static ngx_http_fastcgi_request_start_t ngx_http_fastcgi_request_start = {
+ { 1, /* version */
+ NGX_HTTP_FASTCGI_BEGIN_REQUEST, /* type */
+ 0, /* request_id_hi */
+ 1, /* request_id_lo */
+ 0, /* content_length_hi */
+ sizeof(ngx_http_fastcgi_begin_request_t), /* content_length_lo */
+ 0, /* padding_length */
+ 0 }, /* reserved */
+
+ { 0, /* role_hi */
+ NGX_HTTP_FASTCGI_RESPONDER, /* role_lo */
+ 0, /* NGX_HTTP_FASTCGI_KEEP_CONN */ /* flags */
+ { 0, 0, 0, 0, 0 } }, /* reserved[5] */
+
+ { 1, /* version */
+ NGX_HTTP_FASTCGI_PARAMS, /* type */
+ 0, /* request_id_hi */
+ 1 }, /* request_id_lo */
+
+};
+
+
+#if 0
static ngx_str_t ngx_http_fastcgi_methods[] = {
ngx_string("GET"),
ngx_string("HEAD"),
ngx_string("POST")
};
-
-
-#if (NGX_PCRE)
-static ngx_str_t ngx_http_fastcgi_uri = ngx_string("/");
#endif
-static ngx_http_header_t ngx_http_fastcgi_headers_in[] = {
- { ngx_string("Status"), offsetof(ngx_http_fastcgi_headers_in_t, status) },
+static ngx_str_t ngx_http_fastcgi_script_name =
+ ngx_string("fastcgi_script_name");
- { ngx_string("Content-Type"),
- offsetof(ngx_http_fastcgi_headers_in_t, content_type) },
- { ngx_string("Content-Length"),
- offsetof(ngx_http_fastcgi_headers_in_t, content_length) },
+#if (NGX_PCRE)
+static ngx_str_t ngx_http_fastcgi_uri = ngx_string("/");
+#endif
- { ngx_string("X-Powered-By"),
- offsetof(ngx_http_fastcgi_headers_in_t, x_powered_by) },
-#if (NGX_HTTP_GZIP)
- { ngx_string("Content-Encoding"),
- offsetof(ngx_http_fastcgi_headers_in_t, content_encoding) },
-#endif
+static ngx_conf_post_t ngx_http_fastcgi_lowat_post =
+ { ngx_http_fastcgi_lowat_check };
+static ngx_conf_enum_t ngx_http_fastcgi_set_methods[] = {
+ { ngx_string("get"), NGX_HTTP_GET },
{ ngx_null_string, 0 }
};
-
-static ngx_conf_post_t ngx_http_fastcgi_lowat_post =
- { ngx_http_fastcgi_lowat_check };
-
static ngx_conf_bitmask_t ngx_http_fastcgi_next_upstream_masks[] = {
{ ngx_string("error"), NGX_HTTP_UPSTREAM_FT_ERROR },
{ ngx_string("timeout"), NGX_HTTP_UPSTREAM_FT_TIMEOUT },
@@ -192,28 +180,6 @@ static ngx_conf_bitmask_t ngx_http_fastcgi_next_upstream_masks[] = {
};
-static ngx_conf_bitmask_t ngx_http_fastcgi_params_masks[] = {
- { ngx_string("remote_addr"), NGX_HTTP_FASTCGI_REMOTE_ADDR },
- { ngx_string("server_port"), NGX_HTTP_FASTCGI_SERVER_PORT },
- { ngx_string("server_addr"), NGX_HTTP_FASTCGI_SERVER_ADDR },
- { ngx_string("server_name"), NGX_HTTP_FASTCGI_SERVER_NAME },
- { ngx_string("script_name"), NGX_HTTP_FASTCGI_SCRIPT_NAME },
-
- { ngx_string("server_protocol"), NGX_HTTP_FASTCGI_SERVER_PROTOCOL },
- { ngx_string("server_software"), NGX_HTTP_FASTCGI_SERVER_SOFTWARE },
- { ngx_string("gateway_interface"), NGX_HTTP_FASTCGI_GATEWAY_INTERFACE },
-
- { ngx_string("redirect_status"), NGX_HTTP_FASTCGI_REDIRECT_STATUS },
- { ngx_string("request_uri"), NGX_HTTP_FASTCGI_REQUEST_URI },
-
- { ngx_string("document_root"), NGX_HTTP_FASTCGI_DOCUMENT_ROOT },
- { ngx_string("script_filename"), NGX_HTTP_FASTCGI_SCRIPT_FILENAME },
- { ngx_string("remote_port"), NGX_HTTP_FASTCGI_REMOTE_PORT },
-
- { ngx_null_string, 0 }
-};
-
-
static ngx_command_t ngx_http_fastcgi_commands[] = {
{ ngx_string("fastcgi_pass"),
@@ -223,13 +189,6 @@ static ngx_command_t ngx_http_fastcgi_commands[] = {
0,
NULL },
- { ngx_string("fastcgi_root"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_str_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_fastcgi_loc_conf_t, root),
- NULL },
-
{ ngx_string("fastcgi_index"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
ngx_conf_set_str_slot,
@@ -265,6 +224,27 @@ static ngx_command_t ngx_http_fastcgi_commands[] = {
offsetof(ngx_http_fastcgi_loc_conf_t, upstream.header_buffer_size),
NULL },
+ { ngx_string("fastcgi_method"),
+ 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_fastcgi_loc_conf_t, upstream.method),
+ ngx_http_fastcgi_set_methods },
+
+ { ngx_string("fastcgi_pass_request_headers"),
+ 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.pass_request_headers),
+ NULL },
+
+ { ngx_string("fastcgi_pass_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_fastcgi_loc_conf_t, upstream.pass_request_body),
+ NULL },
+
{ ngx_string("fastcgi_redirect_errors"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
ngx_conf_set_flag_slot,
@@ -276,7 +256,7 @@ static ngx_command_t ngx_http_fastcgi_commands[] = {
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.x_powered_by),
+ offsetof(ngx_http_fastcgi_loc_conf_t, upstream.pass_x_powered_by),
NULL },
{ ngx_string("fastcgi_read_timeout"),
@@ -328,26 +308,20 @@ static ngx_command_t ngx_http_fastcgi_commands[] = {
offsetof(ngx_http_fastcgi_loc_conf_t, upstream.next_upstream),
&ngx_http_fastcgi_next_upstream_masks },
- { ngx_string("fastcgi_set_var"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_http_fastcgi_set_var,
+ { ngx_string("fastcgi_param"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE2,
+ ngx_conf_set_table_elt_slot,
NGX_HTTP_LOC_CONF_OFFSET,
- 0,
+ offsetof(ngx_http_fastcgi_loc_conf_t, params_source),
NULL },
- { ngx_string("fastcgi_params"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_ANY,
- ngx_conf_set_bitmask_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_fastcgi_loc_conf_t, params),
- &ngx_http_fastcgi_params_masks },
-
ngx_null_command
};
ngx_http_module_t ngx_http_fastcgi_module_ctx = {
- NULL, /* pre conf */
+ ngx_http_fastcgi_add_variables, /* preconfiguration */
+ NULL, /* postconfiguration */
NULL, /* create main configuration */
NULL, /* init main configuration */
@@ -361,7 +335,7 @@ ngx_http_module_t ngx_http_fastcgi_module_ctx = {
ngx_module_t ngx_http_fastcgi_module = {
- NGX_MODULE,
+ NGX_MODULE_V1,
&ngx_http_fastcgi_module_ctx, /* module context */
ngx_http_fastcgi_commands, /* module directives */
NGX_HTTP_MODULE, /* module type */
@@ -396,26 +370,15 @@ ngx_http_fastcgi_handler(ngx_http_request_t *r)
u->conf = &flcf->upstream;
- u->location0 = flcf->location;
-
u->create_request = ngx_http_fastcgi_create_request;
u->reinit_request = ngx_http_fastcgi_reinit_request;
u->process_header = ngx_http_fastcgi_process_header;
- u->send_header = ngx_http_fastcgi_send_header;
u->abort_request = ngx_http_fastcgi_abort_request;
u->finalize_request = ngx_http_fastcgi_finalize_request;
u->pipe.input_filter = ngx_http_fastcgi_input_filter;
u->pipe.input_ctx = r;
- u->log_ctx = r->connection->log->data;
- u->log_handler = ngx_http_upstream_log_error;
-
- u->schema0.len = sizeof("fastcgi://") - 1;
- u->schema0.data = (u_char *) "fastcgi://";
- u->uri0.len = sizeof("/") - 1;
- u->uri0.data = (u_char *) "/";
-
r->upstream = u;
rc = ngx_http_read_client_request_body(r, ngx_http_upstream_init);
@@ -431,206 +394,67 @@ ngx_http_fastcgi_handler(ngx_http_request_t *r)
static ngx_int_t
ngx_http_fastcgi_create_request(ngx_http_request_t *r)
{
- u_char ch, *pos, addr_text[INET_ADDRSTRLEN],
- port_text[sizeof("65535") - 1];
- size_t size, len, index, padding,
- addr_len, port_len;
- off_t file_pos;
- ngx_buf_t *b;
- socklen_t slen;
- ngx_chain_t *cl, *body;
- ngx_uint_t i, n, next, *vindex, port;
- ngx_list_part_t *part;
- ngx_table_elt_t *header;
- struct sockaddr_in sin, *sinp;
- ngx_http_variable_t *var;
- ngx_http_variable_value_t *value;
- ngx_http_core_loc_conf_t *clcf;
- ngx_http_core_main_conf_t *cmcf;
- ngx_http_fastcgi_header_t *h;
- ngx_http_fastcgi_loc_conf_t *flcf;
- ngx_http_fastcgi_begin_request_t *br;
+ off_t file_pos;
+ u_char ch, *pos;
+ size_t size, len, key_len, val_len, padding;
+ ngx_uint_t i, n, next;
+ ngx_buf_t *b;
+ ngx_chain_t *cl, *body;
+ ngx_list_part_t *part;
+ ngx_table_elt_t *header;
+ ngx_http_script_code_pt code;
+ ngx_http_script_engine_t e, le;
+ ngx_http_fastcgi_header_t *h;
+ ngx_http_fastcgi_loc_conf_t *flcf;
+ ngx_http_script_len_code_pt lcode;
+ len = 0;
flcf = ngx_http_get_module_loc_conf(r, ngx_http_fastcgi_module);
- if ((flcf->params & NGX_HTTP_FASTCGI_SERVER_ADDR) && r->in_addr == 0) {
-
- slen = sizeof(struct sockaddr_in);
- if (getsockname(r->connection->fd,
- (struct sockaddr *) &sin, &slen) == -1)
- {
- ngx_log_error(NGX_LOG_CRIT, r->connection->log,
- ngx_socket_errno, "getsockname() failed");
- return NGX_ERROR;
- }
-
- r->in_addr = sin.sin_addr.s_addr;
- }
-
- addr_len = ngx_inet_ntop(r->connection->listening->family, &r->in_addr,
- addr_text, INET_ADDRSTRLEN);
- if (addr_len == 0) {
- return NGX_ERROR;
- }
-
-#if (NGX_SUPPRESS_WARN)
- clcf = NULL;
- var = NULL;
- vindex = NULL;
-#endif
-
-
- if (r->upstream->method) {
- len = 1 + 1 + sizeof("REQUEST_METHOD") - 1
- + ngx_http_fastcgi_methods[r->upstream->method - 1].len;
-
- } else {
- len = 1 + ((r->method_name.len - 1 > 127) ? 4 : 1)
- + sizeof("REQUEST_METHOD") - 1
- + r->method_name.len - 1;
- }
-
-
- index = (r->uri.data[r->uri.len - 1] == '/') ? flcf->index.len : 0;
-
- len += 1 + ((flcf->root.len + r->uri.len + index > 127) ? 4 : 1)
- + sizeof("PATH_TRANSLATED") - 1 + flcf->root.len + r->uri.len + index;
-
- if (r->args.len) {
- len += 1 + ((r->args.len > 127) ? 4 : 1) + sizeof("QUERY_STRING") - 1
- + r->args.len;
- }
-
- if (r->headers_in.content_length_n > 0) {
- len += 1 + ((r->headers_in.content_length->value.len > 127) ? 4 : 1)
- + sizeof("CONTENT_LENGTH") - 1
- + r->headers_in.content_length->value.len;
- }
-
-
- if (r->headers_in.content_type) {
- len += 1 + ((r->headers_in.content_type->value.len > 127) ? 4 : 1)
- + sizeof("CONTENT_TYPE") - 1
- + r->headers_in.content_type->value.len;
- }
-
-
- if (flcf->params & NGX_HTTP_FASTCGI_REDIRECT_STATUS) {
- len += 1 + 1 + sizeof("REDIRECT_STATUS200") - 1;
- }
-
- if (flcf->params & NGX_HTTP_FASTCGI_REQUEST_URI) {
- len += 1 + ((r->unparsed_uri.len > 127) ? 4 : 1)
- + sizeof("REQUEST_URI") - 1 + r->unparsed_uri.len;
- }
-
- if (flcf->params & NGX_HTTP_FASTCGI_DOCUMENT_ROOT) {
- clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
- len += 1 + ((clcf->root.len > 127) ? 4 : 1)
- + sizeof("DOCUMENT_ROOT") - 1 + clcf->root.len;
- }
-
- if (flcf->params & NGX_HTTP_FASTCGI_SCRIPT_FILENAME) {
- len += 1 + ((flcf->root.len + r->uri.len + index > 127) ? 4 : 1)
- + sizeof("SCRIPT_FILENAME") - 1
- + flcf->root.len + r->uri.len + index;
- }
+ if (flcf->params_len) {
+ ngx_memzero(&le, sizeof(ngx_http_script_engine_t));
- if (flcf->params & NGX_HTTP_FASTCGI_SCRIPT_NAME) {
- len += 1 + ((r->uri.len + index > 127) ? 4 : 1)
- + sizeof("SCRIPT_NAME") - 1 + r->uri.len + index ;
- }
-
- if (flcf->params & NGX_HTTP_FASTCGI_REMOTE_ADDR) {
- len += 1 + 1 + sizeof("REMOTE_ADDR") - 1 + r->connection->addr_text.len;
- }
+ le.ip = flcf->params_len->elts;
+ le.request = r;
- port_len = 0;
+ while (*(uintptr_t *) le.ip) {
- if (flcf->params & NGX_HTTP_FASTCGI_REMOTE_PORT) {
+ lcode = *(ngx_http_script_len_code_pt *) le.ip;
+ key_len = lcode(&le);
- /* AF_INET only */
-
- if (r->connection->sockaddr->sa_family == AF_INET) {
- sinp = (struct sockaddr_in *) r->connection->sockaddr;
-
- port = ntohs(sinp->sin_port);
-
- if (port > 0 && port < 65536) {
- port_len = ngx_sprintf(port_text, "%ui", port) - port_text;
+ 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);
- len += 1 + 1 + sizeof("REMOTE_PORT") - 1 + port_len;
- }
- }
-
- if (flcf->params & NGX_HTTP_FASTCGI_SERVER_NAME) {
- len += 1 + 1 + sizeof("SERVER_NAME") - 1 + r->server_name.len;
- }
-
- if (flcf->params & NGX_HTTP_FASTCGI_SERVER_PORT) {
- len += 1 + 1 + sizeof("SERVER_PORT") - 1 + r->port_text->len - 1;
- }
-
- if (flcf->params & NGX_HTTP_FASTCGI_SERVER_ADDR) {
- len += 1 + 1 + sizeof("SERVER_ADDR") - 1 + addr_len;
- }
-
- if (flcf->params & NGX_HTTP_FASTCGI_SERVER_PROTOCOL
- && r->http_protocol.len)
- {
- len += 1 + ((r->http_protocol.len > 127) ? 4 : 1)
- + sizeof("SERVER_PROTOCOL") - 1 + r->http_protocol.len;
- }
-
- if (flcf->params & NGX_HTTP_FASTCGI_SERVER_SOFTWARE) {
- len += 1 + 1 + sizeof("SERVER_SOFTWARE") - 1 + sizeof(NGINX_VER) - 1;
- }
-
- if (flcf->params & NGX_HTTP_FASTCGI_GATEWAY_INTERFACE) {
- len += 1 + 1 + sizeof("GATEWAY_INTERFACE") - 1 + sizeof("CGI/1.1") - 1;
- }
-
-
- if (flcf->vars) {
- cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
-
- var = cmcf->variables.elts;
- vindex = flcf->vars->elts;
-
- for (i = 0; i < flcf->vars->nelts; i++) {
-
- value = ngx_http_get_indexed_variable(r, vindex[i]);
- if (value == NULL) {
- continue;
- }
-
- if (value->text.len) {
- len += 1 + 1 + var[vindex[i]].name.len + value->text.len;
+ if (val_len) {
+ len += 1 + key_len + ((val_len > 127) ? 4 : 1) + val_len;
}
}
}
+ if (flcf->upstream.pass_request_headers) {
- part = &r->headers_in.headers.part;
- header = part->elts;
+ part = &r->headers_in.headers.part;
+ header = part->elts;
- for (i = 0; /* void */; i++) {
+ for (i = 0; /* void */; i++) {
- if (i >= part->nelts) {
- if (part->next == NULL) {
- break;
+ if (i >= part->nelts) {
+ if (part->next == NULL) {
+ break;
+ }
+
+ part = part->next;
+ header = part->elts;
+ i = 0;
}
- part = part->next;
- header = part->elts;
- i = 0;
+ len += ((sizeof("HTTP_") - 1 + header[i].key.len > 127) ? 4 : 1)
+ + ((header[i].value.len > 127) ? 4 : 1)
+ + sizeof("HTTP_") - 1 + header[i].key.len + header[i].value.len;
}
-
- len += ((header[i].key.len > 127) ? 4 : 1)
- + ((header[i].value.len > 127) ? 4 : 1)
- + 5 + header[i].key.len + header[i].value.len;
}
@@ -667,36 +491,13 @@ ngx_http_fastcgi_create_request(ngx_http_request_t *r)
cl->buf = b;
- h = (ngx_http_fastcgi_header_t *) b->pos;
-
- h->version = 1;
- h->type = NGX_HTTP_FASTCGI_BEGIN_REQUEST;
- h->request_id_hi = 0;
- h->request_id_lo = 1;
- h->content_length_hi = 0;
- h->content_length_lo = sizeof(ngx_http_fastcgi_begin_request_t);
- h->padding_length = 0;
- h->reserved = 0;
-
- br = (ngx_http_fastcgi_begin_request_t *)
- (b->pos + sizeof(ngx_http_fastcgi_header_t));
- br->role_hi = 0;
- br->role_lo = NGX_HTTP_FASTCGI_RESPONDER;
- br->flags = 0; /* NGX_HTTP_FASTCGI_KEEP_CONN */
- br->reserved[0] = 0;
- br->reserved[1] = 0;
- br->reserved[2] = 0;
- br->reserved[3] = 0;
- br->reserved[4] = 0;
+ ngx_memcpy(b->pos, &ngx_http_fastcgi_request_start,
+ sizeof(ngx_http_fastcgi_request_start_t));
h = (ngx_http_fastcgi_header_t *)
(b->pos + sizeof(ngx_http_fastcgi_header_t)
+ sizeof(ngx_http_fastcgi_begin_request_t));
- h->version = 1;
- h->type = NGX_HTTP_FASTCGI_PARAMS;
- h->request_id_hi = 0;
- h->request_id_lo = 1;
h->content_length_hi = (u_char) ((len >> 8) & 0xff);
h->content_length_lo = (u_char) (len & 0xff);
h->padding_length = (u_char) padding;
@@ -707,376 +508,109 @@ ngx_http_fastcgi_create_request(ngx_http_request_t *r)
+ sizeof(ngx_http_fastcgi_header_t);
- *b->last++ = sizeof("PATH_TRANSLATED") - 1;
+ if (flcf->params_len) {
+ ngx_memzero(&e, sizeof(ngx_http_script_engine_t));
- len = flcf->root.len + r->uri.len + index;
- if (len > 127) {
- *b->last++ = (u_char) (((len >> 24) & 0x7f) | 0x80);
- *b->last++ = (u_char) ((len >> 16) & 0xff);
- *b->last++ = (u_char) ((len >> 8) & 0xff);
- *b->last++ = (u_char) (len & 0xff);
+ e.ip = flcf->params->elts;
+ e.pos = b->last;
+ e.request = r;
- } else {
- *b->last++ = (u_char) len;
- }
-
- b->last = ngx_cpymem(b->last, "PATH_TRANSLATED",
- sizeof("PATH_TRANSLATED") - 1);
- b->last = ngx_cpymem(b->last, flcf->root.data, flcf->root.len);
- b->last = ngx_cpymem(b->last, r->uri.data, r->uri.len);
-
- if (index) {
- b->last = ngx_cpymem(b->last, flcf->index.data, index);
- }
+ le.ip = flcf->params_len->elts;
+ while (*(uintptr_t *) le.ip) {
- *b->last++ = sizeof("REQUEST_METHOD") - 1;
-
- if (r->upstream->method) {
- *b->last++ = (u_char)
- ngx_http_fastcgi_methods[r->upstream->method - 1].len;
-
- b->last = ngx_cpymem(b->last, "REQUEST_METHOD",
- sizeof("REQUEST_METHOD") - 1);
-
- b->last = ngx_cpymem(b->last,
- ngx_http_fastcgi_methods[r->upstream->method - 1].data,
- ngx_http_fastcgi_methods[r->upstream->method - 1].len);
-
- } else {
- len = r->method_name.len - 1;
- if (len > 127) {
- *b->last++ = (u_char) (((len >> 24) & 0x7f) | 0x80);
- *b->last++ = (u_char) ((len >> 16) & 0xff);
- *b->last++ = (u_char) ((len >> 8) & 0xff);
- *b->last++ = (u_char) (len & 0xff);
-
- } else {
- *b->last++ = (u_char) len;
- }
-
- b->last = ngx_cpymem(b->last, "REQUEST_METHOD",
- sizeof("REQUEST_METHOD") - 1);
- b->last = ngx_cpymem(b->last, r->method_name.data, len);
- }
-
-
- if (r->args.len) {
- *b->last++ = sizeof("QUERY_STRING") - 1;
-
- len = r->args.len;
- if (len > 127) {
- *b->last++ = (u_char) (((len >> 24) & 0x7f) | 0x80);
- *b->last++ = (u_char) ((len >> 16) & 0xff);
- *b->last++ = (u_char) ((len >> 8) & 0xff);
- *b->last++ = (u_char) (len & 0xff);
-
- } else {
- *b->last++ = (u_char) len;
- }
-
- b->last = ngx_cpymem(b->last, "QUERY_STRING",
- sizeof("QUERY_STRING") - 1);
- b->last = ngx_cpymem(b->last, r->args.data, len);
- }
-
-
- if (r->headers_in.content_length_n > 0) {
- *b->last++ = sizeof("CONTENT_LENGTH") - 1;
-
- len = r->headers_in.content_length->value.len;
- if (len > 127) {
- *b->last++ = (u_char) (((len >> 24) & 0x7f) | 0x80);
- *b->last++ = (u_char) ((len >> 16) & 0xff);
- *b->last++ = (u_char) ((len >> 8) & 0xff);
- *b->last++ = (u_char) (len & 0xff);
-
- } else {
- *b->last++ = (u_char) len;
- }
-
- b->last = ngx_cpymem(b->last, "CONTENT_LENGTH",
- sizeof("CONTENT_LENGTH") - 1);
- b->last = ngx_cpymem(b->last, r->headers_in.content_length->value.data,
- len);
- }
-
-
- if (r->headers_in.content_type) {
- *b->last++ = sizeof("CONTENT_TYPE") - 1;
-
- len = r->headers_in.content_type->value.len;
- if (len > 127) {
- *b->last++ = (u_char) (((len >> 24) & 0x7f) | 0x80);
- *b->last++ = (u_char) ((len >> 16) & 0xff);
- *b->last++ = (u_char) ((len >> 8) & 0xff);
- *b->last++ = (u_char) (len & 0xff);
-
- } else {
- *b->last++ = (u_char) len;
- }
-
- b->last = ngx_cpymem(b->last, "CONTENT_TYPE",
- sizeof("CONTENT_TYPE") - 1);
- b->last = ngx_cpymem(b->last, r->headers_in.content_type->value.data,
- len);
- }
-
-
- if (flcf->params & NGX_HTTP_FASTCGI_REDIRECT_STATUS) {
- *b->last++ = sizeof("REDIRECT_STATUS") - 1;
- *b->last++ = sizeof("200") - 1;
- b->last = ngx_cpymem(b->last, "REDIRECT_STATUS200",
- sizeof("REDIRECT_STATUS200") - 1);
- }
-
-
- if (flcf->params & NGX_HTTP_FASTCGI_REQUEST_URI) {
- *b->last++ = sizeof("REQUEST_URI") - 1;
-
- len = r->unparsed_uri.len;
- if (len > 127) {
- *b->last++ = (u_char) (((len >> 24) & 0x7f) | 0x80);
- *b->last++ = (u_char) ((len >> 16) & 0xff);
- *b->last++ = (u_char) ((len >> 8) & 0xff);
- *b->last++ = (u_char) (len & 0xff);
-
- } else {
- *b->last++ = (u_char) len;
- }
-
- b->last = ngx_cpymem(b->last, "REQUEST_URI", sizeof("REQUEST_URI") - 1);
- b->last = ngx_cpymem(b->last, r->unparsed_uri.data, len);
- }
-
-
- if (flcf->params & NGX_HTTP_FASTCGI_DOCUMENT_ROOT) {
- *b->last++ = sizeof("DOCUMENT_ROOT") - 1;
-
- len = clcf->root.len;
- if (len > 127) {
- *b->last++ = (u_char) (((len >> 24) & 0x7f) | 0x80);
- *b->last++ = (u_char) ((len >> 16) & 0xff);
- *b->last++ = (u_char) ((len >> 8) & 0xff);
- *b->last++ = (u_char) (len & 0xff);
-
- } else {
- *b->last++ = (u_char) len;
- }
-
- b->last = ngx_cpymem(b->last, "DOCUMENT_ROOT",
- sizeof("DOCUMENT_ROOT") - 1);
- b->last = ngx_cpymem(b->last, clcf->root.data, len);
- }
-
-
- if (flcf->params & NGX_HTTP_FASTCGI_SCRIPT_FILENAME) {
- *b->last++ = sizeof("SCRIPT_FILENAME") - 1;
-
- len = flcf->root.len + r->uri.len + index;
- if (len > 127) {
- *b->last++ = (u_char) (((len >> 24) & 0x7f) | 0x80);
- *b->last++ = (u_char) ((len >> 16) & 0xff);
- *b->last++ = (u_char) ((len >> 8) & 0xff);
- *b->last++ = (u_char) (len & 0xff);
-
- } else {
- *b->last++ = (u_char) len;
- }
-
- b->last = ngx_cpymem(b->last, "SCRIPT_FILENAME",
- sizeof("SCRIPT_FILENAME") - 1);
- b->last = ngx_cpymem(b->last, flcf->root.data, flcf->root.len);
- b->last = ngx_cpymem(b->last, r->uri.data, r->uri.len);
-
- if (index) {
- b->last = ngx_cpymem(b->last, flcf->index.data, index);
- }
- }
-
-
- if (flcf->params & NGX_HTTP_FASTCGI_SCRIPT_NAME) {
- *b->last++ = sizeof("SCRIPT_NAME") - 1;
-
- len = r->uri.len + index;
- if (len > 127) {
- *b->last++ = (u_char) (((len >> 24) & 0x7f) | 0x80);
- *b->last++ = (u_char) ((len >> 16) & 0xff);
- *b->last++ = (u_char) ((len >> 8) & 0xff);
- *b->last++ = (u_char) (len & 0xff);
-
- } else {
- *b->last++ = (u_char) len;
- }
-
- b->last = ngx_cpymem(b->last, "SCRIPT_NAME", sizeof("SCRIPT_NAME") - 1);
- b->last = ngx_cpymem(b->last, r->uri.data, r->uri.len);
-
- if (index) {
- b->last = ngx_cpymem(b->last, flcf->index.data, index);
- }
- }
-
-
- if (flcf->params & NGX_HTTP_FASTCGI_REMOTE_ADDR) {
- *b->last++ = sizeof("REMOTE_ADDR") - 1;
- *b->last++ = (u_char) (r->connection->addr_text.len);
- b->last = ngx_cpymem(b->last, "REMOTE_ADDR", sizeof("REMOTE_ADDR") - 1);
- b->last = ngx_cpymem(b->last, r->connection->addr_text.data,
- r->connection->addr_text.len);
- }
-
-
- if (port_len) {
- *b->last++ = sizeof("REMOTE_PORT") - 1;
- *b->last++ = (u_char) port_len;
- b->last = ngx_cpymem(b->last, "REMOTE_PORT", sizeof("REMOTE_PORT") - 1);
- b->last = ngx_cpymem(b->last, port_text, port_len);
- }
-
-
- if (flcf->params & NGX_HTTP_FASTCGI_SERVER_NAME) {
- *b->last++ = sizeof("SERVER_NAME") - 1;
- *b->last++ = (u_char) r->server_name.len;
- b->last = ngx_cpymem(b->last, "SERVER_NAME", sizeof("SERVER_NAME") - 1);
- b->last = ngx_cpymem(b->last, r->server_name.data, r->server_name.len);
- }
-
-
- if (flcf->params & NGX_HTTP_FASTCGI_SERVER_PORT) {
- *b->last++ = sizeof("SERVER_PORT") - 1;
- *b->last++ = (u_char) (r->port_text->len - 1);
- b->last = ngx_cpymem(b->last, "SERVER_PORT", sizeof("SERVER_PORT") - 1);
- b->last = ngx_cpymem(b->last, r->port_text->data + 1,
- r->port_text->len - 1);
- }
+ lcode = *(ngx_http_script_len_code_pt *) le.ip;
+ key_len = (u_char) 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);
- if (flcf->params & NGX_HTTP_FASTCGI_SERVER_ADDR) {
- *b->last++ = sizeof("SERVER_ADDR") - 1;
- *b->last++ = (u_char) addr_len;
- b->last = ngx_cpymem(b->last, "SERVER_ADDR", sizeof("SERVER_ADDR") - 1);
- b->last = ngx_cpymem(b->last, addr_text, addr_len);
- }
+ if (val_len) {
+ *e.pos++ = (u_char) key_len;
+ if (val_len > 127) {
+ *e.pos++ = (u_char) (((val_len >> 24) & 0x7f) | 0x80);
+ *e.pos++ = (u_char) ((val_len >> 16) & 0xff);
+ *e.pos++ = (u_char) ((val_len >> 8) & 0xff);
+ *e.pos++ = (u_char) (val_len & 0xff);
- if (flcf->params & NGX_HTTP_FASTCGI_SERVER_PROTOCOL
- && r->http_protocol.len)
- {
- *b->last++ = sizeof("SERVER_PROTOCOL") - 1;
+ } else {
+ *e.pos++ = (u_char) val_len;
+ }
+ }
- len = r->http_protocol.len;
- if (len > 127) {
- *b->last++ = (u_char) (((len >> 24) & 0x7f) | 0x80);
- *b->last++ = (u_char) ((len >> 16) & 0xff);
- *b->last++ = (u_char) ((len >> 8) & 0xff);
- *b->last++ = (u_char) (len & 0xff);
+ e.skip = val_len ? 0 : 1;
- } else {
- *b->last++ = (u_char) len;
+ 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);
}
- b->last = ngx_cpymem(b->last, "SERVER_PROTOCOL",
- sizeof("SERVER_PROTOCOL") - 1);
- b->last = ngx_cpymem(b->last, r->http_protocol.data, len);
+ b->last = e.pos;
}
- if (flcf->params & NGX_HTTP_FASTCGI_SERVER_SOFTWARE) {
- *b->last++ = sizeof("SERVER_SOFTWARE") - 1;
- *b->last++ = (u_char) (sizeof(NGINX_VER) - 1);
- b->last = ngx_cpymem(b->last, "SERVER_SOFTWARE",
- sizeof("SERVER_SOFTWARE") - 1);
- b->last = ngx_cpymem(b->last, NGINX_VER, sizeof(NGINX_VER) - 1);
- }
-
+ if (flcf->upstream.pass_request_headers) {
- if (flcf->params & NGX_HTTP_FASTCGI_GATEWAY_INTERFACE) {
- *b->last++ = sizeof("GATEWAY_INTERFACE") - 1;
- *b->last++ = (u_char) (sizeof("CGI/1.1") - 1);
- b->last = ngx_cpymem(b->last, "GATEWAY_INTERFACE",
- sizeof("GATEWAY_INTERFACE") - 1);
- b->last = ngx_cpymem(b->last, "CGI/1.1", sizeof("CGI/1.1") - 1);
- }
+ part = &r->headers_in.headers.part;
+ header = part->elts;
+ for (i = 0; /* void */; i++) {
- if (flcf->vars) {
- for (i = 0; i < flcf->vars->nelts; i++) {
-
- value = ngx_http_get_indexed_variable(r, vindex[i]);
- if (value == NULL) {
- continue;
+ if (i >= part->nelts) {
+ if (part->next == NULL) {
+ break;
+ }
+
+ part = part->next;
+ header = part->elts;
+ i = 0;
}
- if (value->text.len == 0) {
- continue;
+ len = sizeof("HTTP_") - 1 + header[i].key.len;
+ if (len > 127) {
+ *b->last++ = (u_char) (((len >> 24) & 0x7f) | 0x80);
+ *b->last++ = (u_char) ((len >> 16) & 0xff);
+ *b->last++ = (u_char) ((len >> 8) & 0xff);
+ *b->last++ = (u_char) (len & 0xff);
+
+ } else {
+ *b->last++ = (u_char) len;
}
- *b->last++ = (u_char) var[vindex[i]].name.len;
- *b->last++ = (u_char) value->text.len;
-
- b->last = ngx_cpymem(b->last, var[vindex[i]].name.data,
- var[vindex[i]].name.len);
-
- b->last = ngx_cpymem(b->last, value->text.data, value->text.len);
- }
- }
-
-
- part = &r->headers_in.headers.part;
- header = part->elts;
+ len = header[i].value.len;
+ if (len > 127) {
+ *b->last++ = (u_char) (((len >> 24) & 0x7f) | 0x80);
+ *b->last++ = (u_char) ((len >> 16) & 0xff);
+ *b->last++ = (u_char) ((len >> 8) & 0xff);
+ *b->last++ = (u_char) (len & 0xff);
- for (i = 0; /* void */; i++) {
-
- if (i >= part->nelts) {
- if (part->next == NULL) {
- break;
+ } else {
+ *b->last++ = (u_char) len;
}
- part = part->next;
- header = part->elts;
- i = 0;
- }
-
- len = 5 + header[i].key.len;
- if (len > 127) {
- *b->last++ = (u_char) (((len >> 24) & 0x7f) | 0x80);
- *b->last++ = (u_char) ((len >> 16) & 0xff);
- *b->last++ = (u_char) ((len >> 8) & 0xff);
- *b->last++ = (u_char) (len & 0xff);
-
- } else {
- *b->last++ = (u_char) len;
- }
-
- len = header[i].value.len;
- if (len > 127) {
- *b->last++ = (u_char) (((len >> 24) & 0x7f) | 0x80);
- *b->last++ = (u_char) ((len >> 16) & 0xff);
- *b->last++ = (u_char) ((len >> 8) & 0xff);
- *b->last++ = (u_char) (len & 0xff);
-
- } else {
- *b->last++ = (u_char) len;
- }
+ b->last = ngx_cpymem(b->last, "HTTP_", sizeof("HTTP_") - 1);
- b->last = ngx_cpymem(b->last, "HTTP_", sizeof("HTTP_") - 1);
+ for (n = 0; n < header[i].key.len; n++) {
+ ch = header[i].key.data[n];
- for (n = 0; n < header[i].key.len; n++) {
- ch = header[i].key.data[n];
+ if (ch >= 'a' && ch <= 'z') {
+ ch &= ~0x20;
- if (ch >= 'a' && ch <= 'z') {
- ch &= ~0x20;
+ } else if (ch == '-') {
+ ch = '_';
+ }
- } else if (ch == '-') {
- ch = '_';
+ *b->last++ = ch;
}
- *b->last++ = ch;
+ b->last = ngx_cpymem(b->last, header[i].value.data,
+ header[i].value.len);
}
-
- b->last = ngx_cpymem(b->last, header[i].value.data,
- header[i].value.len);
}
@@ -1101,103 +635,109 @@ ngx_http_fastcgi_create_request(ngx_http_request_t *r)
h = (ngx_http_fastcgi_header_t *) b->last;
b->last += sizeof(ngx_http_fastcgi_header_t);
- body = r->request_body->bufs;
- r->request_body->bufs = cl;
+ if (flcf->upstream.pass_request_body) {
+ body = r->upstream->request_bufs;
+ r->upstream->request_bufs = cl;
#if (NGX_SUPPRESS_WARN)
- file_pos = 0;
- pos = NULL;
+ file_pos = 0;
+ pos = NULL;
#endif
- while (body) {
+ while (body) {
- if (body->buf->in_file) {
- file_pos = body->buf->file_pos;
-
- } else {
- pos = body->buf->pos;
- }
-
- next = 0;
+ if (body->buf->in_file) {
+ file_pos = body->buf->file_pos;
- do {
- b = ngx_alloc_buf(r->pool);
- if (b == NULL) {
- return NGX_ERROR;
+ } else {
+ pos = body->buf->pos;
}
- ngx_memcpy(b, body->buf, sizeof(ngx_buf_t));
+ next = 0;
- if (body->buf->in_file) {
- b->file_pos = file_pos;
- file_pos += 32 * 1024;
-
- if (file_pos > body->buf->file_last) {
- file_pos = body->buf->file_last;
- next = 1;
+ do {
+ b = ngx_alloc_buf(r->pool);
+ if (b == NULL) {
+ return NGX_ERROR;
}
- b->file_last = file_pos;
- len = (ngx_uint_t) (file_pos - b->file_pos);
+ ngx_memcpy(b, body->buf, sizeof(ngx_buf_t));
- } else {
- b->pos = pos;
- pos += 32 * 1024;
+ if (body->buf->in_file) {
+ b->file_pos = file_pos;
+ file_pos += 32 * 1024;
- if (pos > body->buf->last) {
- pos = body->buf->last;
- next = 1;
- }
+ if (file_pos > body->buf->file_last) {
+ file_pos = body->buf->file_last;
+ next = 1;
+ }
- b->last = pos;
- len = (ngx_uint_t) (pos - b->pos);
- }
+ b->file_last = file_pos;
+ len = (ngx_uint_t) (file_pos - b->file_pos);
- padding = 8 - len % 8;
- padding = (padding == 8) ? 0 : padding;
+ } else {
+ b->pos = pos;
+ pos += 32 * 1024;
- h->version = 1;
- h->type = NGX_HTTP_FASTCGI_STDIN;
- h->request_id_hi = 0;
- h->request_id_lo = 1;
- h->content_length_hi = (u_char) ((len >> 8) & 0xff);
- h->content_length_lo = (u_char) (len & 0xff);
- h->padding_length = (u_char) padding;
- h->reserved = 0;
+ if (pos > body->buf->last) {
+ pos = body->buf->last;
+ next = 1;
+ }
- cl->next = ngx_alloc_chain_link(r->pool);
- if (cl->next == NULL) {
- return NGX_ERROR;
- }
+ b->last = pos;
+ len = (ngx_uint_t) (pos - b->pos);
+ }
- cl = cl->next;
- cl->buf = b;
+ padding = 8 - len % 8;
+ padding = (padding == 8) ? 0 : padding;
+
+ h->version = 1;
+ h->type = NGX_HTTP_FASTCGI_STDIN;
+ h->request_id_hi = 0;
+ h->request_id_lo = 1;
+ h->content_length_hi = (u_char) ((len >> 8) & 0xff);
+ h->content_length_lo = (u_char) (len & 0xff);
+ h->padding_length = (u_char) padding;
+ h->reserved = 0;
+
+ cl->next = ngx_alloc_chain_link(r->pool);
+ if (cl->next == NULL) {
+ return NGX_ERROR;
+ }
- b = ngx_create_temp_buf(r->pool, sizeof(ngx_http_fastcgi_header_t)
- + padding);
- if (b == NULL) {
- return NGX_ERROR;
- }
+ cl = cl->next;
+ cl->buf = b;
- if (padding) {
- ngx_memzero(b->last, padding);
- b->last += padding;
- }
+ b = ngx_create_temp_buf(r->pool,
+ sizeof(ngx_http_fastcgi_header_t)
+ + padding);
+ if (b == NULL) {
+ return NGX_ERROR;
+ }
- h = (ngx_http_fastcgi_header_t *) b->last;
- b->last += sizeof(ngx_http_fastcgi_header_t);
+ if (padding) {
+ ngx_memzero(b->last, padding);
+ b->last += padding;
+ }
- cl->next = ngx_alloc_chain_link(r->pool);
- if (cl->next == NULL) {
- return NGX_ERROR;
- }
+ h = (ngx_http_fastcgi_header_t *) b->last;
+ b->last += sizeof(ngx_http_fastcgi_header_t);
+
+ cl->next = ngx_alloc_chain_link(r->pool);
+ if (cl->next == NULL) {
+ return NGX_ERROR;
+ }
- cl = cl->next;
- cl->buf = b;
+ cl = cl->next;
+ cl->buf = b;
- } while (!next);
+ } while (!next);
- body = body->next;
+ body = body->next;
+ }
+
+ } else {
+ r->upstream->request_bufs = cl;
}
h->version = 1;
@@ -1229,17 +769,6 @@ ngx_http_fastcgi_reinit_request(ngx_http_request_t *r)
f->state = ngx_http_fastcgi_st_version;
f->header = 0;
- ngx_memzero(&f->upstream->headers_in,
- sizeof(ngx_http_fastcgi_headers_in_t));
-
- if (f->upstream->headers_in.headers.part.elts) {
- if (ngx_list_init(&f->upstream->headers_in.headers, r->pool, 8,
- sizeof(ngx_table_elt_t)) == NGX_ERROR)
- {
- return NGX_ERROR;
- }
- }
-
return NGX_OK;
}
@@ -1247,16 +776,21 @@ ngx_http_fastcgi_reinit_request(ngx_http_request_t *r)
static ngx_int_t
ngx_http_fastcgi_process_header(ngx_http_request_t *r)
{
- u_char *start, *last;
- ngx_str_t *status_line, line;
- ngx_int_t rc, status;
- ngx_uint_t i;
- ngx_table_elt_t *h;
- ngx_http_upstream_t *u;
- ngx_http_fastcgi_ctx_t *f;
+ u_char *start, *last;
+ ngx_str_t *status_line, line;
+ ngx_int_t rc, status;
+ ngx_uint_t key;
+ ngx_table_elt_t *h;
+ ngx_http_upstream_t *u;
+ ngx_http_fastcgi_ctx_t *f;
+ ngx_http_upstream_header_t *hh;
+ ngx_http_upstream_main_conf_t *umcf;
f = ngx_http_get_module_ctx(r, ngx_http_fastcgi_module);
+ umcf = ngx_http_get_module_main_conf(r, ngx_http_upstream_module);
+ hh = (ngx_http_upstream_header_t *) umcf->headers_in_hash.buckets;
+
if (f == NULL) {
f = ngx_pcalloc(r->pool, sizeof(ngx_http_fastcgi_ctx_t));
if (f == NULL) {
@@ -1264,17 +798,6 @@ ngx_http_fastcgi_process_header(ngx_http_request_t *r)
}
ngx_http_set_ctx(r, f, ngx_http_fastcgi_module);
-
- f->upstream = ngx_pcalloc(r->pool, sizeof(ngx_http_fastcgi_upstream_t));
- if (f->upstream == NULL) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- if (ngx_list_init(&f->upstream->headers_in.headers, r->pool, 8,
- sizeof(ngx_table_elt_t)) == NGX_ERROR)
- {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
}
u = r->upstream;
@@ -1424,11 +947,13 @@ ngx_http_fastcgi_process_header(ngx_http_request_t *r)
/* a header line has been parsed successfully */
- h = ngx_list_push(&f->upstream->headers_in.headers);
+ h = ngx_list_push(&u->headers_in.headers);
if (h == NULL) {
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
+ h->hash = r->header_hash;
+
h->key.len = r->header_name_end - r->header_name_start;
h->value.len = r->header_end - r->header_start;
@@ -1443,18 +968,13 @@ ngx_http_fastcgi_process_header(ngx_http_request_t *r)
ngx_cpystrn(h->key.data, r->header_name_start, h->key.len + 1);
ngx_cpystrn(h->value.data, r->header_start, h->value.len + 1);
- for (i = 0; ngx_http_fastcgi_headers_in[i].name.len != 0; i++) {
- if (ngx_http_fastcgi_headers_in[i].name.len != h->key.len) {
- continue;
- }
+ key = h->hash % umcf->headers_in_hash.hash_size;
- if (ngx_strcasecmp(ngx_http_fastcgi_headers_in[i].name.data,
- h->key.data) == 0)
- {
- *((ngx_table_elt_t **)
- ((char *) &f->upstream->headers_in
- + ngx_http_fastcgi_headers_in[i].offset)) = h;
- break;
+ if (hh[key].name.len == h->key.len
+ && ngx_strcasecmp(hh[key].name.data, h->key.data) == 0)
+ {
+ if (hh[key].handler(r, h, hh[key].offset) != NGX_OK) {
+ return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
}
@@ -1472,8 +992,8 @@ ngx_http_fastcgi_process_header(ngx_http_request_t *r)
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"http fastcgi header done");
- if (f->upstream->headers_in.status) {
- status_line = &f->upstream->headers_in.status->value;
+ if (u->headers_in.status) {
+ status_line = &u->headers_in.status->value;
status = ngx_atoi(status_line->data, 3);
@@ -1541,84 +1061,6 @@ ngx_http_fastcgi_process_header(ngx_http_request_t *r)
static ngx_int_t
-ngx_http_fastcgi_send_header(ngx_http_request_t *r)
-{
- ngx_uint_t i;
- ngx_list_part_t *part;
- ngx_table_elt_t *ho, *h;
- ngx_http_fastcgi_ctx_t *f;
- ngx_http_fastcgi_headers_in_t *headers_in;
-
- f = ngx_http_get_module_ctx(r, ngx_http_fastcgi_module);
-
- headers_in = &f->upstream->headers_in;
- part = &headers_in->headers.part;
- h = part->elts;
-
- for (i = 0; /* void */; i++) {
-
- if (i >= part->nelts) {
- if (part->next == NULL) {
- break;
- }
-
- part = part->next;
- h = part->elts;
- i = 0;
- }
-
- /* ignore some headers */
-
- if (&h[i] == headers_in->status) {
- continue;
- }
-
-
- if (&h[i] == headers_in->x_powered_by
- && !r->upstream->conf->x_powered_by)
- {
- continue;
- }
-
-
- /* "Content-Type" is handled specially */
-
- if (&h[i] == headers_in->content_type) {
- r->headers_out.content_type = &h[i];
- r->headers_out.content_type->key.len = 0;
- continue;
- }
-
-
- /* copy some header pointers and set up r->headers_out */
-
- ho = ngx_list_push(&r->headers_out.headers);
- if (ho == NULL) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- *ho = h[i];
-
-#if (NGX_HTTP_GZIP)
- if (&h[i] == headers_in->content_encoding) {
- r->headers_out.content_encoding = ho;
- continue;
- }
-#endif
-
- if (&h[i] == headers_in->content_length) {
- r->headers_out.content_length = ho;
- r->headers_out.content_length_n = ngx_atoi(ho->value.data,
- ho->value.len);
- continue;
- }
- }
-
- return ngx_http_send_header(r);
-}
-
-
-static ngx_int_t
ngx_http_fastcgi_input_filter(ngx_event_pipe_t *p, ngx_buf_t *buf)
{
ngx_int_t rc;
@@ -1937,7 +1379,6 @@ ngx_http_fastcgi_process_record(ngx_http_request_t *r,
}
}
- f->pos = p + 1;
f->state = state;
return NGX_AGAIN;
@@ -1964,140 +1405,19 @@ ngx_http_fastcgi_finalize_request(ngx_http_request_t *r, ngx_int_t rc)
}
-static char *
-ngx_http_fastcgi_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
-{
- ngx_http_fastcgi_loc_conf_t *lcf = conf;
-
- ngx_str_t *value;
- ngx_inet_upstream_t inet_upstream;
- ngx_http_core_loc_conf_t *clcf;
-#if (NGX_HAVE_UNIX_DOMAIN)
- ngx_unix_domain_upstream_t unix_upstream;
-#endif
-
- value = cf->args->elts;
-
- if (ngx_strncasecmp(value[1].data, "unix:", 5) == 0) {
-
-#if (NGX_HAVE_UNIX_DOMAIN)
-
- ngx_memzero(&unix_upstream, sizeof(ngx_unix_domain_upstream_t));
-
- unix_upstream.name = value[1];
- unix_upstream.url = value[1];
-
- lcf->peers = ngx_unix_upstream_parse(cf, &unix_upstream);
- if (lcf->peers == NULL) {
- return NGX_CONF_ERROR;
- }
-
-#else
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "the unix domain sockets are not supported "
- "on this platform");
- return NGX_CONF_ERROR;
-
-#endif
-
- } else {
- ngx_memzero(&inet_upstream, sizeof(ngx_inet_upstream_t));
-
- inet_upstream.name = value[1];
- inet_upstream.url = value[1];
-
- lcf->peers = ngx_inet_upstream_parse(cf, &inet_upstream);
- if (lcf->peers == NULL) {
- return NGX_CONF_ERROR;
- }
- }
-
- clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
-
- clcf->handler = ngx_http_fastcgi_handler;
-
-#if (NGX_PCRE)
- lcf->location = clcf->regex ? &ngx_http_fastcgi_uri : &clcf->name;
-#else
- lcf->location = &clcf->name;
-#endif
-
- if (clcf->name.data[clcf->name.len - 1] == '/') {
- clcf->auto_redirect = 1;
- }
-
- return NGX_CONF_OK;
-}
-
-
-static char *
-ngx_http_fastcgi_set_var(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
-{
- ngx_http_fastcgi_loc_conf_t *lcf = conf;
-
- ngx_uint_t i, *index;
- ngx_str_t *value;
- ngx_http_variable_t *var;
- ngx_http_core_main_conf_t *cmcf;
-
- if (lcf->vars == NULL) {
- lcf->vars = ngx_array_create(cf->pool, 4,
- sizeof(ngx_http_variable_t *));
- if (lcf->vars == NULL) {
- return NGX_CONF_ERROR;
- }
- }
-
- cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
-
- value = cf->args->elts;
-
- var = cmcf->variables.elts;
- for (i = 0; i < cmcf->variables.nelts; i++) {
- if (ngx_strcasecmp(var[i].name.data, value[1].data) == 0) {
-
- index = ngx_array_push(lcf->vars);
- if (index == NULL) {
- return NGX_CONF_ERROR;
- }
-
- *index = var[i].index;
- return NGX_CONF_OK;
- }
- }
-
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "unknown variable name \"%V\"", &value[1]);
- return NGX_CONF_ERROR;
-}
-
-
-static char *
-ngx_http_fastcgi_lowat_check(ngx_conf_t *cf, void *post, void *data)
+static ngx_int_t
+ngx_http_fastcgi_add_variables(ngx_conf_t *cf)
{
-#if (NGX_FREEBSD)
- ssize_t *np = data;
+ ngx_http_variable_t *var;
- if (*np >= ngx_freebsd_net_inet_tcp_sendspace) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "\"fastcgi_send_lowat\" must be less than %d "
- "(sysctl net.inet.tcp.sendspace)",
- ngx_freebsd_net_inet_tcp_sendspace);
-
- return NGX_CONF_ERROR;
+ var = ngx_http_add_variable(cf, &ngx_http_fastcgi_script_name, 0);
+ if (var == NULL) {
+ return NGX_ERROR;
}
-#elif !(NGX_HAVE_SO_SNDLOWAT)
- ssize_t *np = data;
-
- ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
- "\"fastcgi_send_lowat\" is not supported, ignored");
+ var->handler = ngx_http_fastcgi_script_name_variable;
- *np = 0;
-
-#endif
-
- return NGX_CONF_OK;
+ return NGX_OK;
}
@@ -2118,12 +1438,12 @@ ngx_http_fastcgi_create_loc_conf(ngx_conf_t *cf)
* conf->upstream.path = NULL;
* conf->upstream.next_upstream = 0;
* conf->upstream.temp_path = NULL;
- * conf->params = 0;
- * conf->root.len = 0;
- * conf->root.data = NULL;
+ * conf->upstream.schema = { 0, NULL };
+ * conf->upstream.uri = { 0, NULL };
+ * conf->upstream.location = NULL;
+ *
* conf->index.len = 0;
* conf->index.data = NULL;
- * conf->location = NULL;
*/
conf->upstream.connect_timeout = NGX_CONF_UNSET_MSEC;
@@ -2135,14 +1455,23 @@ ngx_http_fastcgi_create_loc_conf(ngx_conf_t *cf)
conf->upstream.busy_buffers_size = NGX_CONF_UNSET_SIZE;
conf->upstream.max_temp_file_size = NGX_CONF_UNSET_SIZE;
conf->upstream.temp_file_write_size = NGX_CONF_UNSET_SIZE;
-
- conf->upstream.redirect_errors = NGX_CONF_UNSET;
+
conf->upstream.pass_unparsed_uri = NGX_CONF_UNSET;
- conf->upstream.x_powered_by = NGX_CONF_UNSET;
+ conf->upstream.method = NGX_CONF_UNSET_UINT;
+ conf->upstream.pass_request_headers = NGX_CONF_UNSET;
+ conf->upstream.pass_request_body = NGX_CONF_UNSET;
+
+ conf->upstream.redirect_errors = NGX_CONF_UNSET;
/* "fastcgi_cyclic_temp_file" is disabled */
conf->upstream.cyclic_temp_file = 0;
+ conf->upstream.pass_x_powered_by = NGX_CONF_UNSET;
+
+ /* the hardcoded values */
+ conf->upstream.pass_server = 1;
+ conf->upstream.pass_date = 1;
+
return conf;
}
@@ -2153,7 +1482,13 @@ ngx_http_fastcgi_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
ngx_http_fastcgi_loc_conf_t *prev = parent;
ngx_http_fastcgi_loc_conf_t *conf = child;
- size_t size;
+ u_char *p;
+ size_t size;
+ uintptr_t *code;
+ ngx_uint_t i;
+ ngx_table_elt_t *src;
+ ngx_http_script_compile_t sc;
+ ngx_http_script_copy_code_t *copy;
ngx_conf_merge_msec_value(conf->upstream.connect_timeout,
prev->upstream.connect_timeout, 60000);
@@ -2263,51 +1598,300 @@ ngx_http_fastcgi_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
NGX_HTTP_FASTCGI_TEMP_PATH, 1, 2, 0,
ngx_garbage_collector_temp_handler, cf);
-
- ngx_conf_merge_msec_value(conf->upstream.redirect_errors,
- prev->upstream.redirect_errors, 0);
-
ngx_conf_merge_msec_value(conf->upstream.pass_unparsed_uri,
prev->upstream.pass_unparsed_uri, 0);
- if (conf->upstream.pass_unparsed_uri && conf->location->len > 1) {
+ if (conf->upstream.pass_unparsed_uri && conf->upstream.location->len > 1) {
ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
"\"fastcgi_pass_unparsed_uri\" can be set for "
"location \"/\" or given by regular expression.");
return NGX_CONF_ERROR;
}
- ngx_conf_merge_msec_value(conf->upstream.x_powered_by,
- prev->upstream.x_powered_by, 1);
+ if (conf->upstream.method == NGX_CONF_UNSET_UINT) {
+ conf->upstream.method = prev->upstream.method;
+ }
+ ngx_conf_merge_value(conf->upstream.pass_request_headers,
+ prev->upstream.pass_request_headers, 1);
+ ngx_conf_merge_value(conf->upstream.pass_request_body,
+ prev->upstream.pass_request_body, 1);
- ngx_conf_merge_bitmask_value(conf->params, prev->params,
- (NGX_CONF_BITMASK_SET
- |NGX_HTTP_FASTCGI_REMOTE_ADDR
- |NGX_HTTP_FASTCGI_REMOTE_USER
- |NGX_HTTP_FASTCGI_SERVER_NAME
- |NGX_HTTP_FASTCGI_SERVER_PORT
- |NGX_HTTP_FASTCGI_SCRIPT_NAME
- |NGX_HTTP_FASTCGI_AUTH_TYPE
- |NGX_HTTP_FASTCGI_REQUEST_URI
- |NGX_HTTP_FASTCGI_REDIRECT_STATUS));
-
- ngx_conf_merge_str_value(conf->root, prev->root, "");
-
- if (conf->root.len && conf->root.data[conf->root.len - 1] == '/') {
- conf->root.len--;
- }
+ ngx_conf_merge_msec_value(conf->upstream.redirect_errors,
+ prev->upstream.redirect_errors, 0);
- ngx_conf_merge_str_value(conf->index, prev->index, "");
+ ngx_conf_merge_msec_value(conf->upstream.pass_x_powered_by,
+ prev->upstream.pass_x_powered_by, 1);
- if (conf->vars == NULL) {
- conf->vars = prev->vars;
- }
+
+ ngx_conf_merge_str_value(conf->index, prev->index, "");
if (conf->peers == NULL) {
conf->peers = prev->peers;
conf->upstream = prev->upstream;
}
+ if (conf->params_source == NULL) {
+ conf->params_source = prev->params_source;
+ conf->params_len = prev->params_len;
+ conf->params = prev->params;
+
+ if (conf->params_source == NULL) {
+ return NGX_CONF_OK;
+ }
+ }
+
+ conf->params_len = ngx_array_create(cf->pool, 64, 1);
+ if (conf->params_len == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ conf->params = ngx_array_create(cf->pool, 512, 1);
+ if (conf->params == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ src = conf->params_source->elts;
+ for (i = 0; i < conf->params_source->nelts; i++) {
+
+ if (ngx_http_script_variables_count(&src[i].value) == 0) {
+ copy = ngx_array_push_n(conf->params_len,
+ sizeof(ngx_http_script_copy_code_t));
+ if (copy == NULL) {
+ return NGX_CONF_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(conf->params_len,
+ sizeof(ngx_http_script_copy_code_t));
+ if (copy == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ copy->code = (ngx_http_script_code_pt)
+ ngx_http_script_copy_len_code;
+ copy->len = src[i].value.len;
+
+
+ size = (sizeof(ngx_http_script_copy_code_t)
+ + src[i].key.len + src[i].value.len
+ + sizeof(uintptr_t) - 1)
+ & ~(sizeof(uintptr_t) - 1);
+
+ copy = ngx_array_push_n(conf->params, size);
+ if (copy == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ copy->code = ngx_http_script_copy_code;
+ copy->len = src[i].key.len + src[i].value.len;
+
+ p = (u_char *) copy + sizeof(ngx_http_script_copy_code_t);
+
+ p = ngx_cpymem(p, src[i].key.data, src[i].key.len);
+ ngx_memcpy(p, src[i].value.data, src[i].value.len);
+
+ } else {
+ copy = ngx_array_push_n(conf->params_len,
+ sizeof(ngx_http_script_copy_code_t));
+ if (copy == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ copy->code = (ngx_http_script_code_pt)
+ ngx_http_script_copy_len_code;
+ copy->len = src[i].key.len;
+
+
+ size = (sizeof(ngx_http_script_copy_code_t)
+ + src[i].key.len + sizeof(uintptr_t) - 1)
+ & ~(sizeof(uintptr_t) - 1);
+
+ copy = ngx_array_push_n(conf->params, size);
+ if (copy == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ copy->code = ngx_http_script_copy_code;
+ copy->len = src[i].key.len;
+
+ p = (u_char *) copy + sizeof(ngx_http_script_copy_code_t);
+ ngx_memcpy(p, src[i].key.data, src[i].key.len);
+
+
+ ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
+
+ sc.cf = cf;
+ sc.source = &src[i].value;
+ sc.lengths = &conf->params_len;
+ sc.values = &conf->params;
+
+ if (ngx_http_script_compile(&sc) != NGX_OK) {
+ return NGX_CONF_ERROR;
+ }
+ }
+
+ code = ngx_array_push_n(conf->params_len, sizeof(uintptr_t));
+ if (code == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ *code = (uintptr_t) NULL;
+
+
+ code = ngx_array_push_n(conf->params, sizeof(uintptr_t));
+ if (code == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ *code = (uintptr_t) NULL;
+ }
+
+ code = ngx_array_push_n(conf->params_len, sizeof(uintptr_t));
+ if (code == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ *code = (uintptr_t) NULL;
+
+ return NGX_CONF_OK;
+}
+
+
+static ngx_http_variable_value_t *
+ngx_http_fastcgi_script_name_variable(ngx_http_request_t *r, uintptr_t data)
+{
+ u_char *p;
+ ngx_http_variable_value_t *vv;
+ ngx_http_fastcgi_loc_conf_t *flcf;
+
+ vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t));
+ if (vv == NULL) {
+ return NULL;
+ }
+
+ vv->value = 0;
+
+ flcf = ngx_http_get_module_loc_conf(r, ngx_http_fastcgi_module);
+
+ if (r->uri.data[r->uri.len - 1] != '/') {
+ vv->text = r->uri;
+ return vv;
+ }
+
+ vv->text.len = r->uri.len + flcf->index.len;
+
+ vv->text.data = ngx_palloc(r->pool, vv->text.len);
+ if (vv->text.data == NULL) {
+ return NULL;
+ }
+
+ p = ngx_cpymem(vv->text.data, r->uri.data, r->uri.len);
+ ngx_memcpy(p, flcf->index.data, flcf->index.len);
+
+ return vv;
+}
+
+
+static char *
+ngx_http_fastcgi_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
+{
+ ngx_http_fastcgi_loc_conf_t *lcf = conf;
+
+ ngx_str_t *value;
+ ngx_inet_upstream_t inet_upstream;
+ ngx_http_core_loc_conf_t *clcf;
+#if (NGX_HAVE_UNIX_DOMAIN)
+ ngx_unix_domain_upstream_t unix_upstream;
+#endif
+
+ value = cf->args->elts;
+
+ if (ngx_strncasecmp(value[1].data, "unix:", 5) == 0) {
+
+#if (NGX_HAVE_UNIX_DOMAIN)
+
+ ngx_memzero(&unix_upstream, sizeof(ngx_unix_domain_upstream_t));
+
+ unix_upstream.name = value[1];
+ unix_upstream.url = value[1];
+
+ lcf->peers = ngx_unix_upstream_parse(cf, &unix_upstream);
+ if (lcf->peers == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+#else
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "the unix domain sockets are not supported "
+ "on this platform");
+ return NGX_CONF_ERROR;
+
+#endif
+
+ } else {
+ ngx_memzero(&inet_upstream, sizeof(ngx_inet_upstream_t));
+
+ inet_upstream.name = value[1];
+ inet_upstream.url = value[1];
+
+ lcf->peers = ngx_inet_upstream_parse(cf, &inet_upstream);
+ if (lcf->peers == NULL) {
+ return NGX_CONF_ERROR;
+ }
+ }
+
+ lcf->upstream.schema.len = sizeof("fastcgi://") - 1;
+ lcf->upstream.schema.data = (u_char *) "fastcgi://";
+ lcf->upstream.uri.len = sizeof("/") - 1;
+ lcf->upstream.uri.data = (u_char *) "/";
+
+ clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
+
+ clcf->handler = ngx_http_fastcgi_handler;
+
+#if (NGX_PCRE)
+ lcf->upstream.location = clcf->regex ? &ngx_http_fastcgi_uri : &clcf->name;
+#else
+ lcf->upstream.location = &clcf->name;
+#endif
+
+ if (clcf->name.data[clcf->name.len - 1] == '/') {
+ clcf->auto_redirect = 1;
+ }
+
+ return NGX_CONF_OK;
+}
+
+
+static char *
+ngx_http_fastcgi_lowat_check(ngx_conf_t *cf, void *post, void *data)
+{
+#if (NGX_FREEBSD)
+ ssize_t *np = data;
+
+ if (*np >= ngx_freebsd_net_inet_tcp_sendspace) {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "\"fastcgi_send_lowat\" must be less than %d "
+ "(sysctl net.inet.tcp.sendspace)",
+ ngx_freebsd_net_inet_tcp_sendspace);
+
+ return NGX_CONF_ERROR;
+ }
+
+#elif !(NGX_HAVE_SO_SNDLOWAT)
+ ssize_t *np = data;
+
+ ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
+ "\"fastcgi_send_lowat\" is not supported, ignored");
+
+ *np = 0;
+
+#endif
+
return NGX_CONF_OK;
}
diff --git a/src/http/modules/ngx_http_geo_module.c b/src/http/modules/ngx_http_geo_module.c
index 865f82551..723eff90f 100644
--- a/src/http/modules/ngx_http_geo_module.c
+++ b/src/http/modules/ngx_http_geo_module.c
@@ -34,7 +34,8 @@ static ngx_command_t ngx_http_geo_commands[] = {
static ngx_http_module_t ngx_http_geo_module_ctx = {
- NULL, /* pre conf */
+ NULL, /* preconfiguration */
+ NULL, /* postconfiguration */
NULL, /* create main configuration */
NULL, /* init main configuration */
@@ -48,7 +49,7 @@ static ngx_http_module_t ngx_http_geo_module_ctx = {
ngx_module_t ngx_http_geo_module = {
- NGX_MODULE,
+ NGX_MODULE_V1,
&ngx_http_geo_module_ctx, /* module context */
ngx_http_geo_commands, /* module directives */
NGX_HTTP_MODULE, /* module type */
@@ -110,7 +111,7 @@ ngx_http_geo_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
name.data++;
}
- var = ngx_http_add_variable(cf, &name, 1);
+ var = ngx_http_add_variable(cf, &name, 0);
if (var == NULL) {
return NGX_CONF_ERROR;
}
diff --git a/src/http/modules/ngx_http_gzip_filter_module.c b/src/http/modules/ngx_http_gzip_filter_module.c
index 4a4da7f58..1f7c2328c 100644
--- a/src/http/modules/ngx_http_gzip_filter_module.c
+++ b/src/http/modules/ngx_http_gzip_filter_module.c
@@ -207,7 +207,8 @@ static ngx_command_t ngx_http_gzip_filter_commands[] = {
static ngx_http_module_t ngx_http_gzip_filter_module_ctx = {
- ngx_http_gzip_add_log_formats, /* pre conf */
+ ngx_http_gzip_add_log_formats, /* preconfiguration */
+ NULL, /* postconfiguration */
NULL, /* create main configuration */
NULL, /* init main configuration */
@@ -221,7 +222,7 @@ static ngx_http_module_t ngx_http_gzip_filter_module_ctx = {
ngx_module_t ngx_http_gzip_filter_module = {
- NGX_MODULE,
+ NGX_MODULE_V1,
&ngx_http_gzip_filter_module_ctx, /* module context */
ngx_http_gzip_filter_commands, /* module directives */
NGX_HTTP_MODULE, /* module type */
@@ -257,6 +258,11 @@ struct gztrailer {
#endif
+static ngx_str_t ngx_http_gzip_no_cache = ngx_string("no-cache");
+static ngx_str_t ngx_http_gzip_no_store = ngx_string("no-store");
+static ngx_str_t ngx_http_gzip_private = ngx_string("private");
+
+
static ngx_http_output_header_filter_pt ngx_http_next_header_filter;
static ngx_http_output_body_filter_pt ngx_http_next_body_filter;
@@ -276,8 +282,9 @@ ngx_http_gzip_header_filter(ngx_http_request_t *r)
&& r->headers_out.status != NGX_HTTP_FORBIDDEN
&& r->headers_out.status != NGX_HTTP_NOT_FOUND)
|| r->header_only
+ || r->main
|| r->http_version < conf->http_version
- || r->headers_out.content_type == NULL
+ || r->headers_out.content_type.len == 0
|| (r->headers_out.content_encoding
&& r->headers_out.content_encoding->value.len)
|| r->headers_in.accept_encoding == NULL
@@ -294,8 +301,8 @@ ngx_http_gzip_header_filter(ngx_http_request_t *r)
type = conf->types->elts;
for (i = 0; i < conf->types->nelts; i++) {
- if (r->headers_out.content_type->value.len >= type[i].name.len
- && ngx_strncasecmp(r->headers_out.content_type->value.data,
+ if (r->headers_out.content_type.len >= type[i].name.len
+ && ngx_strncasecmp(r->headers_out.content_type.data,
type[i].name.data, type[i].name.len) == 0)
{
found = 1;
@@ -346,6 +353,7 @@ ngx_http_gzip_header_filter(ngx_http_request_t *r)
return NGX_ERROR;
}
+ r->headers_out.content_encoding->hash = 1;
r->headers_out.content_encoding->key.len = sizeof("Content-Encoding") - 1;
r->headers_out.content_encoding->key.data = (u_char *) "Content-Encoding";
r->headers_out.content_encoding->value.len = sizeof("gzip") - 1;
@@ -353,10 +361,12 @@ ngx_http_gzip_header_filter(ngx_http_request_t *r)
ctx->length = r->headers_out.content_length_n;
r->headers_out.content_length_n = -1;
+
if (r->headers_out.content_length) {
- r->headers_out.content_length->key.len = 0;
+ r->headers_out.content_length->hash = 0;
r->headers_out.content_length = NULL;
}
+
r->filter_need_in_memory = 1;
return ngx_http_next_header_filter(r);
@@ -404,22 +414,25 @@ ngx_http_gzip_proxied(ngx_http_request_t *r, ngx_http_gzip_conf_t *conf)
return NGX_DECLINED;
}
- if (r->headers_out.cache_control) {
+ if (r->headers_out.cache_control.elts) {
if ((conf->proxied & NGX_HTTP_GZIP_PROXIED_NO_CACHE)
- && ngx_strstr(r->headers_out.cache_control->value.data, "no-cache"))
+ && ngx_http_parse_multi_header_lines(&r->headers_out.cache_control,
+ &ngx_http_gzip_no_cache, NULL) >= 0)
{
return NGX_OK;
}
if ((conf->proxied & NGX_HTTP_GZIP_PROXIED_NO_STORE)
- && ngx_strstr(r->headers_out.cache_control->value.data, "no-store"))
+ && ngx_http_parse_multi_header_lines(&r->headers_out.cache_control,
+ &ngx_http_gzip_no_store, NULL) >= 0)
{
return NGX_OK;
}
if ((conf->proxied & NGX_HTTP_GZIP_PROXIED_PRIVATE)
- && ngx_strstr(r->headers_out.cache_control->value.data, "private"))
+ && ngx_http_parse_multi_header_lines(&r->headers_out.cache_control,
+ &ngx_http_gzip_private, NULL) >= 0)
{
return NGX_OK;
}
@@ -484,8 +497,8 @@ ngx_http_gzip_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
* and do not wait while a whole response will be sent to a client.
*
* 8K is for zlib deflate_state, it takes
- * * 5816 bytes on x86 and sparc64 (32-bit mode)
- * * 5920 bytes on amd64 and sparc64
+ * *) 5816 bytes on i386 and sparc64 (32-bit mode)
+ * *) 5920 bytes on amd64 and sparc64
*/
ctx->allocated = 8192 + (1 << (wbits + 2)) + (1 << (memlevel + 9));
@@ -696,7 +709,8 @@ ngx_http_gzip_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
if (ctx->flush == Z_SYNC_FLUSH) {
- ctx->out_buf->flush = 0;
+ ctx->zstream.avail_out = 0;
+ ctx->out_buf->flush = 1;
ctx->flush = Z_NO_FLUSH;
cl = ngx_alloc_chain_link(r->pool);
diff --git a/src/http/modules/ngx_http_headers_filter_module.c b/src/http/modules/ngx_http_headers_filter_module.c
index 793cefd48..f27ab476d 100644
--- a/src/http/modules/ngx_http_headers_filter_module.c
+++ b/src/http/modules/ngx_http_headers_filter_module.c
@@ -41,7 +41,8 @@ static ngx_command_t ngx_http_headers_filter_commands[] = {
static ngx_http_module_t ngx_http_headers_filter_module_ctx = {
- NULL, /* pre conf */
+ NULL, /* preconfiguration */
+ NULL, /* postconfiguration */
NULL, /* create main configuration */
NULL, /* init main configuration */
@@ -55,7 +56,7 @@ static ngx_http_module_t ngx_http_headers_filter_module_ctx = {
ngx_module_t ngx_http_headers_filter_module = {
- NGX_MODULE,
+ NGX_MODULE_V1,
&ngx_http_headers_filter_module_ctx, /* module context */
ngx_http_headers_filter_commands, /* module directives */
NGX_HTTP_MODULE, /* module type */
@@ -71,10 +72,11 @@ static ngx_int_t
ngx_http_headers_filter(ngx_http_request_t *r)
{
size_t len;
+ ngx_uint_t i;
ngx_table_elt_t *expires, *cc;
ngx_http_headers_conf_t *conf;
- if (r->headers_out.status != NGX_HTTP_OK) {
+ if (r->headers_out.status != NGX_HTTP_OK || r->main) {
return ngx_http_next_header_filter(r);
}
@@ -82,28 +84,43 @@ ngx_http_headers_filter(ngx_http_request_t *r)
if (conf->expires != NGX_HTTP_EXPIRES_OFF) {
- expires = ngx_list_push(&r->headers_out.headers);
+ expires = r->headers_out.expires;
+
if (expires == NULL) {
- return NGX_ERROR;
- }
- r->headers_out.expires = expires;
+ expires = ngx_list_push(&r->headers_out.headers);
+ if (expires == NULL) {
+ return NGX_ERROR;
+ }
- cc = ngx_list_push(&r->headers_out.headers);
- if (cc == NULL) {
- return NGX_ERROR;
- }
+ r->headers_out.expires = expires;
- r->headers_out.cache_control = cc;
+ expires->hash = 1;
+ expires->key.len = sizeof("Expires") - 1;
+ expires->key.data = (u_char *) "Expires";
+ }
len = sizeof("Mon, 28 Sep 1970 06:00:00 GMT");
-
- expires->key.len = sizeof("Expires") - 1;
- expires->key.data = (u_char *) "Expires";
expires->value.len = len - 1;
- cc->key.len = sizeof("Cache-Control") - 1;
- cc->key.data = (u_char *) "Cache-Control";
+ cc = r->headers_out.cache_control.elts;
+
+ if (cc == NULL) {
+
+ cc = ngx_list_push(&r->headers_out.headers);
+ if (cc == NULL) {
+ return NGX_ERROR;
+ }
+
+ cc->hash = 1;
+ cc->key.len = sizeof("Cache-Control") - 1;
+ cc->key.data = (u_char *) "Cache-Control";
+
+ } else {
+ for (i = 1; i < r->headers_out.cache_control.nelts; i++) {
+ cc[i].hash = 0;
+ }
+ }
if (conf->expires == NGX_HTTP_EXPIRES_EPOCH) {
expires->value.data = (u_char *) "Thu, 01 Jan 1970 00:00:01 GMT";
diff --git a/src/http/modules/ngx_http_index_module.c b/src/http/modules/ngx_http_index_module.c
index 373c31552..5315704b4 100644
--- a/src/http/modules/ngx_http_index_module.c
+++ b/src/http/modules/ngx_http_index_module.c
@@ -10,42 +10,52 @@
typedef struct {
- ngx_array_t indices;
+ ngx_str_t name;
+ ngx_array_t *lengths;
+ ngx_array_t *values;
+} ngx_http_index_t;
+
+
+typedef struct {
+ ngx_array_t *indices; /* array of ngx_http_index_t */
size_t max_index_len;
- ngx_http_cache_hash_t *index_cache;
} ngx_http_index_loc_conf_t;
typedef struct {
- ngx_uint_t index;
- u_char *last;
- ngx_str_t path;
- ngx_str_t redirect;
- ngx_http_cache_entry_t *cache;
- ngx_uint_t tested; /* unsigned tested:1 */
+ ngx_uint_t current;
+ size_t allocated;
+
+ u_char *path;
+ ngx_str_t uri;
+ ngx_str_t index;
+
+ ngx_uint_t tested; /* unsigned tested:1 */
} ngx_http_index_ctx_t;
#define NGX_HTTP_DEFAULT_INDEX "index.html"
+static ngx_int_t ngx_http_index_alloc(ngx_http_request_t *r, size_t size,
+ ngx_http_index_ctx_t *ctx, ngx_http_core_loc_conf_t *clcf);
static ngx_int_t ngx_http_index_test_dir(ngx_http_request_t *r,
- ngx_http_index_ctx_t *ctx);
+ ngx_http_index_ctx_t *ctx);
static ngx_int_t ngx_http_index_error(ngx_http_request_t *r,
- ngx_http_index_ctx_t *ctx, ngx_err_t err);
+ ngx_http_index_ctx_t *ctx, ngx_err_t err);
static ngx_int_t ngx_http_index_init(ngx_cycle_t *cycle);
static void *ngx_http_index_create_loc_conf(ngx_conf_t *cf);
static char *ngx_http_index_merge_loc_conf(ngx_conf_t *cf,
- void *parent, void *child);
+ void *parent, void *child);
static char *ngx_http_index_set_index(ngx_conf_t *cf, ngx_command_t *cmd,
- void *conf);
+ void *conf);
static ngx_command_t ngx_http_index_commands[] = {
{ ngx_string("index"),
- NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
ngx_http_index_set_index,
NGX_HTTP_LOC_CONF_OFFSET,
0,
@@ -67,7 +77,8 @@ static ngx_command_t ngx_http_index_commands[] = {
ngx_http_module_t ngx_http_index_module_ctx = {
- NULL, /* pre conf */
+ NULL, /* preconfiguration */
+ NULL, /* postconfiguration */
NULL, /* create main configuration */
NULL, /* init main configuration */
@@ -81,7 +92,7 @@ ngx_http_module_t ngx_http_index_module_ctx = {
ngx_module_t ngx_http_index_module = {
- NGX_MODULE,
+ NGX_MODULE_V1,
&ngx_http_index_module_ctx, /* module context */
ngx_http_index_commands, /* module directives */
NGX_HTTP_MODULE, /* module type */
@@ -100,21 +111,24 @@ ngx_module_t ngx_http_index_module = {
* that path contains the usual file in place of the directory.
*/
-static ngx_int_t ngx_http_index_handler(ngx_http_request_t *r)
+static ngx_int_t
+ngx_http_index_handler(ngx_http_request_t *r)
{
- u_char *name;
- ngx_fd_t fd;
- ngx_int_t rc;
- ngx_str_t *index;
- ngx_err_t err;
- ngx_log_t *log;
- ngx_http_index_ctx_t *ctx;
- ngx_http_core_loc_conf_t *clcf;
- ngx_http_index_loc_conf_t *ilcf;
-#if (NGX_HTTP_CACHE0)
- /* crc must be in ctx !! */
- uint32_t crc;
-#endif
+ u_char *name;
+ size_t len;
+ ngx_fd_t fd;
+ ngx_int_t rc;
+ ngx_err_t err;
+ ngx_log_t *log;
+ ngx_uint_t i;
+ ngx_http_index_t *index;
+ ngx_http_index_ctx_t *ctx;
+ ngx_pool_cleanup_file_t *cln;
+ ngx_http_script_code_pt code;
+ ngx_http_script_engine_t e;
+ ngx_http_core_loc_conf_t *clcf;
+ ngx_http_index_loc_conf_t *ilcf;
+ ngx_http_script_len_code_pt lcode;
if (r->uri.data[r->uri.len - 1] != '/') {
return NGX_DECLINED;
@@ -128,8 +142,8 @@ static ngx_int_t ngx_http_index_handler(ngx_http_request_t *r)
log = r->connection->log;
/*
- * we use context because the handler supports an async file opening
- * and thus can be called several times
+ * we use context because the handler supports an async file opening,
+ * and may be called several times
*/
clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
@@ -144,108 +158,63 @@ static ngx_int_t ngx_http_index_handler(ngx_http_request_t *r)
}
ngx_http_set_ctx(r, ctx, ngx_http_index_module);
+ }
-#if (NGX_HTTP_CACHE)
+ index = ilcf->indices->elts;
+ for (i = ctx->current; i < ilcf->indices->nelts; i++) {
- if (ilcf->index_cache) {
- ctx->cache = ngx_http_cache_get(ilcf->index_cache, NULL,
- &r->uri, &crc);
+ if (index[i].lengths == NULL) {
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0,
- "http index cache get: %p", ctx->cache);
+ if (index[i].name.data[0] == '/') {
+ return ngx_http_internal_redirect(r, &index[i].name, &r->args);
+ }
- if (ctx->cache && !ctx->cache->expired) {
+ len = ilcf->max_index_len;
+ ctx->index.len = index[i].name.len;
- ctx->cache->accessed = ngx_cached_time;
+ } else {
+ ngx_memzero(&e, sizeof(ngx_http_script_engine_t));
- ctx->redirect.len = ctx->cache->data.value.len;
- ctx->redirect.data = ngx_palloc(r->pool, ctx->redirect.len + 1);
- if (ctx->redirect.data == NULL) {
- ngx_http_cache_unlock(ilcf->index_cache, ctx->cache, log);
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
+ e.ip = index[i].lengths->elts;
+ e.request = r;
- ngx_memcpy(ctx->redirect.data, ctx->cache->data.value.data,
- ctx->redirect.len + 1);
- ngx_http_cache_unlock(ilcf->index_cache, ctx->cache, log);
+ len = 1;
- return ngx_http_internal_redirect(r, &ctx->redirect, NULL);
+ while (*(uintptr_t *) e.ip) {
+ lcode = *(ngx_http_script_len_code_pt *) e.ip;
+ len += lcode(&e);
}
- }
-
-#endif
-#if 0
- ctx->path.data = ngx_palloc(r->pool, clcf->root.len + r->uri.len
- + ilcf->max_index_len
- - clcf->alias * clcf->name.len);
- if (ctx->path.data == NULL) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
+ ctx->index.len = len;
}
- ctx->redirect.data = ngx_cpymem(ctx->path.data, clcf->root.data,
- clcf->root.len);
-#endif
-
- if (clcf->alias) {
- ctx->path.data = ngx_palloc(r->pool, clcf->root.len
- + r->uri.len + 1 - clcf->name.len
- + ilcf->max_index_len);
- if (ctx->path.data == NULL) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- ctx->redirect.data = ngx_palloc(r->pool, r->uri.len
- + ilcf->max_index_len);
- if (ctx->redirect.data == NULL) {
+ if (len > ctx->allocated) {
+ if (ngx_http_index_alloc(r, len, ctx, clcf) != NGX_OK) {
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
+ }
- ngx_memcpy(ctx->path.data, clcf->root.data, clcf->root.len);
-
- ctx->last = ngx_cpystrn(ctx->path.data + clcf->root.len,
- r->uri.data + clcf->name.len,
- r->uri.len + 1 - clcf->name.len);
+ if (index[i].values == NULL) {
+ ngx_memcpy(ctx->index.data, index[i].name.data, ctx->index.len);
-#if 0
- /*
- * aliases usually have trailling "/",
- * set it in the start of the possible redirect
- */
+ } else {
+ e.ip = index[i].values->elts;
+ e.pos = ctx->index.data;
- if (*ctx->redirect.data != '/') {
- ctx->redirect.data--;
+ while (*(uintptr_t *) e.ip) {
+ code = *(ngx_http_script_code_pt *) e.ip;
+ code((ngx_http_script_engine_t *) &e);
}
-#endif
- } else {
- ctx->path.data = ngx_palloc(r->pool, clcf->root.len + r->uri.len
- + ilcf->max_index_len);
- if (ctx->path.data == NULL) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
+ if (*ctx->index.data == '/') {
+ ctx->index.len--;
+ return ngx_http_internal_redirect(r, &ctx->index, &r->args);
}
- ctx->redirect.data = ngx_cpymem(ctx->path.data, clcf->root.data,
- clcf->root.len);
-
- ctx->last = ngx_cpystrn(ctx->redirect.data, r->uri.data,
- r->uri.len + 1);
+ *e.pos++ = '\0';
}
- }
-
- ctx->path.len = ctx->last - ctx->path.data;
- index = ilcf->indices.elts;
- for (/* void */; ctx->index < ilcf->indices.nelts; ctx->index++) {
-
- if (index[ctx->index].data[0] == '/') {
- name = index[ctx->index].data;
-
- } else {
- ngx_memcpy(ctx->last, index[ctx->index].data,
- index[ctx->index].len + 1);
- name = ctx->path.data;
- }
+ name = ctx->path;
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0,
"open index \"%s\"", name);
@@ -253,6 +222,7 @@ static ngx_int_t ngx_http_index_handler(ngx_http_request_t *r)
fd = ngx_open_file(name, NGX_FILE_RDONLY, NGX_FILE_OPEN);
if (fd == (ngx_fd_t) NGX_AGAIN) {
+ ctx->current = i;
return NGX_AGAIN;
}
@@ -290,149 +260,132 @@ static ngx_int_t ngx_http_index_handler(ngx_http_request_t *r)
}
- /* STUB: open file cache */
+ cln = ngx_palloc(r->pool, sizeof(ngx_pool_cleanup_file_t));
+ if (cln == NULL) {
+ return NGX_HTTP_INTERNAL_SERVER_ERROR;
+ }
- r->file.name.data = name;
- r->file.fd = fd;
+ cln->fd = fd;
+ cln->name = name;
+ cln->log = r->pool->log;
- if (index[ctx->index].data[0] == '/') {
- r->file.name.len = index[ctx->index].len;
- ctx->redirect.len = index[ctx->index].len;
- ctx->redirect.data = index[ctx->index].data;
+ if (ngx_pool_cleanup_add(r->pool, ngx_pool_cleanup_file, cln) == NULL) {
+ return NGX_HTTP_INTERNAL_SERVER_ERROR;
+ }
- } else {
- if (clcf->alias) {
- name = ngx_cpymem(ctx->redirect.data, r->uri.data, r->uri.len);
- ngx_memcpy(name, index[ctx->index].data,
- index[ctx->index].len + 1);
- }
- ctx->redirect.len = r->uri.len + index[ctx->index].len;
- r->file.name.len = clcf->root.len + r->uri.len
- - clcf->alias * clcf->name.len
- + index[ctx->index].len;
+ if (clcf->alias) {
+ name = ngx_cpymem(ctx->uri.data, r->uri.data, r->uri.len);
+ ngx_memcpy(name, ctx->index.data, ctx->index.len - 1);
}
- /**/
+ ctx->uri.len = r->uri.len + ctx->index.len - 1;
+ return ngx_http_internal_redirect(r, &ctx->uri, &r->args);
+ }
+
+ return NGX_DECLINED;
+}
-#if (NGX_HTTP_CACHE)
- if (ilcf->index_cache) {
+static ngx_int_t
+ngx_http_index_alloc(ngx_http_request_t *r, size_t size,
+ ngx_http_index_ctx_t *ctx, ngx_http_core_loc_conf_t *clcf)
+{
+ ctx->allocated = size;
- if (ctx->cache) {
- if (ctx->redirect.len == ctx->cache->data.value.len
- && ngx_memcmp(ctx->cache->data.value.data,
- ctx->redirect.data, ctx->redirect.len) == 0)
- {
- ctx->cache->accessed = ngx_cached_time;
- ctx->cache->updated = ngx_cached_time;
- ngx_http_cache_unlock(ilcf->index_cache, ctx->cache, log);
+ if (!clcf->alias) {
+ ctx->path = ngx_palloc(r->pool, clcf->root.len + r->uri.len + size);
+ if (ctx->path == NULL) {
+ return NGX_ERROR;
+ }
- return ngx_http_internal_redirect(r, &ctx->redirect, NULL);
- }
- }
+ ctx->uri.data = ngx_cpymem(ctx->path, clcf->root.data, clcf->root.len);
- ctx->redirect.len++;
- ctx->cache = ngx_http_cache_alloc(ilcf->index_cache, ctx->cache,
- NULL, &r->uri, crc,
- &ctx->redirect, log);
- ctx->redirect.len--;
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0,
- "http index cache alloc: %p", ctx->cache);
-
- if (ctx->cache) {
- ctx->cache->fd = NGX_INVALID_FILE;
- ctx->cache->accessed = ngx_cached_time;
- ctx->cache->last_modified = 0;
- ctx->cache->updated = ngx_cached_time;
- ctx->cache->memory = 1;
- ngx_http_cache_unlock(ilcf->index_cache, ctx->cache, log);
- }
+ ctx->index.data = ngx_cpymem(ctx->uri.data, r->uri.data, r->uri.len);
+
+ } else {
+ ctx->path = ngx_palloc(r->pool,
+ clcf->root.len + r->uri.len - clcf->name.len + size);
+ if (ctx->path == NULL) {
+ return NGX_ERROR;
}
-#endif
+ ctx->uri.data = ngx_palloc(r->pool, r->uri.len + size);
+ if (ctx->uri.data == NULL) {
+ return NGX_ERROR;
+ }
+
+ ngx_memcpy(ctx->path, clcf->root.data, clcf->root.len);
- return ngx_http_internal_redirect(r, &ctx->redirect, NULL);
+ ctx->index.data = ngx_cpymem(ctx->path + clcf->root.len,
+ r->uri.data + clcf->name.len,
+ r->uri.len - clcf->name.len);
}
- return NGX_DECLINED;
+ return NGX_OK;
}
-static ngx_int_t ngx_http_index_test_dir(ngx_http_request_t *r,
- ngx_http_index_ctx_t *ctx)
+static ngx_int_t
+ngx_http_index_test_dir(ngx_http_request_t *r, ngx_http_index_ctx_t *ctx)
{
- ngx_err_t err;
+ ngx_err_t err;
+ ngx_file_info_t fi;
- ctx->path.data[ctx->path.len - 1] = '\0';
- ctx->path.data[ctx->path.len] = '\0';
+ *(ctx->index.data - 1) = '\0';
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http check dir: \"%s\"", ctx->path.data);
+ "http index check dir: \"%s\"", ctx->path);
- if (ngx_file_info(ctx->path.data, &r->file.info) == -1) {
+ if (ngx_file_info(ctx->path, &fi) == -1) {
err = ngx_errno;
if (err == NGX_ENOENT) {
- ctx->path.data[ctx->path.len - 1] = '/';
+ *(ctx->index.data - 1) = '/';
return ngx_http_index_error(r, ctx, err);
}
ngx_log_error(NGX_LOG_CRIT, r->connection->log, err,
- ngx_file_info_n " \"%s\" failed", ctx->path.data);
+ ngx_file_info_n " \"%s\" failed", ctx->path);
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
- ctx->path.data[ctx->path.len - 1] = '/';
+ *(ctx->index.data - 1) = '/';
- if (ngx_is_dir(&r->file.info)) {
+ if (ngx_is_dir(&fi)) {
return NGX_OK;
}
- /* THINK: not reached ??? */
- return ngx_http_index_error(r, ctx, 0);
+ ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
+ "\"%s\" is not a directory", ctx->path);
+
+ return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
-static ngx_int_t ngx_http_index_error(ngx_http_request_t *r,
- ngx_http_index_ctx_t *ctx, ngx_err_t err)
+static ngx_int_t
+ngx_http_index_error(ngx_http_request_t *r, ngx_http_index_ctx_t *ctx,
+ ngx_err_t err)
{
if (err == NGX_EACCES) {
ngx_log_error(NGX_LOG_ERR, r->connection->log, err,
- "\"%s\" is forbidden", ctx->path.data);
+ "\"%s\" is forbidden", ctx->path);
return NGX_HTTP_FORBIDDEN;
}
ngx_log_error(NGX_LOG_ERR, r->connection->log, err,
- "\"%s\" is not found", ctx->path.data);
- return NGX_HTTP_NOT_FOUND;
-}
+ "\"%s\" is not found", ctx->path);
-
-static ngx_int_t ngx_http_index_init(ngx_cycle_t *cycle)
-{
- ngx_http_handler_pt *h;
- ngx_http_core_main_conf_t *cmcf;
-
- cmcf = ngx_http_cycle_get_module_main_conf(cycle, ngx_http_core_module);
-
- h = ngx_array_push(&cmcf->phases[NGX_HTTP_CONTENT_PHASE].handlers);
- if (h == NULL) {
- return NGX_ERROR;
- }
-
- *h = ngx_http_index_handler;
-
- return NGX_OK;
+ return NGX_HTTP_NOT_FOUND;
}
-static void *ngx_http_index_create_loc_conf(ngx_conf_t *cf)
+static void *
+ngx_http_index_create_loc_conf(ngx_conf_t *cf)
{
ngx_http_index_loc_conf_t *conf;
@@ -441,118 +394,146 @@ static void *ngx_http_index_create_loc_conf(ngx_conf_t *cf)
return NGX_CONF_ERROR;
}
- if (ngx_array_init(&conf->indices, cf->pool, 2, sizeof(ngx_str_t))
- == NGX_ERROR)
- {
- return NGX_CONF_ERROR;
- }
-
- conf->max_index_len = 0;
-
- conf->index_cache = NULL;
+ conf->indices = NULL;
+ conf->max_index_len = 1;
return conf;
}
-/* TODO: remove duplicate indices */
-
-static char *ngx_http_index_merge_loc_conf(ngx_conf_t *cf,
- void *parent, void *child)
+static char *
+ngx_http_index_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
{
ngx_http_index_loc_conf_t *prev = parent;
ngx_http_index_loc_conf_t *conf = child;
- ngx_str_t *index;
+ ngx_http_index_t *index;
- if (conf->max_index_len == 0) {
- if (prev->max_index_len != 0) {
- ngx_memcpy(conf, prev, sizeof(ngx_http_index_loc_conf_t));
- return NGX_CONF_OK;
+ if (conf->indices == NULL) {
+ conf->indices = prev->indices;
+ conf->max_index_len = prev->max_index_len;
+ }
+
+ if (conf->indices == NULL) {
+ conf->indices = ngx_array_create(cf->pool, 1, sizeof(ngx_http_index_t));
+ if (conf->indices == NULL) {
+ return NGX_CONF_ERROR;
}
- index = ngx_array_push(&conf->indices);
+ index = ngx_array_push(conf->indices);
if (index == NULL) {
return NGX_CONF_ERROR;
}
- index->len = sizeof(NGX_HTTP_DEFAULT_INDEX) - 1;
- index->data = (u_char *) NGX_HTTP_DEFAULT_INDEX;
+ index->name.len = sizeof(NGX_HTTP_DEFAULT_INDEX);
+ index->name.data = (u_char *) NGX_HTTP_DEFAULT_INDEX;
+ index->lengths = NULL;
+ index->values = NULL;
+
conf->max_index_len = sizeof(NGX_HTTP_DEFAULT_INDEX);
return NGX_CONF_OK;
}
-#if 0
-
- if (prev->max_index_len != 0) {
-
- prev_index = prev->indices.elts;
- for (i = 0; i < prev->indices.nelts; i++) {
- index = ngx_array_push(&conf->indices);
- if (index == NULL) {
- return NGX_CONF_ERROR;
- }
-
- index->len = prev_index[i].len;
- index->data = prev_index[i].data;
- }
- }
-
- if (conf->max_index_len < prev->max_index_len) {
- conf->max_index_len = prev->max_index_len;
- }
-
-#endif
-
- if (conf->index_cache == NULL) {
- conf->index_cache = prev->index_cache;
- }
-
return NGX_CONF_OK;
}
/* TODO: warn about duplicate indices */
-static char *ngx_http_index_set_index(ngx_conf_t *cf, ngx_command_t *cmd,
- void *conf)
+static char *
+ngx_http_index_set_index(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
ngx_http_index_loc_conf_t *ilcf = conf;
- ngx_uint_t i;
- ngx_str_t *index, *value;
-
- value = cf->args->elts;
+ ngx_uint_t i, n;
+ ngx_str_t *value;
+ ngx_http_index_t *index;
+ ngx_http_script_compile_t sc;
- if (value[1].data[0] == '/' && ilcf->indices.nelts == 0) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "first index \"%V\" in \"%V\" directive "
- "must not be absolute",
- &value[1], &cmd->name);
- return NGX_CONF_ERROR;
+ if (ilcf->indices == NULL) {
+ ilcf->indices = ngx_array_create(cf->pool, 2, sizeof(ngx_http_index_t));
+ if (ilcf->indices == NULL) {
+ return NGX_CONF_ERROR;
+ }
}
+ value = cf->args->elts;
+
for (i = 1; i < cf->args->nelts; i++) {
+ if (value[i].data[0] == '/' && i != cf->args->nelts - 1) {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "only the last index in \"index\" directive "
+ "may be absolute");
+ return NGX_CONF_ERROR;
+ }
+
if (value[i].len == 0) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "index \"%V\" in \"%V\" directive is invalid",
- &value[1], &cmd->name);
+ "index \"%V\" in \"index\" directive is invalid",
+ &value[1]);
return NGX_CONF_ERROR;
}
- index = ngx_array_push(&ilcf->indices);
+ index = ngx_array_push(ilcf->indices);
if (index == NULL) {
return NGX_CONF_ERROR;
}
- index->len = value[i].len;
- index->data = value[i].data;
+ index->name.len = value[i].len;
+ index->name.data = value[i].data;
+ index->lengths = NULL;
+ index->values = NULL;
+
+ n = ngx_http_script_variables_count(&value[i]);
+
+ if (n == 0) {
+ index->name.len++;
+
+ if (ilcf->max_index_len != 0
+ && ilcf->max_index_len < index->name.len)
+ {
+ ilcf->max_index_len = index->name.len;
+ }
+
+ continue;
+ }
+
+ ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
+
+ sc.cf = cf;
+ sc.source = &value[i];
+ sc.lengths = &index->lengths;
+ sc.values = &index->values;
+ sc.variables = n;
+ sc.complete_lengths = 1;
+ sc.complete_values = 1;
- if (ilcf->max_index_len < index->len + 1) {
- ilcf->max_index_len = index->len + 1;
+ if (ngx_http_script_compile(&sc) != NGX_OK) {
+ return NGX_CONF_ERROR;
}
+
+ ilcf->max_index_len = 0;
}
return NGX_CONF_OK;
}
+
+
+static ngx_int_t
+ngx_http_index_init(ngx_cycle_t *cycle)
+{
+ ngx_http_handler_pt *h;
+ ngx_http_core_main_conf_t *cmcf;
+
+ cmcf = ngx_http_cycle_get_module_main_conf(cycle, ngx_http_core_module);
+
+ h = ngx_array_push(&cmcf->phases[NGX_HTTP_CONTENT_PHASE].handlers);
+ if (h == NULL) {
+ return NGX_ERROR;
+ }
+
+ *h = ngx_http_index_handler;
+
+ return NGX_OK;
+}
diff --git a/src/http/modules/ngx_http_not_modified_filter_module.c b/src/http/modules/ngx_http_not_modified_filter_module.c
index 24ea58d90..23ea57215 100644
--- a/src/http/modules/ngx_http_not_modified_filter_module.c
+++ b/src/http/modules/ngx_http_not_modified_filter_module.c
@@ -14,7 +14,8 @@ static ngx_int_t ngx_http_not_modified_filter_init(ngx_cycle_t *cycle);
static ngx_http_module_t ngx_http_not_modified_filter_module_ctx = {
- NULL, /* pre conf */
+ NULL, /* preconfiguration */
+ NULL, /* postconfiguration */
NULL, /* create main configuration */
NULL, /* init main configuration */
@@ -28,7 +29,7 @@ static ngx_http_module_t ngx_http_not_modified_filter_module_ctx = {
ngx_module_t ngx_http_not_modified_filter_module = {
- NGX_MODULE,
+ NGX_MODULE_V1,
&ngx_http_not_modified_filter_module_ctx, /* module context */
NULL, /* module directives */
NGX_HTTP_MODULE, /* module type */
@@ -45,6 +46,7 @@ static ngx_int_t ngx_http_not_modified_header_filter(ngx_http_request_t *r)
time_t ims;
if (r->headers_out.status != NGX_HTTP_OK
+ || r->main
|| r->headers_in.if_modified_since == NULL
|| r->headers_out.last_modified_time == -1)
{
@@ -63,12 +65,11 @@ static ngx_int_t ngx_http_not_modified_header_filter(ngx_http_request_t *r)
if (ims != NGX_ERROR && ims == r->headers_out.last_modified_time) {
r->headers_out.status = NGX_HTTP_NOT_MODIFIED;
- r->headers_out.content_type->key.len = 0;
- r->headers_out.content_type = NULL;
+ r->headers_out.content_type.len = 0;
r->headers_out.content_length_n = -1;
r->headers_out.content_length = NULL;
#if 0
- r->headers_out.accept_ranges->key.len = 0;
+ r->headers_out.accept_ranges->hash = 0;
#endif
}
diff --git a/src/http/modules/ngx_http_proxy_module.c b/src/http/modules/ngx_http_proxy_module.c
index 8020856c3..5504610e6 100644
--- a/src/http/modules/ngx_http_proxy_module.c
+++ b/src/http/modules/ngx_http_proxy_module.c
@@ -10,89 +10,100 @@
#include <ngx_http.h>
+typedef struct ngx_http_proxy_redirect_s ngx_http_proxy_redirect_t;
+
+typedef ngx_int_t (*ngx_http_proxy_redirect_pt)(ngx_http_request_t *r,
+ ngx_table_elt_t *h, size_t prefix, ngx_http_proxy_redirect_t *pr);
+
+struct ngx_http_proxy_redirect_s {
+ ngx_http_proxy_redirect_pt handler;
+ ngx_str_t redirect;
+
+ union {
+ ngx_str_t text;
+
+ struct {
+ void *lengths;
+ void *values;
+ } vars;
+
+ void *regex;
+ } replacement;
+};
+
+
typedef struct {
- ngx_http_upstream_conf_t upstream;
+ ngx_http_upstream_conf_t upstream;
- ngx_peers_t *peers;
+ ngx_peers_t *peers;
- ngx_array_t *headers_set_len;
- ngx_array_t *headers_set;
- ngx_hash_t *headers_set_hash;
+ ngx_array_t *headers_set_len;
+ ngx_array_t *headers_set;
+ ngx_hash_t *headers_set_hash;
- ngx_flag_t preserve_host;
- ngx_flag_t set_x_url;
- ngx_flag_t set_x_real_ip;
- ngx_flag_t add_x_forwarded_for;
- ngx_flag_t pass_server;
- ngx_flag_t pass_x_accel_expires;
+ ngx_array_t *headers_source;
+ ngx_array_t *headers_names;
- ngx_str_t *location0;
+ ngx_array_t *redirects;
- ngx_str_t host_header;
- ngx_str_t uri0;
+ ngx_str_t host_header;
+ ngx_str_t port_text;
- ngx_array_t *headers_sources;
- ngx_array_t *headers_names;
+ ngx_flag_t redirect;
} ngx_http_proxy_loc_conf_t;
typedef struct {
- ngx_list_t headers;
-
- ngx_table_elt_t *date;
- ngx_table_elt_t *server;
+ ngx_uint_t status;
+ ngx_uint_t status_count;
+ u_char *status_start;
+ u_char *status_end;
+} ngx_http_proxy_ctx_t;
- ngx_table_elt_t *expires;
- ngx_table_elt_t *cache_control;
- ngx_table_elt_t *etag;
- ngx_table_elt_t *x_accel_expires;
- ngx_table_elt_t *connection;
- ngx_table_elt_t *content_type;
- ngx_table_elt_t *content_length;
-
-#if (NGX_HTTP_GZIP)
- ngx_table_elt_t *content_encoding;
-#endif
-
- ngx_table_elt_t *last_modified;
- ngx_table_elt_t *location;
- ngx_table_elt_t *accept_ranges;
- ngx_table_elt_t *x_pad;
-
- off_t content_length_n;
-} ngx_http_proxy_headers_in_t;
+#define NGX_HTTP_PROXY_PARSE_NO_HEADER 20
static ngx_int_t ngx_http_proxy_create_request(ngx_http_request_t *r);
static ngx_int_t ngx_http_proxy_reinit_request(ngx_http_request_t *r);
+static ngx_int_t ngx_http_proxy_process_status_line(ngx_http_request_t *r);
+static ngx_int_t ngx_http_proxy_parse_status_line(ngx_http_request_t *r,
+ ngx_http_proxy_ctx_t *p);
static ngx_int_t ngx_http_proxy_process_header(ngx_http_request_t *r);
-static ngx_int_t ngx_http_proxy_send_header(ngx_http_request_t *r);
static void ngx_http_proxy_abort_request(ngx_http_request_t *r);
static void ngx_http_proxy_finalize_request(ngx_http_request_t *r,
ngx_int_t rc);
-static ngx_int_t ngx_http_proxy_compile_header_start(ngx_table_elt_t *h,
- ngx_array_t *lengths, ngx_array_t *values, ngx_uint_t value);
-static ngx_int_t ngx_http_proxy_compile_header_end(ngx_array_t *lengths,
- ngx_array_t *values);
+static ngx_http_variable_value_t *
+ ngx_http_proxy_host_variable(ngx_http_request_t *r, uintptr_t data);
+static ngx_http_variable_value_t *
+ ngx_http_proxy_port_variable(ngx_http_request_t *r, uintptr_t data);
+static ngx_http_variable_value_t *
+ ngx_http_proxy_add_x_forwarded_for_variable(ngx_http_request_t *r,
+ uintptr_t data);
+static ngx_int_t ngx_http_proxy_rewrite_redirect(ngx_http_request_t *r,
+ ngx_table_elt_t *h, size_t prefix);
-static ngx_int_t ngx_http_proxy_init(ngx_cycle_t *cycle);
-static ngx_http_variable_value_t *ngx_http_proxy_host_variable
- (ngx_http_request_t *r, uintptr_t data);
+static ngx_int_t ngx_http_proxy_add_variables(ngx_conf_t *cf);
static void *ngx_http_proxy_create_loc_conf(ngx_conf_t *cf);
static char *ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf,
void *parent, void *child);
static char *ngx_http_proxy_pass(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
-
-static char *ngx_http_proxy_set_x_var(ngx_conf_t *cf, ngx_command_t *cmd,
+static char *ngx_http_proxy_redirect(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
+
static char *ngx_http_proxy_lowat_check(ngx_conf_t *cf, void *post, void *data);
+
static ngx_conf_post_t ngx_http_proxy_lowat_post =
- { ngx_http_proxy_lowat_check };
+ { ngx_http_proxy_lowat_check };
+
+static ngx_conf_enum_t ngx_http_proxy_set_methods[] = {
+ { ngx_string("get"), NGX_HTTP_GET },
+ { ngx_null_string, 0 }
+};
static ngx_conf_bitmask_t ngx_http_proxy_next_upstream_masks[] = {
{ ngx_string("error"), NGX_HTTP_UPSTREAM_FT_ERROR },
@@ -113,6 +124,13 @@ static ngx_command_t ngx_http_proxy_commands[] = {
0,
NULL },
+ { ngx_string("proxy_redirect"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE12,
+ ngx_http_proxy_redirect,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ 0,
+ NULL },
+
{ ngx_string("proxy_connect_timeout"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
ngx_conf_set_msec_slot,
@@ -134,46 +152,46 @@ static ngx_command_t ngx_http_proxy_commands[] = {
offsetof(ngx_http_proxy_loc_conf_t, upstream.send_lowat),
&ngx_http_proxy_lowat_post },
- { ngx_string("proxy_pass_unparsed_uri"),
+ { ngx_string("proxy_redirect_errors"),
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.pass_unparsed_uri),
+ offsetof(ngx_http_proxy_loc_conf_t, upstream.redirect_errors),
NULL },
- { ngx_string("proxy_preserve_host"),
+ { ngx_string("proxy_pass_unparsed_uri"),
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, preserve_host),
+ offsetof(ngx_http_proxy_loc_conf_t, upstream.pass_unparsed_uri),
NULL },
- { ngx_string("proxy_set_x_url"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
- ngx_conf_set_flag_slot,
+ { ngx_string("proxy_set_header"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE2,
+ ngx_conf_set_table_elt_slot,
NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_proxy_loc_conf_t, set_x_url),
+ offsetof(ngx_http_proxy_loc_conf_t, headers_source),
NULL },
- { ngx_string("proxy_set_x_real_ip"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
- ngx_conf_set_flag_slot,
+ { ngx_string("proxy_method"),
+ 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_proxy_loc_conf_t, set_x_real_ip),
- NULL },
+ offsetof(ngx_http_proxy_loc_conf_t, upstream.method),
+ ngx_http_proxy_set_methods },
- { ngx_string("proxy_set_x_var"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_http_proxy_set_x_var,
+ { ngx_string("proxy_pass_request_headers"),
+ 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,
- 0,
+ offsetof(ngx_http_proxy_loc_conf_t, upstream.pass_request_headers),
NULL },
- { ngx_string("proxy_add_x_forwarded_for"),
+ { ngx_string("proxy_pass_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_proxy_loc_conf_t, add_x_forwarded_for),
+ offsetof(ngx_http_proxy_loc_conf_t, upstream.pass_request_body),
NULL },
{ ngx_string("proxy_header_buffer_size"),
@@ -232,18 +250,25 @@ static ngx_command_t ngx_http_proxy_commands[] = {
offsetof(ngx_http_proxy_loc_conf_t, upstream.next_upstream),
&ngx_http_proxy_next_upstream_masks },
+ { ngx_string("proxy_pass_x_powered_by"),
+ 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.pass_x_powered_by),
+ NULL },
+
{ ngx_string("proxy_pass_server"),
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, pass_server),
+ offsetof(ngx_http_proxy_loc_conf_t, upstream.pass_server),
NULL },
{ ngx_string("proxy_pass_x_accel_expires"),
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, pass_x_accel_expires),
+ offsetof(ngx_http_proxy_loc_conf_t, upstream.pass_x_accel_expires),
NULL },
ngx_null_command
@@ -251,7 +276,8 @@ static ngx_command_t ngx_http_proxy_commands[] = {
ngx_http_module_t ngx_http_proxy_module_ctx = {
- NULL, /* pre conf */
+ ngx_http_proxy_add_variables, /* preconfiguration */
+ NULL, /* postconfiguration */
NULL, /* create main configuration */
NULL, /* init main configuration */
@@ -265,68 +291,53 @@ ngx_http_module_t ngx_http_proxy_module_ctx = {
ngx_module_t ngx_http_proxy_module = {
- NGX_MODULE,
+ NGX_MODULE_V1,
&ngx_http_proxy_module_ctx, /* module context */
ngx_http_proxy_commands, /* module directives */
NGX_HTTP_MODULE, /* module type */
- ngx_http_proxy_init, /* init module */
+ NULL, /* init module */
NULL /* init process */
};
static ngx_str_t ngx_http_proxy_methods[] = {
- ngx_string("GET"),
- ngx_string("HEAD"),
- ngx_string("POST")
+ ngx_string("GET "),
+ ngx_string("HEAD "),
+ ngx_string("POST ")
};
static char ngx_http_proxy_version[] = " HTTP/1.0" CRLF;
-static ngx_str_t ngx_http_proxy_host = ngx_string("PROXY_HOST");
+static ngx_table_elt_t ngx_http_proxy_headers[] = {
+ { 0, ngx_string("Host"), ngx_string("$proxy_host"), },
+ { 0, ngx_string("Connection"), ngx_string("close"), },
+ { 0, ngx_null_string, ngx_null_string }
+};
-#if (NGX_PCRE)
-static ngx_str_t ngx_http_proxy_uri = ngx_string("/");
-#endif
+static ngx_http_variable_t ngx_http_proxy_vars[] = {
-#if 0
+ { ngx_string("proxy_host"), ngx_http_proxy_host_variable, 0,
+ NGX_HTTP_VAR_CHANGABLE },
-ngx_http_header_t ngx_http_proxy_headers_in[] = {
- { ngx_string("Date"), offsetof(ngx_http_proxy_headers_in_t, date) },
- { ngx_string("Server"), offsetof(ngx_http_proxy_headers_in_t, server) },
-
- { ngx_string("Expires"), offsetof(ngx_http_proxy_headers_in_t, expires) },
- { ngx_string("Cache-Control"),
- offsetof(ngx_http_proxy_headers_in_t, cache_control) },
- { ngx_string("ETag"), offsetof(ngx_http_proxy_headers_in_t, etag) },
- { ngx_string("X-Accel-Expires"),
- offsetof(ngx_http_proxy_headers_in_t, x_accel_expires) },
-
- { ngx_string("Connection"),
- offsetof(ngx_http_proxy_headers_in_t, connection) },
- { ngx_string("Content-Type"),
- offsetof(ngx_http_proxy_headers_in_t, content_type) },
- { ngx_string("Content-Length"),
- offsetof(ngx_http_proxy_headers_in_t, content_length) },
-
-#if (NGX_HTTP_GZIP)
- { ngx_string("Content-Encoding"),
- offsetof(ngx_http_proxy_headers_in_t, content_encoding) },
-#endif
+ { ngx_string("proxy_port"), ngx_http_proxy_port_variable, 0,
+ NGX_HTTP_VAR_CHANGABLE },
+
+ { ngx_string("proxy_add_x_forwarded_for"),
+ ngx_http_proxy_add_x_forwarded_for_variable, 0, 0 },
- { ngx_string("Last-Modified"),
- offsetof(ngx_http_proxy_headers_in_t, last_modified) },
- { ngx_string("Location"),
- offsetof(ngx_http_proxy_headers_in_t, location) },
- { ngx_string("Accept-Ranges"),
- offsetof(ngx_http_proxy_headers_in_t, accept_ranges) },
- { ngx_string("X-Pad"), offsetof(ngx_http_proxy_headers_in_t, x_pad) },
+#if 0
+ { ngx_string("proxy_add_via"), NULL, 0, 0 },
+#endif
- { ngx_null_string, 0 }
+ { ngx_null_string, NULL, 0, 0 }
};
+
+#if (NGX_PCRE)
+static ngx_str_t ngx_http_proxy_uri = ngx_string("/");
#endif
@@ -358,20 +369,17 @@ ngx_http_proxy_handler(ngx_http_request_t *r)
u->create_request = ngx_http_proxy_create_request;
u->reinit_request = ngx_http_proxy_reinit_request;
- u->process_header = ngx_http_proxy_process_header;
- u->send_header = ngx_http_proxy_send_header;
+ u->process_header = ngx_http_proxy_process_status_line;
u->abort_request = ngx_http_proxy_abort_request;
u->finalize_request = ngx_http_proxy_finalize_request;
- u->pipe.input_filter = ngx_event_pipe_copy_input_filter;
+ if (plcf->redirects) {
+ u->rewrite_redirect = ngx_http_proxy_rewrite_redirect;
+ }
- u->log_ctx = r->connection->log->data;
- u->log_handler = ngx_http_upstream_log_error;
+ u->pipe.input_filter = ngx_event_pipe_copy_input_filter;
- u->schema0.len = sizeof("http://") - 1;
- u->schema0.data = (u_char *) "http://";
- u->uri0 = plcf->uri0;
- u->location0 = plcf->location0;
+ u->accel = 1;
r->upstream = u;
@@ -388,19 +396,19 @@ ngx_http_proxy_handler(ngx_http_request_t *r)
static ngx_int_t
ngx_http_proxy_create_request(ngx_http_request_t *r)
{
- size_t len;
- ngx_uint_t i, key;
- uintptr_t escape;
- ngx_buf_t *b;
- ngx_str_t *hh;
- ngx_chain_t *cl;
- ngx_list_part_t *part;
- ngx_table_elt_t *header;
- ngx_http_upstream_t *u;
- ngx_http_proxy_loc_conf_t *plcf;
- ngx_http_script_code_pt code;
- ngx_http_script_len_code_pt lcode;
- ngx_http_script_lite_engine_t e;
+ size_t len, loc_len;
+ ngx_uint_t i, key;
+ uintptr_t escape;
+ ngx_buf_t *b;
+ ngx_str_t *hh;
+ ngx_chain_t *cl, *body;
+ ngx_list_part_t *part;
+ ngx_table_elt_t *header;
+ ngx_http_upstream_t *u;
+ ngx_http_script_code_pt code;
+ ngx_http_script_engine_t e, le;
+ ngx_http_proxy_loc_conf_t *plcf;
+ ngx_http_script_len_code_pt lcode;
u = r->upstream;
@@ -409,65 +417,73 @@ ngx_http_proxy_create_request(ngx_http_request_t *r)
len = sizeof(ngx_http_proxy_version) - 1 + sizeof(CRLF) - 1;
if (u->method) {
- len += ngx_http_proxy_methods[u->method - 1].len + u->uri0.len;
+ len += ngx_http_proxy_methods[u->method - 1].len + u->conf->uri.len;
} else {
- len += r->method_name.len + u->uri0.len;
+ len += r->method_name.len + 1 + u->conf->uri.len;
}
escape = 0;
-
+
+ loc_len = r->valid_location ? u->conf->location->len : 1;
+
if (plcf->upstream.pass_unparsed_uri && r->valid_unparsed_uri) {
len += r->unparsed_uri.len - 1;
} else {
if (r->quoted_uri) {
- escape = 2 * ngx_escape_uri(NULL, r->uri.data + u->location0->len,
- r->uri.len - u->location0->len,
- NGX_ESCAPE_URI);
+ escape = 2 * ngx_escape_uri(NULL, r->uri.data + loc_len,
+ r->uri.len - loc_len, NGX_ESCAPE_URI);
}
- len += r->uri.len - u->location0->len + escape
- + sizeof("?") - 1 + r->args.len;
+ len += r->uri.len - loc_len + escape + sizeof("?") - 1 + r->args.len;
}
+ ngx_memzero(&e, sizeof(ngx_http_script_engine_t));
- e.ip = plcf->headers_set_len->elts;
- e.request = r;
+ le.ip = plcf->headers_set_len->elts;
+ le.request = r;
- while (*(uintptr_t *) e.ip) {
- lcode = *(ngx_http_script_len_code_pt *) e.ip;
- len += lcode(&e);
+ while (*(uintptr_t *) le.ip) {
+ while (*(uintptr_t *) le.ip) {
+ lcode = *(ngx_http_script_len_code_pt *) le.ip;
+ len += lcode(&le);
+ }
+ le.ip += sizeof(uintptr_t);
}
- part = &r->headers_in.headers.part;
- header = part->elts;
hh = (ngx_str_t *) plcf->headers_set_hash->buckets;
- for (i = 0; /* void */; i++) {
+ if (plcf->upstream.pass_request_headers) {
+ part = &r->headers_in.headers.part;
+ header = part->elts;
- if (i >= part->nelts) {
- if (part->next == NULL) {
- break;
+ for (i = 0; /* void */; i++) {
+
+ if (i >= part->nelts) {
+ if (part->next == NULL) {
+ break;
+ }
+
+ part = part->next;
+ header = part->elts;
+ i = 0;
}
- part = part->next;
- header = part->elts;
- i = 0;
- }
+ key = header[i].hash % plcf->headers_set_hash->hash_size;
- key = header[i].hash % plcf->headers_set_hash->hash_size;
+ if (hh[key].len == header[i].key.len
+ && ngx_strcasecmp(hh[key].data, header[i].key.data) == 0)
+ {
+ continue;
+ }
- if (hh[key].len == header[i].key.len
- && ngx_strcasecmp(hh[key].data, header[i].key.data) == 0)
- {
- continue;
+ len += header[i].key.len + sizeof(": ") - 1
+ + header[i].value.len + sizeof(CRLF) - 1;
}
-
- len += header[i].key.len + sizeof(": ") - 1
- + header[i].value.len + sizeof(CRLF) - 1;
}
+
b = ngx_create_temp_buf(r->pool, len);
if (b == NULL) {
return NGX_ERROR;
@@ -479,9 +495,6 @@ ngx_http_proxy_create_request(ngx_http_request_t *r)
}
cl->buf = b;
- cl->next = NULL;
-
- r->request_body->bufs = cl;
/* the request line */
@@ -491,23 +504,24 @@ ngx_http_proxy_create_request(ngx_http_request_t *r)
ngx_http_proxy_methods[u->method - 1].data,
ngx_http_proxy_methods[u->method - 1].len);
} else {
- b->last = ngx_cpymem(b->last, r->method_name.data, r->method_name.len);
+ b->last = ngx_cpymem(b->last, r->method_name.data,
+ r->method_name.len + 1);
}
- b->last = ngx_cpymem(b->last, u->uri0.data, u->uri0.len);
+ b->last = ngx_cpymem(b->last, u->conf->uri.data, u->conf->uri.len);
if (plcf->upstream.pass_unparsed_uri && r->valid_unparsed_uri) {
b->last = ngx_cpymem(b->last, r->unparsed_uri.data + 1,
r->unparsed_uri.len - 1);
} else {
if (escape) {
- ngx_escape_uri(b->last, r->uri.data + u->location0->len,
- r->uri.len - u->location0->len, NGX_ESCAPE_URI);
- b->last += r->uri.len - u->location0->len + escape;
+ ngx_escape_uri(b->last, r->uri.data + loc_len,
+ r->uri.len - loc_len, NGX_ESCAPE_URI);
+ b->last += r->uri.len - loc_len + escape;
} else {
- b->last = ngx_cpymem(b->last, r->uri.data + u->location0->len,
- r->uri.len - u->location0->len);
+ b->last = ngx_cpymem(b->last, r->uri.data + loc_len,
+ r->uri.len - loc_len);
}
if (r->args.len > 0) {
@@ -522,50 +536,76 @@ ngx_http_proxy_create_request(ngx_http_request_t *r)
e.ip = plcf->headers_set->elts;
e.pos = b->last;
+ e.request = r;
- while (*(uintptr_t *) e.ip) {
- code = *(ngx_http_script_code_pt *) e.ip;
- code((ngx_http_script_engine_t *) &e);
+ le.ip = plcf->headers_set_len->elts;
+
+ while (*(uintptr_t *) le.ip) {
+ lcode = *(ngx_http_script_len_code_pt *) le.ip;
+ lcode(&le);
+
+ if (*(ngx_http_script_len_code_pt *) le.ip) {
+
+ for (len = 0; *(uintptr_t *) le.ip; len += lcode(&le)) {
+ lcode = *(ngx_http_script_len_code_pt *) le.ip;
+ }
+
+ e.skip = (len == sizeof(CRLF) - 1) ? 1 : 0;
+
+ } else {
+ e.skip = 0;
+ }
+
+ le.ip += sizeof(uintptr_t);
+
+ 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);
}
b->last = e.pos;
- part = &r->headers_in.headers.part;
- header = part->elts;
+ if (plcf->upstream.pass_request_headers) {
+ part = &r->headers_in.headers.part;
+ header = part->elts;
- for (i = 0; /* void */; i++) {
+ for (i = 0; /* void */; i++) {
- if (i >= part->nelts) {
- if (part->next == NULL) {
- break;
- }
+ if (i >= part->nelts) {
+ if (part->next == NULL) {
+ break;
+ }
- part = part->next;
- header = part->elts;
- i = 0;
- }
+ part = part->next;
+ header = part->elts;
+ i = 0;
+ }
- key = header[i].hash % plcf->headers_set_hash->hash_size;
+ key = header[i].hash % plcf->headers_set_hash->hash_size;
- if (hh[key].len == header[i].key.len
- && ngx_strcasecmp(hh[key].data, header[i].key.data) == 0)
- {
- continue;
- }
+ if (hh[key].len == header[i].key.len
+ && ngx_strcasecmp(hh[key].data, header[i].key.data) == 0)
+ {
+ continue;
+ }
- b->last = ngx_cpymem(b->last, header[i].key.data, header[i].key.len);
+ b->last = ngx_cpymem(b->last, header[i].key.data,
+ header[i].key.len);
- *b->last++ = ':'; *b->last++ = ' ';
+ *b->last++ = ':'; *b->last++ = ' ';
- b->last = ngx_cpymem(b->last, header[i].value.data,
- header[i].value.len);
+ b->last = ngx_cpymem(b->last, header[i].value.data,
+ header[i].value.len);
- *b->last++ = CR; *b->last++ = LF;
+ *b->last++ = CR; *b->last++ = LF;
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http proxy header: \"%V: %V\"",
- &header[i].key, &header[i].value);
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "http proxy header: \"%V: %V\"",
+ &header[i].key, &header[i].value);
+ }
}
/* add "\r\n" at the header end */
@@ -582,6 +622,36 @@ ngx_http_proxy_create_request(ngx_http_request_t *r)
}
#endif
+ if (plcf->upstream.pass_request_body) {
+
+ body = u->request_bufs;
+ u->request_bufs = cl;
+
+ while (body) {
+ b = ngx_alloc_buf(r->pool);
+ if (b == NULL) {
+ return NGX_ERROR;
+ }
+
+ ngx_memcpy(b, body->buf, sizeof(ngx_buf_t));
+
+ cl->next = ngx_alloc_chain_link(r->pool);
+ if (cl->next == NULL) {
+ return NGX_ERROR;
+ }
+
+ cl = cl->next;
+ cl->buf = b;
+
+ body = body->next;
+ }
+
+ } else {
+ u->request_bufs = cl;
+ }
+
+ cl->next = NULL;
+
return NGX_OK;
}
@@ -589,24 +659,369 @@ ngx_http_proxy_create_request(ngx_http_request_t *r)
static ngx_int_t
ngx_http_proxy_reinit_request(ngx_http_request_t *r)
{
+ ngx_http_proxy_ctx_t *p;
+
+ p = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
+
+ if (p == NULL) {
+ return NGX_OK;
+ }
+
+ p->status = 0;
+ p->status_count = 0;
+ p->status_start = NULL;
+ p->status_end = NULL;
+
+ r->upstream->process_header = ngx_http_proxy_process_status_line;
+
return NGX_OK;
}
static ngx_int_t
-ngx_http_proxy_process_header(ngx_http_request_t *r)
+ngx_http_proxy_process_status_line(ngx_http_request_t *r)
{
- return NGX_OK;
+ ngx_int_t rc;
+ ngx_http_upstream_t *u;
+ ngx_http_proxy_ctx_t *p;
+
+ p = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
+
+ if (p == NULL) {
+ p = ngx_pcalloc(r->pool, sizeof(ngx_http_proxy_ctx_t));
+ if (p == NULL) {
+ return NGX_HTTP_INTERNAL_SERVER_ERROR;
+ }
+
+ ngx_http_set_ctx(r, p, ngx_http_proxy_module);
+ }
+
+ rc = ngx_http_proxy_parse_status_line(r, p);
+
+ if (rc == NGX_AGAIN) {
+ return rc;
+ }
+
+ u = r->upstream;
+
+ if (rc == NGX_HTTP_PROXY_PARSE_NO_HEADER) {
+ ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
+ "upstream sent no valid HTTP/1.0 header");
+
+ if (u->accel) {
+ return NGX_HTTP_UPSTREAM_INVALID_HEADER;
+ }
+
+ r->http_version = NGX_HTTP_VERSION_9;
+ p->status = NGX_HTTP_OK;
+
+ return NGX_OK;
+ }
+
+ r->headers_out.status = p->status;
+ u->state->status = p->status;
+
+ r->headers_out.status_line.len = p->status_end - p->status_start;
+ r->headers_out.status_line.data = ngx_palloc(r->pool,
+ r->headers_out.status_line.len);
+ if (r->headers_out.status_line.data == NULL) {
+ return NGX_HTTP_INTERNAL_SERVER_ERROR;
+ }
+ ngx_memcpy(r->headers_out.status_line.data, p->status_start,
+ r->headers_out.status_line.len);
+
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "http proxy status %ui \"%V\"",
+ r->headers_out.status, &r->headers_out.status_line);
+
+ u->process_header = ngx_http_proxy_process_header;
+
+ return ngx_http_proxy_process_header(r);
}
static ngx_int_t
-ngx_http_proxy_send_header(ngx_http_request_t *r)
+ngx_http_proxy_parse_status_line(ngx_http_request_t *r, ngx_http_proxy_ctx_t *p)
{
+ u_char ch;
+ u_char *pos;
+ ngx_http_upstream_t *u;
+ enum {
+ sw_start = 0,
+ sw_H,
+ sw_HT,
+ sw_HTT,
+ sw_HTTP,
+ sw_first_major_digit,
+ sw_major_digit,
+ sw_first_minor_digit,
+ sw_minor_digit,
+ sw_status,
+ sw_space_after_status,
+ sw_status_text,
+ sw_almost_done
+ } state;
+
+ u = r->upstream;
+
+ state = r->state;
+
+ for (pos = u->header_in.pos; pos < u->header_in.last; pos++) {
+ ch = *pos;
+
+ switch (state) {
+
+ /* "HTTP/" */
+ case sw_start:
+ switch (ch) {
+ case 'H':
+ state = sw_H;
+ break;
+ default:
+ return NGX_HTTP_PROXY_PARSE_NO_HEADER;
+ }
+ break;
+
+ case sw_H:
+ switch (ch) {
+ case 'T':
+ state = sw_HT;
+ break;
+ default:
+ return NGX_HTTP_PROXY_PARSE_NO_HEADER;
+ }
+ break;
+
+ case sw_HT:
+ switch (ch) {
+ case 'T':
+ state = sw_HTT;
+ break;
+ default:
+ return NGX_HTTP_PROXY_PARSE_NO_HEADER;
+ }
+ break;
+
+ case sw_HTT:
+ switch (ch) {
+ case 'P':
+ state = sw_HTTP;
+ break;
+ default:
+ return NGX_HTTP_PROXY_PARSE_NO_HEADER;
+ }
+ break;
+
+ case sw_HTTP:
+ switch (ch) {
+ case '/':
+ state = sw_first_major_digit;
+ break;
+ default:
+ return NGX_HTTP_PROXY_PARSE_NO_HEADER;
+ }
+ break;
+
+ /* the first digit of major HTTP version */
+ case sw_first_major_digit:
+ if (ch < '1' || ch > '9') {
+ return NGX_HTTP_PROXY_PARSE_NO_HEADER;
+ }
+
+ state = sw_major_digit;
+ break;
+
+ /* the major HTTP version or dot */
+ case sw_major_digit:
+ if (ch == '.') {
+ state = sw_first_minor_digit;
+ break;
+ }
+
+ if (ch < '0' || ch > '9') {
+ return NGX_HTTP_PROXY_PARSE_NO_HEADER;
+ }
+
+ break;
+
+ /* the first digit of minor HTTP version */
+ case sw_first_minor_digit:
+ if (ch < '0' || ch > '9') {
+ return NGX_HTTP_PROXY_PARSE_NO_HEADER;
+ }
+
+ state = sw_minor_digit;
+ break;
+
+ /* the minor HTTP version or the end of the request line */
+ case sw_minor_digit:
+ if (ch == ' ') {
+ state = sw_status;
+ break;
+ }
+
+ if (ch < '0' || ch > '9') {
+ return NGX_HTTP_PROXY_PARSE_NO_HEADER;
+ }
+
+ break;
+
+ /* HTTP status code */
+ case sw_status:
+ if (ch < '0' || ch > '9') {
+ return NGX_HTTP_PROXY_PARSE_NO_HEADER;
+ }
+
+ p->status = p->status * 10 + ch - '0';
+
+ if (++p->status_count == 3) {
+ state = sw_space_after_status;
+ p->status_start = pos - 2;
+ }
+
+ break;
+
+ /* space or end of line */
+ case sw_space_after_status:
+ switch (ch) {
+ case ' ':
+ state = sw_status_text;
+ break;
+ case '.': /* IIS may send 403.1, 403.2, etc */
+ state = sw_status_text;
+ break;
+ case CR:
+ state = sw_almost_done;
+ break;
+ case LF:
+ goto done;
+ default:
+ return NGX_HTTP_PROXY_PARSE_NO_HEADER;
+ }
+ break;
+
+ /* any text until end of line */
+ case sw_status_text:
+ switch (ch) {
+ case CR:
+ state = sw_almost_done;
+
+ break;
+ case LF:
+ goto done;
+ }
+ break;
+
+ /* end of request line */
+ case sw_almost_done:
+ p->status_end = pos - 1;
+ switch (ch) {
+ case LF:
+ goto done;
+ default:
+ return NGX_HTTP_PROXY_PARSE_NO_HEADER;
+ }
+ }
+ }
+
+ u->header_in.pos = pos + 1;
+ r->state = state;
+
+ return NGX_AGAIN;
+
+done:
+
+ u->header_in.pos = pos + 1;
+
+ if (p->status_end == NULL) {
+ p->status_end = pos;
+ }
+
+ r->state = sw_start;
+
return NGX_OK;
}
+static ngx_int_t
+ngx_http_proxy_process_header(ngx_http_request_t *r)
+{
+ ngx_int_t rc;
+ ngx_uint_t key;
+ ngx_table_elt_t *h;
+ ngx_http_upstream_header_t *hh;
+ ngx_http_upstream_main_conf_t *umcf;
+
+ umcf = ngx_http_get_module_main_conf(r, ngx_http_upstream_module);
+ hh = (ngx_http_upstream_header_t *) umcf->headers_in_hash.buckets;
+
+ for ( ;; ) {
+
+ rc = ngx_http_parse_header_line(r, &r->upstream->header_in);
+
+ if (rc == NGX_OK) {
+
+ /* a header line has been parsed successfully */
+
+ h = ngx_list_push(&r->upstream->headers_in.headers);
+ if (h == NULL) {
+ return NGX_HTTP_INTERNAL_SERVER_ERROR;
+ }
+
+ h->hash = r->header_hash;
+
+ h->key.len = r->header_name_end - r->header_name_start;
+ h->value.len = r->header_end - r->header_start;
+
+ h->key.data = ngx_palloc(r->pool,
+ h->key.len + 1 + h->value.len + 1);
+ if (h->key.data == NULL) {
+ return NGX_HTTP_INTERNAL_SERVER_ERROR;
+ }
+
+ h->value.data = h->key.data + h->key.len + 1;
+
+ ngx_cpystrn(h->key.data, r->header_name_start, h->key.len + 1);
+ ngx_cpystrn(h->value.data, r->header_start, h->value.len + 1);
+
+ key = h->hash % umcf->headers_in_hash.hash_size;
+
+ if (hh[key].name.len == h->key.len
+ && ngx_strcasecmp(hh[key].name.data, h->key.data) == 0)
+ {
+ if (hh[key].handler(r, h, hh[key].offset) != NGX_OK) {
+ return NGX_HTTP_INTERNAL_SERVER_ERROR;
+ }
+ }
+
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "http proxy header: \"%V: %V\"",
+ &h->key, &h->value);
+
+ continue;
+ }
+
+ if (rc == NGX_HTTP_PARSE_HEADER_DONE) {
+
+ /* a whole header has been parsed successfully */
+
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "http proxy header done");
+
+ return NGX_OK;
+ }
+
+ /* there was error while a header line parsing */
+
+ ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
+ ngx_http_upstream_header_errors[rc
+ - NGX_HTTP_PARSE_HEADER_ERROR]);
+
+ return NGX_HTTP_UPSTREAM_INVALID_HEADER;
+ }
+}
+
+
static void
ngx_http_proxy_abort_request(ngx_http_request_t *r)
{
@@ -627,57 +1042,222 @@ ngx_http_proxy_finalize_request(ngx_http_request_t *r, ngx_int_t rc)
}
-static ngx_int_t
-ngx_http_proxy_init(ngx_cycle_t *cycle)
+static ngx_http_variable_value_t *
+ngx_http_proxy_host_variable(ngx_http_request_t *r, uintptr_t data)
{
-#if 0
- ngx_http_variable_t *var;
+ ngx_http_variable_value_t *vv;
+ ngx_http_proxy_loc_conf_t *plcf;
- var = ngx_http_add_variable(cf, &ngx_http_proxy_host, 1);
- if (var == NULL) {
- return NGX_ERROR;
+ vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t));
+ if (vv == NULL) {
+ return NULL;
}
- var->handler = ngx_http_proxy_host_variable;
-#endif
+ plcf = ngx_http_get_module_loc_conf(r, ngx_http_proxy_module);
- return NGX_OK;
+ vv->value = 0;
+ vv->text = plcf->host_header;
-#if 0
- ngx_http_log_op_name_t *op;
+ return vv;
+}
- for (op = ngx_http_proxy_log_fmt_ops; op->name.len; op++) { /* void */ }
- op->run = NULL;
- for (op = ngx_http_log_fmt_ops; op->run; op++) {
- if (op->name.len == 0) {
- op = (ngx_http_log_op_name_t *) op->run;
- }
+static ngx_http_variable_value_t *
+ngx_http_proxy_port_variable(ngx_http_request_t *r, uintptr_t data)
+{
+ ngx_http_variable_value_t *vv;
+ ngx_http_proxy_loc_conf_t *plcf;
+
+ vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t));
+ if (vv == NULL) {
+ return NULL;
}
- op->run = (ngx_http_log_op_run_pt) ngx_http_proxy_log_fmt_ops;
+ plcf = ngx_http_get_module_loc_conf(r, ngx_http_proxy_module);
+
+ vv->value = 0;
+ vv->text = plcf->port_text;
-#endif
+ return vv;
}
static ngx_http_variable_value_t *
-ngx_http_proxy_host_variable(ngx_http_request_t *r, uintptr_t data)
+ngx_http_proxy_add_x_forwarded_for_variable(ngx_http_request_t *r,
+ uintptr_t data)
{
- ngx_http_variable_value_t *var;
- ngx_http_proxy_loc_conf_t *plcf;
+ u_char *p;
+ ngx_http_variable_value_t *vv;
- var = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t));
- if (var == NULL) {
+ vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t));
+ if (vv == NULL) {
return NULL;
}
+ vv->value = 0;
+
+ if (r->headers_in.x_forwarded_for == NULL) {
+ vv->text = r->connection->addr_text;
+ return vv;
+ }
+
+ vv->text.len = r->headers_in.x_forwarded_for->value.len
+ + sizeof(", ") - 1 + r->connection->addr_text.len;
+
+ p = ngx_palloc(r->pool, vv->text.len);
+ if (p == NULL) {
+ return NULL;
+ }
+
+ vv->text.data = p;
+
+ p = ngx_cpymem(p, r->headers_in.x_forwarded_for->value.data,
+ r->headers_in.x_forwarded_for->value.len);
+
+ *p++ = ','; *p++ = ' ';
+
+ ngx_memcpy(p, r->connection->addr_text.data, r->connection->addr_text.len);
+
+ return vv;
+}
+
+
+static ngx_int_t
+ngx_http_proxy_rewrite_redirect(ngx_http_request_t *r, ngx_table_elt_t *h,
+ size_t prefix)
+{
+ ngx_int_t rc;
+ ngx_uint_t i;
+ ngx_http_proxy_loc_conf_t *plcf;
+ ngx_http_proxy_redirect_t *pr;
+
plcf = ngx_http_get_module_loc_conf(r, ngx_http_proxy_module);
- var->value = 0;
- var->text = plcf->host_header;
+ pr = plcf->redirects->elts;
+
+ if (pr == NULL) {
+ return NGX_DECLINED;
+ }
+
+ for (i = 0; i < plcf->redirects->nelts; i++) {
+ rc = pr->handler(r, h, prefix, pr);
- return var;
+ if (rc != NGX_DECLINED) {
+ return rc;
+ }
+ }
+
+ return NGX_DECLINED;
+}
+
+
+static ngx_int_t
+ngx_http_proxy_rewrite_redirect_text(ngx_http_request_t *r, ngx_table_elt_t *h,
+ size_t prefix, ngx_http_proxy_redirect_t *pr)
+{
+ size_t len;
+ u_char *data, *p;
+
+ if (pr->redirect.len > h->value.len - prefix
+ || ngx_rstrncmp(h->value.data + prefix, pr->redirect.data,
+ pr->redirect.len) != 0)
+ {
+ return NGX_DECLINED;
+ }
+
+ len = prefix + pr->replacement.text.len + h->value.len - pr->redirect.len;
+
+ data = ngx_palloc(r->pool, len);
+ if (data == NULL) {
+ return NGX_ERROR;
+ }
+
+ p = data;
+
+ if (prefix) {
+ p = ngx_cpymem(p, h->value.data, prefix);
+ }
+
+ p = ngx_cpymem(p, pr->replacement.text.data, pr->replacement.text.len);
+
+ ngx_memcpy(p, h->value.data + prefix + pr->redirect.len,
+ h->value.len - pr->redirect.len - prefix);
+
+ h->value.len = len;
+ h->value.data = data;
+
+ return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_http_proxy_rewrite_redirect_vars(ngx_http_request_t *r, ngx_table_elt_t *h,
+ size_t prefix, ngx_http_proxy_redirect_t *pr)
+{
+ size_t len;
+ u_char *data, *p;
+ ngx_http_script_code_pt code;
+ ngx_http_script_engine_t e;
+ ngx_http_script_len_code_pt lcode;
+
+ if (pr->redirect.len > h->value.len - prefix
+ || ngx_rstrncmp(h->value.data + prefix, pr->redirect.data,
+ pr->redirect.len) != 0)
+ {
+ return NGX_DECLINED;
+ }
+
+ ngx_memzero(&e, sizeof(ngx_http_script_engine_t));
+
+ e.ip = pr->replacement.vars.lengths;
+ e.request = r;
+
+ for (len = prefix; *(uintptr_t *) e.ip; len += lcode(&e)) {
+ lcode = *(ngx_http_script_len_code_pt *) e.ip;
+ }
+
+ data = ngx_palloc(r->pool, len);
+ if (data == NULL) {
+ return NGX_ERROR;
+ }
+
+ p = data;
+
+ if (prefix) {
+ p = ngx_cpymem(p, h->value.data, prefix);
+ }
+
+ e.ip = pr->replacement.vars.values;
+ e.pos = p;
+
+ while (*(uintptr_t *) e.ip) {
+ code = *(ngx_http_script_code_pt *) e.ip;
+ code(&e);
+ }
+
+ h->value.len = len;
+ h->value.data = data;
+
+ return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_http_proxy_add_variables(ngx_conf_t *cf)
+{
+ ngx_http_variable_t *var, *v;
+
+ for (v = ngx_http_proxy_vars; v->name.len; v++) {
+ var = ngx_http_add_variable(cf, &v->name, v->flags);
+ if (var == NULL) {
+ return NGX_ERROR;
+ }
+
+ var->handler = v->handler;
+ var->data = v->data;
+ }
+
+ return NGX_OK;
}
@@ -698,6 +1278,15 @@ ngx_http_proxy_create_loc_conf(ngx_conf_t *cf)
* conf->upstream.path = NULL;
* conf->upstream.next_upstream = 0;
* conf->upstream.temp_path = NULL;
+ * conf->upstream.schema = { 0, NULL };
+ * conf->upstream.uri = { 0, NULL };
+ * conf->upstream.location = NULL;
+ *
+ * conf->headers_source = NULL;
+ * conf->headers_set_len = NULL;
+ * conf->headers_set = NULL;
+ * conf->headers_set_hash = NULL;
+ * conf->rewrite_locations = NULL;
*/
conf->upstream.connect_timeout = NGX_CONF_UNSET_MSEC;
@@ -709,21 +1298,23 @@ ngx_http_proxy_create_loc_conf(ngx_conf_t *cf)
conf->upstream.busy_buffers_size = NGX_CONF_UNSET_SIZE;
conf->upstream.max_temp_file_size = NGX_CONF_UNSET_SIZE;
conf->upstream.temp_file_write_size = NGX_CONF_UNSET_SIZE;
+
+ conf->upstream.pass_unparsed_uri = NGX_CONF_UNSET;
+ conf->upstream.method = NGX_CONF_UNSET_UINT;
+ conf->upstream.pass_request_headers = NGX_CONF_UNSET;
+ conf->upstream.pass_request_body = NGX_CONF_UNSET;
conf->upstream.redirect_errors = NGX_CONF_UNSET;
- conf->upstream.pass_unparsed_uri = NGX_CONF_UNSET;
- conf->upstream.x_powered_by = NGX_CONF_UNSET;
/* "proxy_cyclic_temp_file" is disabled */
conf->upstream.cyclic_temp_file = 0;
- conf->preserve_host = NGX_CONF_UNSET;
- conf->set_x_url = NGX_CONF_UNSET;
- conf->set_x_real_ip = NGX_CONF_UNSET;
- conf->add_x_forwarded_for = NGX_CONF_UNSET;
+ conf->upstream.pass_x_powered_by = NGX_CONF_UNSET;
+ conf->upstream.pass_server = NGX_CONF_UNSET;
+ conf->upstream.pass_date = 0;
+ conf->upstream.pass_x_accel_expires = NGX_CONF_UNSET;
- conf->pass_server = NGX_CONF_UNSET;
- conf->pass_x_accel_expires = NGX_CONF_UNSET;
+ conf->redirect = NGX_CONF_UNSET;
return conf;
}
@@ -735,11 +1326,16 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
ngx_http_proxy_loc_conf_t *prev = parent;
ngx_http_proxy_loc_conf_t *conf = child;
- size_t size;
- ngx_str_t *name;
- ngx_table_elt_t *src;
- ngx_http_variable_t *var;
-
+ u_char *p;
+ size_t size;
+ uintptr_t *code;
+ ngx_str_t *name;
+ ngx_uint_t i;
+ ngx_table_elt_t *src, *s, *h;
+ ngx_http_proxy_redirect_t *pr;
+ ngx_http_script_compile_t sc;
+ ngx_http_script_copy_code_t *copy;
+
ngx_conf_merge_msec_value(conf->upstream.connect_timeout,
prev->upstream.connect_timeout, 60000);
@@ -841,241 +1437,297 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
|NGX_HTTP_UPSTREAM_FT_ERROR
|NGX_HTTP_UPSTREAM_FT_TIMEOUT));
- ngx_conf_merge_msec_value(conf->upstream.redirect_errors,
- prev->upstream.redirect_errors, 0);
+ ngx_conf_merge_path_value(conf->upstream.temp_path,
+ prev->upstream.temp_path,
+ NGX_HTTP_PROXY_TEMP_PATH, 1, 2, 0,
+ ngx_garbage_collector_temp_handler, cf);
ngx_conf_merge_msec_value(conf->upstream.pass_unparsed_uri,
prev->upstream.pass_unparsed_uri, 0);
- if (conf->upstream.pass_unparsed_uri && conf->location0->len > 1) {
+ if (conf->upstream.pass_unparsed_uri && conf->upstream.location->len > 1) {
ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
"\"proxy_pass_unparsed_uri\" can be set for "
"location \"/\" or given by regular expression.");
return NGX_CONF_ERROR;
}
- ngx_conf_merge_msec_value(conf->upstream.x_powered_by,
- prev->upstream.x_powered_by, 1);
+ if (conf->upstream.method == NGX_CONF_UNSET_UINT) {
+ conf->upstream.method = prev->upstream.method;
+ }
+
+ ngx_conf_merge_value(conf->upstream.pass_request_headers,
+ prev->upstream.pass_request_headers, 1);
+ ngx_conf_merge_value(conf->upstream.pass_request_body,
+ prev->upstream.pass_request_body, 1);
+
+ ngx_conf_merge_msec_value(conf->upstream.redirect_errors,
+ prev->upstream.redirect_errors, 0);
+
+ ngx_conf_merge_msec_value(conf->upstream.pass_x_powered_by,
+ prev->upstream.pass_x_powered_by, 1);
+ ngx_conf_merge_msec_value(conf->upstream.pass_server,
+ prev->upstream.pass_server, 0);
+ ngx_conf_merge_msec_value(conf->upstream.pass_x_accel_expires,
+ prev->upstream.pass_x_accel_expires, 0);
+
+
+ ngx_conf_merge_value(conf->redirect, prev->redirect, 1);
+
+ if (conf->redirect) {
+
+ if (conf->redirects == NULL) {
+ conf->redirects = prev->redirects;
+ }
+
+ if (conf->redirects == NULL && conf->upstream.url.data) {
+
+ conf->redirects = ngx_array_create(cf->pool, 1,
+ sizeof(ngx_http_proxy_redirect_t));
+ if (conf->redirects == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ pr = ngx_array_push(conf->redirects);
+ if (pr == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ pr->handler = ngx_http_proxy_rewrite_redirect_text;
+ pr->redirect = conf->upstream.url;
+ pr->replacement.text = *conf->upstream.location;
+ }
+ }
- ngx_conf_merge_value(conf->preserve_host, prev->preserve_host, 0);
- ngx_conf_merge_value(conf->set_x_url, prev->set_x_url, 0);
- ngx_conf_merge_value(conf->set_x_real_ip, prev->set_x_real_ip, 0);
- ngx_conf_merge_value(conf->add_x_forwarded_for,
- prev->add_x_forwarded_for, 0);
if (conf->peers == NULL) {
conf->peers = prev->peers;
conf->upstream = prev->upstream;
}
- if (conf->headers_set_hash == NULL) {
+ if (conf->headers_source == NULL) {
+ conf->headers_source = prev->headers_source;
conf->headers_set_len = prev->headers_set_len;
conf->headers_set = prev->headers_set;
conf->headers_set_hash = prev->headers_set_hash;
}
- if (conf->headers_set_hash == NULL) {
+ if (conf->headers_set_hash) {
+ return NGX_CONF_OK;
+ }
- if (conf->headers_names == NULL) {
- conf->headers_names = ngx_array_create(cf->pool, 4,
- sizeof(ngx_str_t));
- if (conf->headers_names == NULL) {
- return NGX_CONF_ERROR;
- }
- }
- if (conf->headers_sources == NULL) {
- conf->headers_sources = ngx_array_create(cf->pool, 4,
- sizeof(ngx_table_elt_t));
- if (conf->headers_sources == NULL) {
- return NGX_CONF_ERROR;
- }
- }
+ conf->headers_names = ngx_array_create(cf->pool, 4, sizeof(ngx_str_t));
+ if (conf->headers_names == NULL) {
+ return NGX_CONF_ERROR;
+ }
- /* STUB */
- var = ngx_http_add_variable(cf, &ngx_http_proxy_host, 0);
- if (var == NULL) {
+ if (conf->headers_source == NULL) {
+ conf->headers_source = ngx_array_create(cf->pool, 4,
+ sizeof(ngx_table_elt_t));
+ if (conf->headers_source == NULL) {
return NGX_CONF_ERROR;
}
+ }
- var->handler = ngx_http_proxy_host_variable;
- /**/
+ conf->headers_set_len = ngx_array_create(cf->pool, 64, 1);
+ if (conf->headers_set_len == NULL) {
+ return NGX_CONF_ERROR;
+ }
+ conf->headers_set = ngx_array_create(cf->pool, 512, 1);
+ if (conf->headers_set == NULL) {
+ return NGX_CONF_ERROR;
+ }
- name = ngx_array_push(conf->headers_names);
- if (name == NULL) {
- return NGX_CONF_ERROR;
- }
- name->len = sizeof("Host") - 1;
- name->data = (u_char *) "Host";
+ src = conf->headers_source->elts;
- src = ngx_array_push(conf->headers_sources);
- if (src == NULL) {
+ for (h = ngx_http_proxy_headers; h->key.len; h++) {
+
+ for (i = 0; i < conf->headers_source->nelts; i++) {
+ if (ngx_strcasecmp(h->key.data, src[i].key.data) == 0) {
+ goto next;
+ }
+ }
+
+ s = ngx_array_push(conf->headers_source);
+ if (s == NULL) {
return NGX_CONF_ERROR;
}
- src->hash = 0;
- src->key.len = sizeof("Host") - 1;
- src->key.data = (u_char *) "Host";
- src->value.len = sizeof("$PROXY_HOST") - 1;
- src->value.data = (u_char *) "$PROXY_HOST";
+ *s = *h;
+ next:
+
+ continue;
+ }
+
+ for (i = 0; i < conf->headers_source->nelts; i++) {
name = ngx_array_push(conf->headers_names);
if (name == NULL) {
return NGX_CONF_ERROR;
}
- name->len = sizeof("Connection") - 1;
- name->data = (u_char *) "Connection";
+ *name = src[i].key;
- src = ngx_array_push(conf->headers_sources);
- if (src == NULL) {
- return NGX_CONF_ERROR;
- }
+ if (ngx_http_script_variables_count(&src[i].value) == 0) {
+ copy = ngx_array_push_n(conf->headers_set_len,
+ sizeof(ngx_http_script_copy_code_t));
+ if (copy == NULL) {
+ return NGX_CONF_ERROR;
+ }
- src->hash = 0;
- src->key.len = sizeof("Connection") - 1;
- src->key.data = (u_char *) "Connection";
- src->value.len = sizeof("close") - 1;
- src->value.data = (u_char *) "close";
+ 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;
- name = ngx_array_push(conf->headers_names);
- if (name == NULL) {
- return NGX_CONF_ERROR;
- }
+ 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);
- name->len = 0;
- name->data = NULL;
+ copy = ngx_array_push_n(conf->headers_set, size);
+ if (copy == NULL) {
+ return NGX_CONF_ERROR;
+ }
+ copy->code = ngx_http_script_copy_code;
+ copy->len = src[i].key.len + sizeof(": ") - 1
+ + src[i].value.len + sizeof(CRLF) - 1;
- if (ngx_http_script_compile_lite(cf, conf->headers_sources,
- &conf->headers_set_len, &conf->headers_set,
- ngx_http_proxy_compile_header_start,
- ngx_http_proxy_compile_header_end) != NGX_OK)
- {
- return NGX_CONF_ERROR;
- }
+ 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;
- conf->headers_set_hash = ngx_pcalloc(cf->pool, sizeof(ngx_hash_t));
- if (conf->headers_set_hash == NULL) {
- return NGX_CONF_ERROR;
- }
+ } else {
+ copy = ngx_array_push_n(conf->headers_set_len,
+ sizeof(ngx_http_script_copy_code_t));
+ if (copy == NULL) {
+ return NGX_CONF_ERROR;
+ }
- conf->headers_set_hash->max_size = 100;
- conf->headers_set_hash->bucket_limit = 1;
- conf->headers_set_hash->bucket_size = sizeof(ngx_str_t);
- conf->headers_set_hash->name = "proxy_headers";
+ copy->code = (ngx_http_script_code_pt)
+ ngx_http_script_copy_len_code;
+ copy->len = src[i].key.len + sizeof(": ") - 1;
- if (ngx_hash_init(conf->headers_set_hash, cf->pool,
- conf->headers_names->elts) != NGX_OK)
- {
- return NGX_CONF_ERROR;
- }
-#if 0
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, cf->log, 0,
-#endif
- ngx_log_error(NGX_LOG_NOTICE, cf->log, 0,
- "proxy_headers hash size: %ui, "
- "max buckets per entry: %ui",
- conf->headers_set_hash->hash_size,
- conf->headers_set_hash->min_buckets);
- }
+ size = (sizeof(ngx_http_script_copy_code_t)
+ + src[i].key.len + sizeof(": ") - 1 + sizeof(uintptr_t) - 1)
+ & ~(sizeof(uintptr_t) - 1);
- return NGX_CONF_OK;
-}
+ copy = ngx_array_push_n(conf->headers_set, size);
+ if (copy == NULL) {
+ return NGX_CONF_ERROR;
+ }
+ copy->code = ngx_http_script_copy_code;
+ copy->len = src[i].key.len + sizeof(": ") - 1;
-static ngx_int_t
-ngx_http_proxy_compile_header_start(ngx_table_elt_t *h,
- ngx_array_t *lengths, ngx_array_t *values, ngx_uint_t value)
-{
- u_char *p;
- size_t size;
- ngx_http_script_copy_code_t *copy;
+ 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 = ' ';
- copy = ngx_array_push_n(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;
- copy->len = h->key.len + sizeof(": ") - 1;
+ ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
- if (value) {
- copy->len += h->value.len + sizeof(CRLF) - 1;
- }
+ sc.cf = cf;
+ sc.source = &src[i].value;
+ sc.lengths = &conf->headers_set_len;
+ sc.values = &conf->headers_set;
- size = (copy->len + sizeof(uintptr_t) - 1) & ~(sizeof(uintptr_t) - 1);
+ if (ngx_http_script_compile(&sc) != NGX_OK) {
+ return NGX_CONF_ERROR;
+ }
- copy = ngx_array_push_n(values,
- sizeof(ngx_http_script_copy_code_t) + size);
- if (copy == NULL) {
- return NGX_ERROR;
- }
- copy->code = ngx_http_script_copy;
- copy->len = h->key.len + sizeof(": ") - 1;
+ copy = ngx_array_push_n(conf->headers_set_len,
+ sizeof(ngx_http_script_copy_code_t));
+ if (copy == NULL) {
+ return NGX_CONF_ERROR;
+ }
- if (value) {
- copy->len += h->value.len + sizeof(CRLF) - 1;
- }
+ copy->code = (ngx_http_script_code_pt)
+ ngx_http_script_copy_len_code;
+ copy->len = sizeof(CRLF) - 1;
- p = (u_char *) copy + sizeof(ngx_http_script_copy_code_t);
- p = ngx_cpymem(p, h->key.data, h->key.len);
- p = ngx_cpymem(p, ": ", sizeof(": ") - 1);
+ size = (sizeof(ngx_http_script_copy_code_t)
+ + sizeof(CRLF) - 1 + sizeof(uintptr_t) - 1)
+ & ~(sizeof(uintptr_t) - 1);
- if (value) {
- p = ngx_cpymem(p, h->value.data, h->value.len);
- ngx_memcpy(p, CRLF, sizeof(CRLF) - 1);
- }
+ copy = ngx_array_push_n(conf->headers_set, size);
+ if (copy == NULL) {
+ return NGX_CONF_ERROR;
+ }
- return NGX_OK;
-}
+ copy->code = ngx_http_script_copy_code;
+ copy->len = sizeof(CRLF) - 1;
+ p = (u_char *) copy + sizeof(ngx_http_script_copy_code_t);
+ *p++ = CR; *p = LF;
+ }
-static ngx_int_t
-ngx_http_proxy_compile_header_end(ngx_array_t *lengths, ngx_array_t *values)
-{
- size_t size;
- ngx_http_script_copy_code_t *copy;
+ code = ngx_array_push_n(conf->headers_set_len, sizeof(uintptr_t));
+ if (code == NULL) {
+ return NGX_CONF_ERROR;
+ }
- copy = ngx_array_push_n(lengths, sizeof(ngx_http_script_copy_code_t));
- if (copy == NULL) {
- return NGX_ERROR;
+ *code = (uintptr_t) NULL;
+
+ code = ngx_array_push_n(conf->headers_set, sizeof(uintptr_t));
+ if (code == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ *code = (uintptr_t) NULL;
}
- copy->code = (ngx_http_script_code_pt) ngx_http_script_copy_len;
- copy->len = sizeof(CRLF) - 1;
+ code = ngx_array_push_n(conf->headers_set_len, sizeof(uintptr_t));
+ if (code == NULL) {
+ return NGX_CONF_ERROR;
+ }
- size = (sizeof(CRLF) - 1 + sizeof(uintptr_t) - 1)
- & ~(sizeof(uintptr_t) - 1);
+ *code = (uintptr_t) NULL;
- copy = ngx_array_push_n(values,
- sizeof(ngx_http_script_copy_code_t) + size);
- if (copy == NULL) {
- return NGX_ERROR;
+
+ conf->headers_set_hash = ngx_pcalloc(cf->pool, sizeof(ngx_hash_t));
+ if (conf->headers_set_hash == NULL) {
+ return NGX_CONF_ERROR;
}
- copy->code = ngx_http_script_copy;
- copy->len = sizeof(CRLF) - 1;
+ conf->headers_set_hash->max_size = 100;
+ conf->headers_set_hash->bucket_limit = 1;
+ conf->headers_set_hash->bucket_size = sizeof(ngx_str_t);
+ conf->headers_set_hash->name = "proxy_headers";
+
+ if (ngx_hash_init(conf->headers_set_hash, cf->pool,
+ conf->headers_names->elts, conf->headers_names->nelts) != NGX_OK)
+ {
+ return NGX_CONF_ERROR;
+ }
- ngx_memcpy((u_char *) copy + sizeof(ngx_http_script_copy_code_t),
- CRLF, sizeof(CRLF) - 1);
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, cf->log, 0,
+ "proxy_headers hash size: %ui, "
+ "max buckets per entry: %ui",
+ conf->headers_set_hash->hash_size,
+ conf->headers_set_hash->min_buckets);
- return NGX_OK;
+ return NGX_CONF_OK;
}
static char *
ngx_http_proxy_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
- ngx_http_proxy_loc_conf_t *lcf = conf;
+ ngx_http_proxy_loc_conf_t *plcf = conf;
ngx_uint_t i;
ngx_str_t *value, *url;
@@ -1105,20 +1757,16 @@ ngx_http_proxy_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
unix_upstream.url.data = url->data + 7;
unix_upstream.uri_part = 1;
- lcf->peers = ngx_unix_upstream_parse(cf, &unix_upstream);
- if (lcf->peers == NULL) {
+ plcf->peers = ngx_unix_upstream_parse(cf, &unix_upstream);
+ if (plcf->peers == NULL) {
return NGX_CONF_ERROR;
}
- lcf->peers->peer[0].uri_separator = ":";
+ plcf->peers->peer[0].uri_separator = ":";
- lcf->host_header.len = sizeof("localhost") - 1;
- lcf->host_header.data = (u_char *) "localhost";
- lcf->uri0 = unix_upstream.uri;
-#if 0
- STUB
- lcf->upstream->default_port = 1;
-#endif
+ plcf->host_header.len = sizeof("localhost") - 1;
+ plcf->host_header.data = (u_char *) "localhost";
+ plcf->upstream.uri = unix_upstream.uri;
#else
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
@@ -1137,34 +1785,35 @@ ngx_http_proxy_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
inet_upstream.default_port_value = 80;
inet_upstream.uri_part = 1;
- lcf->peers = ngx_inet_upstream_parse(cf, &inet_upstream);
- if (lcf->peers == NULL) {
+ plcf->peers = ngx_inet_upstream_parse(cf, &inet_upstream);
+ if (plcf->peers == NULL) {
return NGX_CONF_ERROR;
}
- for (i = 0; i < lcf->peers->number; i++) {
- lcf->peers->peer[i].uri_separator = ":";
+ for (i = 0; i < plcf->peers->number; i++) {
+ plcf->peers->peer[i].uri_separator = ":";
}
- lcf->host_header = inet_upstream.host_header;
- lcf->uri0 = inet_upstream.uri;
-#if 0
- STUB
- lcf->port_text = inet_upstream.port_text;
- lcf->upstream->default_port = inet_upstream.default_port;
-#endif
+ plcf->host_header = inet_upstream.host_header;
+ plcf->port_text = inet_upstream.port_text;
+ plcf->upstream.uri = inet_upstream.uri;
}
+ plcf->upstream.schema.len = sizeof("http://") - 1;
+ plcf->upstream.schema.data = (u_char *) "http://";
+
clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
clcf->handler = ngx_http_proxy_handler;
#if (NGX_PCRE)
- lcf->location0 = clcf->regex ? &ngx_http_proxy_uri : &clcf->name;
+ plcf->upstream.location = clcf->regex ? &ngx_http_proxy_uri : &clcf->name;
#else
- lcf->location0 = &clcf->name;
+ plcf->upstream.location = &clcf->name;
#endif
+ plcf->upstream.url = *url;
+
if (clcf->name.data[clcf->name.len - 1] == '/') {
clcf->auto_redirect = 1;
}
@@ -1174,8 +1823,84 @@ ngx_http_proxy_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
static char *
-ngx_http_proxy_set_x_var(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
+ngx_http_proxy_redirect(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
+ ngx_http_proxy_loc_conf_t *plcf = conf;
+
+ ngx_str_t *value;
+ ngx_array_t *vars_lengths, *vars_values;
+ ngx_http_script_compile_t sc;
+ ngx_http_proxy_redirect_t *pr;
+
+ if (plcf->redirect == 0) {
+ return NGX_CONF_OK;
+ }
+
+ value = cf->args->elts;
+
+ if (ngx_strcmp(value[1].data, "off") == 0) {
+ plcf->redirect = 0;
+ plcf->redirects = NULL;
+ return NGX_CONF_OK;
+ }
+
+ if (plcf->redirects == NULL) {
+ plcf->redirects = ngx_array_create(cf->pool, 1,
+ sizeof(ngx_http_proxy_redirect_t));
+ if (plcf->redirects == NULL) {
+ return NGX_CONF_ERROR;
+ }
+ }
+
+ pr = ngx_array_push(plcf->redirects);
+ if (pr == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ if (cf->args->nelts == 2 && ngx_strcmp(value[1].data, "default") == 0) {
+ if (plcf->upstream.url.data == NULL) {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "\"proxy_rewrite_location default\" must go "
+ "after the \"proxy_pass\" directive");
+ return NGX_CONF_ERROR;
+ }
+
+ pr->handler = ngx_http_proxy_rewrite_redirect_text;
+ pr->redirect = plcf->upstream.url;
+ pr->replacement.text = *plcf->upstream.location;
+
+ return NGX_CONF_OK;
+ }
+
+ if (ngx_http_script_variables_count(&value[2]) == 0) {
+ pr->handler = ngx_http_proxy_rewrite_redirect_text;
+ pr->redirect = value[1];
+ pr->replacement.text = value[2];
+
+ return NGX_CONF_OK;
+ }
+
+ ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
+
+ vars_lengths = NULL;
+ vars_values = NULL;
+
+ sc.cf = cf;
+ sc.source = &value[2];
+ sc.lengths = &vars_lengths;
+ sc.values = &vars_values;
+ sc.complete_lengths = 1;
+ sc.complete_values = 1;
+
+ if (ngx_http_script_compile(&sc) != NGX_OK) {
+ return NGX_CONF_ERROR;
+ }
+
+ pr->handler = ngx_http_proxy_rewrite_redirect_vars;
+ pr->redirect = value[1];
+ pr->replacement.vars.lengths = vars_lengths->elts;
+ pr->replacement.vars.values = vars_values->elts;
+
return NGX_CONF_OK;
}
diff --git a/src/http/modules/ngx_http_range_filter_module.c b/src/http/modules/ngx_http_range_filter_module.c
index 84381c930..cfc23f6e1 100644
--- a/src/http/modules/ngx_http_range_filter_module.c
+++ b/src/http/modules/ngx_http_range_filter_module.c
@@ -54,7 +54,8 @@ static ngx_int_t ngx_http_range_body_filter_init(ngx_cycle_t *cycle);
static ngx_http_module_t ngx_http_range_header_filter_module_ctx = {
- NULL, /* pre conf */
+ NULL, /* preconfiguration */
+ NULL, /* postconfiguration */
NULL, /* create main configuration */
NULL, /* init main configuration */
@@ -68,7 +69,7 @@ static ngx_http_module_t ngx_http_range_header_filter_module_ctx = {
ngx_module_t ngx_http_range_header_filter_module = {
- NGX_MODULE,
+ NGX_MODULE_V1,
&ngx_http_range_header_filter_module_ctx, /* module context */
NULL, /* module directives */
NGX_HTTP_MODULE, /* module type */
@@ -78,7 +79,8 @@ ngx_module_t ngx_http_range_header_filter_module = {
static ngx_http_module_t ngx_http_range_body_filter_module_ctx = {
- NULL, /* pre conf */
+ NULL, /* preconfiguration */
+ NULL, /* postconfiguration */
NULL, /* create main configuration */
NULL, /* init main configuration */
@@ -92,7 +94,7 @@ static ngx_http_module_t ngx_http_range_body_filter_module_ctx = {
ngx_module_t ngx_http_range_body_filter_module = {
- NGX_MODULE,
+ NGX_MODULE_V1,
&ngx_http_range_body_filter_module_ctx, /* module context */
NULL, /* module directives */
NGX_HTTP_MODULE, /* module type */
@@ -120,6 +122,7 @@ ngx_http_range_header_filter(ngx_http_request_t *r)
if (r->http_version < NGX_HTTP_VERSION_10
|| r->headers_out.status != NGX_HTTP_OK
+ || r->main
|| r->headers_out.content_length_n == -1
|| !r->filter_allow_ranges)
{
@@ -136,6 +139,7 @@ ngx_http_range_header_filter(ngx_http_request_t *r)
return NGX_ERROR;
}
+ r->headers_out.accept_ranges->hash = 1;
r->headers_out.accept_ranges->key.len = sizeof("Accept-Ranges") - 1;
r->headers_out.accept_ranges->key.data = (u_char *) "Accept-Ranges";
r->headers_out.accept_ranges->value.len = sizeof("bytes") - 1;
@@ -269,6 +273,7 @@ ngx_http_range_header_filter(ngx_http_request_t *r)
r->headers_out.content_range = content_range;
+ content_range->hash = 1;
content_range->key.len = sizeof("Content-Range") - 1;
content_range->key.data = (u_char *) "Content-Range";
@@ -303,6 +308,7 @@ ngx_http_range_header_filter(ngx_http_request_t *r)
r->headers_out.content_range = content_range;
+ content_range->hash = 1;
content_range->key.len = sizeof("Content-Range") - 1;
content_range->key.data = (u_char *) "Content-Range";
@@ -338,7 +344,7 @@ ngx_http_range_header_filter(ngx_http_request_t *r)
len = sizeof(CRLF "--") - 1 + NGX_ATOMIC_T_LEN
+ sizeof(CRLF "Content-Type: ") - 1
- + r->headers_out.content_type->value.len
+ + r->headers_out.content_type.len
+ sizeof(CRLF "Content-Range: bytes ") - 1;
if (r->headers_out.charset.len) {
@@ -366,7 +372,7 @@ ngx_http_range_header_filter(ngx_http_request_t *r)
"Content-Type: %V; charset=%V" CRLF
"Content-Range: bytes ",
boundary,
- &r->headers_out.content_type->value,
+ &r->headers_out.content_type,
&r->headers_out.charset)
- ctx->boundary_header.data;
@@ -378,26 +384,26 @@ ngx_http_range_header_filter(ngx_http_request_t *r)
"Content-Type: %V" CRLF
"Content-Range: bytes ",
boundary,
- &r->headers_out.content_type->value)
+ &r->headers_out.content_type)
- ctx->boundary_header.data;
}
- r->headers_out.content_type->value.data =
- ngx_palloc(r->pool,
- sizeof("Content-Type: multipart/byteranges; boundary=") - 1
- + NGX_ATOMIC_T_LEN);
+ r->headers_out.content_type.data =
+ ngx_palloc(r->pool,
+ sizeof("Content-Type: multipart/byteranges; boundary=") - 1
+ + NGX_ATOMIC_T_LEN);
- if (r->headers_out.content_type->value.data == NULL) {
+ if (r->headers_out.content_type.data == NULL) {
return NGX_ERROR;
}
/* "Content-Type: multipart/byteranges; boundary=0123456789" */
- r->headers_out.content_type->value.len =
- ngx_sprintf(r->headers_out.content_type->value.data,
+ r->headers_out.content_type.len =
+ ngx_sprintf(r->headers_out.content_type.data,
"multipart/byteranges; boundary=%0muA",
boundary)
- - r->headers_out.content_type->value.data;
+ - r->headers_out.content_type.data;
/* the size of the last boundary CRLF "--0123456789--" CRLF */
diff --git a/src/http/modules/ngx_http_rewrite_module.c b/src/http/modules/ngx_http_rewrite_module.c
index 1da475cc8..2dc7a7fff 100644
--- a/src/http/modules/ngx_http_rewrite_module.c
+++ b/src/http/modules/ngx_http_rewrite_module.c
@@ -9,136 +9,36 @@
#include <ngx_http.h>
-typedef struct ngx_http_rewrite_engine_s ngx_http_rewrite_engine_t;
-
-typedef void (*ngx_http_rewrite_code_pt) (ngx_http_rewrite_engine_t *e);
-
-
typedef struct {
- ngx_str_t name;
- ngx_uint_t wildcard;
+ ngx_str_t name;
+ ngx_uint_t wildcard;
} ngx_http_rewrite_referer_t;
typedef struct {
- ngx_str_t *name;
- ngx_http_variable_value_t *value;
+ ngx_str_t *name;
+ ngx_http_variable_value_t *value;
} ngx_http_rewrite_variable_t;
typedef struct {
- ngx_array_t *codes; /* uintptr_t */
- ngx_array_t *referers; /* ngx_http_rewrite_referer_t */
+ ngx_array_t *codes; /* uintptr_t */
+ ngx_array_t *referers; /* ngx_http_rewrite_referer_t */
- ngx_uint_t max_captures;
- ngx_uint_t stack_size;
+ ngx_uint_t max_captures;
+ ngx_uint_t stack_size;
- ngx_flag_t log;
+ ngx_flag_t log;
- ngx_flag_t no_referer;
- ngx_flag_t blocked_referer;
+ ngx_flag_t no_referer;
+ ngx_flag_t blocked_referer;
} ngx_http_rewrite_loc_conf_t;
-typedef struct {
- ngx_http_rewrite_code_pt code;
- ngx_regex_t *regex;
- uintptr_t size;
- uintptr_t ncaptures;
- uintptr_t status;
- uintptr_t next;
-
- uintptr_t test:1;
- uintptr_t uri:1;
-
- /* add the r->args to the new arguments */
- uintptr_t args:1;
-
- uintptr_t redirect:1;
- uintptr_t break_cycle:1;
-
- ngx_str_t name;
-} ngx_http_rewrite_regex_code_t;
-
-
-typedef struct {
- ngx_http_rewrite_code_pt code;
-
- uintptr_t uri:1;
-
- /* add the r->args to the new arguments */
- uintptr_t args:1;
-
- uintptr_t redirect:1;
-} ngx_http_rewrite_regex_end_code_t;
-
-typedef struct {
- ngx_http_rewrite_code_pt code;
- uintptr_t n;
-} ngx_http_rewrite_copy_capture_code_t;
-
-
-typedef struct {
- ngx_http_rewrite_code_pt code;
- uintptr_t len;
-} ngx_http_rewrite_copy_code_t;
-
-
-typedef struct {
- ngx_http_rewrite_code_pt code;
- uintptr_t status;
- uintptr_t null;
-} ngx_http_rewrite_return_code_t;
-
-
-typedef struct {
- ngx_http_rewrite_code_pt code;
- uintptr_t next;
- void **loc_conf;
-} ngx_http_rewrite_if_code_t;
-
-
-typedef struct {
- ngx_http_rewrite_code_pt code;
- uintptr_t value;
- uintptr_t text_len;
- uintptr_t text_data;
-} ngx_http_rewrite_value_code_t;
-
-
-typedef struct {
- ngx_http_rewrite_code_pt code;
- uintptr_t index;
-} ngx_http_rewrite_var_code_t;
-
-
-struct ngx_http_rewrite_engine_s {
- u_char *ip;
- ngx_http_variable_value_t *sp;
-
- ngx_str_t buf;
- ngx_str_t *line;
-
- u_char *pos;
-
- /* the start of the rewritten arguments */
- u_char *args;
-
- unsigned quote:1;
-
- ngx_int_t status;
-
- int *captures;
-
- ngx_http_request_t *request;
- ngx_http_rewrite_loc_conf_t *conf;
-};
-
-
-static ngx_int_t ngx_http_rewrite_init(ngx_cycle_t *cycle);
static void *ngx_http_rewrite_create_loc_conf(ngx_conf_t *cf);
static char *ngx_http_rewrite_merge_loc_conf(ngx_conf_t *cf,
void *parent, void *child);
+static ngx_int_t ngx_http_rewrite_init(ngx_cycle_t *cycle);
static char *ngx_http_rewrite(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
static char *ngx_http_rewrite_return(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
@@ -150,12 +50,8 @@ static char *ngx_http_rewrite_variable(ngx_conf_t *cf,
ngx_http_rewrite_loc_conf_t *lcf, ngx_str_t *value);
static char *ngx_http_rewrite_valid_referers(ngx_conf_t *cf,
ngx_command_t *cmd, void *conf);
-static char * ngx_http_rewrite_set(ngx_conf_t *cf, ngx_command_t *cmd,
+static char *ngx_http_rewrite_set(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
-static void *ngx_http_rewrite_start_code(ngx_pool_t *pool,
- ngx_array_t **codes, size_t size);
-static void *ngx_http_rewrite_add_code(ngx_array_t *codes, size_t size,
- void *code);
static ngx_command_t ngx_http_rewrite_commands[] = {
@@ -211,7 +107,8 @@ static ngx_command_t ngx_http_rewrite_commands[] = {
ngx_http_module_t ngx_http_rewrite_module_ctx = {
- NULL, /* pre conf */
+ NULL, /* preconfiguration */
+ NULL, /* postconfiguration */
NULL, /* create main configuration */
NULL, /* init main configuration */
@@ -225,7 +122,7 @@ ngx_http_module_t ngx_http_rewrite_module_ctx = {
ngx_module_t ngx_http_rewrite_module = {
- NGX_MODULE,
+ NGX_MODULE_V1,
&ngx_http_rewrite_module_ctx, /* module context */
ngx_http_rewrite_commands, /* module directives */
NGX_HTTP_MODULE, /* module type */
@@ -234,19 +131,15 @@ ngx_module_t ngx_http_rewrite_module = {
};
-#define ngx_http_rewrite_exit (u_char *) &ngx_http_rewrite_exit_code
-
-uintptr_t ngx_http_rewrite_exit_code = (uintptr_t) NULL;
-
static ngx_http_variable_value_t ngx_http_rewrite_null_value =
- { 0, ngx_string("") };
+ { 0, ngx_string("") };
static ngx_int_t
ngx_http_rewrite_handler(ngx_http_request_t *r)
{
- ngx_http_rewrite_code_pt code;
- ngx_http_rewrite_engine_t *e;
+ ngx_http_script_code_pt code;
+ ngx_http_script_engine_t *e;
ngx_http_rewrite_loc_conf_t *cf;
cf = ngx_http_get_module_loc_conf(r, ngx_http_rewrite_module);
@@ -255,13 +148,13 @@ ngx_http_rewrite_handler(ngx_http_request_t *r)
return NGX_DECLINED;
}
- e = ngx_palloc(r->pool, sizeof(ngx_http_rewrite_engine_t));
+ e = ngx_pcalloc(r->pool, sizeof(ngx_http_script_engine_t));
if (e == NULL) {
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
- e->sp = ngx_palloc(r->pool,
- cf->stack_size * sizeof(ngx_http_variable_value_t));
+ e->sp = ngx_pcalloc(r->pool,
+ cf->stack_size * sizeof(ngx_http_variable_value_t));
if (e->sp == NULL) {
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
@@ -277,18 +170,13 @@ ngx_http_rewrite_handler(ngx_http_request_t *r)
}
e->ip = cf->codes->elts;
- e->buf.len = 0;
- e->buf.data = NULL;
- e->line = NULL;
- e->pos = NULL;
- e->args = NULL;
+ e->request = r;
e->quote = 1;
+ e->log = cf->log;
e->status = NGX_DECLINED;
- e->request = r;
- e->conf = cf;
while (*(uintptr_t *) e->ip) {
- code = *(ngx_http_rewrite_code_pt *) e->ip;
+ code = *(ngx_http_script_code_pt *) e->ip;
code(e);
}
@@ -297,392 +185,7 @@ ngx_http_rewrite_handler(ngx_http_request_t *r)
static void
-ngx_http_rewrite_regex_start_code(ngx_http_rewrite_engine_t *e)
-{
- ngx_int_t rc;
- ngx_uint_t n;
- ngx_http_request_t *r;
- ngx_http_rewrite_regex_code_t *code;
-
- code = (ngx_http_rewrite_regex_code_t *) e->ip;
-
- r = e->request;
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http rewrite regex: \"%V\"", &code->name);
-
- if (code->uri) {
- e->line = &r->uri;
- } else {
- e->sp--;
- e->line = &e->sp->text;
- }
-
- rc = ngx_regex_exec(code->regex, e->line, e->captures, code->ncaptures);
-
- if (rc == NGX_REGEX_NO_MATCHED) {
- if (e->conf->log) {
- ngx_log_error(NGX_LOG_NOTICE, r->connection->log, 0,
- "\"%V\" does not match \"%V\"", &code->name, e->line);
- }
-
- if (code->test) {
- e->sp->value = 0;
- e->sp->text.len = 0;
- e->sp->text.data = (u_char *) "";
- e->sp++;
-
- e->ip += sizeof(ngx_http_rewrite_regex_code_t);
- return;
- }
-
- e->ip += code->next;
- return;
- }
-
- if (rc < 0) {
- ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
- ngx_regex_exec_n " failed: %d on \"%V\" using \"%V\"",
- rc, e->line, &code->name);
-
- e->ip = ngx_http_rewrite_exit;
- e->status = NGX_HTTP_INTERNAL_SERVER_ERROR;
- return;
- }
-
- if (e->conf->log) {
- ngx_log_error(NGX_LOG_NOTICE, r->connection->log, 0,
- "\"%V\" matches \"%V\"", &code->name, e->line);
- }
-
- if (code->test) {
- e->sp->value = 1;
- e->sp->text.len = 1;
- e->sp->text.data = (u_char *) "1";
- e->sp++;
-
- e->ip += sizeof(ngx_http_rewrite_regex_code_t);
- return;
- }
-
- if (code->status) {
- e->status = code->status;
-
- if (!code->redirect) {
- e->ip = ngx_http_rewrite_exit;
- return;
- }
- }
-
- e->buf.len = code->size;
-
- if (code->uri) {
- if (!code->break_cycle) {
- r->uri_changed = 1;
- r->valid_unparsed_uri = 1;
- }
-
- if (rc && (r->quoted_uri || r->plus_in_uri)) {
- e->buf.len += 2 * ngx_escape_uri(NULL, r->uri.data, r->uri.len,
- NGX_ESCAPE_ARGS);
- }
- }
-
- for (n = 1; n < (ngx_uint_t) rc; n++) {
- e->buf.len += e->captures[2 * n + 1] - e->captures[2 * n];
- }
-
- if (code->args && r->args.len) {
- e->buf.len += r->args.len + 1;
- }
-
- e->buf.data = ngx_palloc(r->pool, e->buf.len);
- if (e->buf.data == NULL) {
- e->ip = ngx_http_rewrite_exit;
- e->status = NGX_HTTP_INTERNAL_SERVER_ERROR;
- return;
- }
-
- e->quote = code->redirect;
-
- e->pos = e->buf.data;
-
- e->ip += sizeof(ngx_http_rewrite_regex_code_t);
-}
-
-
-static void
-ngx_http_rewrite_regex_end_code(ngx_http_rewrite_engine_t *e)
-{
- ngx_http_request_t *r;
- ngx_http_rewrite_regex_end_code_t *code;
-
- code = (ngx_http_rewrite_regex_end_code_t *) e->ip;
-
- r = e->request;
-
- e->quote = 0;
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http rewrite regex end");
-
- if (e->args) {
- e->buf.len = e->args - e->buf.data;
-
- if (code->args && r->args.len) {
- *e->pos++ = '&';
- e->pos = ngx_cpymem(e->pos, r->args.data, r->args.len);
- }
-
- r->args.len = e->pos - e->args;
- r->args.data = e->args;
-
- e->args = NULL;
-
- } else {
- if (code->args && r->args.len) {
- *e->pos++ = '?';
- e->pos = ngx_cpymem(e->pos, r->args.data, r->args.len);
- }
-
- e->buf.len = e->pos - e->buf.data;
- }
-
- if (!code->redirect) {
- if (e->conf->log) {
- ngx_log_error(NGX_LOG_NOTICE, r->connection->log, 0,
- "rewritten data: \"%V\", args: \"%V\"",
- &e->buf, &r->args);
- }
-
- if (code->uri) {
- r->uri = e->buf;
-
- if (ngx_http_set_exten(r) != NGX_OK) {
- e->ip = ngx_http_rewrite_exit;
- e->status = NGX_HTTP_INTERNAL_SERVER_ERROR;
- return;
- }
- }
-
- e->ip += sizeof(ngx_http_rewrite_regex_end_code_t);
- return;
- }
-
- ngx_log_error(NGX_LOG_NOTICE, r->connection->log, 0,
- "rewritten redirect: \"%V\"", &e->buf);
-
- r->headers_out.location = ngx_list_push(&r->headers_out.headers);
- if (r->headers_out.location == NULL) {
- e->ip = ngx_http_rewrite_exit;
- e->status = NGX_HTTP_INTERNAL_SERVER_ERROR;
- return;
- }
-
- if (e->buf.data[0] != '/') {
- r->headers_out.location->key.len = sizeof("Location") - 1;
- r->headers_out.location->key.data = (u_char *) "Location";
- }
-
- r->headers_out.location->value = e->buf;
-
- e->ip += sizeof(ngx_http_rewrite_regex_end_code_t);
-}
-
-
-static void
-ngx_http_rewrite_copy_capture_code(ngx_http_rewrite_engine_t *e)
-{
- ngx_http_rewrite_copy_capture_code_t *code;
-
- code = (ngx_http_rewrite_copy_capture_code_t *) e->ip;
-
- e->ip += sizeof(ngx_http_rewrite_copy_capture_code_t);
-
- if ((e->args || e->quote)
- && (e->request->quoted_uri || e->request->plus_in_uri))
- {
- e->pos = (u_char *) ngx_escape_uri(e->pos,
- &e->line->data[e->captures[code->n]],
- e->captures[code->n + 1] - e->captures[code->n],
- NGX_ESCAPE_ARGS);
- } else {
- e->pos = ngx_cpymem(e->pos, &e->line->data[e->captures[code->n]],
- e->captures[code->n + 1] - e->captures[code->n]);
- }
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
- "http rewrite capture: \"%V\"", &e->buf);
-}
-
-
-static void
-ngx_http_rewrite_copy_code(ngx_http_rewrite_engine_t *e)
-{
- ngx_http_rewrite_copy_code_t *code;
-
- code = (ngx_http_rewrite_copy_code_t *) e->ip;
-
- e->pos = ngx_cpymem(e->pos, e->ip + sizeof(ngx_http_rewrite_copy_code_t),
- code->len);
-
- e->ip += sizeof(ngx_http_rewrite_copy_code_t)
- + ((code->len + sizeof(uintptr_t) - 1) & ~(sizeof(uintptr_t) - 1));
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
- "http rewrite copy: \"%V\"", &e->buf);
-}
-
-
-static void
-ngx_http_rewrite_start_args_code(ngx_http_rewrite_engine_t *e)
-{
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
- "http rewrite args");
-
- e->args = e->pos;
- e->ip += sizeof(uintptr_t);
-}
-
-
-static void
-ngx_http_rewrite_return_code(ngx_http_rewrite_engine_t *e)
-{
- ngx_http_rewrite_return_code_t *code;
-
- code = (ngx_http_rewrite_return_code_t *) e->ip;
-
- e->status = code->status;
-
- e->ip += sizeof(ngx_http_rewrite_return_code_t) - sizeof(uintptr_t);
-}
-
-
-static void
-ngx_http_rewrite_if_code(ngx_http_rewrite_engine_t *e)
-{
- ngx_http_rewrite_if_code_t *code;
-
- code = (ngx_http_rewrite_if_code_t *) e->ip;
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
- "http rewrite if");
-
- e->sp--;
-
- if (e->sp->value) {
- if (code->loc_conf) {
- e->request->loc_conf = code->loc_conf;
- }
-
- e->ip += sizeof(ngx_http_rewrite_if_code_t);
- return;
- }
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
- "http rewrite if false");
-
- e->ip += code->next;
-}
-
-
-static void
-ngx_http_rewrite_value_code(ngx_http_rewrite_engine_t *e)
-{
- ngx_http_rewrite_value_code_t *code;
-
- code = (ngx_http_rewrite_value_code_t *) e->ip;
-
- e->ip += sizeof(ngx_http_rewrite_value_code_t);
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
- "http rewrite value");
-
- e->sp->value = (ngx_uint_t) code->value;
- e->sp->text.len = (size_t) code->text_len;
- e->sp->text.data = (u_char *) code->text_data;
- e->sp++;
-}
-
-
-static void
-ngx_http_rewrite_set_var_code(ngx_http_rewrite_engine_t *e)
-{
- ngx_http_request_t *r;
- ngx_http_variable_value_t *value;
- ngx_http_core_main_conf_t *cmcf;
- ngx_http_rewrite_var_code_t *code;
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
- "http rewrite set var");
-
- code = (ngx_http_rewrite_var_code_t *) e->ip;
-
- e->ip += sizeof(ngx_http_rewrite_var_code_t);
-
- r = e->request;
-
- if (r->variables == NULL) {
- cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
-
- r->variables = ngx_pcalloc(r->pool, cmcf->variables.nelts
- * sizeof(ngx_http_variable_value_t *));
- if (r->variables == NULL) {
- e->ip = ngx_http_rewrite_exit;
- e->status = NGX_HTTP_INTERNAL_SERVER_ERROR;
- return;
- }
- }
-
- value = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t));
- if (value == NULL) {
- e->ip = ngx_http_rewrite_exit;
- e->status = NGX_HTTP_INTERNAL_SERVER_ERROR;
- return;
- }
-
- e->sp--;
-
- *value = *e->sp;
-
- r->variables[code->index] = value;
-}
-
-
-static void
-ngx_http_rewrite_var_code(ngx_http_rewrite_engine_t *e)
-{
- ngx_http_variable_value_t *value;
- ngx_http_rewrite_var_code_t *code;
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
- "http rewrite var");
-
- code = (ngx_http_rewrite_var_code_t *) e->ip;
-
- e->ip += sizeof(ngx_http_rewrite_var_code_t);
-
- value = ngx_http_get_indexed_variable(e->request, code->index);
-
- if (value == NULL || value == NGX_HTTP_VARIABLE_NOT_FOUND) {
- e->sp->value = 0;
- e->sp->text.len = 0;
- e->sp->text.data = (u_char *) "";
- e->sp++;
-
- return;
- }
-
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
- "http rewrite var: %ui, \"%V\"", value->value, &value->text);
-
- *e->sp = *value;
- e->sp++;
-}
-
-
-static void
-ngx_http_rewrite_invalid_referer_code(ngx_http_rewrite_engine_t *e)
+ngx_http_rewrite_invalid_referer_code(ngx_http_script_engine_t *e)
{
u_char *ref;
size_t len;
@@ -804,13 +307,6 @@ ngx_http_rewrite_invalid_referer_code(ngx_http_rewrite_engine_t *e)
}
-static void
-ngx_http_rewrite_nop_code(ngx_http_rewrite_engine_t *e)
-{
- e->ip += sizeof(uintptr_t);
-}
-
-
static ngx_http_variable_value_t *
ngx_http_rewrite_var(ngx_http_request_t *r, uintptr_t data)
{
@@ -834,25 +330,6 @@ ngx_http_rewrite_var(ngx_http_request_t *r, uintptr_t data)
}
-static ngx_int_t
-ngx_http_rewrite_init(ngx_cycle_t *cycle)
-{
- ngx_http_handler_pt *h;
- ngx_http_core_main_conf_t *cmcf;
-
- cmcf = ngx_http_cycle_get_module_main_conf(cycle, ngx_http_core_module);
-
- h = ngx_array_push(&cmcf->phases[NGX_HTTP_REWRITE_PHASE].handlers);
- if (h == NULL) {
- return NGX_ERROR;
- }
-
- *h = ngx_http_rewrite_handler;
-
- return NGX_OK;
-}
-
-
static void *
ngx_http_rewrite_create_loc_conf(ngx_conf_t *cf)
{
@@ -878,8 +355,7 @@ ngx_http_rewrite_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
ngx_http_rewrite_loc_conf_t *prev = parent;
ngx_http_rewrite_loc_conf_t *conf = child;
- uintptr_t *code, *last;
- ngx_http_rewrite_regex_code_t *regex;
+ uintptr_t *code;
ngx_conf_merge_value(conf->log, prev->log, 0);
ngx_conf_merge_unsigned_value(conf->stack_size, prev->stack_size, 10);
@@ -906,65 +382,6 @@ ngx_http_rewrite_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
return NGX_CONF_OK;
}
- code = conf->codes->elts;
- last = (uintptr_t *) ((u_char *) code + conf->codes->nelts);
-
- while (code < last) {
- if (*code == (uintptr_t) NULL) {
- return NGX_CONF_OK;
- }
-
- if (*code == (uintptr_t) &ngx_http_rewrite_regex_start_code) {
- regex = (ngx_http_rewrite_regex_code_t *) code;
- if (conf->max_captures < regex->ncaptures) {
- conf->max_captures = regex->ncaptures;
- }
- code = (uintptr_t *) ((u_char *) code + regex->next);
- continue;
- }
-
- if (*code == (uintptr_t) &ngx_http_rewrite_if_code) {
- code += sizeof(ngx_http_rewrite_if_code_t) / sizeof(uintptr_t);
- continue;
- }
-
- if (*code == (uintptr_t) &ngx_http_rewrite_return_code) {
- code += sizeof(ngx_http_rewrite_return_code_t) / sizeof(uintptr_t);
- continue;
- }
-
- if (*code == (uintptr_t) &ngx_http_rewrite_set_var_code) {
- code += sizeof(ngx_http_rewrite_var_code_t) / sizeof(uintptr_t);
- continue;
- }
-
- if (*code == (uintptr_t) &ngx_http_rewrite_var_code) {
- code += sizeof(ngx_http_rewrite_var_code_t) / sizeof(uintptr_t);
- continue;
- }
-
- if (*code == (uintptr_t) &ngx_http_rewrite_value_code) {
- code += sizeof(ngx_http_rewrite_value_code_t) / sizeof(uintptr_t);
- continue;
- }
-
- if (*code == (uintptr_t) &ngx_http_rewrite_invalid_referer_code) {
- code++;
- continue;
- }
-
- if (*code == (uintptr_t) &ngx_http_rewrite_nop_code) {
- code++;
- continue;
- }
-
-#if (NGX_DEBUG)
- ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
- "unknown rewrite code: %p", *code);
- return NGX_CONF_ERROR;
-#endif
- }
-
code = ngx_array_push_n(conf->codes, sizeof(uintptr_t));
if (code == NULL) {
return NGX_CONF_ERROR;
@@ -976,29 +393,47 @@ ngx_http_rewrite_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
}
+static ngx_int_t
+ngx_http_rewrite_init(ngx_cycle_t *cycle)
+{
+ ngx_http_handler_pt *h;
+ ngx_http_core_main_conf_t *cmcf;
+
+ cmcf = ngx_http_cycle_get_module_main_conf(cycle, ngx_http_core_module);
+
+ h = ngx_array_push(&cmcf->phases[NGX_HTTP_REWRITE_PHASE].handlers);
+ if (h == NULL) {
+ return NGX_ERROR;
+ }
+
+ *h = ngx_http_rewrite_handler;
+
+ return NGX_OK;
+}
+
+
static char *
ngx_http_rewrite(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
ngx_http_rewrite_loc_conf_t *lcf = conf;
- u_char *data;
- size_t len, size;
- ngx_str_t *value, err;
- ngx_int_t n;
- ngx_uint_t i, last;
- ngx_http_rewrite_code_pt *code;
- ngx_http_rewrite_copy_code_t *copy;
- ngx_http_rewrite_regex_code_t *regex;
- ngx_http_rewrite_regex_end_code_t *regex_end;
- ngx_http_rewrite_copy_capture_code_t *copy_capture;
- u_char errstr[NGX_MAX_CONF_ERRSTR];
-
- regex = ngx_http_rewrite_start_code(cf->pool, &lcf->codes,
- sizeof(ngx_http_rewrite_regex_code_t));
+ ngx_str_t *value, err;
+ ngx_int_t n;
+ ngx_uint_t last;
+ ngx_http_script_code_pt *code;
+ ngx_http_script_compile_t sc;
+ ngx_http_script_regex_code_t *regex;
+ ngx_http_script_regex_end_code_t *regex_end;
+ u_char errstr[NGX_MAX_CONF_ERRSTR];
+
+ regex = ngx_http_script_start_code(cf->pool, &lcf->codes,
+ sizeof(ngx_http_script_regex_code_t));
if (regex == NULL) {
return NGX_CONF_ERROR;
}
+ ngx_memzero(regex, sizeof(ngx_http_script_regex_code_t));
+
value = cf->args->elts;
err.len = NGX_MAX_CONF_ERRSTR;
@@ -1013,17 +448,19 @@ ngx_http_rewrite(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
return NGX_CONF_ERROR;
}
- regex->code = ngx_http_rewrite_regex_start_code;
- regex->size = 0;
- regex->ncaptures = 0;
- regex->status = 0;
- regex->test = 0;
+ regex->code = ngx_http_script_regex_start_code;
regex->uri = 1;
- regex->args = 1;
- regex->redirect = 0;
- regex->break_cycle = 0;
regex->name = value[1];
+ if (value[2].data[value[2].len - 1] == '?') {
+
+ /* the last "?" drops the original arguments */
+ value[2].len--;
+
+ } else {
+ regex->add_args = 1;
+ }
+
last = 0;
if (ngx_strncmp(value[2].data, "http://", sizeof("http://") - 1) == 0) {
@@ -1057,113 +494,29 @@ ngx_http_rewrite(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
}
}
- i = 0;
-
- while (i < value[2].len) {
-
- data = &value[2].data[i];
-
- if (value[2].data[i] == '$' && i < value[2].len
- && value[2].data[i + 1] >= '1' && value[2].data[i + 1] <= '9')
- {
-
- /* the "$1" - "$9" captures */
-
- copy_capture = ngx_http_rewrite_add_code(lcf->codes,
- sizeof(ngx_http_rewrite_copy_capture_code_t),
- &regex);
- if (copy_capture == NULL) {
- return NGX_CONF_ERROR;
- }
-
- i++;
-
- copy_capture->code = ngx_http_rewrite_copy_capture_code;
- copy_capture->n = value[2].data[i] - '0';
-
- if (regex->ncaptures < copy_capture->n) {
- regex->ncaptures = copy_capture->n;
- }
-
- copy_capture->n *= 2;
-
- i++;
-
- continue;
- }
-
- if (value[2].data[i] == '?') {
-
- /* the arguments */
-
- if (i == value[2].len - 1) {
- /* the last "?" drops the original arguments */
- regex->args = 0;
- break;
- }
-
- if (!regex->redirect) {
- code = ngx_http_rewrite_add_code(lcf->codes, sizeof(uintptr_t),
- &regex);
- if (code == NULL) {
- return NGX_CONF_ERROR;
- }
-
- *code = ngx_http_rewrite_start_args_code;
-
- i++;
-
- continue;
- }
- }
-
- i++;
-
- /* the substituion strings */
-
- while (i < value[2].len && value[2].data[i] != '$') {
-
- if (value[2].data[i] == '?') {
-
- if (i == value[2].len - 1) {
- /*
- * the last "?" drops the original arguments,
- * and it should not be copied to a substituion
- */
- regex->args = 0;
- break;
- }
-
- if (!regex->redirect) {
- break;
- }
- }
+ ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
- i++;
- }
-
- len = &value[2].data[i] - data;
+ sc.cf = cf;
+ sc.source = &value[2];
+ sc.lengths = &regex->lengths;
+ sc.values = &lcf->codes;
+ sc.variables = ngx_http_script_variables_count(&value[2]);
+ sc.main = regex;
+ sc.complete_lengths = 1;
+ sc.compile_args = !regex->redirect;
- if (len == 0) {
- continue;
- }
-
- regex->size += len;
-
- size = (len + sizeof(uintptr_t) - 1) & ~(sizeof(uintptr_t) - 1);
+ if (ngx_http_script_compile(&sc) != NGX_OK) {
+ return NGX_CONF_ERROR;
+ }
- copy = ngx_http_rewrite_add_code(lcf->codes,
- sizeof(ngx_http_rewrite_copy_code_t) + size,
- &regex);
- if (copy == NULL) {
- return NGX_CONF_ERROR;
- }
+ regex = sc.main;
- copy->code = ngx_http_rewrite_copy_code;
- copy->len = len;
+ regex->ncaptures = sc.ncaptures;
+ regex->size = sc.size;
+ regex->args = sc.args;
- ngx_memcpy((u_char *) copy + sizeof(ngx_http_rewrite_copy_code_t),
- data, len);
+ if (sc.variables == 0) {
+ regex->lengths = NULL;
}
n = ngx_regex_capture_count(regex->regex);
@@ -1191,21 +544,26 @@ ngx_http_rewrite(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
regex->ncaptures = (regex->ncaptures + 1) * 3;
}
- regex_end = ngx_http_rewrite_add_code(lcf->codes,
- sizeof(ngx_http_rewrite_regex_end_code_t),
- &regex);
+ if (lcf->max_captures < regex->ncaptures) {
+ lcf->max_captures = regex->ncaptures;
+ }
+
+ regex_end = ngx_http_script_add_code(lcf->codes,
+ sizeof(ngx_http_script_regex_end_code_t),
+ &regex);
if (regex_end == NULL) {
return NGX_CONF_ERROR;
}
- regex_end->code = ngx_http_rewrite_regex_end_code;
+ regex_end->code = ngx_http_script_regex_end_code;
regex_end->uri = regex->uri;
regex_end->args = regex->args;
+ regex_end->add_args = regex->add_args;
regex_end->redirect = regex->redirect;
if (last) {
- code = ngx_http_rewrite_add_code(lcf->codes, sizeof(uintptr_t),
- &regex);
+ code = ngx_http_script_add_code(lcf->codes, sizeof(uintptr_t),
+ &regex);
if (code == NULL) {
return NGX_CONF_ERROR;
}
@@ -1225,18 +583,18 @@ ngx_http_rewrite_return(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
ngx_http_rewrite_loc_conf_t *lcf = conf;
- ngx_str_t *value;
- ngx_http_rewrite_return_code_t *ret;
+ ngx_str_t *value;
+ ngx_http_script_return_code_t *ret;
- ret = ngx_http_rewrite_start_code(cf->pool, &lcf->codes,
- sizeof(ngx_http_rewrite_return_code_t));
+ ret = ngx_http_script_start_code(cf->pool, &lcf->codes,
+ sizeof(ngx_http_script_return_code_t));
if (ret == NULL) {
return NGX_CONF_ERROR;
}
value = cf->args->elts;
- ret->code = ngx_http_rewrite_return_code;
+ ret->code = ngx_http_script_return_code;
ret->null = (uintptr_t) NULL;
ret->status = ngx_atoi(value[1].data, value[1].len);
@@ -1262,7 +620,7 @@ ngx_http_rewrite_if(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
ngx_http_module_t *module;
ngx_http_conf_ctx_t *ctx, *pctx;
ngx_http_core_loc_conf_t *clcf, *pclcf, **clcfp;
- ngx_http_rewrite_if_code_t *if_code;
+ ngx_http_script_if_code_t *if_code;
ngx_http_rewrite_loc_conf_t *nlcf;
ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t));
@@ -1324,12 +682,12 @@ ngx_http_rewrite_if(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
return NGX_CONF_ERROR;
}
- if_code = ngx_array_push_n(lcf->codes, sizeof(ngx_http_rewrite_if_code_t));
+ if_code = ngx_array_push_n(lcf->codes, sizeof(ngx_http_script_if_code_t));
if (if_code == NULL) {
return NULL;
}
- if_code->code = ngx_http_rewrite_if_code;
+ if_code->code = ngx_http_script_if_code;
elts = lcf->codes->elts;
@@ -1362,7 +720,7 @@ ngx_http_rewrite_if(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
if (elts != lcf->codes->elts) {
- if_code = (ngx_http_rewrite_if_code_t *)
+ if_code = (ngx_http_script_if_code_t *)
((u_char *) if_code + ((u_char *) lcf->codes->elts - elts));
}
@@ -1376,10 +734,10 @@ ngx_http_rewrite_if(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
static char *
ngx_http_rewrite_if_condition(ngx_conf_t *cf, ngx_http_rewrite_loc_conf_t *lcf)
{
- ngx_str_t *value, err;
- ngx_uint_t cur, last;
- ngx_http_rewrite_regex_code_t *regex;
- u_char errstr[NGX_MAX_CONF_ERRSTR];
+ ngx_str_t *value, err;
+ ngx_uint_t cur, last;
+ ngx_http_script_regex_code_t *regex;
+ u_char errstr[NGX_MAX_CONF_ERRSTR];
value = cf->args->elts;
last = cf->args->nelts - 1;
@@ -1440,12 +798,14 @@ ngx_http_rewrite_if_condition(ngx_conf_t *cf, ngx_http_rewrite_loc_conf_t *lcf)
return NGX_CONF_ERROR;
}
- regex = ngx_http_rewrite_start_code(cf->pool, &lcf->codes,
- sizeof(ngx_http_rewrite_regex_code_t));
+ regex = ngx_http_script_start_code(cf->pool, &lcf->codes,
+ sizeof(ngx_http_script_regex_code_t));
if (regex == NULL) {
return NGX_CONF_ERROR;
}
+ ngx_memzero(regex, sizeof(ngx_http_script_regex_code_t));
+
err.len = NGX_MAX_CONF_ERRSTR;
err.data = errstr;
@@ -1458,16 +818,9 @@ ngx_http_rewrite_if_condition(ngx_conf_t *cf, ngx_http_rewrite_loc_conf_t *lcf)
return NGX_CONF_ERROR;
}
- regex->code = ngx_http_rewrite_regex_start_code;
- regex->size = 0;
- regex->ncaptures = 0;
- regex->status = 0;
- regex->next = sizeof(ngx_http_rewrite_regex_code_t);
+ regex->code = ngx_http_script_regex_start_code;
+ regex->next = sizeof(ngx_http_script_regex_code_t);
regex->test = 1;
- regex->uri = 0;
- regex->args = 0;
- regex->redirect = 0;
- regex->break_cycle = 0;
regex->name = value[last];
return NGX_CONF_OK;
@@ -1484,9 +837,9 @@ static char *
ngx_http_rewrite_variable(ngx_conf_t *cf, ngx_http_rewrite_loc_conf_t *lcf,
ngx_str_t *value)
{
- ngx_http_variable_t *var;
- ngx_http_rewrite_code_pt *code;
- ngx_http_rewrite_var_code_t *var_code;
+ ngx_int_t index;
+ ngx_http_script_code_pt *code;
+ ngx_http_script_var_code_t *var_code;
value->len--;
value->data++;
@@ -1495,8 +848,8 @@ ngx_http_rewrite_variable(ngx_conf_t *cf, ngx_http_rewrite_loc_conf_t *lcf,
&& ngx_strncmp(value->data, "invalid_referer",
sizeof("invalid_referer") - 1) == 0)
{
- code = ngx_http_rewrite_start_code(cf->pool, &lcf->codes,
- sizeof(ngx_http_rewrite_code_pt));
+ code = ngx_http_script_start_code(cf->pool, &lcf->codes,
+ sizeof(ngx_http_script_code_pt));
if (code == NULL) {
return NGX_CONF_ERROR;
}
@@ -1504,20 +857,20 @@ ngx_http_rewrite_variable(ngx_conf_t *cf, ngx_http_rewrite_loc_conf_t *lcf,
*code = ngx_http_rewrite_invalid_referer_code;
} else {
- var = ngx_http_add_variable(cf, value, 0);
+ index = ngx_http_get_variable_index(cf, value);
- if (var == NULL) {
+ if (index == NGX_ERROR) {
return NGX_CONF_ERROR;
}
- var_code = ngx_http_rewrite_start_code(cf->pool, &lcf->codes,
- sizeof(ngx_http_rewrite_var_code_t));
+ var_code = ngx_http_script_start_code(cf->pool, &lcf->codes,
+ sizeof(ngx_http_script_var_code_t));
if (var_code == NULL) {
return NGX_CONF_ERROR;
}
- var_code->code = ngx_http_rewrite_var_code;
- var_code->index = var->index;
+ var_code->code = ngx_http_script_var_code;
+ var_code->index = index;
}
return NGX_CONF_OK;
@@ -1624,11 +977,11 @@ ngx_http_rewrite_set(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
ngx_http_rewrite_loc_conf_t *lcf = conf;
- ngx_int_t n;
- ngx_str_t *value;
- ngx_http_variable_t *v;
- ngx_http_rewrite_var_code_t *var;
- ngx_http_rewrite_value_code_t *val;
+ ngx_int_t n, index;
+ ngx_str_t *value;
+ ngx_http_variable_t *v;
+ ngx_http_script_var_code_t *var;
+ ngx_http_script_value_code_t *val;
value = cf->args->elts;
@@ -1641,16 +994,21 @@ 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], 1);
+ v = ngx_http_add_variable(cf, &value[1], NGX_HTTP_VAR_CHANGABLE);
if (v == NULL) {
return NGX_CONF_ERROR;
}
+ index = ngx_http_get_variable_index(cf, &value[1]);
+ if (index == NGX_ERROR) {
+ return NGX_CONF_ERROR;
+ }
+
v->handler = ngx_http_rewrite_var;
- v->data = v->index;
+ v->data = index;
- val = ngx_http_rewrite_start_code(cf->pool, &lcf->codes,
- sizeof(ngx_http_rewrite_value_code_t));
+ val = ngx_http_script_start_code(cf->pool, &lcf->codes,
+ sizeof(ngx_http_script_value_code_t));
if (val == NULL) {
return NGX_CONF_ERROR;
}
@@ -1661,55 +1019,19 @@ ngx_http_rewrite_set(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
n = 0;
}
- val->code = ngx_http_rewrite_value_code;
+ val->code = ngx_http_script_value_code;
val->value = (uintptr_t) n;
val->text_len = (uintptr_t) value[2].len;
val->text_data = (uintptr_t) value[2].data;
- var = ngx_http_rewrite_start_code(cf->pool, &lcf->codes,
- sizeof(ngx_http_rewrite_var_code_t));
+ var = ngx_http_script_start_code(cf->pool, &lcf->codes,
+ sizeof(ngx_http_script_var_code_t));
if (var == NULL) {
return NGX_CONF_ERROR;
}
- var->code = ngx_http_rewrite_set_var_code;
- var->index = (uintptr_t) v->index;
+ var->code = ngx_http_script_set_var_code;
+ var->index = (uintptr_t) index;
return NGX_CONF_OK;
}
-
-
-static void *
-ngx_http_rewrite_start_code(ngx_pool_t *pool, ngx_array_t **codes, size_t size)
-{
- if (*codes == NULL) {
- *codes = ngx_array_create(pool, 256, 1);
- if (*codes == NULL) {
- return NULL;
- }
- }
-
- return ngx_array_push_n(*codes, size);
-}
-
-
-static void *
-ngx_http_rewrite_add_code(ngx_array_t *codes, size_t size, void *code)
-{
- u_char *elts, **p;
- void *new;
-
- elts = codes->elts;
-
- new = ngx_array_push_n(codes, size);
- if (new == NULL) {
- return NGX_CONF_ERROR;
- }
-
- if (elts != codes->elts) {
- p = code;
- *p += (u_char *) codes->elts - elts;
- }
-
- return new;
-}
diff --git a/src/http/modules/ngx_http_ssi_filter_module.c b/src/http/modules/ngx_http_ssi_filter_module.c
index a351747b5..acaeeeda6 100644
--- a/src/http/modules/ngx_http_ssi_filter_module.c
+++ b/src/http/modules/ngx_http_ssi_filter_module.c
@@ -16,10 +16,13 @@
#define NGX_HTTP_SSI_ERROR 1
+#define NGX_HTTP_SSI_DATE_LEN 2048
+
typedef struct {
ngx_flag_t enable;
ngx_flag_t silent_errors;
+ ngx_flag_t ignore_recycled_buffers;
size_t min_file_chunk;
size_t value_len;
@@ -50,6 +53,10 @@ typedef struct {
size_t looked;
size_t value_len;
+
+ ngx_uint_t output; /* unsigned output:1; */
+
+ ngx_str_t timefmt;
} ngx_http_ssi_ctx_t;
@@ -70,7 +77,8 @@ typedef struct {
ngx_http_ssi_command_pt handler;
ngx_http_ssi_param_t *params;
- ngx_uint_t flush; /* unsigned flush:1; */
+ unsigned conditional:1;
+ unsigned flush:1;
} ngx_http_ssi_command_t;
@@ -98,12 +106,28 @@ typedef enum {
} ngx_http_ssi_state_e;
+static ngx_int_t ngx_http_ssi_output(ngx_http_request_t *r,
+ ngx_http_ssi_ctx_t *ctx);
static ngx_int_t ngx_http_ssi_parse(ngx_http_request_t *r,
ngx_http_ssi_ctx_t *ctx);
static ngx_int_t ngx_http_ssi_echo(ngx_http_request_t *r,
ngx_http_ssi_ctx_t *ctx, ngx_str_t **params);
+static ngx_int_t ngx_http_ssi_config(ngx_http_request_t *r,
+ ngx_http_ssi_ctx_t *ctx, ngx_str_t **params);
+static ngx_int_t ngx_http_ssi_include(ngx_http_request_t *r,
+ ngx_http_ssi_ctx_t *ctx, ngx_str_t **params);
+static ngx_int_t ngx_http_ssi_if(ngx_http_request_t *r,
+ ngx_http_ssi_ctx_t *ctx, ngx_str_t **params);
+static ngx_int_t ngx_http_ssi_else(ngx_http_request_t *r,
+ ngx_http_ssi_ctx_t *ctx, ngx_str_t **params);
+static ngx_int_t ngx_http_ssi_endif(ngx_http_request_t *r,
+ ngx_http_ssi_ctx_t *ctx, ngx_str_t **params);
+
+static ngx_http_variable_value_t *
+ ngx_http_ssi_date_gmt_local_variable(ngx_http_request_t *r, uintptr_t gmt);
+static ngx_int_t ngx_http_ssi_add_variables(ngx_conf_t *cf);
static void *ngx_http_ssi_create_conf(ngx_conf_t *cf);
static char *ngx_http_ssi_merge_conf(ngx_conf_t *cf,
void *parent, void *child);
@@ -126,6 +150,13 @@ static ngx_command_t ngx_http_ssi_filter_commands[] = {
offsetof(ngx_http_ssi_conf_t, silent_errors),
NULL },
+ { ngx_string("ssi_ignore_recycled_buffers"),
+ 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_ssi_conf_t, ignore_recycled_buffers),
+ NULL },
+
{ ngx_string("ssi_min_file_chunk"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
ngx_conf_set_size_slot,
@@ -139,7 +170,8 @@ static ngx_command_t ngx_http_ssi_filter_commands[] = {
static ngx_http_module_t ngx_http_ssi_filter_module_ctx = {
- NULL, /* pre conf */
+ ngx_http_ssi_add_variables, /* preconfiguration */
+ NULL, /* postconfiguration */
NULL, /* create main configuration */
NULL, /* init main configuration */
@@ -153,7 +185,7 @@ static ngx_http_module_t ngx_http_ssi_filter_module_ctx = {
ngx_module_t ngx_http_ssi_filter_module = {
- NGX_MODULE,
+ NGX_MODULE_V1,
&ngx_http_ssi_filter_module_ctx, /* module context */
ngx_http_ssi_filter_commands, /* module directives */
NGX_HTTP_MODULE, /* module type */
@@ -174,8 +206,16 @@ static u_char ngx_http_ssi_error_string[] =
static ngx_str_t ngx_http_ssi_none = ngx_string("(none)");
-#define NGX_HTTP_SSI_ECHO_VAR 0
-#define NGX_HTTP_SSI_ECHO_DEFAULT 1
+#define NGX_HTTP_SSI_ECHO_VAR 0
+#define NGX_HTTP_SSI_ECHO_DEFAULT 1
+
+#define NGX_HTTP_SSI_CONFIG_TIMEFMT 0
+
+#define NGX_HTTP_SSI_INCLUDE_VIRTUAL 0
+#define NGX_HTTP_SSI_INCLUDE_FILE 1
+
+#define NGX_HTTP_SSI_IF_EXPR 0
+
static ngx_http_ssi_param_t ngx_http_ssi_echo_params[] = {
{ ngx_string("var"), NGX_HTTP_SSI_ECHO_VAR, 1 },
@@ -183,13 +223,60 @@ static ngx_http_ssi_param_t ngx_http_ssi_echo_params[] = {
{ ngx_null_string, 0, 0 }
};
+static ngx_http_ssi_param_t ngx_http_ssi_include_params[] = {
+ { ngx_string("virtual"), NGX_HTTP_SSI_INCLUDE_VIRTUAL, 0 },
+#if 0
+ { ngx_string("file"), NGX_HTTP_SSI_INCLUDE_FILE, 0 },
+#endif
+ { ngx_null_string, 0, 0 }
+};
+
+
+static ngx_http_ssi_param_t ngx_http_ssi_config_params[] = {
+ { ngx_string("timefmt"), NGX_HTTP_SSI_CONFIG_TIMEFMT, 0 },
+ { ngx_null_string, 0, 0 }
+};
+
+
+static ngx_http_ssi_param_t ngx_http_ssi_if_params[] = {
+ { ngx_string("expr"), NGX_HTTP_SSI_IF_EXPR, 0 },
+ { ngx_null_string, 0, 0 }
+};
+
+
+static ngx_http_ssi_param_t ngx_http_ssi_no_params[] = {
+ { ngx_null_string, 0, 0 }
+};
+
static ngx_http_ssi_command_t ngx_http_ssi_commands[] = {
- { ngx_string("echo"), ngx_http_ssi_echo, ngx_http_ssi_echo_params, 0 },
- { ngx_null_string, NULL, NULL, 0 }
+ { ngx_string("echo"), ngx_http_ssi_echo, ngx_http_ssi_echo_params, 0, 0 },
+ { ngx_string("config"), ngx_http_ssi_config,
+ ngx_http_ssi_config_params, 0, 0 },
+ { ngx_string("include"), ngx_http_ssi_include,
+ ngx_http_ssi_include_params, 0, 1 },
+
+ { ngx_string("if"), ngx_http_ssi_if, ngx_http_ssi_if_params, 0, 0 },
+ { ngx_string("else"), ngx_http_ssi_else, ngx_http_ssi_no_params, 1, 0 },
+ { ngx_string("endif"), ngx_http_ssi_endif, ngx_http_ssi_no_params, 1, 0 },
+
+ { ngx_null_string, NULL, NULL, 0, 0 }
};
+static ngx_http_variable_t ngx_http_ssi_vars[] = {
+
+ { ngx_string("date_local"), ngx_http_ssi_date_gmt_local_variable, 0,
+ NGX_HTTP_VAR_NOCACHABLE },
+
+ { ngx_string("date_gmt"), ngx_http_ssi_date_gmt_local_variable, 1,
+ NGX_HTTP_VAR_NOCACHABLE },
+
+ { ngx_null_string, NULL, 0, 0 }
+};
+
+
+
static ngx_int_t
ngx_http_ssi_header_filter(ngx_http_request_t *r)
{
@@ -204,9 +291,9 @@ ngx_http_ssi_header_filter(ngx_http_request_t *r)
/* TODO: "text/html" -> custom types */
- if (r->headers_out.content_type
- && ngx_strncasecmp(r->headers_out.content_type->value.data,
- "text/html", 5) != 0)
+ if (r->headers_out.content_type.len == 0
+ || ngx_strncasecmp(r->headers_out.content_type.data, "text/html", 5)
+ != 0)
{
return ngx_http_next_header_filter(r);
}
@@ -223,26 +310,33 @@ ngx_http_ssi_header_filter(ngx_http_request_t *r)
ctx->value_len = conf->value_len;
ctx->last_out = &ctx->out;
+ ctx->output = 1;
+
ctx->params.elts = ctx->params_array;
ctx->params.size = sizeof(ngx_table_elt_t);
ctx->params.nalloc = NGX_HTTP_SSI_PARAMS_N;
ctx->params.pool = r->pool;
- r->headers_out.content_length_n = -1;
- if (r->headers_out.content_length) {
- r->headers_out.content_length->key.len = 0;
- r->headers_out.content_length = NULL;
- }
-
- r->headers_out.last_modified_time = -1;
- if (r->headers_out.last_modified) {
- r->headers_out.last_modified->key.len = 0;
- r->headers_out.last_modified = NULL;
- }
+ ctx->timefmt.len = sizeof("%A, %d-%b-%Y %H:%M:%S %Z") - 1;
+ ctx->timefmt.data = (u_char *) "%A, %d-%b-%Y %H:%M:%S %Z";
r->filter_need_in_memory = 1;
r->filter_ssi_need_in_memory = 1;
+ if (r->main == NULL) {
+ r->headers_out.content_length_n = -1;
+ if (r->headers_out.content_length) {
+ r->headers_out.content_length->hash = 0;
+ r->headers_out.content_length = NULL;
+ }
+
+ r->headers_out.last_modified_time = -1;
+ if (r->headers_out.last_modified) {
+ r->headers_out.last_modified->hash = 0;
+ r->headers_out.last_modified = NULL;
+ }
+ }
+
return ngx_http_next_header_filter(r);
}
@@ -277,8 +371,8 @@ ngx_http_ssi_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
conf = ngx_http_get_module_loc_conf(r, ngx_http_ssi_filter_module);
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http ssi filter");
+ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "http ssi filter \"%V\"", &r->uri);
while (ctx->in || ctx->buf) {
@@ -312,19 +406,50 @@ ngx_http_ssi_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
if (ctx->copy_start != ctx->copy_end) {
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "saved: %d", ctx->saved);
+ if (ctx->output) {
+
+ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "saved: %d", ctx->saved);
+
+ if (ctx->saved) {
+
+ if (ctx->free) {
+ cl = ctx->free;
+ ctx->free = ctx->free->next;
+ b = cl->buf;
+ ngx_memzero(b, sizeof(ngx_buf_t));
- if (ctx->saved) {
+ } else {
+ b = ngx_calloc_buf(r->pool);
+ if (b == NULL) {
+ return NGX_ERROR;
+ }
+
+ cl = ngx_alloc_chain_link(r->pool);
+ if (cl == NULL) {
+ return NGX_ERROR;
+ }
+
+ cl->buf = b;
+ }
+
+ b->memory = 1;
+ b->pos = ngx_http_ssi_string;
+ b->last = ngx_http_ssi_string + ctx->saved;
+
+ *ctx->last_out = cl;
+ ctx->last_out = &cl->next;
+
+ ctx->saved = 0;
+ }
if (ctx->free) {
cl = ctx->free;
ctx->free = ctx->free->next;
b = cl->buf;
- ngx_memzero(b, sizeof(ngx_buf_t));
} else {
- b = ngx_calloc_buf(r->pool);
+ b = ngx_alloc_buf(r->pool);
if (b == NULL) {
return NGX_ERROR;
}
@@ -337,56 +462,31 @@ ngx_http_ssi_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
cl->buf = b;
}
- b->memory = 1;
- b->pos = ngx_http_ssi_string;
- b->last = ngx_http_ssi_string + ctx->saved;
-
- *ctx->last_out = cl;
- ctx->last_out = &cl->next;
-
- ctx->saved = 0;
- }
+ ngx_memcpy(b, ctx->buf, sizeof(ngx_buf_t));
- if (ctx->free) {
- cl = ctx->free;
- ctx->free = ctx->free->next;
- b = cl->buf;
+ b->last_buf = 0;
+ b->recycled = 0;
+ b->pos = ctx->copy_start;
+ b->last = ctx->copy_end;
- } else {
- b = ngx_alloc_buf(r->pool);
- if (b == NULL) {
- return NGX_ERROR;
- }
+ if (b->in_file) {
+ if (conf->min_file_chunk < (size_t) (b->last - b->pos))
+ {
+ b->file_last = b->file_pos + (b->last - b->start);
+ b->file_pos += b->pos - b->start;
- cl = ngx_alloc_chain_link(r->pool);
- if (cl == NULL) {
- return NGX_ERROR;
+ } else {
+ b->in_file = 0;
+ }
}
- cl->buf = b;
- }
-
- ngx_memcpy(b, ctx->buf, sizeof(ngx_buf_t));
-
- b->last_buf = 0;
- b->recycled = 0;
- b->pos = ctx->copy_start;
- b->last = ctx->copy_end;
-
- if (b->in_file) {
-
- if (conf->min_file_chunk < (size_t) (b->last - b->pos)) {
- b->file_last = b->file_pos + (b->last - b->start);
- b->file_pos += b->pos - b->start;
+ cl->next = NULL;
+ *ctx->last_out = cl;
+ ctx->last_out = &cl->next;
- } else {
- b->in_file = 0;
- }
+ } else {
+ ctx->saved = 0;
}
-
- cl->next = NULL;
- *ctx->last_out = cl;
- ctx->last_out = &cl->next;
}
if (ctx->state == ssi_start_state) {
@@ -420,12 +520,16 @@ ngx_http_ssi_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
break;
}
- if (cmd->name.len == 0) {
+ if (cmd->name.len == 0 && ctx->output) {
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
"invalid SSI command: \"%V\"", &ctx->command);
goto ssi_error;
}
+ if (!ctx->output && !cmd->conditional) {
+ continue;
+ }
+
ngx_memzero(params,
NGX_HTTP_SSI_MAX_PARAMS * sizeof(ngx_str_t *));
@@ -479,6 +583,14 @@ ngx_http_ssi_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
}
}
+ if (cmd->flush && ctx->out) {
+ rc = ngx_http_ssi_output(r, ctx);
+
+ if (rc == NGX_ERROR) {
+ return NGX_ERROR;
+ }
+ }
+
if (cmd->handler(r, ctx, params) == NGX_OK) {
continue;
}
@@ -525,9 +637,9 @@ ngx_http_ssi_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
continue;
}
- if (ctx->buf->recycled || ctx->buf->last_buf) {
- if (b == NULL) {
+ if (ctx->buf->last_buf || ctx->buf->recycled) {
+ if (b == NULL) {
if (ctx->free) {
cl = ctx->free;
ctx->free = ctx->free->next;
@@ -548,14 +660,19 @@ ngx_http_ssi_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
cl->buf = b;
}
+ b->sync = 1;
+
cl->next = NULL;
*ctx->last_out = cl;
ctx->last_out = &cl->next;
}
b->last_buf = ctx->buf->last_buf;
- b->flush = ctx->buf->recycled;
b->shadow = ctx->buf;
+
+ if (conf->ignore_recycled_buffers == 0) {
+ b->recycled = ctx->buf->recycled;
+ }
}
ctx->buf = NULL;
@@ -567,6 +684,17 @@ ngx_http_ssi_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
return NGX_OK;
}
+ return ngx_http_ssi_output(r, ctx);
+}
+
+
+static ngx_int_t
+ngx_http_ssi_output(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx)
+{
+ ngx_int_t rc;
+ ngx_buf_t *b;
+ ngx_chain_t *cl;
+
rc = ngx_http_next_body_filter(r, ctx->out);
if (ctx->busy == NULL) {
@@ -1154,7 +1282,7 @@ ngx_http_ssi_echo(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx,
var = params[NGX_HTTP_SSI_ECHO_VAR];
for (i = 0; i < var->len; i++) {
- var->data[i] = ngx_toupper(var->data[i]);
+ var->data[i] = ngx_tolower(var->data[i]);
}
vv = ngx_http_get_variable(r, var);
@@ -1163,7 +1291,7 @@ ngx_http_ssi_echo(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx,
return NGX_HTTP_SSI_ERROR;
}
- if (vv == NGX_HTTP_VARIABLE_NOT_FOUND) {
+ if (vv == NGX_HTTP_VAR_NOT_FOUND) {
value = params[NGX_HTTP_SSI_ECHO_DEFAULT];
if (value == NULL) {
@@ -1204,6 +1332,325 @@ ngx_http_ssi_echo(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx,
}
+static ngx_int_t
+ngx_http_ssi_config(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx,
+ ngx_str_t **params)
+{
+ ngx_str_t *value;
+
+ value = params[NGX_HTTP_SSI_CONFIG_TIMEFMT];
+
+ if (value) {
+ ctx->timefmt = *value;
+ }
+
+ return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_http_ssi_include(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx,
+ ngx_str_t **params)
+{
+ u_char ch, *p, **value;
+ size_t *size, len;
+ ngx_uint_t i, j, n, bracket;
+ ngx_str_t uri, args, name;
+ ngx_array_t lengths, values;
+ ngx_http_variable_value_t *vv;
+
+ /* TODO: file, virtual vs file */
+
+ uri = *params[NGX_HTTP_SSI_INCLUDE_VIRTUAL];
+ args.len = 0;
+ args.data = NULL;
+
+ n = ngx_http_script_variables_count(&uri);
+
+ if (n > 0) {
+
+ if (ngx_array_init(&lengths, r->pool, 8, sizeof(size_t *)) != NGX_OK) {
+ return NGX_HTTP_SSI_ERROR;
+ }
+
+ if (ngx_array_init(&values, r->pool, 8, sizeof(u_char *)) != NGX_OK) {
+ return NGX_HTTP_SSI_ERROR;
+ }
+
+ len = 0;
+
+ for (i = 0; i < uri.len; /* void */ ) {
+
+ name.len = 0;
+
+ if (uri.data[i] == '$') {
+
+ if (++i == uri.len) {
+ goto invalid_variable;
+ }
+
+ if (uri.data[i] == '{') {
+ bracket = 1;
+
+ if (++i == uri.len) {
+ goto invalid_variable;
+ }
+
+ name.data = &uri.data[i];
+
+ } else {
+ bracket = 0;
+ name.data = &uri.data[i];
+ }
+
+ for ( /* void */ ; i < uri.len; i++, name.len++) {
+ ch = uri.data[i];
+
+ if (ch == '}' && bracket) {
+ i++;
+ bracket = 0;
+ break;
+ }
+
+ if ((ch >= 'A' && ch <= 'Z')
+ || (ch >= 'a' && ch <= 'z')
+ || (ch >= '0' && ch <= '9')
+ || ch == '_')
+ {
+ continue;
+ }
+
+ break;
+ }
+
+ if (bracket) {
+ ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
+ "the closing bracket in \"%V\" "
+ "variable is missing", &name);
+ return NGX_HTTP_SSI_ERROR;
+ }
+
+ if (name.len == 0) {
+ goto invalid_variable;
+ }
+
+ for (j = 0; j < name.len; j++) {
+ name.data[j] = ngx_tolower(name.data[j]);
+ }
+
+ vv = ngx_http_get_variable(r, &name);
+
+ if (vv == NULL) {
+ return NGX_HTTP_SSI_ERROR;
+ }
+
+ if (vv == NGX_HTTP_VAR_NOT_FOUND) {
+ continue;
+ }
+
+ name = vv->text;
+
+ } else {
+ name.data = &uri.data[i];
+
+ while (i < uri.len && uri.data[i] != '$') {
+ i++;
+ name.len++;
+ }
+ }
+
+ len += name.len;
+
+ size = ngx_array_push(&lengths);
+ if (size == NULL) {
+ return NGX_HTTP_SSI_ERROR;
+ }
+
+ *size = name.len;
+
+ value = ngx_array_push(&values);
+ if (value == NULL) {
+ return NGX_HTTP_SSI_ERROR;
+ }
+
+ *value = name.data;
+ }
+
+ p = ngx_palloc(r->pool, len);
+ if (p == NULL) {
+ return NGX_HTTP_SSI_ERROR;
+ }
+
+ uri.len = len;
+ uri.data = p;
+
+ size = lengths.elts;
+ value = values.elts;
+
+ for (i = 0; i < values.nelts; i++) {
+ p = ngx_cpymem(p, value[i], size[i]);
+ }
+ }
+
+ for (i = 0; i < uri.len; i++) {
+ if (uri.data[i] == '?') {
+ args.len = uri.len - i - 1;
+ args.data = &uri.data[i + 1];
+ uri.len -= args.len + 1;
+
+ break;
+ }
+ }
+
+ if (ngx_http_subrequest(r, &uri, &args) != NGX_OK) {
+ return NGX_HTTP_SSI_ERROR;
+ }
+
+ return NGX_OK;
+
+invalid_variable:
+
+ ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
+ "invalid variable name in \"%V\"", &uri);
+
+ return NGX_ERROR;
+}
+
+
+static ngx_int_t
+ngx_http_ssi_if(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx,
+ ngx_str_t **params)
+{
+ ngx_str_t *expr, var;
+ ngx_uint_t i;
+ ngx_http_variable_value_t *vv;
+
+ expr = params[NGX_HTTP_SSI_IF_EXPR];
+
+ if (expr->data[0] != '$') {
+ ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
+ "invalid variable name in \"%V\"", expr);
+ return NGX_HTTP_SSI_ERROR;
+ }
+
+ var.len = expr->len - 1;
+ var.data = expr->data + 1;
+
+ for (i = 0; i < var.len; i++) {
+ var.data[i] = ngx_tolower(var.data[i]);
+ }
+
+ vv = ngx_http_get_variable(r, &var);
+
+ if (vv == NULL) {
+ return NGX_HTTP_SSI_ERROR;
+ }
+
+ if (vv != NGX_HTTP_VAR_NOT_FOUND && vv->text.len != 0) {
+ ctx->output = 1;
+
+ } else {
+ ctx->output = 0;
+ }
+
+ return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_http_ssi_else(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx,
+ ngx_str_t **params)
+{
+ ctx->output = !ctx->output;
+
+ return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_http_ssi_endif(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx,
+ ngx_str_t **params)
+{
+ ctx->output = 1;
+
+ return NGX_OK;
+}
+
+
+static ngx_http_variable_value_t *
+ngx_http_ssi_date_gmt_local_variable(ngx_http_request_t *r, uintptr_t gmt)
+{
+ ngx_http_ssi_ctx_t *ctx;
+ ngx_http_variable_value_t *vv;
+ struct tm tm;
+ char buf[NGX_HTTP_SSI_DATE_LEN];
+
+ vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t));
+ if (vv == NULL) {
+ return NULL;
+ }
+
+ ctx = ngx_http_get_module_ctx(r, ngx_http_ssi_filter_module);
+
+ if (ctx->timefmt.len == sizeof("%s") - 1
+ && ctx->timefmt.data[0] == '%' && ctx->timefmt.data[1] == 's')
+ {
+ vv->value = ngx_time() + (gmt ? 0 : ngx_gmtoff);
+
+ vv->text.data = ngx_palloc(r->pool, NGX_TIME_T_LEN);
+ if (vv->text.data == NULL) {
+ return NULL;
+ }
+
+ vv->text.len = ngx_sprintf(vv->text.data, "%T", vv->value)
+ - vv->text.data;
+ return vv;
+ }
+
+ if (gmt) {
+ ngx_libc_gmtime(&tm);
+ } else {
+ ngx_libc_localtime(&tm);
+ }
+
+ vv->value = ngx_time() + (gmt ? 0 : ngx_gmtoff);
+
+ vv->text.len = strftime(buf, NGX_HTTP_SSI_DATE_LEN,
+ (char *) ctx->timefmt.data, &tm);
+ if (vv->text.len == 0) {
+ return NULL;
+ }
+
+ vv->text.data = ngx_palloc(r->pool, vv->text.len);
+ if (vv->text.data == NULL) {
+ return NULL;
+ }
+
+ ngx_memcpy(vv->text.data, buf, vv->text.len);
+
+ return vv;
+}
+
+
+static ngx_int_t
+ngx_http_ssi_add_variables(ngx_conf_t *cf)
+{
+ ngx_http_variable_t *var, *v;
+
+ for (v = ngx_http_ssi_vars; v->name.len; v++) {
+ var = ngx_http_add_variable(cf, &v->name, v->flags);
+ if (var == NULL) {
+ return NGX_ERROR;
+ }
+
+ var->handler = v->handler;
+ var->data = v->data;
+ }
+
+ return NGX_OK;
+}
+
+
static void *
ngx_http_ssi_create_conf(ngx_conf_t *cf)
{
@@ -1216,6 +1663,7 @@ ngx_http_ssi_create_conf(ngx_conf_t *cf)
conf->enable = NGX_CONF_UNSET;
conf->silent_errors = NGX_CONF_UNSET;
+ conf->ignore_recycled_buffers = NGX_CONF_UNSET;
conf->min_file_chunk = NGX_CONF_UNSET_SIZE;
conf->value_len = NGX_CONF_UNSET_SIZE;
@@ -1232,6 +1680,8 @@ ngx_http_ssi_merge_conf(ngx_conf_t *cf, void *parent, void *child)
ngx_conf_merge_value(conf->enable, prev->enable, 0);
ngx_conf_merge_value(conf->silent_errors, prev->silent_errors, 0);
+ ngx_conf_merge_value(conf->ignore_recycled_buffers,
+ prev->ignore_recycled_buffers, 0);
ngx_conf_merge_size_value(conf->min_file_chunk, prev->min_file_chunk, 1024);
ngx_conf_merge_size_value(conf->value_len, prev->value_len, 256);
diff --git a/src/http/modules/ngx_http_ssl_module.c b/src/http/modules/ngx_http_ssl_module.c
index c18c493ac..04d4c9100 100644
--- a/src/http/modules/ngx_http_ssl_module.c
+++ b/src/http/modules/ngx_http_ssl_module.c
@@ -64,7 +64,8 @@ static ngx_command_t ngx_http_ssl_commands[] = {
static ngx_http_module_t ngx_http_ssl_module_ctx = {
- NULL, /* pre conf */
+ NULL, /* preconfiguration */
+ NULL, /* postconfiguration */
ngx_http_ssl_create_main_conf, /* create main configuration */
ngx_http_ssl_init_main_conf, /* init main configuration */
@@ -78,7 +79,7 @@ static ngx_http_module_t ngx_http_ssl_module_ctx = {
ngx_module_t ngx_http_ssl_module = {
- NGX_MODULE,
+ NGX_MODULE_V1,
&ngx_http_ssl_module_ctx, /* module context */
ngx_http_ssl_commands, /* module directives */
NGX_HTTP_MODULE, /* module type */
@@ -197,6 +198,13 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
return NGX_CONF_ERROR;
}
+ if (ngx_pool_cleanup_add(cf->pool, ngx_ssl_cleanup_ctx, conf->ssl_ctx)
+ == NULL)
+ {
+ return NGX_CONF_ERROR;
+ }
+
+
#if 0
SSL_CTX_set_options(conf->ssl_ctx, SSL_OP_ALL);
SSL_CTX_set_options(conf->ssl_ctx, SSL_OP_NO_SSLv3);
diff --git a/src/http/modules/ngx_http_static_module.c b/src/http/modules/ngx_http_static_module.c
index c2c45828f..a84a70eb6 100644
--- a/src/http/modules/ngx_http_static_module.c
+++ b/src/http/modules/ngx_http_static_module.c
@@ -17,7 +17,7 @@ typedef struct {
static ngx_int_t ngx_http_static_handler(ngx_http_request_t *r);
static void *ngx_http_static_create_loc_conf(ngx_conf_t *cf);
static char *ngx_http_static_merge_loc_conf(ngx_conf_t *cf,
- void *parent, void *child);
+ void *parent, void *child);
static ngx_int_t ngx_http_static_init(ngx_cycle_t *cycle);
@@ -38,9 +38,9 @@ static ngx_command_t ngx_http_static_commands[] = {
};
-
ngx_http_module_t ngx_http_static_module_ctx = {
- NULL, /* pre conf */
+ NULL, /* preconfiguration */
+ NULL, /* postconfiguration */
NULL, /* create main configuration */
NULL, /* init main configuration */
@@ -54,7 +54,7 @@ ngx_http_module_t ngx_http_static_module_ctx = {
ngx_module_t ngx_http_static_module = {
- NGX_MODULE,
+ NGX_MODULE_V1,
&ngx_http_static_module_ctx, /* module context */
ngx_http_static_commands, /* module directives */
NGX_HTTP_MODULE, /* module type */
@@ -63,7 +63,8 @@ ngx_module_t ngx_http_static_module = {
};
-static ngx_int_t ngx_http_static_handler(ngx_http_request_t *r)
+static ngx_int_t
+ngx_http_static_handler(ngx_http_request_t *r)
{
u_char *last;
ngx_fd_t fd;
@@ -75,16 +76,8 @@ static ngx_int_t ngx_http_static_handler(ngx_http_request_t *r)
ngx_buf_t *b;
ngx_chain_t out;
ngx_file_info_t fi;
- ngx_http_cleanup_t *file_cleanup;
-#if (NGX_HTTP_CACHE)
- ngx_http_cleanup_t *redirect_cleanup;
-#endif
+ ngx_pool_cleanup_file_t *cln;
ngx_http_core_loc_conf_t *clcf;
-#if (NGX_HTTP_CACHE)
- ngx_http_static_loc_conf_t *slcf;
- uint32_t file_crc, redirect_crc;
- ngx_http_cache_t *file, *redirect;
-#endif
if (r->uri.data[r->uri.len - 1] == '/') {
return NGX_DECLINED;
@@ -105,19 +98,6 @@ static ngx_int_t ngx_http_static_handler(ngx_http_request_t *r)
return rc;
}
-#if (NGX_HTTP_CACHE)
-
- /*
- * there is a valid cached open file, i.e by the index handler,
- * and it should be already registered in r->cleanup
- */
-
- if (r->cache && !r->cache->expired) {
- return ngx_http_send_cached(r);
- }
-
-#endif
-
log = r->connection->log;
clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
@@ -127,7 +107,19 @@ static ngx_int_t ngx_http_static_handler(ngx_http_request_t *r)
* in a possible redirect and for the last '\0'
*/
- if (clcf->alias) {
+ if (!clcf->alias) {
+ name.data = ngx_palloc(r->pool, clcf->root.len + r->uri.len + 2);
+ if (name.data == NULL) {
+ return NGX_HTTP_INTERNAL_SERVER_ERROR;
+ }
+
+ location.data = ngx_cpymem(name.data, clcf->root.data, clcf->root.len);
+ last = ngx_cpystrn(location.data, r->uri.data, r->uri.len + 1);
+
+ name.len = last - name.data;
+ location.len = last - location.data + 1;
+
+ } else {
name.data = ngx_palloc(r->pool, clcf->root.len + r->uri.len + 2
- clcf->name.len);
if (name.data == NULL) {
@@ -147,119 +139,16 @@ static ngx_int_t ngx_http_static_handler(ngx_http_request_t *r)
last = ngx_cpystrn(location.data, r->uri.data, r->uri.len + 1);
-#if 0
- /*
- * aliases usually have trailling "/",
- * set it in the start of the possible redirect
- */
-
- if (*location.data != '/') {
- location.data--;
- }
-#endif
-
- location.len = last - location.data + 1;
-
- } else {
- name.data = ngx_palloc(r->pool, clcf->root.len + r->uri.len + 2);
- if (name.data == NULL) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- location.data = ngx_cpymem(name.data, clcf->root.data, clcf->root.len);
- last = ngx_cpystrn(location.data, r->uri.data, r->uri.len + 1);
-
- name.len = last - name.data;
location.len = last - location.data + 1;
}
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0,
"http filename: \"%s\"", name.data);
-
- /* allocate cleanups */
-
- file_cleanup = ngx_array_push(&r->cleanup);
- if (file_cleanup == NULL) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
- file_cleanup->valid = 0;
-
-#if (NGX_HTTP_CACHE)
-
- slcf = ngx_http_get_module_loc_conf(r, ngx_http_static_module);
- if (slcf->redirect_cache) {
- redirect_cleanup = ngx_array_push(&r->cleanup);
- if (redirect_cleanup == NULL) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
- redirect_cleanup->valid = 0;
-
- } else {
- redirect_cleanup = NULL;
- }
-
- /* look up an open files cache */
-
- if (clcf->open_files) {
- file = ngx_http_cache_get(clcf->open_files, file_cleanup,
- &name, &file_crc);
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0,
- "http open file cache get: %p", file);
-
- if (file && !file->expired) {
- r->cache = file;
- return ngx_http_send_cached(r);
- }
-
- } else {
- file = NULL;
- }
-
-
- /* look up an redirect cache */
-
- if (slcf->redirect_cache) {
- redirect = ngx_http_cache_get(slcf->redirect_cache, redirect_cleanup,
- &name, &redirect_crc);
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0,
- "http redirect cache get: %p", redirect);
-
- if (redirect && !redirect->expired) {
-
- /*
- * We do not copy a cached value so the cache entry is locked
- * until the end of the request. In a single threaded model
- * the redirected request should complete before other event
- * will be processed. In a multithreaded model this locking
- * should keep more popular redirects in cache.
- */
-
- r->headers_out.location = ngx_http_add_header(&r->headers_out,
- ngx_http_headers_out);
- if (r->headers_out.location == NULL) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- r->headers_out.location->value = redirect->data.value;
-
- return NGX_HTTP_MOVED_PERMANENTLY;
- }
-
- } else {
- redirect = NULL;
- }
-
-#endif
-
/* open file */
#if (NGX_WIN9X)
- /* TODO: redirect cache */
-
if (ngx_win32_version < NGX_WIN_NT) {
/*
@@ -285,9 +174,6 @@ static ngx_int_t ngx_http_static_handler(ngx_http_request_t *r)
}
if (ngx_is_dir(&fi)) {
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0,
- "HTTP DIR: \"%s\"", name.data);
-
r->headers_out.location = ngx_http_add_header(&r->headers_out,
ngx_http_headers_out);
if (r->headers_out.location == NULL) {
@@ -356,59 +242,17 @@ static ngx_int_t ngx_http_static_handler(ngx_http_request_t *r)
*last++ = '/';
*last = '\0';
- r->headers_out.location = ngx_list_push(&r->headers_out.headers);
+ r->headers_out.location = ngx_palloc(r->pool, sizeof(ngx_table_elt_t));
if (r->headers_out.location == NULL) {
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
- r->headers_out.location->value = location;
-
-#if (NGX_HTTP_CACHE)
-
- if (slcf->redirect_cache) {
- if (redirect) {
- if (location.len == redirect->data.value.len
- && ngx_memcmp(redirect->data.value.data, location.data,
- location.len) == 0)
- {
- redirect->accessed = ngx_cached_time;
- redirect->updated = ngx_cached_time;
-
- /*
- * we can unlock the cache entry because
- * we have the local copy anyway
- */
-
- ngx_http_cache_unlock(slcf->redirect_cache, redirect, log);
- redirect_cleanup->valid = 0;
-
- return NGX_HTTP_MOVED_PERMANENTLY;
- }
- }
-
- location.len++;
- redirect = ngx_http_cache_alloc(slcf->redirect_cache, redirect,
- redirect_cleanup,
- &name, redirect_crc,
- &location, log);
- location.len--;
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0,
- "http redirect cache alloc: %p", redirect);
-
- if (redirect) {
- redirect->fd = NGX_INVALID_FILE;
- redirect->accessed = ngx_cached_time;
- redirect->last_modified = 0;
- redirect->updated = ngx_cached_time;
- redirect->memory = 1;
- ngx_http_cache_unlock(slcf->redirect_cache, redirect, log);
- redirect_cleanup->valid = 0;
- }
-
- }
+ /*
+ * we do not need to set the r->headers_out.location->hash and
+ * r->headers_out.location->key fields
+ */
-#endif
+ r->headers_out.location->value = location;
return NGX_HTTP_MOVED_PERMANENTLY;
}
@@ -429,68 +273,20 @@ static ngx_int_t ngx_http_static_handler(ngx_http_request_t *r)
#endif
+ log->action = "sending response to client";
-#if (NGX_HTTP_CACHE)
-
- if (clcf->open_files) {
-
-#if (NGX_USE_HTTP_FILE_CACHE_UNIQ)
-
- if (file && file->uniq == ngx_file_uniq(&fi)) {
- if (ngx_close_file(fd) == NGX_FILE_ERROR) {
- ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
- ngx_close_file_n " \"%s\" failed", name.data);
- }
- file->accessed = ngx_cached_time;
- file->updated = ngx_cached_time;
- file->expired = 0;
- r->cache = file;
-
- return ngx_http_send_cached(r);
-
- } else {
- if (file) {
- ngx_http_cache_unlock(clcf->open_files, file, log);
- file = NULL;
- }
-
- file = ngx_http_cache_alloc(clcf->open_files, file,
- file_cleanup,
- &name, file_crc, NULL, log);
- if (file) {
- file->uniq = ngx_file_uniq(&fi);
- }
- }
-
-#else
- file = ngx_http_cache_alloc(clcf->open_files, file,
- file_cleanup,
- &name, file_crc, NULL, log);
-#endif
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0,
- "http open file cache alloc: %p", file);
-
- if (file) {
- file->fd = fd;
- file->data.size = ngx_file_size(&fi);
- file->accessed = ngx_cached_time;
- file->last_modified = ngx_file_mtime(&fi);
- file->updated = ngx_cached_time;
- r->cache = file;
- }
-
- return ngx_http_send_cached(r);
+ cln = ngx_palloc(r->pool, sizeof(ngx_pool_cleanup_file_t));
+ if (cln == NULL) {
+ return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
-#endif
-
- log->action = "sending response to client";
+ cln->fd = fd;
+ cln->name = name.data;
+ cln->log = r->pool->log;
- file_cleanup->data.file.fd = fd;
- file_cleanup->data.file.name = name.data;
- file_cleanup->valid = 1;
- file_cleanup->cache = 0;
+ if (ngx_pool_cleanup_add(r->pool, ngx_pool_cleanup_file, cln) == NULL) {
+ return NGX_HTTP_INTERNAL_SERVER_ERROR;
+ }
r->headers_out.status = NGX_HTTP_OK;
r->headers_out.content_length_n = ngx_file_size(&fi);
@@ -532,10 +328,12 @@ static ngx_int_t ngx_http_static_handler(ngx_http_request_t *r)
b->in_file = 1;
- if (!r->main) {
+ if (r->main == NULL) {
b->last_buf = 1;
}
+ b->last_in_chain = 1;
+
b->file_pos = 0;
b->file_last = ngx_file_size(&fi);
@@ -550,7 +348,8 @@ static ngx_int_t ngx_http_static_handler(ngx_http_request_t *r)
}
-static void *ngx_http_static_create_loc_conf(ngx_conf_t *cf)
+static void *
+ngx_http_static_create_loc_conf(ngx_conf_t *cf)
{
ngx_http_static_loc_conf_t *conf;
@@ -565,8 +364,8 @@ static void *ngx_http_static_create_loc_conf(ngx_conf_t *cf)
}
-static char *ngx_http_static_merge_loc_conf(ngx_conf_t *cf,
- void *parent, void *child)
+static char *
+ngx_http_static_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
{
ngx_http_static_loc_conf_t *prev = parent;
ngx_http_static_loc_conf_t *conf = child;
@@ -579,7 +378,8 @@ static char *ngx_http_static_merge_loc_conf(ngx_conf_t *cf,
}
-static ngx_int_t ngx_http_static_init(ngx_cycle_t *cycle)
+static ngx_int_t
+ngx_http_static_init(ngx_cycle_t *cycle)
{
ngx_http_handler_pt *h;
ngx_http_core_main_conf_t *cmcf;
diff --git a/src/http/modules/ngx_http_stub_status_module.c b/src/http/modules/ngx_http_stub_status_module.c
index 1a01bcea8..0f1a252a8 100644
--- a/src/http/modules/ngx_http_stub_status_module.c
+++ b/src/http/modules/ngx_http_stub_status_module.c
@@ -22,7 +22,8 @@ static ngx_command_t ngx_http_status_commands[] = {
ngx_http_module_t ngx_http_stub_status_module_ctx = {
- NULL, /* pre conf */
+ NULL, /* preconfiguration */
+ NULL, /* postconfiguration */
NULL, /* create main configuration */
NULL, /* init main configuration */
@@ -36,7 +37,7 @@ ngx_http_module_t ngx_http_stub_status_module_ctx = {
ngx_module_t ngx_http_stub_status_module = {
- NGX_MODULE,
+ NGX_MODULE_V1,
&ngx_http_stub_status_module_ctx, /* module context */
ngx_http_status_commands, /* module directives */
NGX_HTTP_MODULE, /* module type */
@@ -63,15 +64,8 @@ static ngx_int_t ngx_http_status_handler(ngx_http_request_t *r)
return rc;
}
- r->headers_out.content_type = ngx_list_push(&r->headers_out.headers);
- if (r->headers_out.content_type == NULL) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- r->headers_out.content_type->key.len = 0;
- r->headers_out.content_type->key.data = NULL;
- r->headers_out.content_type->value.len = sizeof("text/plain") - 1;
- r->headers_out.content_type->value.data = (u_char *) "text/plain";
+ r->headers_out.content_type.len = sizeof("text/plain") - 1;
+ r->headers_out.content_type.data = (u_char *) "text/plain";
if (r->method == NGX_HTTP_HEAD) {
r->headers_out.status = NGX_HTTP_OK;
@@ -103,14 +97,14 @@ static ngx_int_t ngx_http_status_handler(ngx_http_request_t *r)
rd = *ngx_stat_reading;
wr = *ngx_stat_writing;
- b->last = ngx_sprintf(b->last, "Active connections: %A \n", ac);
+ b->last = ngx_sprintf(b->last, "Active connections: %uA \n", ac);
b->last = ngx_cpymem(b->last, "server accepts handled requests\n",
sizeof("server accepts handled requests\n") - 1);
- b->last = ngx_sprintf(b->last, " %A %A %A \n", ap, hn, rq);
+ b->last = ngx_sprintf(b->last, " %uA %uA %uA \n", ap, hn, rq);
- b->last = ngx_sprintf(b->last, "Reading: %A Writing: %A Waiting: %A \n",
+ b->last = ngx_sprintf(b->last, "Reading: %uA Writing: %uA Waiting: %uA \n",
rd, wr, ac - (rd + wr));
r->headers_out.status = NGX_HTTP_OK;
diff --git a/src/http/modules/ngx_http_userid_filter_module.c b/src/http/modules/ngx_http_userid_filter_module.c
index 4889fbffd..af60d80b3 100644
--- a/src/http/modules/ngx_http_userid_filter_module.c
+++ b/src/http/modules/ngx_http_userid_filter_module.c
@@ -19,7 +19,7 @@
typedef struct {
- ngx_flag_t enable;
+ ngx_uint_t enable;
ngx_int_t service;
@@ -83,7 +83,7 @@ static ngx_conf_enum_t ngx_http_userid_state[] = {
static ngx_conf_post_handler_pt ngx_http_userid_domain_p =
- ngx_http_userid_domain;
+ ngx_http_userid_domain;
static ngx_conf_post_handler_pt ngx_http_userid_path_p = ngx_http_userid_path;
static ngx_conf_post_handler_pt ngx_http_userid_p3p_p = ngx_http_userid_p3p;
@@ -145,7 +145,8 @@ static ngx_command_t ngx_http_userid_commands[] = {
ngx_http_module_t ngx_http_userid_filter_module_ctx = {
- ngx_http_userid_add_log_formats, /* pre conf */
+ ngx_http_userid_add_log_formats, /* preconfiguration */
+ NULL, /* postconfiguration */
NULL, /* create main configuration */
NULL, /* init main configuration */
@@ -159,7 +160,7 @@ ngx_http_module_t ngx_http_userid_filter_module_ctx = {
ngx_module_t ngx_http_userid_filter_module = {
- NGX_MODULE,
+ NGX_MODULE_V1,
&ngx_http_userid_filter_module_ctx, /* module context */
ngx_http_userid_commands, /* module directives */
NGX_HTTP_MODULE, /* module type */
@@ -186,6 +187,10 @@ ngx_http_userid_filter(ngx_http_request_t *r)
ngx_http_userid_ctx_t *ctx;
ngx_http_userid_conf_t *conf;
+ if (r->main) {
+ return ngx_http_next_header_filter(r);
+ }
+
conf = ngx_http_get_module_loc_conf(r, ngx_http_userid_filter_module);
if (conf->enable == NGX_HTTP_USERID_OFF) {
@@ -225,82 +230,47 @@ static ngx_int_t
ngx_http_userid_get_uid(ngx_http_request_t *r, ngx_http_userid_ctx_t *ctx,
ngx_http_userid_conf_t *conf)
{
- u_char *start, *last, *end;
- ngx_uint_t i;
+ ngx_int_t n;
ngx_str_t src, dst;
ngx_table_elt_t **cookies;
- cookies = r->headers_in.cookies.elts;
-
- for (i = 0; i < r->headers_in.cookies.nelts; i++) {
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "cookie: \"%V\"", &cookies[i]->value);
-
- if (conf->name.len >= cookies[i]->value.len) {
- continue;
- }
-
- start = cookies[i]->value.data;
- end = cookies[i]->value.data + cookies[i]->value.len;
-
- while (start < end) {
-
- if (ngx_strncmp(start, conf->name.data, conf->name.len) != 0) {
-
- while (start < end && *start++ != ';') { /* void */ }
- while (start < end && *start == ' ') { start++; }
-
- continue;
- }
-
- start += conf->name.len;
-
- while (start < end && *start == ' ') { start++; }
-
- if (start == end || *start++ != '=') {
- /* the invalid "Cookie" header */
- break;
- }
-
- while (start < end && *start == ' ') { start++; }
-
- last = start;
+ n = ngx_http_parse_multi_header_lines(&r->headers_in.cookies, &conf->name,
+ &src);
+ if (n == NGX_DECLINED) {
+ return NGX_OK;
+ }
- while (last < end && *last++ != ';') { /* void */ }
+ if (src.len < 22) {
+ cookies = r->headers_in.cookies.elts;
+ ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
+ "client sent too short userid cookie \"%V\"",
+ &cookies[n]->value);
+ return NGX_OK;
+ }
- if (last - start < 22) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "client sent too short userid cookie \"%V\"",
- &cookies[i]->value);
- break;
- }
+ /*
+ * we have to limit encoded string to 22 characters
+ * because there are already the millions cookies with a garbage
+ * instead of the correct base64 trail "=="
+ */
- /*
- * we have to limit encoded string to 22 characters
- * because there are already the millions cookies with a garbage
- * instead of the correct base64 trail "=="
- */
-
- src.len = 22;
- src.data = start;
- dst.data = (u_char *) ctx->uid_got;
-
- if (ngx_decode_base64(&dst, &src) == NGX_ERROR) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "client sent invalid userid cookie \"%V\"",
- &cookies[i]->value);
- break;
- }
+ src.len = 22;
- ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "uid: %08XD%08XD%08XD%08XD",
- ctx->uid_got[0], ctx->uid_got[1],
- ctx->uid_got[2], ctx->uid_got[3]);
+ dst.data = (u_char *) ctx->uid_got;
- return NGX_OK;
- }
+ if (ngx_decode_base64(&dst, &src) == NGX_ERROR) {
+ cookies = r->headers_in.cookies.elts;
+ ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
+ "client sent invalid userid cookie \"%V\"",
+ &cookies[n]->value);
+ return NGX_OK;
}
+ ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "uid: %08XD%08XD%08XD%08XD",
+ ctx->uid_got[0], ctx->uid_got[1],
+ ctx->uid_got[2], ctx->uid_got[3]);
+
return NGX_OK;
}
@@ -404,6 +374,7 @@ ngx_http_userid_set_uid(ngx_http_request_t *r, ngx_http_userid_ctx_t *ctx,
return NGX_ERROR;
}
+ set_cookie->hash = 1;
set_cookie->key.len = sizeof("Set-Cookie") - 1;
set_cookie->key.data = (u_char *) "Set-Cookie";
set_cookie->value.len = p - cookie;
@@ -421,6 +392,7 @@ ngx_http_userid_set_uid(ngx_http_request_t *r, ngx_http_userid_ctx_t *ctx,
return NGX_ERROR;
}
+ p3p->hash = 1;
p3p->key.len = sizeof("P3P") - 1;
p3p->key.data = (u_char *) "P3P";
p3p->value = conf->p3p;
@@ -570,7 +542,7 @@ ngx_http_userid_create_conf(ngx_conf_t *cf)
* conf->p3p.date = NULL;
*/
- conf->enable = NGX_CONF_UNSET;
+ conf->enable = NGX_CONF_UNSET_UINT;
conf->service = NGX_CONF_UNSET;
conf->expires = NGX_CONF_UNSET;
@@ -584,7 +556,8 @@ ngx_http_userid_merge_conf(ngx_conf_t *cf, void *parent, void *child)
ngx_http_userid_conf_t *prev = parent;
ngx_http_userid_conf_t *conf = child;
- ngx_conf_merge_value(conf->enable, prev->enable, NGX_HTTP_USERID_OFF);
+ ngx_conf_merge_unsigned_value(conf->enable, prev->enable,
+ NGX_HTTP_USERID_OFF);
ngx_conf_merge_str_value(conf->name, prev->name, "uid");
ngx_conf_merge_str_value(conf->domain, prev->domain, "");
diff --git a/src/http/modules/proxy/ngx_http_proxy_handler.c b/src/http/modules/proxy/ngx_http_proxy_handler.c
index 12d417176..bc91df9a1 100644
--- a/src/http/modules/proxy/ngx_http_proxy_handler.c
+++ b/src/http/modules/proxy/ngx_http_proxy_handler.c
@@ -311,7 +311,7 @@ static ngx_http_log_op_name_t ngx_http_proxy_log_fmt_ops[] = {
-ngx_http_header_t ngx_http_proxy_headers_in[] = {
+ngx_http_header0_t ngx_http_proxy_headers_in[] = {
{ ngx_string("Date"), offsetof(ngx_http_proxy_headers_in_t, date) },
{ ngx_string("Server"), offsetof(ngx_http_proxy_headers_in_t, server) },
@@ -490,13 +490,25 @@ static ngx_int_t ngx_http_proxy_cache_get(ngx_http_proxy_ctx_t *p)
#endif
-void ngx_http_proxy_check_broken_connection(ngx_event_t *ev)
+void ngx_http_proxy_rd_check_broken_connection(ngx_http_request_t *r)
+{
+ ngx_http_proxy_check_broken_connection(r, r->connection->read);
+}
+
+
+void ngx_http_proxy_wr_check_broken_connection(ngx_http_request_t *r)
+{
+ ngx_http_proxy_check_broken_connection(r, r->connection->read);
+}
+
+
+void ngx_http_proxy_check_broken_connection(ngx_http_request_t *r,
+ ngx_event_t *ev)
{
int n;
char buf[1];
ngx_err_t err;
ngx_connection_t *c;
- ngx_http_request_t *r;
ngx_http_proxy_ctx_t *p;
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ev->log, 0,
@@ -510,8 +522,7 @@ void ngx_http_proxy_check_broken_connection(ngx_event_t *ev)
return;
}
- c = ev->data;
- r = c->data;
+ c = r->connection;
p = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
ev->eof = 1;
@@ -542,8 +553,7 @@ void ngx_http_proxy_check_broken_connection(ngx_event_t *ev)
#endif
- c = ev->data;
- r = c->data;
+ c = r->connection;
p = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
n = recv(c->fd, buf, 1, MSG_PEEK);
@@ -712,13 +722,6 @@ void ngx_http_proxy_finalize_request(ngx_http_proxy_ctx_t *p, int rc)
p->cache->ctx.file.fd);
}
- if (p->upstream && p->upstream->event_pipe) {
- r->file.fd = p->upstream->event_pipe->temp_file->file.fd;
-
- } else if (p->cache) {
- r->file.fd = p->cache->ctx.file.fd;
- }
-
if (rc == 0 && r->main == NULL) {
rc = ngx_http_send_last(r);
}
diff --git a/src/http/modules/proxy/ngx_http_proxy_handler.h b/src/http/modules/proxy/ngx_http_proxy_handler.h
index 2c9210f9c..11c24b1ea 100644
--- a/src/http/modules/proxy/ngx_http_proxy_handler.h
+++ b/src/http/modules/proxy/ngx_http_proxy_handler.h
@@ -249,7 +249,10 @@ void ngx_http_proxy_cache_busy_lock(ngx_http_proxy_ctx_t *p);
#endif
-void ngx_http_proxy_check_broken_connection(ngx_event_t *ev);
+void ngx_http_proxy_rd_check_broken_connection(ngx_http_request_t *r);
+void ngx_http_proxy_wr_check_broken_connection(ngx_http_request_t *r);
+void ngx_http_proxy_check_broken_connection(ngx_http_request_t *r,
+ ngx_event_t *ev);
void ngx_http_proxy_busy_lock_handler(ngx_event_t *rev);
void ngx_http_proxy_upstream_busy_lock(ngx_http_proxy_ctx_t *p);
@@ -265,7 +268,7 @@ int ngx_http_proxy_copy_header(ngx_http_proxy_ctx_t *p,
extern ngx_module_t ngx_http_proxy_module;
-extern ngx_http_header_t ngx_http_proxy_headers_in[];
+extern ngx_http_header0_t ngx_http_proxy_headers_in[];
diff --git a/src/http/modules/proxy/ngx_http_proxy_upstream.c b/src/http/modules/proxy/ngx_http_proxy_upstream.c
index 107aba3df..0f17b953f 100644
--- a/src/http/modules/proxy/ngx_http_proxy_upstream.c
+++ b/src/http/modules/proxy/ngx_http_proxy_upstream.c
@@ -24,6 +24,7 @@ static void ngx_http_proxy_process_upstream_status_line(ngx_event_t *rev);
static void ngx_http_proxy_process_upstream_headers(ngx_event_t *rev);
static ssize_t ngx_http_proxy_read_upstream_header(ngx_http_proxy_ctx_t *);
static void ngx_http_proxy_send_response(ngx_http_proxy_ctx_t *p);
+static void ngx_http_proxy_process_downstream(ngx_http_request_t *r);
static void ngx_http_proxy_process_body(ngx_event_t *ev);
static void ngx_http_proxy_next_upstream(ngx_http_proxy_ctx_t *p,
ngx_uint_t ft_type);
@@ -112,7 +113,7 @@ static ngx_chain_t *ngx_http_proxy_create_request(ngx_http_proxy_ctx_t *p)
len = http_methods[p->upstream->method - 1].len + uc->uri.len;
} else {
- len = r->method_name.len + uc->uri.len;
+ len = r->method_name.len + 1 + uc->uri.len;
}
if (p->lcf->pass_unparsed_uri && r->valid_unparsed_uri) {
@@ -261,7 +262,8 @@ static ngx_chain_t *ngx_http_proxy_create_request(ngx_http_proxy_ctx_t *p)
http_methods[p->upstream->method - 1].data,
http_methods[p->upstream->method - 1].len);
} else {
- b->last = ngx_cpymem(b->last, r->method_name.data, r->method_name.len);
+ b->last = ngx_cpymem(b->last, r->method_name.data,
+ r->method_name.len + 1);
}
b->last = ngx_cpymem(b->last, uc->uri.data, uc->uri.len);
@@ -502,12 +504,11 @@ static void ngx_http_proxy_init_upstream(ngx_http_request_t *r)
ngx_del_timer(r->connection->read);
}
- r->connection->read->event_handler = ngx_http_proxy_check_broken_connection;
+ r->read_event_handler = ngx_http_proxy_rd_check_broken_connection;
if (ngx_event_flags & NGX_USE_CLEAR_EVENT) {
- r->connection->write->event_handler =
- ngx_http_proxy_check_broken_connection;
+ r->write_event_handler = ngx_http_proxy_wr_check_broken_connection;
if (!r->connection->write->active) {
if (ngx_add_event(r->connection->write, NGX_WRITE_EVENT,
@@ -770,8 +771,8 @@ static void ngx_http_proxy_connect(ngx_http_proxy_ctx_t *p)
c = p->upstream->peer.connection;
c->data = p;
- c->write->event_handler = ngx_http_proxy_send_request_handler;
- c->read->event_handler = ngx_http_proxy_process_upstream_status_line;
+ c->write->handler = ngx_http_proxy_send_request_handler;
+ c->read->handler = ngx_http_proxy_process_upstream_status_line;
c->sendfile = r->connection->sendfile;
@@ -925,9 +926,9 @@ static void ngx_http_proxy_send_request(ngx_http_proxy_ctx_t *p)
}
#endif
- c->write->event_handler = ngx_http_proxy_dummy_handler;
+ c->write->handler = ngx_http_proxy_dummy_handler;
- if (ngx_handle_level_write_event(c->write) == NGX_ERROR) {
+ if (ngx_handle_write_event(c->write, 0) == NGX_ERROR) {
ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR);
return;
}
@@ -1124,7 +1125,7 @@ static void ngx_http_proxy_process_upstream_status_line(ngx_event_t *rev)
}
- c->read->event_handler = ngx_http_proxy_process_upstream_headers;
+ c->read->handler = ngx_http_proxy_process_upstream_headers;
ngx_http_proxy_process_upstream_headers(rev);
}
@@ -1174,7 +1175,7 @@ static void ngx_http_proxy_process_upstream_headers(ngx_event_t *rev)
rc = ngx_http_parse_header_line(p->request, p->header_in);
- if (rc == NGX_OK) {
+ if (rc == NGX_OK && !r->invalid_header) {
/* a header line has been parsed successfully */
@@ -1241,6 +1242,10 @@ static void ngx_http_proxy_process_upstream_headers(ngx_event_t *rev)
} else if (rc != NGX_AGAIN) {
+ if (r->invalid_header) {
+ rc = NGX_HTTP_PARSE_INVALID_HEADER;
+ }
+
/* there was error while a header line parsing */
ngx_log_error(NGX_LOG_ERR, rev->log, 0,
@@ -1465,9 +1470,8 @@ static void ngx_http_proxy_send_response(ngx_http_proxy_ctx_t *p)
ep->send_timeout = clcf->send_timeout;
ep->send_lowat = clcf->send_lowat;
- p->upstream->peer.connection->read->event_handler =
- ngx_http_proxy_process_body;
- r->connection->write->event_handler = ngx_http_proxy_process_body;
+ p->upstream->peer.connection->read->handler = ngx_http_proxy_process_body;
+ r->write_event_handler = ngx_http_proxy_process_downstream;
ngx_http_proxy_process_body(p->upstream->peer.connection->read);
@@ -1475,6 +1479,12 @@ static void ngx_http_proxy_send_response(ngx_http_proxy_ctx_t *p)
}
+static void ngx_http_proxy_process_downstream(ngx_http_request_t *r)
+{
+ ngx_http_proxy_process_body(r->connection->write);
+}
+
+
static void ngx_http_proxy_process_body(ngx_event_t *ev)
{
ngx_connection_t *c;
diff --git a/src/http/ngx_http.c b/src/http/ngx_http.c
index e2d5fe41e..94f718d50 100644
--- a/src/http/ngx_http.c
+++ b/src/http/ngx_http.c
@@ -53,7 +53,7 @@ static ngx_core_module_t ngx_http_module_ctx = {
ngx_module_t ngx_http_module = {
- NGX_MODULE,
+ NGX_MODULE_V1,
&ngx_http_module_ctx, /* module context */
ngx_http_commands, /* module directives */
NGX_CORE_MODULE, /* module type */
@@ -85,11 +85,6 @@ ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
ngx_iocp_conf_t *iocpcf;
#endif
-#if (NGX_SUPPRESS_WARN)
- /* MSVC thinks "in_ports" may be used without having been initialized */
- ngx_memzero(&in_ports, sizeof(ngx_array_t));
-#endif
-
/* the main http context */
ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t));
@@ -156,12 +151,6 @@ ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
module = ngx_modules[m]->ctx;
mi = ngx_modules[m]->ctx_index;
- if (module->pre_conf) {
- if (module->pre_conf(cf) != NGX_OK) {
- return NGX_CONF_ERROR;
- }
- }
-
if (module->create_main_conf) {
ctx->main_conf[mi] = module->create_main_conf(cf);
if (ctx->main_conf[mi] == NULL) {
@@ -184,11 +173,26 @@ ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
}
}
+ pcf = *cf;
+ cf->ctx = ctx;
+
+ for (m = 0; ngx_modules[m]; m++) {
+ if (ngx_modules[m]->type != NGX_HTTP_MODULE) {
+ continue;
+ }
+
+ module = ngx_modules[m]->ctx;
+ mi = ngx_modules[m]->ctx_index;
+
+ if (module->preconfiguration) {
+ if (module->preconfiguration(cf) != NGX_OK) {
+ return NGX_CONF_ERROR;
+ }
+ }
+ }
/* parse inside the http{} block */
- pcf = *cf;
- cf->ctx = ctx;
cf->module_type = NGX_HTTP_MODULE;
cf->cmd_type = NGX_HTTP_MAIN_CONF;
rv = ngx_conf_parse(cf, NULL);
@@ -264,11 +268,6 @@ ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
}
- /* we needed http{}'s cf->ctx while the merging configuration */
-
- *cf = pcf;
-
-
/* init lists of the handlers */
if (ngx_array_init(&cmcf->phases[NGX_HTTP_REWRITE_PHASE].handlers,
@@ -321,7 +320,7 @@ ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
cmcf->headers_in_hash.bucket_size = sizeof(ngx_http_header_t);
cmcf->headers_in_hash.name = "http headers_in";
- if (ngx_hash_init(&cmcf->headers_in_hash, cf->pool, ngx_http_headers_in)
+ if (ngx_hash_init(&cmcf->headers_in_hash, cf->pool, ngx_http_headers_in, 0)
!= NGX_OK)
{
return NGX_CONF_ERROR;
@@ -329,8 +328,32 @@ ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, cf->log, 0,
"http headers_in hash size: %ui, max buckets per entry: %ui",
- cmcf->headers_in_hash.hash_size,
- cmcf->headers_in_hash.min_buckets);
+ cmcf->headers_in_hash.hash_size,
+ cmcf->headers_in_hash.min_buckets);
+
+ for (m = 0; ngx_modules[m]; m++) {
+ if (ngx_modules[m]->type != NGX_HTTP_MODULE) {
+ continue;
+ }
+
+ module = ngx_modules[m]->ctx;
+ mi = ngx_modules[m]->ctx_index;
+
+ if (module->postconfiguration) {
+ if (module->postconfiguration(cf) != NGX_OK) {
+ return NGX_CONF_ERROR;
+ }
+ }
+ }
+
+
+ /*
+ * http{}'s cf->ctx was needed while the configuration merging
+ * and in postconfiguration process
+ */
+
+ *cf = pcf;
+
/*
* create the lists of ports, addresses and server names
diff --git a/src/http/ngx_http.h b/src/http/ngx_http.h
index ded94e2ca..8af06d2c3 100644
--- a/src/http/ngx_http.h
+++ b/src/http/ngx_http.h
@@ -12,11 +12,16 @@
#include <ngx_core.h>
#include <ngx_garbage_collector.h>
-typedef struct ngx_http_request_s ngx_http_request_t;
-typedef struct ngx_http_log_ctx_s ngx_http_log_ctx_t;
-typedef struct ngx_http_cleanup_s ngx_http_cleanup_t;
-typedef struct ngx_http_in_addr_s ngx_http_in_addr_t;
-typedef struct ngx_http_variable_value_s ngx_http_variable_value_t;
+
+typedef struct ngx_http_request_s ngx_http_request_t;
+typedef struct ngx_http_upstream_s ngx_http_upstream_t;
+typedef struct ngx_http_log_ctx_s ngx_http_log_ctx_t;
+typedef struct ngx_http_in_addr_s ngx_http_in_addr_t;
+
+typedef ngx_int_t (*ngx_http_header_handler_pt)(ngx_http_request_t *r,
+ ngx_table_elt_t *h, ngx_uint_t offset);
+typedef u_char *(*ngx_http_log_handler_pt)(ngx_http_request_t *r, u_char *buf,
+ size_t len);
#if (NGX_HTTP_CACHE)
@@ -25,13 +30,13 @@ typedef struct ngx_http_variable_value_s ngx_http_variable_value_t;
/* STUB */
#include <ngx_http_cache.h>
-#include <ngx_http_upstream.h>
+#include <ngx_http_variables.h>
#include <ngx_http_request.h>
+#include <ngx_http_upstream.h>
#include <ngx_http_config.h>
#include <ngx_http_busy_lock.h>
#include <ngx_http_log_module.h>
#include <ngx_http_core_module.h>
-#include <ngx_http_variables.h>
#include <ngx_http_script.h>
#if (NGX_HTTP_SSL)
@@ -58,16 +63,18 @@ void ngx_http_init_connection(ngx_connection_t *c);
ngx_int_t ngx_http_parse_request_line(ngx_http_request_t *r, ngx_buf_t *b);
ngx_int_t ngx_http_parse_complex_uri(ngx_http_request_t *r);
ngx_int_t ngx_http_parse_header_line(ngx_http_request_t *r, ngx_buf_t *b);
+ngx_int_t ngx_http_parse_multi_header_lines(ngx_array_t *headers,
+ ngx_str_t *name, ngx_str_t *value);
ngx_int_t ngx_http_find_server_conf(ngx_http_request_t *r);
void ngx_http_handler(ngx_http_request_t *r);
-void ngx_http_finalize_request(ngx_http_request_t *r, int error);
-void ngx_http_writer(ngx_event_t *wev);
+void ngx_http_finalize_request(ngx_http_request_t *r, ngx_int_t rc);
void ngx_http_empty_handler(ngx_event_t *wev);
+void ngx_http_request_empty_handler(ngx_http_request_t *r);
ngx_int_t ngx_http_send_last(ngx_http_request_t *r);
-void ngx_http_close_request(ngx_http_request_t *r, int error);
+void ngx_http_close_request(ngx_http_request_t *r, ngx_int_t error);
void ngx_http_close_connection(ngx_connection_t *c);
u_char * ngx_http_log_error_info(ngx_http_request_t *r, u_char *buf,
size_t len);
diff --git a/src/http/ngx_http_busy_lock.c b/src/http/ngx_http_busy_lock.c
index fe04390a1..2bc211048 100644
--- a/src/http/ngx_http_busy_lock.c
+++ b/src/http/ngx_http_busy_lock.c
@@ -46,8 +46,10 @@ int ngx_http_busy_lock(ngx_http_busy_lock_t *bl, ngx_http_busy_lock_ctx_t *bc)
if (bl->waiting < bl->max_waiting) {
bl->waiting++;
+#if 0
ngx_add_timer(bc->event, 1000);
bc->event->event_handler = bc->event_handler;
+#endif
/* TODO: ngx_handle_level_read_event() */
@@ -95,9 +97,11 @@ int ngx_http_busy_lock_cachable(ngx_http_busy_lock_t *bl,
}
if (bl->waiting < bl->max_waiting) {
+#if 0
bl->waiting++;
ngx_add_timer(bc->event, 1000);
bc->event->event_handler = bc->event_handler;
+#endif
/* TODO: ngx_handle_level_read_event() */
diff --git a/src/http/ngx_http_config.h b/src/http/ngx_http_config.h
index 581556fe4..89110c023 100644
--- a/src/http/ngx_http_config.h
+++ b/src/http/ngx_http_config.h
@@ -20,7 +20,8 @@ typedef struct {
typedef struct {
- ngx_int_t (*pre_conf)(ngx_conf_t *cf);
+ ngx_int_t (*preconfiguration)(ngx_conf_t *cf);
+ ngx_int_t (*postconfiguration)(ngx_conf_t *cf);
void *(*create_main_conf)(ngx_conf_t *cf);
char *(*init_main_conf)(ngx_conf_t *cf, void *conf);
diff --git a/src/http/ngx_http_copy_filter_module.c b/src/http/ngx_http_copy_filter_module.c
index 4e8943844..98579a2c0 100644
--- a/src/http/ngx_http_copy_filter_module.c
+++ b/src/http/ngx_http_copy_filter_module.c
@@ -34,7 +34,8 @@ static ngx_command_t ngx_http_copy_filter_commands[] = {
static ngx_http_module_t ngx_http_copy_filter_module_ctx = {
- NULL, /* pre conf */
+ NULL, /* preconfiguration */
+ NULL, /* postconfiguration */
NULL, /* create main configuration */
NULL, /* init main configuration */
@@ -48,7 +49,7 @@ static ngx_http_module_t ngx_http_copy_filter_module_ctx = {
ngx_module_t ngx_http_copy_filter_module = {
- NGX_MODULE,
+ NGX_MODULE_V1,
&ngx_http_copy_filter_module_ctx, /* module context */
ngx_http_copy_filter_commands, /* module directives */
NGX_HTTP_MODULE, /* module type */
@@ -63,6 +64,7 @@ static ngx_http_output_body_filter_pt ngx_http_next_filter;
static ngx_int_t
ngx_http_copy_filter(ngx_http_request_t *r, ngx_chain_t *in)
{
+ ngx_int_t rc;
ngx_output_chain_ctx_t *ctx;
ngx_http_copy_filter_conf_t *conf;
@@ -70,12 +72,13 @@ ngx_http_copy_filter(ngx_http_request_t *r, ngx_chain_t *in)
return NGX_ERROR;
}
- ctx = ngx_http_get_module_ctx(r->main ? r->main : r,
- ngx_http_copy_filter_module);
+ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "copy filter: \"%V\"", &r->uri);
+
+ ctx = ngx_http_get_module_ctx(r, ngx_http_copy_filter_module);
if (ctx == NULL) {
- conf = ngx_http_get_module_loc_conf(r->main ? r->main : r,
- ngx_http_copy_filter_module);
+ conf = ngx_http_get_module_loc_conf(r, ngx_http_copy_filter_module);
ctx = ngx_pcalloc(r->pool, sizeof(ngx_output_chain_ctx_t));
if (ctx == NULL) {
@@ -97,7 +100,12 @@ ngx_http_copy_filter(ngx_http_request_t *r, ngx_chain_t *in)
}
- return ngx_output_chain(ctx, in);
+ rc = ngx_output_chain(ctx, in);
+
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "copy filter: %i \"%V\"", rc, &r->uri);
+
+ return rc;
}
diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c
index 0ad08d5e1..13aa44032 100644
--- a/src/http/ngx_http_core_module.c
+++ b/src/http/ngx_http_core_module.c
@@ -17,11 +17,12 @@
#define NGX_HTTP_LOCATION_REGEX 4
-static void ngx_http_core_phase_event_handler(ngx_event_t *rev);
static void ngx_http_core_run_phases(ngx_http_request_t *r);
static ngx_int_t ngx_http_core_find_location(ngx_http_request_t *r,
ngx_array_t *locations, size_t len);
+static ngx_int_t ngx_http_core_preconfiguration(ngx_conf_t *cf);
+static ngx_int_t ngx_http_core_postconfiguration(ngx_conf_t *cf);
static void *ngx_http_core_create_main_conf(ngx_conf_t *cf);
static char *ngx_http_core_init_main_conf(ngx_conf_t *cf, void *conf);
static void *ngx_http_core_create_srv_conf(ngx_conf_t *cf);
@@ -54,9 +55,10 @@ static char *ngx_http_core_error_log(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
static char *ngx_http_core_keepalive(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
+static char *ngx_http_core_internal(ngx_conf_t *cf, ngx_command_t *cmd,
+ void *conf);
static char *ngx_http_core_lowat_check(ngx_conf_t *cf, void *post, void *data);
-static ngx_int_t ngx_http_core_init(ngx_cycle_t *cycle);
static ngx_conf_post_t ngx_http_core_lowat_post =
{ ngx_http_core_lowat_check };
@@ -183,7 +185,8 @@ static ngx_command_t ngx_http_core_commands[] = {
NULL },
{ ngx_string("root"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
+ |NGX_CONF_TAKE1,
ngx_http_core_root,
NGX_HTTP_LOC_CONF_OFFSET,
0,
@@ -281,6 +284,13 @@ static ngx_command_t ngx_http_core_commands[] = {
0,
NULL },
+ { ngx_string("internal"),
+ NGX_HTTP_LOC_CONF|NGX_CONF_NOARGS,
+ ngx_http_core_internal,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ 0,
+ NULL },
+
{ ngx_string("lingering_time"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
ngx_conf_set_msec_slot,
@@ -310,7 +320,8 @@ static ngx_command_t ngx_http_core_commands[] = {
NULL },
{ ngx_string("error_page"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_2MORE,
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
+ |NGX_CONF_2MORE,
ngx_http_core_error_page,
NGX_HTTP_LOC_CONF_OFFSET,
0,
@@ -339,7 +350,8 @@ static ngx_command_t ngx_http_core_commands[] = {
ngx_http_module_t ngx_http_core_module_ctx = {
- NULL, /* pre conf */
+ ngx_http_core_preconfiguration, /* preconfiguration */
+ ngx_http_core_postconfiguration, /* postconfiguration */
ngx_http_core_create_main_conf, /* create main configuration */
ngx_http_core_init_main_conf, /* init main configuration */
@@ -353,11 +365,11 @@ ngx_http_module_t ngx_http_core_module_ctx = {
ngx_module_t ngx_http_core_module = {
- NGX_MODULE,
+ NGX_MODULE_V1,
&ngx_http_core_module_ctx, /* module context */
ngx_http_core_commands, /* module directives */
NGX_HTTP_MODULE, /* module type */
- ngx_http_core_init, /* init module */
+ NULL, /* init module */
NULL /* init process */
};
@@ -413,11 +425,12 @@ ngx_http_handler(ngx_http_request_t *r)
/* TEST STUB */ r->lingering_close = 1;
#endif
- r->connection->write->event_handler = ngx_http_core_phase_event_handler;
+ r->write_event_handler = ngx_http_core_run_phases;
r->valid_unparsed_uri = 1;
+ r->valid_location = 1;
r->uri_changed = 1;
- r->uri_changes = 11;
+ r->uri_changes = NGX_HTTP_MAX_REWRITE_CYCLES + 1;
r->phase = NGX_HTTP_REWRITE_PHASE;
r->phase_handler = 0;
@@ -427,21 +440,6 @@ ngx_http_handler(ngx_http_request_t *r)
static void
-ngx_http_core_phase_event_handler(ngx_event_t *ev)
-{
- ngx_connection_t *c;
- ngx_http_request_t *r;
-
- c = ev->data;
- r = c->data;
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ev->log, 0, "phase event handler");
-
- ngx_http_core_run_phases(r);
-}
-
-
-static void
ngx_http_core_run_phases(ngx_http_request_t *r)
{
ngx_int_t rc;
@@ -449,6 +447,9 @@ ngx_http_core_run_phases(ngx_http_request_t *r)
ngx_http_core_loc_conf_t *clcf;
ngx_http_core_main_conf_t *cmcf;
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "http phase handler");
+
cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
for (/* void */; r->phase < NGX_HTTP_LAST_PHASE; r->phase++) {
@@ -478,7 +479,7 @@ ngx_http_core_run_phases(ngx_http_request_t *r)
}
if (r->phase == NGX_HTTP_CONTENT_PHASE && r->content_handler) {
- r->connection->write->event_handler = ngx_http_empty_handler;
+ r->write_event_handler = ngx_http_request_empty_handler;
ngx_http_finalize_request(r, r->content_handler(r));
return;
}
@@ -564,6 +565,10 @@ ngx_http_find_location_config(ngx_http_request_t *r)
clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
+ if (!r->internal && clcf->internal) {
+ return NGX_HTTP_NOT_FOUND;
+ }
+
r->connection->log->file = clcf->err_log->file;
if (!(r->connection->log->log_level & NGX_LOG_DEBUG_CONNECTION)) {
r->connection->log->log_level = clcf->err_log->log_level;
@@ -608,6 +613,11 @@ ngx_http_find_location_config(ngx_http_request_t *r)
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
+ /*
+ * we do not need to set the r->headers_out.location->hash and
+ * r->headers_out.location->key fields
+ */
+
r->headers_out.location->value = clcf->name;
return NGX_HTTP_MOVED_PERMANENTLY;
@@ -765,16 +775,6 @@ ngx_http_set_content_type(ngx_http_request_t *r)
ngx_http_type_t *type;
ngx_http_core_loc_conf_t *clcf;
- r->headers_out.content_type = ngx_list_push(&r->headers_out.headers);
- if (r->headers_out.content_type == NULL) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- r->headers_out.content_type->key.len = 0;
- r->headers_out.content_type->key.data = NULL;
- r->headers_out.content_type->value.len = 0;
- r->headers_out.content_type->value.data = NULL;
-
clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
if (r->exten.len) {
@@ -810,9 +810,6 @@ ngx_http_set_content_type(ngx_http_request_t *r)
r->low_case_exten = 1;
}
-#if 0
- key = ngx_crc(r->exten.data, r->exten.key);
-#endif
ngx_http_types_hash_key(key, r->exten);
type = clcf->types[key].elts;
@@ -824,14 +821,14 @@ ngx_http_set_content_type(ngx_http_request_t *r)
if (ngx_memcmp(r->exten.data, type[i].exten.data, r->exten.len)
== 0)
{
- r->headers_out.content_type->value = type[i].type;
+ r->headers_out.content_type = type[i].type;
break;
}
}
}
- if (r->headers_out.content_type->value.len == 0) {
- r->headers_out.content_type->value = clcf->default_type;
+ if (r->headers_out.content_type.len == 0) {
+ r->headers_out.content_type= clcf->default_type;
}
return NGX_OK;
@@ -841,10 +838,6 @@ ngx_http_set_content_type(ngx_http_request_t *r)
ngx_int_t
ngx_http_send_header(ngx_http_request_t *r)
{
- if (r->main) {
- return NGX_OK;
- }
-
if (r->err_ctx) {
r->headers_out.status = r->err_status;
r->headers_out.status_line.len = 0;
@@ -863,12 +856,13 @@ ngx_http_output_filter(ngx_http_request_t *r, ngx_chain_t *in)
return NGX_ERROR;
}
+ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "http output filter \"%V\"", &r->uri);
+
rc = ngx_http_top_body_filter(r, in);
if (rc == NGX_ERROR) {
-
/* NGX_ERROR may be returned by any filter */
-
r->connection->write->error = 1;
}
@@ -924,6 +918,114 @@ ngx_http_set_exten(ngx_http_request_t *r)
ngx_int_t
+ngx_http_subrequest(ngx_http_request_t *r,
+ ngx_str_t *uri, ngx_str_t *args)
+{
+ ngx_http_request_t *sr;
+ ngx_http_core_srv_conf_t *cscf;
+ ngx_http_postponed_request_t *pr, *p;
+
+ sr = ngx_pcalloc(r->pool, sizeof(ngx_http_request_t));
+ if (sr == NULL) {
+ return NGX_HTTP_INTERNAL_SERVER_ERROR;
+ }
+
+ sr->signature = NGX_HTTP_MODULE;
+ sr->connection = r->connection;
+
+ sr->ctx = ngx_pcalloc(r->pool, sizeof(void *) * ngx_http_max_module);
+ if (sr->ctx == NULL) {
+ return NGX_HTTP_INTERNAL_SERVER_ERROR;
+ }
+
+ if (ngx_list_init(&sr->headers_out.headers, r->pool, 20,
+ sizeof(ngx_table_elt_t)) == NGX_ERROR)
+ {
+ return NGX_HTTP_INTERNAL_SERVER_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;
+ sr->loc_conf = cscf->ctx->loc_conf;
+
+ sr->pool = r->pool;
+
+ sr->headers_in = r->headers_in;
+
+ sr->start_time = ngx_time();
+ sr->headers_out.content_length_n = -1;
+ sr->headers_out.last_modified_time = -1;
+
+ sr->request_body = r->request_body;
+
+ sr->method = NGX_HTTP_GET;
+ sr->http_version = r->http_version;
+ sr->http_major = r->http_minor;
+
+ sr->request_line = r->request_line;
+ sr->uri = *uri;
+ if (args) {
+ sr->args = *args;
+ }
+ sr->unparsed_uri = r->unparsed_uri;
+ sr->method_name = r->method_name;
+ sr->http_protocol = r->http_protocol;
+
+ if (ngx_http_set_exten(sr) != NGX_OK) {
+ return NGX_HTTP_INTERNAL_SERVER_ERROR;
+ }
+
+ sr->main = r->main ? r->main : r;
+ sr->parent = r;
+ sr->read_event_handler = ngx_http_request_empty_handler;
+ sr->write_event_handler = ngx_http_request_empty_handler;
+
+ if (r->connection->data == r) {
+ sr->connection->data = sr;
+ }
+
+ sr->in_addr = r->in_addr;
+ sr->port = r->port;
+ sr->port_text = r->port_text;
+ sr->server_name = r->server_name;
+
+ sr->variables = r->variables;
+
+ sr->log_handler = r->log_handler;
+
+ pr = ngx_palloc(r->pool, sizeof(ngx_http_postponed_request_t));
+ if (pr == NULL) {
+ return NGX_HTTP_INTERNAL_SERVER_ERROR;
+ }
+
+ pr->request = sr;
+ pr->out = NULL;
+ pr->next = NULL;
+
+ if (r->postponed) {
+ for (p = r->postponed; p->next; p = p->next) { /* void */ }
+ p->next = pr;
+
+ } else {
+ r->postponed = pr;
+ }
+
+ sr->internal = 1;
+
+ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "http subrequest \"%V\"", uri);
+
+ ngx_http_handler(sr);
+
+ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "http subrequest \"%V\" done", uri);
+
+ return NGX_OK;
+}
+
+
+ngx_int_t
ngx_http_internal_redirect(ngx_http_request_t *r,
ngx_str_t *uri, ngx_str_t *args)
{
@@ -936,6 +1038,10 @@ ngx_http_internal_redirect(ngx_http_request_t *r,
if (args) {
r->args = *args;
+
+ } else {
+ r->args.len = 0;
+ r->args.data = NULL;
}
if (ngx_http_set_exten(r) != NGX_OK) {
@@ -961,6 +1067,8 @@ ngx_http_internal_redirect(ngx_http_request_t *r,
cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
r->loc_conf = cscf->ctx->loc_conf;
+ r->internal = 1;
+
ngx_http_handler(r);
return NGX_DONE;
@@ -1376,6 +1484,20 @@ ngx_http_core_type(ngx_conf_t *cf, ngx_command_t *dummy, void *conf)
}
+static ngx_int_t
+ngx_http_core_preconfiguration(ngx_conf_t *cf)
+{
+ return ngx_http_variables_add_core_vars(cf);
+}
+
+
+static ngx_int_t
+ngx_http_core_postconfiguration(ngx_conf_t *cf)
+{
+ return ngx_http_variables_init_vars(cf);
+}
+
+
static void *
ngx_http_core_create_main_conf(ngx_conf_t *cf)
{
@@ -1575,6 +1697,7 @@ ngx_http_core_create_loc_conf(ngx_conf_t *cf)
lcf->client_max_body_size = NGX_CONF_UNSET_SIZE;
lcf->client_body_buffer_size = NGX_CONF_UNSET_SIZE;
lcf->client_body_timeout = NGX_CONF_UNSET_MSEC;
+ lcf->internal = NGX_CONF_UNSET;
lcf->sendfile = NGX_CONF_UNSET;
lcf->tcp_nopush = NGX_CONF_UNSET;
lcf->tcp_nodelay = NGX_CONF_UNSET;
@@ -1673,9 +1796,12 @@ ngx_http_core_merge_loc_conf(ngx_conf_t *cf,
(size_t) 2 * ngx_pagesize);
ngx_conf_merge_msec_value(conf->client_body_timeout,
prev->client_body_timeout, 60000);
+
+ ngx_conf_merge_value(conf->internal, prev->internal, 0);
ngx_conf_merge_value(conf->sendfile, prev->sendfile, 0);
ngx_conf_merge_value(conf->tcp_nopush, prev->tcp_nopush, 0);
ngx_conf_merge_value(conf->tcp_nodelay, prev->tcp_nodelay, 0);
+
ngx_conf_merge_msec_value(conf->send_timeout, prev->send_timeout, 60000);
ngx_conf_merge_size_value(conf->send_lowat, prev->send_lowat, 0);
ngx_conf_merge_size_value(conf->postpone_output, prev->postpone_output,
@@ -1963,6 +2089,20 @@ ngx_http_core_error_page(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, void *conf)
+{
+ ngx_http_core_loc_conf_t *lcf = conf;
+
+ lcf->err_log = ngx_log_create_errlog(cf->cycle, cf->args);
+ if (lcf->err_log == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ return ngx_set_error_log_levels(cf, lcf->err_log);
+}
+
+
+static char *
ngx_http_core_keepalive(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
ngx_http_core_loc_conf_t *lcf = conf;
@@ -2004,16 +2144,17 @@ ngx_http_core_keepalive(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, void *conf)
+ngx_http_core_internal(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
ngx_http_core_loc_conf_t *lcf = conf;
- lcf->err_log = ngx_log_create_errlog(cf->cycle, cf->args);
- if (lcf->err_log == NULL) {
- return NGX_CONF_ERROR;
+ if (lcf->internal != NGX_CONF_UNSET) {
+ return "is duplicate";
}
- return ngx_set_error_log_levels(cf, lcf->err_log);
+ lcf->internal = 1;
+
+ return NGX_CONF_OK;
}
@@ -2044,10 +2185,3 @@ ngx_http_core_lowat_check(ngx_conf_t *cf, void *post, void *data)
return NGX_CONF_OK;
}
-
-
-static ngx_int_t
-ngx_http_core_init(ngx_cycle_t *cycle)
-{
- return ngx_http_variables_init(cycle);
-}
diff --git a/src/http/ngx_http_core_module.h b/src/http/ngx_http_core_module.h
index ac572d6c9..2b2a1d003 100644
--- a/src/http/ngx_http_core_module.h
+++ b/src/http/ngx_http_core_module.h
@@ -49,6 +49,7 @@ typedef struct {
ngx_array_t index_handlers;
ngx_hash_t headers_in_hash;
+ ngx_hash_t variables_hash;
ngx_uint_t server_names_hash;
ngx_uint_t server_names_hash_threshold;
@@ -56,6 +57,7 @@ typedef struct {
size_t max_server_name_len;
ngx_array_t variables; /* ngx_http_variable_t */
+ ngx_array_t all_variables; /* ngx_http_variable_t */
} ngx_http_core_main_conf_t;
@@ -197,6 +199,7 @@ struct ngx_http_core_loc_conf_s {
time_t keepalive_header; /* keepalive_timeout */
+ ngx_flag_t internal; /* internal */
ngx_flag_t sendfile; /* sendfile */
ngx_flag_t tcp_nopush; /* tcp_nopush */
ngx_flag_t tcp_nodelay; /* tcp_nodelay */
@@ -230,6 +233,8 @@ ngx_int_t ngx_http_find_location_config(ngx_http_request_t *r);
ngx_int_t ngx_http_set_content_type(ngx_http_request_t *r);
ngx_int_t ngx_http_set_exten(ngx_http_request_t *r);
+ngx_int_t ngx_http_subrequest(ngx_http_request_t *r,
+ ngx_str_t *uri, ngx_str_t *args);
ngx_int_t ngx_http_internal_redirect(ngx_http_request_t *r,
ngx_str_t *uri, ngx_str_t *args);
diff --git a/src/http/ngx_http_header_filter_module.c b/src/http/ngx_http_header_filter_module.c
index b9dd88d5d..c1d26fa3b 100644
--- a/src/http/ngx_http_header_filter_module.c
+++ b/src/http/ngx_http_header_filter_module.c
@@ -15,7 +15,8 @@ static ngx_int_t ngx_http_header_filter(ngx_http_request_t *r);
static ngx_http_module_t ngx_http_header_filter_module_ctx = {
- NULL, /* pre conf */
+ NULL, /* preconfiguration */
+ NULL, /* postconfiguration */
NULL, /* create main configuration */
NULL, /* init main configuration */
@@ -29,7 +30,7 @@ static ngx_http_module_t ngx_http_header_filter_module_ctx = {
ngx_module_t ngx_http_header_filter_module = {
- NGX_MODULE,
+ NGX_MODULE_V1,
&ngx_http_header_filter_module_ctx, /* module context */
NULL, /* module directives */
NGX_HTTP_MODULE, /* module type */
@@ -38,10 +39,10 @@ ngx_module_t ngx_http_header_filter_module = {
};
-static char server_string[] = "Server: " NGINX_VER CRLF;
+static char ngx_http_server_string[] = "Server: " NGINX_VER CRLF;
-static ngx_str_t http_codes[] = {
+static ngx_str_t ngx_http_status_lines[] = {
ngx_string("200 OK"),
ngx_null_string, /* "201 Created" */
@@ -115,11 +116,13 @@ static ngx_str_t http_codes[] = {
};
-ngx_http_header_t ngx_http_headers_out[] = {
+ngx_http_header0_t ngx_http_headers_out[] = {
{ ngx_string("Server"), offsetof(ngx_http_headers_out_t, server) },
{ ngx_string("Date"), offsetof(ngx_http_headers_out_t, date) },
+#if 0
{ ngx_string("Content-Type"),
offsetof(ngx_http_headers_out_t, content_type) },
+#endif
{ ngx_string("Content-Length"),
offsetof(ngx_http_headers_out_t, content_length) },
{ ngx_string("Content-Encoding"),
@@ -150,6 +153,10 @@ ngx_http_header_filter(ngx_http_request_t *r)
ngx_table_elt_t *header;
ngx_http_core_loc_conf_t *clcf;
+ if (r->main) {
+ return NGX_OK;
+ }
+
if (r->http_version < NGX_HTTP_VERSION_10) {
return NGX_OK;
}
@@ -209,44 +216,44 @@ ngx_http_header_filter(ngx_http_request_t *r)
+ NGX_HTTP_LEVEL_400;
}
- len += http_codes[status].len;
+ len += ngx_http_status_lines[status].len;
}
- if (r->headers_out.server && r->headers_out.server->key.len) {
- len += r->headers_out.server->key.len
- + r->headers_out.server->value.len + 2;
- } else {
- len += sizeof(server_string) - 1;
+ if (r->headers_out.server == NULL) {
+ len += sizeof(ngx_http_server_string) - 1;
}
- if (r->headers_out.date && r->headers_out.date->key.len) {
- len += r->headers_out.date->key.len
- + r->headers_out.date->value.len + 2;
- } else {
+ if (r->headers_out.date == NULL) {
len += sizeof("Date: Mon, 28 Sep 1970 06:00:00 GMT" CRLF) - 1;
}
- if (r->headers_out.content_length == NULL) {
- if (r->headers_out.content_length_n >= 0) {
- len += sizeof("Content-Length: ") - 1 + NGX_OFF_T_LEN + 2;
- }
- }
-
- if (r->headers_out.content_type && r->headers_out.content_type->value.len) {
- r->headers_out.content_type->key.len = 0;
+ if (r->headers_out.content_type.len) {
len += sizeof("Content-Type: ") - 1
- + r->headers_out.content_type->value.len + 2;
+ + r->headers_out.content_type.len + 2;
if (r->headers_out.charset.len) {
len += sizeof("; charset=") - 1 + r->headers_out.charset.len;
}
}
+ if (r->headers_out.content_length == NULL
+ && r->headers_out.content_length_n >= 0)
+ {
+ len += sizeof("Content-Length: ") - 1 + NGX_OFF_T_LEN + 2;
+ }
+
+ if (r->headers_out.last_modified == NULL
+ && r->headers_out.last_modified_time != -1)
+ {
+ len += sizeof("Last-Modified: Mon, 28 Sep 1970 06:00:00 GMT" CRLF) - 1;
+ }
+
if (r->headers_out.location
&& r->headers_out.location->value.len
&& r->headers_out.location->value.data[0] == '/')
{
- r->headers_out.location->key.len = 0;
+ r->headers_out.location->hash = 0;
+
len += sizeof("Location: http://") - 1
+ r->server_name.len + r->headers_out.location->value.len + 2;
@@ -255,14 +262,6 @@ ngx_http_header_filter(ngx_http_request_t *r)
}
}
- if (r->headers_out.last_modified && r->headers_out.last_modified->key.len) {
- len += r->headers_out.last_modified->key.len
- + r->headers_out.last_modified->value.len + 2;
-
- } else if (r->headers_out.last_modified_time != -1) {
- len += sizeof("Last-Modified: Mon, 28 Sep 1970 06:00:00 GMT" CRLF) - 1;
- }
-
if (r->chunked) {
len += sizeof("Transfer-Encoding: chunked" CRLF) - 1;
}
@@ -303,7 +302,7 @@ ngx_http_header_filter(ngx_http_request_t *r)
i = 0;
}
- if (header[i].key.len == 0) {
+ if (header[i].hash == 0) {
continue;
}
@@ -325,16 +324,17 @@ ngx_http_header_filter(ngx_http_request_t *r)
r->headers_out.status_line.len);
} else {
- b->last = ngx_cpymem(b->last, http_codes[status].data,
- http_codes[status].len);
+ b->last = ngx_cpymem(b->last, ngx_http_status_lines[status].data,
+ ngx_http_status_lines[status].len);
}
*b->last++ = CR; *b->last++ = LF;
- if (!(r->headers_out.server && r->headers_out.server->key.len)) {
- b->last = ngx_cpymem(b->last, server_string, sizeof(server_string) - 1);
+ if (r->headers_out.server == NULL) {
+ b->last = ngx_cpymem(b->last, ngx_http_server_string,
+ sizeof(ngx_http_server_string) - 1);
}
- if (!(r->headers_out.date && r->headers_out.date->key.len)) {
+ if (r->headers_out.date == NULL) {
b->last = ngx_cpymem(b->last, "Date: ", sizeof("Date: ") - 1);
b->last = ngx_cpymem(b->last, ngx_cached_http_time.data,
ngx_cached_http_time.len);
@@ -342,19 +342,12 @@ ngx_http_header_filter(ngx_http_request_t *r)
*b->last++ = CR; *b->last++ = LF;
}
- if (r->headers_out.content_length == NULL) {
- if (r->headers_out.content_length_n >= 0) {
- b->last = ngx_sprintf(b->last, "Content-Length: %O" CRLF,
- r->headers_out.content_length_n);
- }
- }
-
- if (r->headers_out.content_type && r->headers_out.content_type->value.len) {
+ if (r->headers_out.content_type.len) {
b->last = ngx_cpymem(b->last, "Content-Type: ",
sizeof("Content-Type: ") - 1);
p = b->last;
- b->last = ngx_cpymem(b->last, r->headers_out.content_type->value.data,
- r->headers_out.content_type->value.len);
+ b->last = ngx_cpymem(b->last, r->headers_out.content_type.data,
+ r->headers_out.content_type.len);
if (r->headers_out.charset.len) {
b->last = ngx_cpymem(b->last, "; charset=",
@@ -362,13 +355,32 @@ ngx_http_header_filter(ngx_http_request_t *r)
b->last = ngx_cpymem(b->last, r->headers_out.charset.data,
r->headers_out.charset.len);
- r->headers_out.content_type->value.len = b->last - p;
- r->headers_out.content_type->value.data = p;
+ /* update r->headers_out.content_type for possible logging */
+
+ r->headers_out.content_type.len = b->last - p;
+ r->headers_out.content_type.data = p;
}
*b->last++ = CR; *b->last++ = LF;
}
+ if (r->headers_out.content_length == NULL
+ && r->headers_out.content_length_n >= 0)
+ {
+ b->last = ngx_sprintf(b->last, "Content-Length: %O" CRLF,
+ r->headers_out.content_length_n);
+ }
+
+ if (r->headers_out.last_modified == NULL
+ && r->headers_out.last_modified_time != -1)
+ {
+ b->last = ngx_cpymem(b->last, "Last-Modified: ",
+ sizeof("Last-Modified: ") - 1);
+ b->last = ngx_http_time(b->last, r->headers_out.last_modified_time);
+
+ *b->last++ = CR; *b->last++ = LF;
+ }
+
if (r->headers_out.location
&& r->headers_out.location->value.len
&& r->headers_out.location->value.data[0] == '/')
@@ -386,22 +398,14 @@ ngx_http_header_filter(ngx_http_request_t *r)
b->last = ngx_cpymem(b->last, r->headers_out.location->value.data,
r->headers_out.location->value.len);
+ /* update r->headers_out.location->value for possible logging */
+
r->headers_out.location->value.len = b->last - p;
r->headers_out.location->value.data = p;
*b->last++ = CR; *b->last++ = LF;
}
- if (!(r->headers_out.last_modified && r->headers_out.last_modified->key.len)
- && r->headers_out.last_modified_time != -1)
- {
- b->last = ngx_cpymem(b->last, "Last-Modified: ",
- sizeof("Last-Modified: ") - 1);
- b->last = ngx_http_time(b->last, r->headers_out.last_modified_time);
-
- *b->last++ = CR; *b->last++ = LF;
- }
-
if (r->chunked) {
b->last = ngx_cpymem(b->last, "Transfer-Encoding: chunked" CRLF,
sizeof("Transfer-Encoding: chunked" CRLF) - 1);
@@ -436,7 +440,7 @@ ngx_http_header_filter(ngx_http_request_t *r)
i = 0;
}
- if (header[i].key.len == 0) {
+ if (header[i].hash == 0) {
continue;
}
diff --git a/src/http/ngx_http_log_module.c b/src/http/ngx_http_log_module.c
index 36a98ddf0..333472ecc 100644
--- a/src/http/ngx_http_log_module.c
+++ b/src/http/ngx_http_log_module.c
@@ -106,7 +106,8 @@ static ngx_command_t ngx_http_log_commands[] = {
ngx_http_module_t ngx_http_log_module_ctx = {
- ngx_http_log_set_formats, /* pre conf */
+ ngx_http_log_set_formats, /* preconfiguration */
+ NULL, /* postconfiguration */
ngx_http_log_create_main_conf, /* create main configuration */
NULL, /* init main configuration */
@@ -120,7 +121,7 @@ ngx_http_module_t ngx_http_log_module_ctx = {
ngx_module_t ngx_http_log_module = {
- NGX_MODULE,
+ NGX_MODULE_V1,
&ngx_http_log_module_ctx, /* module context */
ngx_http_log_commands, /* module directives */
NGX_HTTP_MODULE, /* module type */
@@ -391,6 +392,11 @@ ngx_http_log_header_in_compile(ngx_conf_t *cf, ngx_http_log_op_t *op,
continue;
}
+ /* STUB: "Cookie" speacial handling */
+ if (ngx_http_headers_in[i].offset == 0) {
+ continue;
+ }
+
if (ngx_strncasecmp(ngx_http_headers_in[i].name.data, value->data,
value->len) == 0)
{
@@ -733,22 +739,17 @@ static ngx_int_t
ngx_http_log_variable_compile(ngx_conf_t *cf, ngx_http_log_op_t *op,
ngx_str_t *value)
{
- ngx_uint_t i;
- ngx_http_variable_t *var;
-
- for (i = 0; i < value->len; i++) {
- value->data[i] = ngx_toupper(value->data[i]);
- }
+ ngx_int_t index;
- var = ngx_http_add_variable(cf, value, 0);
- if (var == NULL) {
+ index = ngx_http_get_variable_index(cf, value);
+ if (index == NGX_ERROR) {
return NGX_ERROR;
}
op->len = 0;
op->getlen = ngx_http_log_variable_getlen;
op->run = ngx_http_log_variable;
- op->data = var->index;
+ op->data = index;
return NGX_OK;
}
@@ -762,7 +763,7 @@ ngx_http_log_variable_getlen(ngx_http_request_t *r, uintptr_t data)
value = ngx_http_get_indexed_variable(r, data);
if (value == NULL
- || value == NGX_HTTP_VARIABLE_NOT_FOUND
+ || value == NGX_HTTP_VAR_NOT_FOUND
|| value->text.len == 0)
{
return 1;
@@ -780,7 +781,7 @@ ngx_http_log_variable(ngx_http_request_t *r, u_char *buf, ngx_http_log_op_t *op)
value = ngx_http_get_indexed_variable(r, op->data);
if (value == NULL
- || value == NGX_HTTP_VARIABLE_NOT_FOUND
+ || value == NGX_HTTP_VAR_NOT_FOUND
|| value->text.len == 0)
{
*buf = '-';
diff --git a/src/http/ngx_http_parse.c b/src/http/ngx_http_parse.c
index 5a9685c86..752b6a16c 100644
--- a/src/http/ngx_http_parse.c
+++ b/src/http/ngx_http_parse.c
@@ -9,7 +9,8 @@
#include <ngx_http.h>
-ngx_int_t ngx_http_parse_request_line(ngx_http_request_t *r, ngx_buf_t *b)
+ngx_int_t
+ngx_http_parse_request_line(ngx_http_request_t *r, ngx_buf_t *b)
{
u_char c, ch, *p, *m;
enum {
@@ -63,7 +64,7 @@ ngx_int_t ngx_http_parse_request_line(ngx_http_request_t *r, ngx_buf_t *b)
case sw_method:
if (ch == ' ') {
- r->method_end = p;
+ r->method_end = p - 1;
m = r->request_start;
if (p - m == 3) {
@@ -502,7 +503,8 @@ done:
}
-ngx_int_t ngx_http_parse_header_line(ngx_http_request_t *r, ngx_buf_t *b)
+ngx_int_t
+ngx_http_parse_header_line(ngx_http_request_t *r, ngx_buf_t *b)
{
u_char c, ch, *p;
ngx_uint_t hash;
@@ -513,7 +515,6 @@ ngx_int_t ngx_http_parse_header_line(ngx_http_request_t *r, ngx_buf_t *b)
sw_value,
sw_space_after_value,
sw_ignore_line,
- sw_skip_line,
sw_almost_done,
sw_header_almost_done
} state;
@@ -528,8 +529,6 @@ ngx_int_t ngx_http_parse_header_line(ngx_http_request_t *r, ngx_buf_t *b)
/* first char */
case sw_start:
- r->invalid_header = 0;
-
switch (ch) {
case CR:
r->header_end = p;
@@ -548,18 +547,11 @@ ngx_int_t ngx_http_parse_header_line(ngx_http_request_t *r, ngx_buf_t *b)
break;
}
- if (ch == '-') {
- hash = ch;
- break;
- }
-
if (ch >= '0' && ch <= '9') {
hash = ch;
break;
}
- r->invalid_header = 1;
- state = sw_skip_line;
break;
}
@@ -589,18 +581,31 @@ ngx_int_t ngx_http_parse_header_line(ngx_http_request_t *r, ngx_buf_t *b)
break;
}
+ if (ch == CR) {
+ r->header_name_end = p;
+ r->header_start = p;
+ r->header_end = p;
+ state = sw_almost_done;
+ break;
+ }
+
+ if (ch == LF) {
+ r->header_name_end = p;
+ r->header_start = p;
+ r->header_end = p;
+ goto done;
+ }
+
/* IIS may send the duplicate "HTTP/1.1 ..." lines */
if (ch == '/'
- && r->proxy
- && p - r->header_start == 4
- && ngx_strncmp(r->header_start, "HTTP", 4) == 0)
+ && r->upstream
+ && p - r->header_name_start == 4
+ && ngx_strncmp(r->header_name_start, "HTTP", 4) == 0)
{
state = sw_ignore_line;
break;
}
- r->invalid_header = 1;
- state = sw_skip_line;
break;
/* space* before header value */
@@ -609,11 +614,13 @@ ngx_int_t ngx_http_parse_header_line(ngx_http_request_t *r, ngx_buf_t *b)
case ' ':
break;
case CR:
- r->header_start = r->header_end = p;
+ r->header_start = p;
+ r->header_end = p;
state = sw_almost_done;
break;
case LF:
- r->header_start = r->header_end = p;
+ r->header_start = p;
+ r->header_end = p;
goto done;
default:
r->header_start = p;
@@ -666,21 +673,6 @@ ngx_int_t ngx_http_parse_header_line(ngx_http_request_t *r, ngx_buf_t *b)
}
break;
- /* skip header line */
- case sw_skip_line:
- switch (ch) {
- case CR:
- r->header_end = p;
- state = sw_almost_done;
- break;
- case LF:
- r->header_end = p;
- goto done;
- default:
- break;
- }
- break;
-
/* end of header line */
case sw_almost_done:
switch (ch) {
@@ -724,7 +716,8 @@ header_done:
}
-ngx_int_t ngx_http_parse_complex_uri(ngx_http_request_t *r)
+ngx_int_t
+ngx_http_parse_complex_uri(ngx_http_request_t *r)
{
u_char c, ch, decoded, *p, *u;
enum {
@@ -1001,3 +994,75 @@ done:
return NGX_OK;
}
+
+
+ngx_int_t
+ngx_http_parse_multi_header_lines(ngx_array_t *headers, ngx_str_t *name,
+ ngx_str_t *value)
+{
+ ngx_uint_t i;
+ u_char *start, *last, *end, ch;
+ ngx_table_elt_t **h;
+
+ h = headers->elts;
+
+ for (i = 0; i < headers->nelts; i++) {
+
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, headers->pool->log, 0,
+ "parse header: \"%V: %V\"", &h[i]->key, &h[i]->value);
+
+ if (name->len > h[i]->value.len) {
+ continue;
+ }
+
+ start = h[i]->value.data;
+ end = h[i]->value.data + h[i]->value.len;
+
+ while (start < end) {
+
+ if (ngx_strncasecmp(start, name->data, name->len) != 0) {
+ goto skip;
+ }
+
+ for (start += name->len; start < end && *start == ' '; start++) {
+ /* void */
+ }
+
+ if (value == NULL) {
+ if (start == end || *start == ',') {
+ return i;
+ }
+
+ goto skip;
+ }
+
+ if (start == end || *start++ != '=') {
+ /* the invalid header value */
+ goto skip;
+ }
+
+ while (start < end && *start == ' ') { start++; }
+
+ for (last = start; last < end && *last != ';'; last++) {
+ /* void */
+ }
+
+ value->len = last - start;
+ value->data = start;
+
+ return i;
+
+ skip:
+ while (start < end) {
+ ch = *start++;
+ if (ch == ';' || ch == ',') {
+ break;
+ }
+ }
+
+ while (start < end && *start == ' ') { start++; }
+ }
+ }
+
+ return NGX_DECLINED;
+}
diff --git a/src/http/ngx_http_postpone_filter_module.c b/src/http/ngx_http_postpone_filter_module.c
new file mode 100644
index 000000000..4f99bc484
--- /dev/null
+++ b/src/http/ngx_http_postpone_filter_module.c
@@ -0,0 +1,126 @@
+
+/*
+ * Copyright (C) Igor Sysoev
+ */
+
+
+#include <ngx_config.h>
+#include <ngx_core.h>
+#include <ngx_http.h>
+
+
+static ngx_int_t ngx_http_postpone_filter_init(ngx_cycle_t *cycle);
+
+
+static ngx_http_module_t ngx_http_postpone_filter_module_ctx = {
+ NULL, /* preconfiguration */
+ NULL, /* postconfiguration */
+
+ NULL, /* create main configuration */
+ NULL, /* init main configuration */
+
+ NULL, /* create server configuration */
+ NULL, /* merge server configuration */
+
+ NULL, /* create location configuration */
+ NULL /* merge location configuration */
+};
+
+
+ngx_module_t ngx_http_postpone_filter_module = {
+ NGX_MODULE_V1,
+ &ngx_http_postpone_filter_module_ctx, /* module context */
+ NULL, /* module directives */
+ NGX_HTTP_MODULE, /* module type */
+ ngx_http_postpone_filter_init, /* init module */
+ NULL /* init process */
+};
+
+
+static ngx_http_output_body_filter_pt ngx_http_next_filter;
+
+
+static ngx_int_t
+ngx_http_postpone_filter(ngx_http_request_t *r, ngx_chain_t *in)
+{
+ ngx_int_t rc;
+ ngx_chain_t *out;
+ ngx_http_postponed_request_t *pr, **ppr;
+
+ if (r->connection->write->error) {
+ return NGX_ERROR;
+ }
+
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "http postpone filter \"%V\" %p", &r->uri, in);
+
+ if (r != r->connection->data || (r->postponed && in)) {
+
+ if (r->postponed) {
+ for (pr = r->postponed; pr->next; pr = pr->next) { /* void */ }
+
+ ppr = pr->request ? &pr->next : NULL;
+
+ } else {
+ ppr = &r->postponed;
+#if (NGX_SUPPRESS_WARN)
+ pr = NULL;
+#endif
+ }
+
+ if (ppr) {
+ pr = ngx_palloc(r->pool, sizeof(ngx_http_postponed_request_t));
+ if (pr == NULL) {
+ return NGX_ERROR;
+ }
+
+ *ppr = pr;
+
+ pr->request = NULL;
+ pr->out = NULL;
+ pr->next = NULL;
+ }
+
+ if (ngx_chain_add_copy(r->pool, &pr->out, in) == NGX_ERROR) {
+ return NGX_ERROR;
+ }
+
+ if (r != r->connection->data || r->postponed->request) {
+ return NGX_AGAIN;
+ }
+ }
+
+ if (r->postponed) {
+ out = r->postponed->out;
+ r->postponed = r->postponed->next;
+
+ } else {
+ out = in;
+ }
+
+ if (out == NULL && r->out == NULL) {
+ return NGX_OK;
+ }
+
+ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "http postpone filter out \"%V\"", &r->uri);
+
+ rc = ngx_http_next_filter(r->main ? r->main : r, out);
+
+ if (rc == NGX_ERROR) {
+ /* NGX_ERROR may be returned by any filter */
+ r->connection->write->error = 1;
+ }
+
+ return rc;
+}
+
+
+static ngx_int_t
+ngx_http_postpone_filter_init(ngx_cycle_t *cycle)
+{
+ ngx_http_next_filter = ngx_http_top_body_filter;
+ ngx_http_top_body_filter = ngx_http_postpone_filter;
+
+ return NGX_OK;
+}
diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c
index 48b735779..28412b656 100644
--- a/src/http/ngx_http_request.c
+++ b/src/http/ngx_http_request.c
@@ -19,13 +19,22 @@ static void ngx_http_process_request_headers(ngx_event_t *rev);
static ssize_t ngx_http_read_request_header(ngx_http_request_t *r);
static ngx_int_t ngx_http_alloc_large_header_buffer(ngx_http_request_t *r,
ngx_uint_t request_line);
+
+static ngx_int_t ngx_http_process_header_line(ngx_http_request_t *r,
+ ngx_table_elt_t *h, ngx_uint_t offset);
+static ngx_int_t ngx_http_process_cookie(ngx_http_request_t *r,
+ ngx_table_elt_t *h, ngx_uint_t offset);
+
static ngx_int_t ngx_http_process_request_header(ngx_http_request_t *r);
static ngx_int_t ngx_http_find_virtual_server(ngx_http_request_t *r);
+static void ngx_http_request_handler(ngx_event_t *ev);
static void ngx_http_set_write_handler(ngx_http_request_t *r);
+static void ngx_http_writer(ngx_http_request_t *r);
+static ngx_int_t ngx_http_postponed_handler(ngx_http_request_t *r);
-static void ngx_http_block_read(ngx_event_t *ev);
-static void ngx_http_read_discarded_body_event(ngx_event_t *rev);
+static void ngx_http_block_read(ngx_http_request_t *r);
+static void ngx_http_read_discarded_body_handler(ngx_http_request_t *r);
static ngx_int_t ngx_http_read_discarded_body(ngx_http_request_t *r);
static void ngx_http_set_keepalive(ngx_http_request_t *r);
@@ -34,6 +43,8 @@ static void ngx_http_set_lingering_close(ngx_http_request_t *r);
static void ngx_http_lingering_close_handler(ngx_event_t *ev);
static u_char *ngx_http_log_error(ngx_log_t *log, u_char *buf, size_t len);
+static u_char *ngx_http_log_error_handler(ngx_http_request_t *r, u_char *buf,
+ size_t len);
static char *ngx_http_client_errors[] = {
@@ -50,57 +61,79 @@ static char *ngx_http_client_errors[] = {
ngx_http_header_t ngx_http_headers_in[] = {
- { ngx_string("Host"), offsetof(ngx_http_headers_in_t, host) },
- { ngx_string("Connection"), offsetof(ngx_http_headers_in_t, connection) },
+ { ngx_string("Host"), offsetof(ngx_http_headers_in_t, host),
+ ngx_http_process_header_line },
+
+ { ngx_string("Connection"), offsetof(ngx_http_headers_in_t, connection),
+ ngx_http_process_header_line },
+
{ ngx_string("If-Modified-Since"),
- offsetof(ngx_http_headers_in_t, if_modified_since) },
- { ngx_string("User-Agent"), offsetof(ngx_http_headers_in_t, user_agent) },
- { ngx_string("Referer"), offsetof(ngx_http_headers_in_t, referer) },
+ offsetof(ngx_http_headers_in_t, if_modified_since),
+ ngx_http_process_header_line },
+
+ { ngx_string("User-Agent"), offsetof(ngx_http_headers_in_t, user_agent),
+ ngx_http_process_header_line },
+
+ { ngx_string("Referer"), offsetof(ngx_http_headers_in_t, referer),
+ ngx_http_process_header_line },
+
{ ngx_string("Content-Length"),
- offsetof(ngx_http_headers_in_t, content_length) },
+ offsetof(ngx_http_headers_in_t, content_length),
+ ngx_http_process_header_line },
+
{ ngx_string("Content-Type"),
- offsetof(ngx_http_headers_in_t, content_type) },
+ offsetof(ngx_http_headers_in_t, content_type),
+ ngx_http_process_header_line },
+
+ { ngx_string("Range"), offsetof(ngx_http_headers_in_t, range),
+ ngx_http_process_header_line },
- { ngx_string("Range"), offsetof(ngx_http_headers_in_t, range) },
#if 0
- { ngx_string("If-Range"), offsetof(ngx_http_headers_in_t, if_range) },
+ { ngx_string("If-Range"), offsetof(ngx_http_headers_in_t, if_range),
+ ngx_http_process_header_line },
#endif
#if (NGX_HTTP_GZIP)
{ ngx_string("Accept-Encoding"),
- offsetof(ngx_http_headers_in_t, accept_encoding) },
- { ngx_string("Via"), offsetof(ngx_http_headers_in_t, via) },
+ offsetof(ngx_http_headers_in_t, accept_encoding),
+ ngx_http_process_header_line },
+
+ { ngx_string("Via"), offsetof(ngx_http_headers_in_t, via),
+ ngx_http_process_header_line },
#endif
{ ngx_string("Authorization"),
- offsetof(ngx_http_headers_in_t, authorization) },
+ offsetof(ngx_http_headers_in_t, authorization),
+ ngx_http_process_header_line },
- { ngx_string("Keep-Alive"), offsetof(ngx_http_headers_in_t, keep_alive) },
+ { ngx_string("Keep-Alive"), offsetof(ngx_http_headers_in_t, keep_alive),
+ ngx_http_process_header_line },
#if (NGX_HTTP_PROXY)
{ ngx_string("X-Forwarded-For"),
- offsetof(ngx_http_headers_in_t, x_forwarded_for) },
- { ngx_string("X-Real-IP"), offsetof(ngx_http_headers_in_t, x_real_ip) },
- { ngx_string("X-URL"), offsetof(ngx_http_headers_in_t, x_url) },
+ offsetof(ngx_http_headers_in_t, x_forwarded_for),
+ ngx_http_process_header_line },
+
+ { ngx_string("X-Real-IP"), offsetof(ngx_http_headers_in_t, x_real_ip),
+ ngx_http_process_header_line },
+
+ { ngx_string("X-URL"), offsetof(ngx_http_headers_in_t, x_url),
+ ngx_http_process_header_line },
#endif
#if (NGX_HTTP_HEADERS)
- { ngx_string("Accept"), offsetof(ngx_http_headers_in_t, accept) },
+ { ngx_string("Accept"), offsetof(ngx_http_headers_in_t, accept),
+ ngx_http_process_header_line },
+
{ ngx_string("Accept-Language"),
- offsetof(ngx_http_headers_in_t, accept_language) },
+ offsetof(ngx_http_headers_in_t, accept_language),
+ ngx_http_process_header_line },
#endif
- { ngx_null_string, 0 }
-};
-
+ { ngx_string("Cookie"), 0, ngx_http_process_cookie },
-#if 0
-static void
-ngx_http_dummy(ngx_event_t *wev)
-{
- return;
-}
-#endif
+ { ngx_null_string, 0, NULL }
+};
void
@@ -126,9 +159,9 @@ ngx_http_init_connection(ngx_connection_t *c)
c->log_error = NGX_ERROR_INFO;
rev = c->read;
- rev->event_handler = ngx_http_init_request;
+ rev->handler = ngx_http_init_request;
- /* STUB: epoll edge */ c->write->event_handler = ngx_http_empty_handler;
+ /* STUB: epoll edge */ c->write->handler = ngx_http_empty_handler;
if (rev->ready) {
/* the deferred accept(), rtsig, aio, iocp */
@@ -165,18 +198,6 @@ ngx_http_init_connection(ngx_connection_t *c)
return;
}
-#if 0
- /* TODO: learn SO_SNDBUF (to use in zerocopy) via kqueue's EV_CLEAR event */
-
- c->write->ready = 0;
- c->write->event_handler = ngx_http_dummy;
-
- if (ngx_handle_write_event(c->write, 0) == NGX_ERROR) {
- ngx_http_close_connection(c);
- return;
- }
-#endif
-
#if (NGX_STAT_STUB)
ngx_atomic_inc(ngx_stat_reading);
#endif
@@ -335,7 +356,7 @@ void ngx_http_init_request(ngx_event_t *rev)
r->srv_conf = cscf->ctx->srv_conf;
r->loc_conf = cscf->ctx->loc_conf;
- rev->event_handler = ngx_http_process_request_line;
+ rev->handler = ngx_http_process_request_line;
#if (NGX_HTTP_SSL)
@@ -350,7 +371,7 @@ void ngx_http_init_request(ngx_event_t *rev)
return;
}
- rev->event_handler = ngx_http_ssl_handshake;
+ rev->handler = ngx_http_ssl_handshake;
/*
* The majority of browsers do not send the "close notify" alert.
@@ -396,17 +417,9 @@ void ngx_http_init_request(ngx_event_t *rev)
return;
}
- if (ngx_array_init(&r->cleanup, r->pool, 4, sizeof(ngx_http_cleanup_t))
- == NGX_ERROR)
- {
- ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
- ngx_http_close_connection(c);
- return;
- }
-
if (ngx_list_init(&r->headers_out.headers, r->pool, 20,
- sizeof(ngx_table_elt_t)) == NGX_ERROR)
+ sizeof(ngx_table_elt_t)) == NGX_ERROR)
{
ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
ngx_http_close_connection(c);
@@ -426,8 +439,6 @@ void ngx_http_init_request(ngx_event_t *rev)
r->start_time = ngx_time();
- r->file.fd = NGX_INVALID_FILE;
-
r->headers_in.content_length_n = -1;
r->headers_in.keep_alive_n = -1;
r->headers_out.content_length_n = -1;
@@ -437,6 +448,7 @@ void ngx_http_init_request(ngx_event_t *rev)
ctx = c->log->data;
ctx->request = r;
+ r->log_handler = ngx_http_log_error_handler;
#if (NGX_STAT_STUB)
ngx_atomic_inc(ngx_stat_reading);
@@ -444,7 +456,7 @@ void ngx_http_init_request(ngx_event_t *rev)
ngx_atomic_inc(ngx_stat_requests);
#endif
- rev->event_handler(rev);
+ rev->handler(rev);
}
@@ -507,7 +519,7 @@ ngx_http_ssl_handshake(ngx_event_t *rev)
}
}
- rev->event_handler = ngx_http_process_request_line;
+ rev->handler = ngx_http_process_request_line;
ngx_http_process_request_line(rev);
}
@@ -593,10 +605,8 @@ ngx_http_process_request_line(ngx_event_t *rev)
r->unparsed_uri.data = r->uri_start;
- if (r->method == 0) {
- r->method_name.len = r->method_end - r->request_start + 1;
- r->method_name.data = r->request_line.data;
- }
+ r->method_name.len = r->method_end - r->request_start + 1;
+ r->method_name.data = r->request_line.data;
if (r->http_protocol.data) {
@@ -634,7 +644,7 @@ ngx_http_process_request_line(ngx_event_t *rev)
"http exten: \"%V\"", &r->exten);
if (r->http_version < NGX_HTTP_VERSION_10) {
- rev->event_handler = ngx_http_block_read;
+ r->read_event_handler = ngx_http_block_read;
ngx_http_handler(r);
return;
}
@@ -659,7 +669,7 @@ ngx_http_process_request_line(ngx_event_t *rev)
c->log->action = "reading client request headers";
- rev->event_handler = ngx_http_process_request_headers;
+ rev->handler = ngx_http_process_request_headers;
ngx_http_process_request_headers(rev);
return;
@@ -711,7 +721,7 @@ ngx_http_process_request_headers(ngx_event_t *rev)
ngx_int_t rc, rv;
ngx_uint_t key;
ngx_str_t header;
- ngx_table_elt_t *h, **cookie;
+ ngx_table_elt_t *h;
ngx_connection_t *c;
ngx_http_header_t *hh;
ngx_http_request_t *r;
@@ -773,6 +783,7 @@ ngx_http_process_request_headers(ngx_event_t *rev)
if (rc == NGX_OK) {
+#if 0
if (r->invalid_header) {
/* there was error while a header line parsing */
@@ -785,11 +796,10 @@ ngx_http_process_request_headers(ngx_event_t *rev)
&header);
continue;
}
+#endif
/* a header line has been parsed successfully */
- r->headers_n++;
-
h = ngx_list_push(&r->headers_in.headers);
if (h == NULL) {
ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
@@ -807,27 +817,14 @@ ngx_http_process_request_headers(ngx_event_t *rev)
h->value.data = r->header_start;
h->value.data[h->value.len] = '\0';
- if (h->key.len == sizeof("Cookie") - 1
- && ngx_strcasecmp(h->key.data, "Cookie") == 0)
+ key = h->hash % cmcf->headers_in_hash.hash_size;
+
+ if (hh[key].name.len == h->key.len
+ && ngx_strcasecmp(hh[key].name.data, h->key.data) == 0)
{
- cookie = ngx_array_push(&r->headers_in.cookies);
- if (cookie == NULL) {
- ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
- ngx_http_close_connection(c);
+ if (hh[key].handler(r, h, hh[key].offset) != NGX_OK) {
return;
}
-
- *cookie = h;
-
- } else {
- key = h->hash % cmcf->headers_in_hash.hash_size;
-
- if (hh[key].name.len == h->key.len
- && ngx_strcasecmp(hh[key].name.data, h->key.data) == 0)
- {
- *((ngx_table_elt_t **)
- ((char *) &r->headers_in + hh[key].offset)) = h;
- }
}
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
@@ -865,7 +862,10 @@ ngx_http_process_request_headers(ngx_event_t *rev)
r->stat_writing = 1;
#endif
- rev->event_handler = ngx_http_block_read;
+ rev->handler = ngx_http_request_handler;
+ c->write->handler = ngx_http_request_handler;
+ r->read_event_handler = ngx_http_block_read;
+
ngx_http_handler(r);
return;
}
@@ -1091,6 +1091,41 @@ ngx_http_alloc_large_header_buffer(ngx_http_request_t *r,
static ngx_int_t
+ngx_http_process_header_line(ngx_http_request_t *r, ngx_table_elt_t *h,
+ ngx_uint_t offset)
+{
+ ngx_table_elt_t **ph;
+
+ ph = (ngx_table_elt_t **) ((char *) &r->headers_in + offset);
+
+ if (*ph == NULL) {
+ *ph = h;
+ }
+
+ return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_http_process_cookie(ngx_http_request_t *r, ngx_table_elt_t *h,
+ ngx_uint_t offset)
+{
+ ngx_table_elt_t **cookie;
+
+ cookie = ngx_array_push(&r->headers_in.cookies);
+ if (cookie == NULL) {
+ ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
+ ngx_http_close_connection(r->connection);
+ return NGX_ERROR;
+ }
+
+ *cookie = h;
+
+ return NGX_OK;
+}
+
+
+static ngx_int_t
ngx_http_process_request_header(ngx_http_request_t *r)
{
size_t len;
@@ -1108,6 +1143,10 @@ ngx_http_process_request_header(ngx_http_request_t *r)
r->headers_in.host->value.data[len] = ngx_tolower(ch);
}
+ if (r->headers_in.host->value.data[len - 1] == '.') {
+ len--;
+ }
+
r->headers_in.host_name_len = len;
if (ngx_http_find_virtual_server(r) != NGX_OK) {
@@ -1167,13 +1206,13 @@ ngx_http_process_request_header(ngx_http_request_t *r)
if (r->headers_in.connection) {
if (r->headers_in.connection->value.len == 5
&& ngx_strcasecmp(r->headers_in.connection->value.data, "close")
- == 0)
+ == 0)
{
r->headers_in.connection_type = NGX_HTTP_CONNECTION_CLOSE;
} else if (r->headers_in.connection->value.len == 10
&& ngx_strcasecmp(r->headers_in.connection->value.data,
- "keep-alive") == 0)
+ "keep-alive") == 0)
{
r->headers_in.connection_type = NGX_HTTP_CONNECTION_KEEP_ALIVE;
@@ -1237,7 +1276,7 @@ static ngx_int_t
ngx_http_find_virtual_server(ngx_http_request_t *r)
{
ngx_int_t rc;
- ngx_uint_t i, n, key, found;
+ ngx_uint_t i, n, key;
ngx_http_server_name_t *name;
ngx_http_core_loc_conf_t *clcf;
ngx_http_core_srv_conf_t *cscf;
@@ -1259,8 +1298,6 @@ ngx_http_find_virtual_server(ngx_http_request_t *r)
n = r->virtual_names->names.nelts;
}
- found = 0;
-
for (i = 0; i < n; i++) {
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
@@ -1275,9 +1312,7 @@ ngx_http_find_virtual_server(ngx_http_request_t *r)
if (rc == 0) {
r->server_name = name[i].name;
-
- found = 1;
- break;
+ goto found;
}
if (rc < 0) {
@@ -1286,7 +1321,7 @@ ngx_http_find_virtual_server(ngx_http_request_t *r)
}
}
- if (!found && r->virtual_names->wildcards.nelts) {
+ if (r->virtual_names->wildcards.nelts) {
name = r->virtual_names->wildcards.elts;
for (i = 0; i < r->virtual_names->wildcards.nelts; i++) {
@@ -1310,49 +1345,110 @@ ngx_http_find_virtual_server(ngx_http_request_t *r)
r->server_name.len = r->headers_in.host_name_len;
r->server_name.data = r->headers_in.host->value.data;
- found = 1;
- break;
+ goto found;
}
}
}
- if (found) {
- r->srv_conf = name[i].core_srv_conf->ctx->srv_conf;
- r->loc_conf = name[i].core_srv_conf->ctx->loc_conf;
-
- clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
- r->connection->log->file = clcf->err_log->file;
-
- if (!(r->connection->log->log_level & NGX_LOG_DEBUG_CONNECTION)) {
- r->connection->log->log_level = clcf->err_log->log_level;
- }
+ cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
+ if (cscf->restrict_host_names == NGX_HTTP_RESTRICT_HOST_OFF) {
return NGX_OK;
}
- cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
+ return NGX_ERROR;
- if (cscf->restrict_host_names != NGX_HTTP_RESTRICT_HOST_OFF) {
- return NGX_ERROR;
+found:
+
+ r->srv_conf = name[i].core_srv_conf->ctx->srv_conf;
+ r->loc_conf = name[i].core_srv_conf->ctx->loc_conf;
+
+ clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
+ r->connection->log->file = clcf->err_log->file;
+
+ if (!(r->connection->log->log_level & NGX_LOG_DEBUG_CONNECTION)) {
+ r->connection->log->log_level = clcf->err_log->log_level;
}
return NGX_OK;
}
+static void
+ngx_http_request_handler(ngx_event_t *ev)
+{
+ ngx_connection_t *c;
+ ngx_http_request_t *r;
+
+ c = ev->data;
+ r = c->data;
+
+ if (ev->write) {
+ r->write_event_handler(r);
+
+ } else {
+ r->read_event_handler(r);
+ }
+}
+
+
void
-ngx_http_finalize_request(ngx_http_request_t *r, int rc)
+ngx_http_finalize_request(ngx_http_request_t *r, ngx_int_t rc)
{
+ ngx_http_request_t *pr;
ngx_http_core_loc_conf_t *clcf;
- /* r may be already destroyed when rc == NGX_DONE */
+ if (rc == NGX_DONE) {
+ /* r may be already destroyed when rc == NGX_DONE */
+ return;
+ }
+
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "http finalize request: %d, \"%V\"", rc, &r->uri);
- if (rc == NGX_DONE || r->main) {
+ if (r->parent && rc >= NGX_HTTP_SPECIAL_RESPONSE) {
+ ngx_http_finalize_request(r, ngx_http_special_response_handler(r, rc));
return;
}
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http finalize request: %d", rc);
+ if (r->parent || rc == NGX_AGAIN) {
+ r->write_event_handler = ngx_http_writer;
+ }
+
+ r->done = 1;
+
+ if (r != r->connection->data) {
+ return;
+ }
+
+ if (r->parent) {
+
+ pr = r->parent;
+
+ if (rc != NGX_AGAIN) {
+ pr->connection->data = pr;
+ }
+
+ if (pr->postponed) {
+
+ if (rc != NGX_AGAIN && pr->postponed->request == r) {
+ pr->postponed = pr->postponed->next;
+
+ if (pr->postponed == NULL) {
+ return;
+ }
+ }
+
+ if (pr->done) {
+ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "http wake request: \"%V\"", &pr->uri);
+
+ pr->write_event_handler(pr);
+ }
+ }
+
+ return;
+ }
if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
@@ -1379,7 +1475,7 @@ ngx_http_finalize_request(ngx_http_request_t *r, int rc)
ngx_http_close_connection(r->connection);
return;
- } else if (rc == NGX_AGAIN) {
+ } else if (rc == NGX_AGAIN || r->out) {
ngx_http_set_write_handler(r);
return;
}
@@ -1430,17 +1526,15 @@ ngx_http_set_write_handler(ngx_http_request_t *r)
ngx_event_t *wev;
ngx_http_core_loc_conf_t *clcf;
- wev = r->connection->write;
- wev->event_handler = ngx_http_writer;
-
r->http_state = NGX_HTTP_WRITING_REQUEST_STATE;
+ wev = r->connection->write;
+
if (wev->ready && wev->delayed) {
return;
}
- clcf = ngx_http_get_module_loc_conf(r->main ? r->main : r,
- ngx_http_core_module);
+ clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
if (!wev->delayed) {
ngx_add_timer(wev, clcf->send_timeout);
}
@@ -1449,23 +1543,22 @@ ngx_http_set_write_handler(ngx_http_request_t *r)
ngx_http_close_request(r, 0);
ngx_http_close_connection(r->connection);
}
-
- return;
}
-void
-ngx_http_writer(ngx_event_t *wev)
+static void
+ngx_http_writer(ngx_http_request_t *r)
{
int rc;
+ ngx_event_t *wev;
ngx_connection_t *c;
- ngx_http_request_t *r;
ngx_http_core_loc_conf_t *clcf;
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, wev->log, 0, "http writer handler");
+ c = r->connection;
+ wev = c->write;
- c = wev->data;
- r = c->data;
+ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, wev->log, 0,
+ "http writer handler: \"%V\"", &r->uri);
if (wev->timedout) {
if (!wev->delayed) {
@@ -1510,10 +1603,21 @@ ngx_http_writer(ngx_event_t *wev)
}
}
- rc = ngx_http_output_filter(r, NULL);
+ if (r->postponed) {
+ rc = ngx_http_postponed_handler(r);
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
- "http writer output filter: %d", rc);
+ if (rc == NGX_DONE) {
+ /* r may be already destroyed when rc == NGX_DONE */
+ return;
+ }
+
+ } else {
+ rc = ngx_http_output_filter(r, NULL);
+
+ }
+
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
+ "http writer output filter: %d, \"%V\"", rc, &r->uri);
if (rc == NGX_AGAIN) {
clcf = ngx_http_get_module_loc_conf(r->main ? r->main : r,
@@ -1530,28 +1634,81 @@ ngx_http_writer(ngx_event_t *wev)
return;
}
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http writer done");
+ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, wev->log, 0,
+ "http writer done: \"%V\"", &r->uri);
ngx_http_finalize_request(r, rc);
}
-static void
-ngx_http_block_read(ngx_event_t *rev)
+static ngx_int_t
+ngx_http_postponed_handler(ngx_http_request_t *r)
{
- ngx_connection_t *c;
- ngx_http_request_t *r;
+ ngx_int_t rc;
+ ngx_http_postponed_request_t *pr;
+
+ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "http postpone handler \"%V\"", &r->uri);
+
+ pr = r->postponed;
+
+ if (pr->request == NULL) {
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "http postponed data \"%V\" %p", &r->uri, pr->out);
+
+ rc = ngx_http_output_filter(r, NULL);
+
+ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "http postponed output filter: %d", rc);
+
+ if (rc == NGX_AGAIN) {
+ return rc;
+ }
+
+ if (rc == NGX_ERROR) {
+ /* NGX_ERROR may be returned by any filter */
+ r->connection->write->error = 1;
+
+ ngx_http_finalize_request(r, rc);
+
+ return NGX_DONE;
+ }
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0, "http read blocked");
+ pr = r->postponed;
+
+ if (pr == NULL) {
+ return NGX_OK;
+ }
+ }
+
+ r = pr->request;
+ r->connection->data = r;
+
+ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "http postponed request \"%V\"", &r->uri);
+
+ r->write_event_handler(r);
+
+ return NGX_DONE;
+}
+
+
+static void
+ngx_http_block_read(ngx_http_request_t *r)
+{
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "http read blocked");
/* aio does not call this handler */
- if ((ngx_event_flags & NGX_USE_LEVEL_EVENT) && rev->active) {
- if (ngx_del_event(rev, NGX_READ_EVENT, 0) == NGX_ERROR) {
- c = rev->data;
- r = c->data;
+ if ((ngx_event_flags & NGX_USE_LEVEL_EVENT)
+ && r->connection->read->active)
+ {
+ if (ngx_del_event(r->connection->read, NGX_READ_EVENT, 0)
+ == NGX_ERROR)
+ {
ngx_http_close_request(r, 0);
- ngx_http_close_connection(c);
+ ngx_http_close_connection(r->connection);
}
}
}
@@ -1588,9 +1745,9 @@ ngx_http_discard_body(ngx_http_request_t *r)
}
}
- rev->event_handler = ngx_http_read_discarded_body_event;
+ r->read_event_handler = ngx_http_read_discarded_body_handler;
- if (ngx_handle_level_read_event(rev) == NGX_ERROR) {
+ if (ngx_handle_read_event(rev, 0) == NGX_ERROR) {
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
@@ -1599,28 +1756,23 @@ ngx_http_discard_body(ngx_http_request_t *r)
static void
-ngx_http_read_discarded_body_event(ngx_event_t *rev)
+ngx_http_read_discarded_body_handler(ngx_http_request_t *r)
{
- ngx_int_t rc;
- ngx_connection_t *c;
- ngx_http_request_t *r;
-
- c = rev->data;
- r = c->data;
+ ngx_int_t rc;
rc = ngx_http_read_discarded_body(r);
if (rc == NGX_AGAIN) {
- if (ngx_handle_level_read_event(rev) == NGX_ERROR) {
+ if (ngx_handle_read_event(r->connection->read, 0) == NGX_ERROR) {
ngx_http_close_request(r, rc);
- ngx_http_close_connection(c);
+ ngx_http_close_connection(r->connection);
return;
}
}
if (rc != NGX_OK) {
ngx_http_close_request(r, rc);
- ngx_http_close_connection(c);
+ ngx_http_close_connection(r->connection);
}
}
@@ -1737,13 +1889,13 @@ ngx_http_set_keepalive(ngx_http_request_t *r)
ngx_add_timer(rev, clcf->keepalive_timeout);
- if (ngx_handle_level_read_event(rev) == NGX_ERROR) {
+ if (ngx_handle_read_event(rev, 0) == NGX_ERROR) {
ngx_http_close_connection(c);
return;
}
wev = c->write;
- wev->event_handler = ngx_http_empty_handler;
+ wev->handler = ngx_http_empty_handler;
if (b->pos < b->last) {
@@ -1809,7 +1961,7 @@ ngx_http_set_keepalive(ngx_http_request_t *r)
hc->nbusy = 0;
}
- rev->event_handler = ngx_http_keepalive_handler;
+ rev->handler = ngx_http_keepalive_handler;
if (wev->active) {
if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) {
@@ -1944,7 +2096,7 @@ ngx_http_keepalive_handler(ngx_event_t *rev)
c->log_error = NGX_ERROR_INFO;
if (n == NGX_AGAIN) {
- if (ngx_handle_level_read_event(rev) == NGX_ERROR) {
+ if (ngx_handle_read_event(rev, 0) == NGX_ERROR) {
ngx_http_close_connection(c);
}
@@ -1986,19 +2138,19 @@ ngx_http_set_lingering_close(ngx_http_request_t *r)
clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
rev = c->read;
- rev->event_handler = ngx_http_lingering_close_handler;
+ rev->handler = ngx_http_lingering_close_handler;
r->lingering_time = ngx_time() + clcf->lingering_time / 1000;
ngx_add_timer(rev, clcf->lingering_timeout);
- if (ngx_handle_level_read_event(rev) == NGX_ERROR) {
+ if (ngx_handle_read_event(rev, 0) == NGX_ERROR) {
ngx_http_close_request(r, 0);
ngx_http_close_connection(c);
return;
}
wev = c->write;
- wev->event_handler = ngx_http_empty_handler;
+ wev->handler = ngx_http_empty_handler;
if (wev->active) {
if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) {
@@ -2075,7 +2227,7 @@ ngx_http_lingering_close_handler(ngx_event_t *rev)
} while (rev->ready);
- if (ngx_handle_level_read_event(rev) == NGX_ERROR) {
+ if (ngx_handle_read_event(rev, 0) == NGX_ERROR) {
ngx_http_close_request(r, 0);
ngx_http_close_connection(c);
return;
@@ -2102,6 +2254,16 @@ ngx_http_empty_handler(ngx_event_t *wev)
}
+void
+ngx_http_request_empty_handler(ngx_http_request_t *r)
+{
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "http requets empty handler");
+
+ return;
+}
+
+
ngx_int_t
ngx_http_send_last(ngx_http_request_t *r)
{
@@ -2122,14 +2284,12 @@ ngx_http_send_last(ngx_http_request_t *r)
void
-ngx_http_close_request(ngx_http_request_t *r, int error)
+ngx_http_close_request(ngx_http_request_t *r, ngx_int_t error)
{
- ngx_uint_t i;
ngx_log_t *log;
+ struct linger linger;
ngx_http_log_ctx_t *ctx;
- ngx_http_cleanup_t *cleanup;
ngx_http_core_loc_conf_t *clcf;
- struct linger l;
log = r->connection->log;
@@ -2157,62 +2317,15 @@ ngx_http_close_request(ngx_http_request_t *r, int error)
ngx_http_log_handler(r);
- cleanup = r->cleanup.elts;
- for (i = 0; i < r->cleanup.nelts; i++) {
- if (!cleanup[i].valid) {
- continue;
- }
-
-#if (NGX_HTTP_CACHE)
-
- if (cleanup[i].cache) {
- ngx_http_cache_unlock(cleanup[i].data.cache.hash,
- cleanup[i].data.cache.cache, log);
- continue;
- }
-
-#endif
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0, "http cleanup fd: %d",
- cleanup[i].data.file.fd);
-
- if (ngx_close_file(cleanup[i].data.file.fd) == NGX_FILE_ERROR) {
- ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
- ngx_close_file_n " \"%s\" failed",
- cleanup[i].data.file.name);
- }
- }
-
- /* STUB */
- if (r->file.fd != NGX_INVALID_FILE) {
- if (ngx_close_file(r->file.fd) == NGX_FILE_ERROR) {
- ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
- ngx_close_file_n " \"%V\" failed", &r->file.name);
- }
- }
-
- if (r->request_body
- && r->request_body->temp_file
- && r->request_body->temp_file->file.fd != NGX_INVALID_FILE)
- {
- if (ngx_close_file(r->request_body->temp_file->file.fd)
- == NGX_FILE_ERROR)
- {
- ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
- ngx_close_file_n " deleted file \"%V\" failed",
- &r->request_body->temp_file->file.name);
- }
- }
-
if (r->connection->timedout) {
clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
if (clcf->reset_timedout_connection) {
- l.l_onoff = 1;
- l.l_linger = 0;
+ linger.l_onoff = 1;
+ linger.l_linger = 0;
if (setsockopt(r->connection->fd, SOL_SOCKET, SO_LINGER,
- (const void *) &l, sizeof(struct linger)) == -1)
+ (const void *) &linger, sizeof(struct linger)) == -1)
{
ngx_log_error(NGX_LOG_ALERT, log, ngx_socket_errno,
"setsockopt(SO_LINGER) failed");
@@ -2220,7 +2333,7 @@ ngx_http_close_request(ngx_http_request_t *r, int error)
}
}
- /* the variuos request strings were allocated from r->pool */
+ /* the various request strings were allocated from r->pool */
ctx = log->data;
ctx->request = NULL;
@@ -2263,8 +2376,8 @@ ngx_http_close_connection(ngx_connection_t *c)
if (c->ssl) {
if (ngx_ssl_shutdown(c) == NGX_AGAIN) {
- c->read->event_handler = ngx_ssl_close_handler;
- c->write->event_handler = ngx_ssl_close_handler;
+ c->read->handler = ngx_ssl_close_handler;
+ c->write->handler = ngx_ssl_close_handler;
return;
}
}
@@ -2290,26 +2403,31 @@ ngx_http_log_error(ngx_log_t *log, u_char *buf, size_t len)
ngx_http_request_t *r;
ngx_http_log_ctx_t *ctx;
- p = buf;
-
- ctx = log->data;
-
if (log->action) {
- p = ngx_snprintf(p, len, " while %s", log->action);
+ p = ngx_snprintf(buf, len, " while %s", log->action);
len -= p - buf;
buf = p;
}
+ ctx = log->data;
+
p = ngx_snprintf(buf, len, ", client: %V", ctx->client);
+ len -= p - buf;
r = ctx->request;
- if (r == NULL) {
- return p;
+ if (r) {
+ return r->log_handler(r, p, len);
}
- len -= p - buf;
- buf = p;
+ return p;
+}
+
+
+static u_char *
+ngx_http_log_error_handler(ngx_http_request_t *r, u_char *buf, size_t len)
+{
+ u_char *p;
if (r->server_name.data) {
p = ngx_snprintf(buf, len, ", server: %V", &r->server_name);
diff --git a/src/http/ngx_http_request.h b/src/http/ngx_http_request.h
index d9889c82e..5b2615119 100644
--- a/src/http/ngx_http_request.h
+++ b/src/http/ngx_http_request.h
@@ -8,6 +8,9 @@
#define _NGX_HTTP_REQUEST_H_INCLUDED_
+#define NGX_HTTP_MAX_REWRITE_CYCLES 10
+
+
#define NGX_HTTP_DISCARD_BUFFER_SIZE 4096
#define NGX_HTTP_LINGERING_BUFFER_SIZE 4096
@@ -114,10 +117,17 @@ typedef enum {
typedef struct {
ngx_str_t name;
ngx_uint_t offset;
+ ngx_http_header_handler_pt handler;
} ngx_http_header_t;
typedef struct {
+ ngx_str_t name;
+ ngx_uint_t offset;
+} ngx_http_header0_t;
+
+
+typedef struct {
ngx_list_t headers;
ngx_table_elt_t *host;
@@ -183,7 +193,6 @@ typedef struct {
ngx_table_elt_t *server;
ngx_table_elt_t *date;
- ngx_table_elt_t *content_type;
ngx_table_elt_t *content_length;
ngx_table_elt_t *content_encoding;
ngx_table_elt_t *location;
@@ -192,12 +201,14 @@ typedef struct {
ngx_table_elt_t *accept_ranges;
ngx_table_elt_t *www_authenticate;
ngx_table_elt_t *expires;
- ngx_table_elt_t *cache_control;
ngx_table_elt_t *etag;
+ ngx_str_t content_type;
ngx_str_t charset;
ngx_array_t ranges;
+ ngx_array_t cache_control;
+
off_t content_length_n;
time_t date_time;
time_t last_modified_time;
@@ -215,24 +226,6 @@ typedef struct {
} ngx_http_request_body_t;
-struct ngx_http_cleanup_s {
- union {
- struct {
- ngx_fd_t fd;
- u_char *name;
- } file;
-
- struct {
- ngx_http_cache_hash_t *hash;
- ngx_http_cache_entry_t *cache;
- } cache;
- } data;
-
- unsigned valid:1;
- unsigned cache:1;
-};
-
-
typedef struct {
ngx_http_request_t *request;
@@ -246,7 +239,18 @@ typedef struct {
} ngx_http_connection_t;
+typedef struct ngx_http_postponed_request_s ngx_http_postponed_request_t;
+
+struct ngx_http_postponed_request_s {
+ ngx_http_request_t *request;
+ ngx_chain_t *out;
+ ngx_http_postponed_request_t *next;
+};
+
+
typedef ngx_int_t (*ngx_http_handler_pt)(ngx_http_request_t *r);
+typedef void (*ngx_http_event_handler_pt)(ngx_http_request_t *r);
+
struct ngx_http_request_s {
uint32_t signature; /* "HTTP" */
@@ -258,12 +262,13 @@ struct ngx_http_request_s {
void **srv_conf;
void **loc_conf;
+ ngx_http_event_handler_pt read_event_handler;
+ ngx_http_event_handler_pt write_event_handler;
+
ngx_http_cache_t *cache;
ngx_http_upstream_t *upstream;
- ngx_file_t file;
-
ngx_pool_t *pool;
ngx_buf_t *header_in;
@@ -289,7 +294,10 @@ struct ngx_http_request_s {
ngx_str_t method_name;
ngx_str_t http_protocol;
+ ngx_chain_t *out;
ngx_http_request_t *main;
+ ngx_http_request_t *parent;
+ ngx_http_postponed_request_t *postponed;
uint32_t in_addr;
ngx_uint_t port;
@@ -303,19 +311,18 @@ struct ngx_http_request_s {
ngx_http_variable_value_t **variables;
- ngx_array_t cleanup;
-
/* used to learn the Apache compatible response length without a header */
size_t header_size;
size_t request_length;
- u_char *discarded_buffer;
void **err_ctx;
ngx_uint_t err_status;
ngx_http_connection_t *http_connection;
+ ngx_http_log_handler_pt log_handler;
+
unsigned http_state:4;
/* URI with "/." and on Win32 with "//" */
@@ -330,12 +337,11 @@ struct ngx_http_request_s {
/* URI with "\0" or "%00" */
unsigned zero_in_uri:1;
+ unsigned valid_location:1;
unsigned valid_unparsed_uri:1;
unsigned uri_changed:1;
unsigned uri_changes:4;
- unsigned invalid_header:1;
-
unsigned low_case_exten:1;
unsigned header_timeout_set:1;
@@ -346,14 +352,16 @@ struct ngx_http_request_s {
#if 0
unsigned cachable:1;
#endif
- unsigned pipeline:1;
+ unsigned pipeline:1;
unsigned plain_http:1;
unsigned chunked:1;
unsigned header_only:1;
unsigned keepalive:1;
unsigned lingering_close:1;
+ unsigned internal:1;
unsigned closed:1;
+ unsigned done:1;
unsigned filter_need_in_memory:1;
unsigned filter_ssi_need_in_memory:1;
@@ -365,8 +373,6 @@ struct ngx_http_request_s {
unsigned stat_writing:1;
#endif
- ngx_uint_t headers_n;
-
/* used to parse HTTP headers */
ngx_uint_t state;
u_char *uri_start;
@@ -391,8 +397,7 @@ struct ngx_http_request_s {
extern ngx_http_header_t ngx_http_headers_in[];
-extern ngx_http_header_t ngx_http_headers_out[];
-
+extern ngx_http_header0_t ngx_http_headers_out[];
#endif /* _NGX_HTTP_REQUEST_H_INCLUDED_ */
diff --git a/src/http/ngx_http_request_body.c b/src/http/ngx_http_request_body.c
index eeffd8afd..42edfef52 100644
--- a/src/http/ngx_http_request_body.c
+++ b/src/http/ngx_http_request_body.c
@@ -10,9 +10,8 @@
#include <ngx_http.h>
-static void ngx_http_read_client_request_body_handler(ngx_event_t *rev);
-static ngx_int_t ngx_http_do_read_client_request_body(ngx_http_request_t *r,
- ngx_connection_t *c);
+static void ngx_http_read_client_request_body_handler(ngx_http_request_t *r);
+static ngx_int_t ngx_http_do_read_client_request_body(ngx_http_request_t *r);
/*
* on completion ngx_http_read_client_request_body() adds to
@@ -29,10 +28,14 @@ ngx_http_read_client_request_body(ngx_http_request_t *r,
ssize_t size;
ngx_buf_t *b;
ngx_chain_t *cl;
- ngx_connection_t *c;
ngx_http_request_body_t *rb;
ngx_http_core_loc_conf_t *clcf;
+ if (r->request_body) {
+ 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;
@@ -40,16 +43,6 @@ ngx_http_read_client_request_body(ngx_http_request_t *r,
r->request_body = rb;
- /* STUB */
- if (r->file.fd != NGX_INVALID_FILE) {
- if (ngx_close_file(r->file.fd) == NGX_FILE_ERROR) {
- ngx_log_error(NGX_LOG_ALERT, r->connection->log, ngx_errno,
- ngx_close_file_n " \"%V\" failed", &r->file.name);
- }
- r->file.fd = NGX_INVALID_FILE;
- }
- /**/
-
if (r->headers_in.content_length_n <= 0) {
post_handler(r);
return NGX_OK;
@@ -138,30 +131,23 @@ ngx_http_read_client_request_body(ngx_http_request_t *r,
rb->bufs = cl;
}
- c = r->connection;
-
- c->read->event_handler = ngx_http_read_client_request_body_handler;
+ r->read_event_handler = ngx_http_read_client_request_body_handler;
- return ngx_http_do_read_client_request_body(r, c);
+ return ngx_http_do_read_client_request_body(r);
}
static void
-ngx_http_read_client_request_body_handler(ngx_event_t *rev)
+ngx_http_read_client_request_body_handler(ngx_http_request_t *r)
{
- ngx_int_t rc;
- ngx_connection_t *c;
- ngx_http_request_t *r;
-
- c = rev->data;
- r = c->data;
+ ngx_int_t rc;
- if (rev->timedout) {
+ if (r->connection->read->timedout) {
ngx_http_finalize_request(r, NGX_HTTP_REQUEST_TIME_OUT);
return;
}
- rc = ngx_http_do_read_client_request_body(r, c);
+ rc = ngx_http_do_read_client_request_body(r);
if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
ngx_http_finalize_request(r, rc);
@@ -170,16 +156,17 @@ ngx_http_read_client_request_body_handler(ngx_event_t *rev)
static ngx_int_t
-ngx_http_do_read_client_request_body(ngx_http_request_t *r,
- ngx_connection_t *c)
+ngx_http_do_read_client_request_body(ngx_http_request_t *r)
{
size_t size;
ssize_t n;
ngx_buf_t *b;
ngx_temp_file_t *tf;
+ ngx_connection_t *c;
ngx_http_request_body_t *rb;
ngx_http_core_loc_conf_t *clcf;
+ c = r->connection;
rb = r->request_body;
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
@@ -218,8 +205,6 @@ ngx_http_do_read_client_request_body(ngx_http_request_t *r,
}
rb->temp_file->offset += n;
-
- rb->buf->pos = rb->buf->start;
rb->buf->last = rb->buf->start;
}
diff --git a/src/http/ngx_http_script.c b/src/http/ngx_http_script.c
index c7eb07455..362807aae 100644
--- a/src/http/ngx_http_script.c
+++ b/src/http/ngx_http_script.c
@@ -9,107 +9,274 @@
#include <ngx_http.h>
-ngx_int_t
-ngx_http_script_compile_lite(ngx_conf_t *cf, ngx_array_t *sources,
- ngx_array_t **lengths, ngx_array_t **values,
- ngx_http_script_compile_lite_start_pt start,
- ngx_http_script_compile_lite_end_pt end)
+#define ngx_http_script_exit (u_char *) &ngx_http_script_exit_code
+
+static uintptr_t ngx_http_script_exit_code = (uintptr_t) NULL;
+
+
+ngx_uint_t
+ngx_http_script_variables_count(ngx_str_t *value)
{
- uintptr_t *code;
- ngx_uint_t i;
- ngx_table_elt_t *src;
- ngx_http_variable_t *var;
- ngx_http_script_var_code_t *var_code;
+ ngx_uint_t i, n;
- if (sources->nelts == 0) {
- return NGX_OK;
+ for (n = 0, i = 0; i < value->len; i++) {
+ if (value->data[i] == '$') {
+ n++;
+ }
}
- if (*lengths == NULL) {
- *lengths = ngx_array_create(cf->pool, 64, 1);
- if (*lengths == NULL) {
+ return n;
+}
+
+
+ngx_int_t
+ngx_http_script_compile(ngx_http_script_compile_t *sc)
+{
+ u_char ch;
+ size_t size;
+ ngx_int_t index;
+ ngx_str_t name;
+ uintptr_t *code;
+ ngx_uint_t i, n, bracket;
+ ngx_http_script_var_code_t *var_code;
+ ngx_http_script_copy_code_t *copy;
+ ngx_http_script_copy_capture_code_t *copy_capture;
+
+ if (*sc->lengths == NULL) {
+ n = sc->variables * (2 * sizeof(ngx_http_script_copy_code_t)
+ + sizeof(ngx_http_script_var_code_t))
+ + sizeof(uintptr_t);
+
+ *sc->lengths = ngx_array_create(sc->cf->pool, n, 1);
+ if (*sc->lengths == NULL) {
return NGX_ERROR;
}
}
- if (*values == NULL) {
- *values = ngx_array_create(cf->pool, 256, 1);
- if (*values == NULL) {
+
+ if (*sc->values == NULL) {
+ n = (sc->variables * (2 * sizeof(ngx_http_script_copy_code_t)
+ + sizeof(ngx_http_script_var_code_t))
+ + sizeof(uintptr_t)
+ + sc->source->len
+ + sizeof(uintptr_t) - 1)
+ & ~(sizeof(uintptr_t) - 1);
+
+ *sc->values = ngx_array_create(sc->cf->pool, n, 1);
+ if (*sc->values == NULL) {
return NGX_ERROR;
}
}
- src = sources->elts;
- for (i = 0; i < sources->nelts; i++) {
+ sc->variables = 0;
+
+ for (i = 0; i < sc->source->len; /* void */ ) {
+
+ name.len = 0;
+
+ if (sc->source->data[i] == '$') {
+
+ if (++i == sc->source->len) {
+ goto invalid_variable;
+ }
+
+ if (sc->source->data[i] >= '1' && sc->source->data[i] <= '9') {
+
+ copy_capture = ngx_http_script_add_code(*sc->lengths,
+ sizeof(ngx_http_script_copy_capture_code_t),
+ NULL);
+ if (copy_capture == NULL) {
+ return NGX_ERROR;
+ }
+
+ copy_capture->code = (ngx_http_script_code_pt)
+ ngx_http_script_copy_capture_len_code;
+ copy_capture->n = 2 * (sc->source->data[i] - '0');
+
+ copy_capture = ngx_http_script_add_code(*sc->values,
+ sizeof(ngx_http_script_copy_capture_code_t),
+ &sc->main);
+ if (copy_capture == NULL) {
+ return NGX_ERROR;
+ }
+
+ copy_capture->code = ngx_http_script_copy_capture_code;
+ copy_capture->n = sc->source->data[i] - '0';
+
+ if (sc->ncaptures < copy_capture->n) {
+ sc->ncaptures = copy_capture->n;
+ }
+
+ copy_capture->n *= 2;
+
+ i++;
+
+ continue;
+ }
+
+ if (sc->source->data[i] == '{') {
+ bracket = 1;
+
+ if (++i == sc->source->len) {
+ goto invalid_variable;
+ }
+
+ name.data = &sc->source->data[i];
+
+ } else {
+ bracket = 0;
+ name.data = &sc->source->data[i];
+ }
+
+ for ( /* void */ ; i < sc->source->len; i++, name.len++) {
+ ch = sc->source->data[i];
- if (src[i].value.data[0] == '$') {
- if (start(&src[i], *lengths, *values, 0) != NGX_OK) {
+ if (ch == '}' && bracket) {
+ i++;
+ bracket = 0;
+ break;
+ }
+
+ if ((ch >= 'A' && ch <= 'Z')
+ || (ch >= 'a' && ch <= 'z')
+ || (ch >= '0' && ch <= '9')
+ || ch == '_')
+ {
+ continue;
+ }
+
+ break;
+ }
+
+ if (bracket) {
+ ngx_conf_log_error(NGX_LOG_EMERG, sc->cf, 0,
+ "the closing bracket in \"%V\" "
+ "variable is missing", &name);
return NGX_ERROR;
}
- src[i].value.len--;
- src[i].value.data++;
+ if (name.len == 0) {
+ goto invalid_variable;
+ }
- var = ngx_http_add_variable(cf, &src[i].value, 0);
+ sc->variables++;
- if (var == NULL) {
+ index = ngx_http_get_variable_index(sc->cf, &name);
+
+ if (index == NGX_ERROR) {
return NGX_ERROR;
}
- var_code = ngx_array_push_n(*lengths,
- sizeof(ngx_http_script_var_code_t));
+ var_code = ngx_http_script_add_code(*sc->lengths,
+ sizeof(ngx_http_script_var_code_t),
+ NULL);
if (var_code == NULL) {
return NGX_ERROR;
}
var_code->code = (ngx_http_script_code_pt)
- ngx_http_script_copy_var_len;
- var_code->index = var->index;
+ ngx_http_script_copy_var_len_code;
+ var_code->index = (uintptr_t) index;
- var_code = ngx_array_push_n(*values,
- sizeof(ngx_http_script_var_code_t));
+ var_code = ngx_http_script_add_code(*sc->values,
+ sizeof(ngx_http_script_var_code_t),
+ &sc->main);
if (var_code == NULL) {
return NGX_ERROR;
}
- var_code->code = ngx_http_script_copy_var;
- var_code->index = var->index;
+ var_code->code = ngx_http_script_copy_var_code;
+ var_code->index = (uintptr_t) index;
+
+ continue;
+ }
+ if (sc->source->data[i] == '?' && sc->compile_args) {
+ sc->args = 1;
+ sc->compile_args = 0;
- if (end(*lengths, *values) != NGX_OK) {
+ code = ngx_http_script_add_code(*sc->values, sizeof(uintptr_t),
+ &sc->main);
+ if (code == NULL) {
return NGX_ERROR;
}
+ *code = (uintptr_t) ngx_http_script_start_args_code;
+
+ i++;
+
continue;
}
- if (start(&src[i], *lengths, *values, 1) != NGX_OK) {
+ name.data = &sc->source->data[i];
+
+ while (i < sc->source->len
+ && sc->source->data[i] != '$'
+ && !(sc->source->data[i] == '?' && sc->compile_args))
+ {
+ i++;
+ name.len++;
+ }
+
+ sc->size += name.len;
+
+ copy = ngx_http_script_add_code(*sc->lengths,
+ sizeof(ngx_http_script_copy_code_t),
+ NULL);
+ if (copy == NULL) {
return NGX_ERROR;
}
- }
- code = ngx_array_push_n(*lengths, sizeof(uintptr_t));
- if (code == NULL) {
- return NGX_ERROR;
+ copy->code = (ngx_http_script_code_pt) ngx_http_script_copy_len_code;
+ copy->len = name.len;
+
+ size = (sizeof(ngx_http_script_copy_code_t) + name.len
+ + sizeof(uintptr_t) - 1)
+ & ~(sizeof(uintptr_t) - 1);
+
+ copy = ngx_http_script_add_code(*sc->values, size, &sc->main);
+ if (copy == NULL) {
+ return NGX_ERROR;
+ }
+
+ copy->code = ngx_http_script_copy_code;
+ copy->len = name.len;
+
+ ngx_memcpy((u_char *) copy + sizeof(ngx_http_script_copy_code_t),
+ name.data, name.len);
}
- *code = (uintptr_t) NULL;
+ if (sc->complete_lengths) {
+ code = ngx_http_script_add_code(*sc->lengths, sizeof(uintptr_t), NULL);
+ if (code == NULL) {
+ return NGX_ERROR;
+ }
- code = ngx_array_push_n(*values, sizeof(uintptr_t));
- if (code == NULL) {
- return NGX_ERROR;
+ *code = (uintptr_t) NULL;
}
- *code = (uintptr_t) NULL;
+ if (sc->complete_values) {
+ code = ngx_http_script_add_code(*sc->values, sizeof(uintptr_t),
+ &sc->main);
+ if (code == NULL) {
+ return NGX_ERROR;
+ }
+
+ *code = (uintptr_t) NULL;
+ }
return NGX_OK;
-}
+invalid_variable:
-#if 0
+ ngx_conf_log_error(NGX_LOG_EMERG, sc->cf, 0, "invalid variable name");
-static void *
+ return NGX_ERROR;
+}
+
+
+void *
ngx_http_script_start_code(ngx_pool_t *pool, ngx_array_t **codes, size_t size)
{
if (*codes == NULL) {
@@ -122,51 +289,79 @@ ngx_http_script_start_code(ngx_pool_t *pool, ngx_array_t **codes, size_t size)
return ngx_array_push_n(*codes, size);
}
-#endif
+
+void *
+ngx_http_script_add_code(ngx_array_t *codes, size_t size, void *code)
+{
+ u_char *elts, **p;
+ void *new;
+
+ elts = codes->elts;
+
+ new = ngx_array_push_n(codes, size);
+ if (new == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ if (code) {
+ if (elts != codes->elts) {
+ p = code;
+ *p += (u_char *) codes->elts - elts;
+ }
+ }
+
+ return new;
+}
size_t
-ngx_http_script_copy_len(ngx_http_script_engine_t *e)
+ngx_http_script_copy_len_code(ngx_http_script_engine_t *e)
{
ngx_http_script_copy_code_t *code;
- code = (ngx_http_script_copy_code_t *) e->lite.ip;
+ code = (ngx_http_script_copy_code_t *) e->ip;
- e->lite.ip += sizeof(ngx_http_script_copy_code_t);
+ e->ip += sizeof(ngx_http_script_copy_code_t);
return code->len;
}
void
-ngx_http_script_copy(ngx_http_script_engine_t *e)
+ngx_http_script_copy_code(ngx_http_script_engine_t *e)
{
ngx_http_script_copy_code_t *code;
- code = (ngx_http_script_copy_code_t *) e->lite.ip;
+ code = (ngx_http_script_copy_code_t *) e->ip;
- e->lite.pos = ngx_cpymem(e->lite.pos,
- e->lite.ip + sizeof(ngx_http_script_copy_code_t),
- code->len);
+ if (!e->skip) {
+ e->pos = ngx_cpymem(e->pos, e->ip + sizeof(ngx_http_script_copy_code_t),
+ code->len);
+ }
+
+ e->ip += sizeof(ngx_http_script_copy_code_t)
+ + ((code->len + sizeof(uintptr_t) - 1) & ~(sizeof(uintptr_t) - 1));
- e->lite.ip += sizeof(ngx_http_script_copy_code_t)
- + ((code->len + sizeof(uintptr_t) - 1) & ~(sizeof(uintptr_t) - 1));
+ if (e->log) {
+ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
+ "http script copy: \"%V\"", &e->buf);
+ }
}
size_t
-ngx_http_script_copy_var_len(ngx_http_script_engine_t *e)
+ngx_http_script_copy_var_len_code(ngx_http_script_engine_t *e)
{
ngx_http_variable_value_t *value;
ngx_http_script_var_code_t *code;
- code = (ngx_http_script_var_code_t *) e->lite.ip;
+ code = (ngx_http_script_var_code_t *) e->ip;
- e->lite.ip += sizeof(ngx_http_script_var_code_t);
+ e->ip += sizeof(ngx_http_script_var_code_t);
- value = ngx_http_get_indexed_variable(e->lite.request, code->index);
+ value = ngx_http_get_indexed_variable(e->request, code->index);
- if (value == NULL || value == NGX_HTTP_VARIABLE_NOT_FOUND) {
+ if (value == NULL || value == NGX_HTTP_VAR_NOT_FOUND) {
return 0;
}
@@ -175,20 +370,456 @@ ngx_http_script_copy_var_len(ngx_http_script_engine_t *e)
void
-ngx_http_script_copy_var(ngx_http_script_engine_t *e)
+ngx_http_script_copy_var_code(ngx_http_script_engine_t *e)
{
ngx_http_variable_value_t *value;
ngx_http_script_var_code_t *code;
- code = (ngx_http_script_var_code_t *) e->lite.ip;
+ code = (ngx_http_script_var_code_t *) e->ip;
+
+ e->ip += sizeof(ngx_http_script_var_code_t);
+
+ if (!e->skip) {
+ value = ngx_http_get_indexed_variable(e->request, code->index);
+
+ if (value == NULL || value == NGX_HTTP_VAR_NOT_FOUND) {
+ return;
+ }
+
+ e->pos = ngx_cpymem(e->pos, value->text.data, value->text.len);
- e->lite.ip += sizeof(ngx_http_script_var_code_t);
+ if (e->log) {
+ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
+ "http script var: \"%V\"", &e->buf);
+ }
+ }
+}
+
+
+size_t
+ngx_http_script_copy_capture_len_code(ngx_http_script_engine_t *e)
+{
+ ngx_http_script_copy_capture_code_t *code;
+
+ code = (ngx_http_script_copy_capture_code_t *) e->ip;
+
+ e->ip += sizeof(ngx_http_script_copy_capture_code_t);
+
+ if ((e->args || e->quote)
+ && (e->request->quoted_uri || e->request->plus_in_uri))
+ {
+ return e->captures[code->n + 1] - e->captures[code->n]
+ + ngx_escape_uri(NULL,
+ &e->line->data[e->captures[code->n]],
+ e->captures[code->n + 1] - e->captures[code->n],
+ NGX_ESCAPE_ARGS);
+ } else {
+ return e->captures[code->n + 1] - e->captures[code->n];
+ }
+}
+
+
+void
+ngx_http_script_copy_capture_code(ngx_http_script_engine_t *e)
+{
+ ngx_http_script_copy_capture_code_t *code;
+
+ code = (ngx_http_script_copy_capture_code_t *) e->ip;
+
+ e->ip += sizeof(ngx_http_script_copy_capture_code_t);
+
+ if ((e->args || e->quote)
+ && (e->request->quoted_uri || e->request->plus_in_uri))
+ {
+ e->pos = (u_char *) ngx_escape_uri(e->pos,
+ &e->line->data[e->captures[code->n]],
+ e->captures[code->n + 1] - e->captures[code->n],
+ NGX_ESCAPE_ARGS);
+ } else {
+ e->pos = ngx_cpymem(e->pos,
+ &e->line->data[e->captures[code->n]],
+ e->captures[code->n + 1] - e->captures[code->n]);
+ }
+
+ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
+ "http script capture: \"%V\"", &e->buf);
+}
- value = ngx_http_get_indexed_variable(e->lite.request, code->index);
- if (value == NULL || value == NGX_HTTP_VARIABLE_NOT_FOUND) {
+void
+ngx_http_script_start_args_code(ngx_http_script_engine_t *e)
+{
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
+ "http script args");
+
+ e->args = e->pos;
+ e->ip += sizeof(uintptr_t);
+}
+
+
+void
+ngx_http_script_regex_start_code(ngx_http_script_engine_t *e)
+{
+ size_t len;
+ ngx_int_t rc;
+ ngx_uint_t n;
+ ngx_http_request_t *r;
+ ngx_http_script_engine_t le;
+ ngx_http_script_len_code_pt lcode;
+ ngx_http_script_regex_code_t *code;
+
+ code = (ngx_http_script_regex_code_t *) e->ip;
+
+ r = e->request;
+
+ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "http script regex: \"%V\"", &code->name);
+
+ if (code->uri) {
+ e->line = &r->uri;
+ } else {
+ e->sp--;
+ e->line = &e->sp->text;
+ }
+
+ rc = ngx_regex_exec(code->regex, e->line, e->captures, code->ncaptures);
+
+ if (rc == NGX_REGEX_NO_MATCHED) {
+ if (e->log) {
+ ngx_log_error(NGX_LOG_NOTICE, r->connection->log, 0,
+ "\"%V\" does not match \"%V\"", &code->name, e->line);
+ }
+
+ if (code->test) {
+ e->sp->value = 0;
+ e->sp->text.len = 0;
+ e->sp->text.data = (u_char *) "";
+ e->sp++;
+
+ e->ip += sizeof(ngx_http_script_regex_code_t);
+ return;
+ }
+
+ e->ip += code->next;
+ return;
+ }
+
+ if (rc < 0) {
+ ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
+ ngx_regex_exec_n " failed: %d on \"%V\" using \"%V\"",
+ rc, e->line, &code->name);
+
+ e->ip = ngx_http_script_exit;
+ e->status = NGX_HTTP_INTERNAL_SERVER_ERROR;
+ return;
+ }
+
+ if (e->log) {
+ ngx_log_error(NGX_LOG_NOTICE, r->connection->log, 0,
+ "\"%V\" matches \"%V\"", &code->name, e->line);
+ }
+
+ if (code->test) {
+ e->sp->value = 1;
+ e->sp->text.len = 1;
+ e->sp->text.data = (u_char *) "1";
+ e->sp++;
+
+ e->ip += sizeof(ngx_http_script_regex_code_t);
return;
}
- e->lite.pos = ngx_cpymem(e->lite.pos, value->text.data, value->text.len);
+ if (code->status) {
+ e->status = code->status;
+
+ if (!code->redirect) {
+ e->ip = ngx_http_script_exit;
+ return;
+ }
+ }
+
+ if (code->uri) {
+ r->internal = 1;
+ r->valid_unparsed_uri = 0;
+
+ if (code->break_cycle) {
+ r->valid_location = 0;
+
+ } else {
+ r->uri_changed = 1;
+ }
+ }
+
+ if (code->lengths == NULL) {
+ e->buf.len = code->size;
+
+ if (code->uri) {
+ if (rc && (r->quoted_uri || r->plus_in_uri)) {
+ e->buf.len += 2 * ngx_escape_uri(NULL, r->uri.data, r->uri.len,
+ NGX_ESCAPE_ARGS);
+ }
+ }
+
+ for (n = 1; n < (ngx_uint_t) rc; n++) {
+ e->buf.len += e->captures[2 * n + 1] - e->captures[2 * n];
+ }
+
+ } else {
+ ngx_memzero(&le, sizeof(ngx_http_script_engine_t));
+
+ le.ip = code->lengths->elts;
+ le.request = r;
+ le.captures = e->captures;
+
+ len = 1; /* reserve 1 byte for possible "?" */
+
+ while (*(uintptr_t *) le.ip) {
+ lcode = *(ngx_http_script_len_code_pt *) le.ip;
+ len += lcode(&le);
+ }
+
+ e->buf.len = len;
+ }
+
+ if (code->args && code->add_args && r->args.len) {
+ e->buf.len += r->args.len + 1;
+ }
+
+ e->buf.data = ngx_palloc(r->pool, e->buf.len);
+ if (e->buf.data == NULL) {
+ e->ip = ngx_http_script_exit;
+ e->status = NGX_HTTP_INTERNAL_SERVER_ERROR;
+ return;
+ }
+
+ e->quote = code->redirect;
+
+ e->pos = e->buf.data;
+
+ e->ip += sizeof(ngx_http_script_regex_code_t);
+}
+
+
+void
+ngx_http_script_regex_end_code(ngx_http_script_engine_t *e)
+{
+ ngx_http_request_t *r;
+ ngx_http_script_regex_end_code_t *code;
+
+ code = (ngx_http_script_regex_end_code_t *) e->ip;
+
+ r = e->request;
+
+ e->quote = 0;
+
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "http script regex end");
+
+ if (code->redirect) {
+
+ if (code->add_args && r->args.len) {
+ *e->pos++ = (u_char) (code->args ? '&' : '?');
+ e->pos = ngx_cpymem(e->pos, r->args.data, r->args.len);
+ }
+
+ e->buf.len = e->pos - e->buf.data;
+
+ if (e->log) {
+ ngx_log_error(NGX_LOG_NOTICE, r->connection->log, 0,
+ "rewritten redirect: \"%V\"", &e->buf);
+ }
+
+ r->headers_out.location = ngx_list_push(&r->headers_out.headers);
+ if (r->headers_out.location == NULL) {
+ e->ip = ngx_http_script_exit;
+ e->status = NGX_HTTP_INTERNAL_SERVER_ERROR;
+ return;
+ }
+
+ r->headers_out.location->hash = 1;
+ r->headers_out.location->key.len = sizeof("Location") - 1;
+ r->headers_out.location->key.data = (u_char *) "Location";
+ r->headers_out.location->value = e->buf;
+
+ e->ip += sizeof(ngx_http_script_regex_end_code_t);
+ return;
+ }
+
+ if (e->args) {
+ e->buf.len = e->args - e->buf.data;
+
+ if (code->add_args && r->args.len) {
+ *e->pos++ = '&';
+ e->pos = ngx_cpymem(e->pos, r->args.data, r->args.len);
+ }
+
+ r->args.len = e->pos - e->args;
+ r->args.data = e->args;
+
+ e->args = NULL;
+
+ } else {
+ e->buf.len = e->pos - e->buf.data;
+ }
+
+ if (e->log) {
+ ngx_log_error(NGX_LOG_NOTICE, r->connection->log, 0,
+ "rewritten data: \"%V\", args: \"%V\"",
+ &e->buf, &r->args);
+ }
+
+ if (code->uri) {
+ r->uri = e->buf;
+
+ if (ngx_http_set_exten(r) != NGX_OK) {
+ e->ip = ngx_http_script_exit;
+ e->status = NGX_HTTP_INTERNAL_SERVER_ERROR;
+ return;
+ }
+ }
+
+ e->ip += sizeof(ngx_http_script_regex_end_code_t);
+}
+
+
+void
+ngx_http_script_return_code(ngx_http_script_engine_t *e)
+{
+ ngx_http_script_return_code_t *code;
+
+ code = (ngx_http_script_return_code_t *) e->ip;
+
+ e->status = code->status;
+
+ e->ip += sizeof(ngx_http_script_return_code_t) - sizeof(uintptr_t);
+}
+
+
+void
+ngx_http_script_if_code(ngx_http_script_engine_t *e)
+{
+ ngx_http_script_if_code_t *code;
+
+ code = (ngx_http_script_if_code_t *) e->ip;
+
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
+ "http script if");
+
+ e->sp--;
+
+ if (e->sp->value) {
+ if (code->loc_conf) {
+ e->request->loc_conf = code->loc_conf;
+ }
+
+ e->ip += sizeof(ngx_http_script_if_code_t);
+ return;
+ }
+
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
+ "http script if false");
+
+ e->ip += code->next;
+}
+
+
+void
+ngx_http_script_value_code(ngx_http_script_engine_t *e)
+{
+ ngx_http_script_value_code_t *code;
+
+ code = (ngx_http_script_value_code_t *) e->ip;
+
+ e->ip += sizeof(ngx_http_script_value_code_t);
+
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
+ "http script value");
+
+ e->sp->value = (ngx_uint_t) code->value;
+ e->sp->text.len = (size_t) code->text_len;
+ e->sp->text.data = (u_char *) code->text_data;
+ e->sp++;
+}
+
+
+void
+ngx_http_script_set_var_code(ngx_http_script_engine_t *e)
+{
+ ngx_http_request_t *r;
+ ngx_http_variable_value_t *value;
+ ngx_http_core_main_conf_t *cmcf;
+ ngx_http_script_var_code_t *code;
+
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
+ "http script set var");
+
+ code = (ngx_http_script_var_code_t *) e->ip;
+
+ e->ip += sizeof(ngx_http_script_var_code_t);
+
+ r = e->request;
+
+ if (r->variables == NULL) {
+ cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
+
+ r->variables = ngx_pcalloc(r->pool, cmcf->variables.nelts
+ * sizeof(ngx_http_variable_value_t *));
+ if (r->variables == NULL) {
+ e->ip = ngx_http_script_exit;
+ e->status = NGX_HTTP_INTERNAL_SERVER_ERROR;
+ return;
+ }
+ }
+
+ value = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t));
+ if (value == NULL) {
+ e->ip = ngx_http_script_exit;
+ e->status = NGX_HTTP_INTERNAL_SERVER_ERROR;
+ return;
+ }
+
+ e->sp--;
+
+ *value = *e->sp;
+
+ r->variables[code->index] = value;
+}
+
+
+void
+ngx_http_script_var_code(ngx_http_script_engine_t *e)
+{
+ ngx_http_variable_value_t *value;
+ ngx_http_script_var_code_t *code;
+
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
+ "http script var");
+
+ code = (ngx_http_script_var_code_t *) e->ip;
+
+ e->ip += sizeof(ngx_http_script_var_code_t);
+
+ value = ngx_http_get_indexed_variable(e->request, code->index);
+
+ if (value == NULL || value == NGX_HTTP_VAR_NOT_FOUND) {
+ e->sp->value = 0;
+ e->sp->text.len = 0;
+ e->sp->text.data = (u_char *) "";
+ e->sp++;
+
+ return;
+ }
+
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
+ "http script var: %ui, \"%V\"", value->value, &value->text);
+
+ *e->sp = *value;
+ e->sp++;
+}
+
+
+void
+ngx_http_script_nop_code(ngx_http_script_engine_t *e)
+{
+ e->ip += sizeof(uintptr_t);
}
diff --git a/src/http/ngx_http_script.h b/src/http/ngx_http_script.h
index fae2b7bb1..21927c1f7 100644
--- a/src/http/ngx_http_script.h
+++ b/src/http/ngx_http_script.h
@@ -16,23 +16,48 @@
typedef struct {
u_char *ip;
u_char *pos;
+ ngx_http_variable_value_t *sp;
+
+ ngx_str_t buf;
+ ngx_str_t *line;
+
+ /* the start of the rewritten arguments */
+ u_char *args;
+
+ unsigned skip:1;
+ unsigned quote:1;
+ unsigned log:1;
+
+ int *captures;
+
+ ngx_int_t status;
ngx_http_request_t *request;
-} ngx_http_script_lite_engine_t;
+} ngx_http_script_engine_t;
typedef struct {
- ngx_http_script_lite_engine_t lite;
-} ngx_http_script_engine_t;
+ ngx_conf_t *cf;
+ ngx_str_t *source;
+ ngx_array_t **lengths;
+ ngx_array_t **values;
+ ngx_uint_t variables;
+ ngx_uint_t ncaptures;
+ ngx_uint_t size;
-typedef void (*ngx_http_script_code_pt) (ngx_http_script_engine_t *e);
-typedef size_t (*ngx_http_script_len_code_pt)
- (ngx_http_script_lite_engine_t *e);
+ void *main;
+
+ unsigned compile_args:1;
+ unsigned compile_null:1;
+ unsigned complete_lengths:1;
+ unsigned complete_values:1;
-typedef ngx_int_t (*ngx_http_script_compile_lite_start_pt) (ngx_table_elt_t *h,
- ngx_array_t *lengths, ngx_array_t *values, ngx_uint_t value);
-typedef ngx_int_t (*ngx_http_script_compile_lite_end_pt) (ngx_array_t *lengths,
- ngx_array_t *values);
+ unsigned args:1;
+} ngx_http_script_compile_t;
+
+
+typedef void (*ngx_http_script_code_pt) (ngx_http_script_engine_t *e);
+typedef size_t (*ngx_http_script_len_code_pt) (ngx_http_script_engine_t *e);
typedef struct {
@@ -47,20 +72,93 @@ typedef struct {
} ngx_http_script_var_code_t;
-ngx_int_t ngx_http_script_compile_lite(ngx_conf_t *cf, ngx_array_t *sources,
- ngx_array_t **lengths, ngx_array_t **values,
- ngx_http_script_compile_lite_start_pt start,
- ngx_http_script_compile_lite_end_pt end);
+typedef struct {
+ ngx_http_script_code_pt code;
+ uintptr_t n;
+} ngx_http_script_copy_capture_code_t;
-static void *ngx_http_script_start_code(ngx_pool_t *pool, ngx_array_t **codes,
- size_t size);
+typedef struct {
+ ngx_http_script_code_pt code;
+ ngx_regex_t *regex;
+ ngx_array_t *lengths;
+ uintptr_t size;
+ uintptr_t ncaptures;
+ uintptr_t status;
+ uintptr_t next;
+
+ uintptr_t test:1;
+ uintptr_t uri:1;
+ uintptr_t args:1;
+
+ /* add the r->args to the new arguments */
+ uintptr_t add_args:1;
+
+ uintptr_t redirect:1;
+ uintptr_t break_cycle:1;
+
+ ngx_str_t name;
+} ngx_http_script_regex_code_t;
-size_t ngx_http_script_copy_len(ngx_http_script_engine_t *e);
-void ngx_http_script_copy(ngx_http_script_engine_t *e);
-size_t ngx_http_script_copy_var_len(ngx_http_script_engine_t *e);
-void ngx_http_script_copy_var(ngx_http_script_engine_t *e);
+typedef struct {
+ ngx_http_script_code_pt code;
+
+ uintptr_t uri:1;
+ uintptr_t args:1;
+
+ /* add the r->args to the new arguments */
+ uintptr_t add_args:1;
+
+ uintptr_t redirect:1;
+} ngx_http_script_regex_end_code_t;
+
+
+typedef struct {
+ ngx_http_script_code_pt code;
+ uintptr_t status;
+ uintptr_t null;
+} ngx_http_script_return_code_t;
+
+
+typedef struct {
+ ngx_http_script_code_pt code;
+ uintptr_t next;
+ void **loc_conf;
+} ngx_http_script_if_code_t;
+
+
+typedef struct {
+ ngx_http_script_code_pt code;
+ uintptr_t value;
+ uintptr_t text_len;
+ uintptr_t text_data;
+} ngx_http_script_value_code_t;
+
+
+ngx_uint_t ngx_http_script_variables_count(ngx_str_t *value);
+ngx_int_t ngx_http_script_compile(ngx_http_script_compile_t *sc);
+
+void *ngx_http_script_start_code(ngx_pool_t *pool, ngx_array_t **codes,
+ size_t size);
+void *ngx_http_script_add_code(ngx_array_t *codes, size_t size, void *code);
+
+size_t ngx_http_script_copy_len_code(ngx_http_script_engine_t *e);
+void ngx_http_script_copy_code(ngx_http_script_engine_t *e);
+size_t ngx_http_script_copy_var_len_code(ngx_http_script_engine_t *e);
+void ngx_http_script_copy_var_code(ngx_http_script_engine_t *e);
+size_t ngx_http_script_copy_capture_len_code(ngx_http_script_engine_t *e);
+void ngx_http_script_copy_capture_code(ngx_http_script_engine_t *e);
+void ngx_http_script_regex_start_code(ngx_http_script_engine_t *e);
+void ngx_http_script_regex_end_code(ngx_http_script_engine_t *e);
+void ngx_http_script_copy_capture_code(ngx_http_script_engine_t *e);
+void ngx_http_script_start_args_code(ngx_http_script_engine_t *e);
+void ngx_http_script_return_code(ngx_http_script_engine_t *e);
+void ngx_http_script_if_code(ngx_http_script_engine_t *e);
+void ngx_http_script_value_code(ngx_http_script_engine_t *e);
+void ngx_http_script_set_var_code(ngx_http_script_engine_t *e);
+void ngx_http_script_var_code(ngx_http_script_engine_t *e);
+void ngx_http_script_nop_code(ngx_http_script_engine_t *e);
#endif /* _NGX_HTTP_SCRIPT_H_INCLUDED_ */
diff --git a/src/http/ngx_http_special_response.c b/src/http/ngx_http_special_response.c
index 2ccf51cf4..536068b03 100644
--- a/src/http/ngx_http_special_response.c
+++ b/src/http/ngx_http_special_response.c
@@ -331,22 +331,15 @@ ngx_http_special_response_handler(ngx_http_request_t *r, ngx_int_t error)
msie_padding = 1;
}
- r->headers_out.content_type = ngx_list_push(&r->headers_out.headers);
- if (r->headers_out.content_type == NULL) {
- return NGX_ERROR;
- }
-
- r->headers_out.content_type->key.len = sizeof("Content-Type") - 1;
- r->headers_out.content_type->key.data = (u_char *) "Content-Type";
- r->headers_out.content_type->value.len = sizeof("text/html") - 1;
- r->headers_out.content_type->value.data = (u_char *) "text/html";
+ r->headers_out.content_type.len = sizeof("text/html") - 1;
+ r->headers_out.content_type.data = (u_char *) "text/html";
} else {
r->headers_out.content_length_n = -1;
}
if (r->headers_out.content_length) {
- r->headers_out.content_length->key.len = 0;
+ r->headers_out.content_length->hash = 0;
r->headers_out.content_length = NULL;
}
@@ -415,7 +408,11 @@ ngx_http_special_response_handler(ngx_http_request_t *r, ngx_int_t error)
cl->buf = b;
}
- b->last_buf = 1;
+ if (r->main == NULL) {
+ b->last_buf = 1;
+ }
+
+ b->last_in_chain = 1;
cl->next = NULL;
diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c
index 3dab5c39d..f766d7d05 100644
--- a/src/http/ngx_http_upstream.c
+++ b/src/http/ngx_http_upstream.c
@@ -6,14 +6,17 @@
#include <ngx_config.h>
#include <ngx_core.h>
-#include <ngx_http.h>
#include <ngx_event_connect.h>
+#include <ngx_http.h>
-static void ngx_http_upstream_check_broken_connection(ngx_event_t *ev);
+static void ngx_http_upstream_rd_check_broken_connection(ngx_http_request_t *r);
+static void ngx_http_upstream_wr_check_broken_connection(ngx_http_request_t *r);
+static void ngx_http_upstream_check_broken_connection(ngx_http_request_t *r,
+ ngx_event_t *ev);
static void ngx_http_upstream_connect(ngx_http_request_t *r,
ngx_http_upstream_t *u);
-static void ngx_http_upstream_reinit(ngx_http_request_t *r,
+static ngx_int_t ngx_http_upstream_reinit(ngx_http_request_t *r,
ngx_http_upstream_t *u);
static void ngx_http_upstream_send_request(ngx_http_request_t *r,
ngx_http_upstream_t *u);
@@ -21,6 +24,7 @@ static void ngx_http_upstream_send_request_handler(ngx_event_t *wev);
static void ngx_http_upstream_process_header(ngx_event_t *rev);
static void ngx_http_upstream_send_response(ngx_http_request_t *r,
ngx_http_upstream_t *u);
+static void ngx_http_upstream_process_downstream(ngx_http_request_t *r);
static void ngx_http_upstream_process_body(ngx_event_t *ev);
static void ngx_http_upstream_dummy_handler(ngx_event_t *wev);
static void ngx_http_upstream_next(ngx_http_request_t *r,
@@ -28,19 +32,125 @@ static void ngx_http_upstream_next(ngx_http_request_t *r,
static void ngx_http_upstream_finalize_request(ngx_http_request_t *r,
ngx_http_upstream_t *u, ngx_int_t rc);
+static ngx_int_t ngx_http_upstream_process_header_line(ngx_http_request_t *r,
+ ngx_table_elt_t *h, ngx_uint_t offset);
+static ngx_int_t
+ ngx_http_upstream_process_multi_header_lines(ngx_http_request_t *r,
+ ngx_table_elt_t *h, ngx_uint_t offset);
+static ngx_int_t ngx_http_upstream_ignore_header_line(ngx_http_request_t *r,
+ ngx_table_elt_t *h, ngx_uint_t offset);
+static ngx_int_t ngx_http_upstream_copy_header_line(ngx_http_request_t *r,
+ ngx_table_elt_t *h, ngx_uint_t offset);
+static ngx_int_t
+ ngx_http_upstream_conditional_copy_header_line(ngx_http_request_t *r,
+ ngx_table_elt_t *h, ngx_uint_t offset);
+static ngx_int_t
+ ngx_http_upstream_copy_multi_header_lines(ngx_http_request_t *r,
+ ngx_table_elt_t *h, ngx_uint_t offset);
+static ngx_int_t ngx_http_upstream_copy_content_type(ngx_http_request_t *r,
+ ngx_table_elt_t *h, ngx_uint_t offset);
+static ngx_int_t ngx_http_upstream_copy_content_length(ngx_http_request_t *r,
+ ngx_table_elt_t *h, ngx_uint_t offset);
+static ngx_int_t ngx_http_upstream_rewrite_location(ngx_http_request_t *r,
+ ngx_table_elt_t *h, ngx_uint_t offset);
+static ngx_int_t ngx_http_upstream_rewrite_refresh(ngx_http_request_t *r,
+ ngx_table_elt_t *h, ngx_uint_t offset);
+#if (NGX_HTTP_GZIP)
+static ngx_int_t ngx_http_upstream_copy_content_encoding(ngx_http_request_t *r,
+ ngx_table_elt_t *h, ngx_uint_t offset);
+#endif
+
static size_t ngx_http_upstream_log_status_getlen(ngx_http_request_t *r,
uintptr_t data);
static u_char *ngx_http_upstream_log_status(ngx_http_request_t *r,
u_char *buf, ngx_http_log_op_t *op);
+static u_char *ngx_http_upstream_log_error(ngx_http_request_t *r, u_char *buf,
+ size_t len);
static ngx_int_t ngx_http_upstream_add_log_formats(ngx_conf_t *cf);
+static void *ngx_http_upstream_create_main_conf(ngx_conf_t *cf);
+static char *ngx_http_core_init_main_conf(ngx_conf_t *cf, void *conf);
+
+
+ngx_http_upstream_header_t ngx_http_upstream_headers_in[] = {
+
+ { ngx_string("Status"),
+ ngx_http_upstream_process_header_line,
+ offsetof(ngx_http_upstream_headers_in_t, status),
+ /* STUB */ ngx_http_upstream_ignore_header_line, 0 },
+
+ { ngx_string("Content-Type"),
+ ngx_http_upstream_process_header_line,
+ offsetof(ngx_http_upstream_headers_in_t, content_type),
+ ngx_http_upstream_copy_content_type, 0 },
+
+ { ngx_string("Content-Length"),
+ ngx_http_upstream_process_header_line,
+ offsetof(ngx_http_upstream_headers_in_t, content_length),
+ ngx_http_upstream_copy_content_length, 0 },
+
+ { ngx_string("Date"),
+ ngx_http_upstream_process_header_line,
+ offsetof(ngx_http_upstream_headers_in_t, date),
+ ngx_http_upstream_conditional_copy_header_line,
+ offsetof(ngx_http_upstream_conf_t, pass_date) },
+
+ { ngx_string("Server"),
+ ngx_http_upstream_process_header_line,
+ offsetof(ngx_http_upstream_headers_in_t, server),
+ ngx_http_upstream_conditional_copy_header_line,
+ offsetof(ngx_http_upstream_conf_t, pass_server) },
+
+ { ngx_string("Location"),
+ ngx_http_upstream_ignore_header_line, 0,
+ ngx_http_upstream_rewrite_location, 0 },
+
+ { ngx_string("Refresh"),
+ ngx_http_upstream_ignore_header_line, 0,
+ ngx_http_upstream_rewrite_refresh, 0 },
+
+ { ngx_string("Cache-Control"),
+ ngx_http_upstream_process_multi_header_lines,
+ offsetof(ngx_http_upstream_headers_in_t, cache_control),
+ ngx_http_upstream_copy_multi_header_lines,
+ offsetof(ngx_http_headers_out_t, cache_control) },
+
+ { ngx_string("Connection"),
+ ngx_http_upstream_ignore_header_line, 0,
+ ngx_http_upstream_ignore_header_line, 0 },
+
+ { ngx_string("X-Pad"),
+ ngx_http_upstream_ignore_header_line, 0,
+ ngx_http_upstream_ignore_header_line, 0 },
+
+ { ngx_string("X-Powered-By"),
+ ngx_http_upstream_ignore_header_line, 0,
+ ngx_http_upstream_conditional_copy_header_line,
+ offsetof(ngx_http_upstream_conf_t, pass_x_powered_by) },
+
+ { ngx_string("X-Accel-Expires"),
+ ngx_http_upstream_process_header_line,
+ offsetof(ngx_http_upstream_headers_in_t, x_accel_expires),
+ ngx_http_upstream_conditional_copy_header_line,
+ offsetof(ngx_http_upstream_conf_t, pass_x_accel_expires) },
+
+#if (NGX_HTTP_GZIP)
+ { ngx_string("Content-Encoding"),
+ ngx_http_upstream_process_header_line,
+ offsetof(ngx_http_upstream_headers_in_t, content_encoding),
+ ngx_http_upstream_copy_content_encoding, 0 },
+#endif
+
+ { ngx_null_string, NULL, 0, NULL, 0 }
+};
ngx_http_module_t ngx_http_upstream_module_ctx = {
- ngx_http_upstream_add_log_formats, /* pre conf */
-
- NULL, /* create main configuration */
- NULL, /* init main configuration */
+ ngx_http_upstream_add_log_formats, /* preconfiguration */
+ NULL, /* postconfiguration */
+
+ ngx_http_upstream_create_main_conf, /* create main configuration */
+ ngx_http_core_init_main_conf, /* init main configuration */
NULL, /* create server configuration */
NULL, /* merge server configuration */
@@ -51,7 +161,7 @@ ngx_http_module_t ngx_http_upstream_module_ctx = {
ngx_module_t ngx_http_upstream_module = {
- NGX_MODULE,
+ NGX_MODULE_V1,
&ngx_http_upstream_module_ctx, /* module context */
NULL, /* module directives */
NGX_HTTP_MODULE, /* module type */
@@ -77,8 +187,9 @@ char *ngx_http_upstream_header_errors[] = {
void
ngx_http_upstream_init(ngx_http_request_t *r)
{
- ngx_connection_t *c;
- ngx_http_upstream_t *u;
+ ngx_connection_t *c;
+ ngx_http_upstream_t *u;
+ ngx_http_core_loc_conf_t *clcf;
c = r->connection;
@@ -89,11 +200,11 @@ ngx_http_upstream_init(ngx_http_request_t *r)
ngx_del_timer(c->read);
}
- c->read->event_handler = ngx_http_upstream_check_broken_connection;
+ r->read_event_handler = ngx_http_upstream_rd_check_broken_connection;
if (ngx_event_flags & NGX_USE_CLEAR_EVENT) {
- c->write->event_handler = ngx_http_upstream_check_broken_connection;
+ r->write_event_handler = ngx_http_upstream_wr_check_broken_connection;
if (!c->write->active) {
if (ngx_add_event(c->write, NGX_WRITE_EVENT,
@@ -107,7 +218,14 @@ ngx_http_upstream_init(ngx_http_request_t *r)
u = r->upstream;
- u->method = r->method;
+ u->request_bufs = r->request_body->bufs;
+
+ if (u->conf->method == NGX_CONF_UNSET_UINT) {
+ u->method = r->method;
+
+ } else {
+ u->method = u->conf->method;
+ }
if (u->create_request(r) == NGX_ERROR) {
ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
@@ -115,14 +233,15 @@ ngx_http_upstream_init(ngx_http_request_t *r)
}
u->peer.log = r->connection->log;
- u->saved_log_ctx = r->connection->log->data;
- u->saved_log_handler = r->connection->log->handler;
- r->connection->log->data = u->log_ctx;
- r->connection->log->handler = u->log_handler;
+ u->saved_log_handler = r->log_handler;
+ r->log_handler = ngx_http_upstream_log_error;
+
+ clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
u->output.sendfile = r->connection->sendfile;
u->output.pool = r->pool;
u->output.bufs.num = 1;
+ u->output.bufs.size = clcf->client_body_buffer_size;
u->output.output_filter = ngx_chain_writer;
u->output.filter_ctx = &u->writer;
@@ -148,20 +267,33 @@ ngx_http_upstream_init(ngx_http_request_t *r)
static void
-ngx_http_upstream_check_broken_connection(ngx_event_t *ev)
+ngx_http_upstream_rd_check_broken_connection(ngx_http_request_t *r)
+{
+ ngx_http_upstream_check_broken_connection(r, r->connection->read);
+}
+
+
+static void
+ngx_http_upstream_wr_check_broken_connection(ngx_http_request_t *r)
+{
+ ngx_http_upstream_check_broken_connection(r, r->connection->write);
+}
+
+
+static void
+ngx_http_upstream_check_broken_connection(ngx_http_request_t *r,
+ ngx_event_t *ev)
{
int n;
char buf[1];
ngx_err_t err;
ngx_connection_t *c;
- ngx_http_request_t *r;
ngx_http_upstream_t *u;
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ev->log, 0,
"http upstream check client, write event:%d", ev->write);
- c = ev->data;
- r = c->data;
+ c = r->connection;
u = r->upstream;
if (u->peer.connection == NULL) {
@@ -296,8 +428,8 @@ ngx_http_upstream_connect(ngx_http_request_t *r, ngx_http_upstream_t *u)
c = u->peer.connection;
c->data = r;
- c->write->event_handler = ngx_http_upstream_send_request_handler;
- c->read->event_handler = ngx_http_upstream_process_header;
+ c->write->handler = ngx_http_upstream_send_request_handler;
+ c->read->handler = ngx_http_upstream_process_header;
c->sendfile = r->connection->sendfile;
@@ -312,11 +444,20 @@ ngx_http_upstream_connect(ngx_http_request_t *r, ngx_http_upstream_t *u)
u->writer.limit = 0;
if (u->request_sent) {
- ngx_http_upstream_reinit(r, u);
+ if (ngx_http_upstream_reinit(r, u) != NGX_OK) {
+ ngx_http_upstream_finalize_request(r, u,
+ NGX_HTTP_INTERNAL_SERVER_ERROR);
+ return;
+ }
}
- if (r->request_body->buf) {
- if (r->request_body->temp_file) {
+ if (r->request_body) {
+ if (r->request_body->temp_file && r->main == NULL) {
+
+ /*
+ * the r->request_body->buf can be reused for one request only,
+ * the subrequests should allocate their own temporay bufs
+ */
u->output.free = ngx_alloc_chain_link(r->pool);
if (u->output.free == NULL) {
@@ -332,9 +473,6 @@ ngx_http_upstream_connect(ngx_http_request_t *r, ngx_http_upstream_t *u)
r->request_body->buf->pos = r->request_body->buf->start;
r->request_body->buf->last = r->request_body->buf->start;
r->request_body->buf->tag = u->output.tag;
-
- } else {
- r->request_body->buf->pos = r->request_body->buf->start;
}
}
@@ -351,29 +489,51 @@ ngx_http_upstream_connect(ngx_http_request_t *r, ngx_http_upstream_t *u)
}
-static void
+static ngx_int_t
ngx_http_upstream_reinit(ngx_http_request_t *r, ngx_http_upstream_t *u)
{
ngx_chain_t *cl;
- if (u->reinit_request(r) == NGX_ERROR) {
- ngx_http_upstream_finalize_request(r, u,
- NGX_HTTP_INTERNAL_SERVER_ERROR);
- return;
+ if (u->reinit_request(r) != NGX_OK) {
+ return NGX_ERROR;
+ }
+
+ ngx_memzero(&r->upstream->headers_in,
+ sizeof(ngx_http_upstream_headers_in_t));
+
+ if (ngx_list_init(&r->upstream->headers_in.headers, r->pool, 8,
+ sizeof(ngx_table_elt_t)) != NGX_OK)
+ {
+ return NGX_ERROR;
}
/* reinit the request chain */
- for (cl = r->request_body->bufs; cl; cl = cl->next) {
+ for (cl = u->request_bufs; cl; cl = cl->next) {
cl->buf->pos = cl->buf->start;
cl->buf->file_pos = 0;
}
- /* reinit the ngx_output_chain() context */
+ /* reinit the subrequest's ngx_output_chain() context */
+
+ if (r->request_body) {
+ if (r->request_body->temp_file && r->main && u->output.buf) {
+
+ u->output.free = ngx_alloc_chain_link(r->pool);
+ if (u->output.free == NULL) {
+ return NGX_ERROR;
+ }
+
+ u->output.free->buf = u->output.buf;
+ u->output.free->next = NULL;
+
+ u->output.buf->pos = u->output.buf->start;
+ u->output.buf->last = u->output.buf->start;
+ }
+ }
u->output.buf = NULL;
u->output.in = NULL;
- u->output.free = NULL;
u->output.busy = NULL;
/* reinit u->header_in buffer */
@@ -388,20 +548,22 @@ ngx_http_upstream_reinit(ngx_http_request_t *r, ngx_http_upstream_t *u)
u->header_in.last = u->header_in.start;
}
#else
+
u->header_in.pos = u->header_in.start;
u->header_in.last = u->header_in.start;
+
#endif
/* add one more state */
u->state = ngx_array_push(&u->states);
if (u->state == NULL) {
- ngx_http_upstream_finalize_request(r, u,
- NGX_HTTP_INTERNAL_SERVER_ERROR);
- return;
+ return NGX_ERROR;
}
ngx_memzero(u->state, sizeof(ngx_http_upstream_state_t));
+
+ return NGX_OK;
}
@@ -433,8 +595,7 @@ ngx_http_upstream_send_request(ngx_http_request_t *r, ngx_http_upstream_t *u)
c->log->action = "sending request to upstream";
- rc = ngx_output_chain(&u->output,
- u->request_sent ? NULL : r->request_body->bufs);
+ rc = ngx_output_chain(&u->output, u->request_sent ? NULL : u->request_bufs);
u->request_sent = 1;
@@ -494,9 +655,9 @@ ngx_http_upstream_send_request(ngx_http_request_t *r, ngx_http_upstream_t *u)
}
#endif
- c->write->event_handler = ngx_http_upstream_dummy_handler;
+ c->write->handler = ngx_http_upstream_dummy_handler;
- if (ngx_handle_level_write_event(c->write) == NGX_ERROR) {
+ if (ngx_handle_write_event(c->write, 0) == NGX_ERROR) {
ngx_http_upstream_finalize_request(r, u,
NGX_HTTP_INTERNAL_SERVER_ERROR);
return;
@@ -575,6 +736,14 @@ ngx_http_upstream_process_header(ngx_event_t *rev)
u->header_in.tag = u->output.tag;
+ if (ngx_list_init(&r->upstream->headers_in.headers, r->pool, 8,
+ sizeof(ngx_table_elt_t)) == NGX_ERROR)
+ {
+ ngx_http_upstream_finalize_request(r, u,
+ NGX_HTTP_INTERNAL_SERVER_ERROR);
+ return;
+ }
+
#if 0
if (u->cache) {
u->header_in.pos += u->cache->ctx.header_size;
@@ -631,7 +800,7 @@ ngx_http_upstream_process_header(ngx_event_t *rev)
ngx_add_timer(rev, u->read_timeout);
#endif
- if (u->header_in.last == u->header_in.end) {
+ if (u->header_in.pos == u->header_in.end) {
ngx_log_error(NGX_LOG_ERR, rev->log, 0,
"upstream sent too big header");
@@ -661,6 +830,38 @@ ngx_http_upstream_process_header(ngx_event_t *rev)
/* rc == NGX_OK */
+ if (r->headers_out.status == NGX_HTTP_INTERNAL_SERVER_ERROR) {
+
+ if (u->peer.tries > 1
+ && (u->conf->next_upstream & NGX_HTTP_UPSTREAM_FT_HTTP_500))
+ {
+ ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_HTTP_500);
+ return;
+ }
+
+#if (NGX_HTTP_CACHE)
+
+ if (u->peer.tries == 0
+ && u->stale
+ && (u->conf->use_stale & NGX_HTTP_UPSTREAM_FT_HTTP_500))
+ {
+ ngx_http_upstream_finalize_request(r, u,
+ ngx_http_send_cached_response(r));
+ return;
+ }
+
+#endif
+ }
+
+ if (r->headers_out.status == NGX_HTTP_NOT_FOUND
+ && u->peer.tries > 1
+ && u->conf->next_upstream & NGX_HTTP_UPSTREAM_FT_HTTP_404)
+ {
+ ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_HTTP_404);
+ return;
+ }
+
+
if (r->headers_out.status >= NGX_HTTP_BAD_REQUEST
&& u->conf->redirect_errors
&& r->err_ctx == NULL)
@@ -687,11 +888,55 @@ ngx_http_upstream_process_header(ngx_event_t *rev)
static void
ngx_http_upstream_send_response(ngx_http_request_t *r, ngx_http_upstream_t *u)
{
- ngx_int_t rc;
- ngx_event_pipe_t *p;
- ngx_http_core_loc_conf_t *clcf;
+ ngx_int_t rc;
+ ngx_uint_t i, key;
+ ngx_list_part_t *part;
+ ngx_table_elt_t *h;
+ ngx_event_pipe_t *p;
+ ngx_http_core_loc_conf_t *clcf;
+ ngx_http_upstream_header_t *hh;
+ ngx_http_upstream_main_conf_t *umcf;
+
+ umcf = ngx_http_get_module_main_conf(r, ngx_http_upstream_module);
+ hh = (ngx_http_upstream_header_t *) umcf->headers_in_hash.buckets;
+
+ part = &r->upstream->headers_in.headers.part;
+ h = part->elts;
+
+ for (i = 0; /* void */; i++) {
+
+ if (i >= part->nelts) {
+ if (part->next == NULL) {
+ break;
+ }
+
+ part = part->next;
+ h = part->elts;
+ i = 0;
+ }
+
+ key = h[i].hash % umcf->headers_in_hash.hash_size;
+
+ if (hh[key].name.len == h[i].key.len
+ && ngx_strcasecmp(hh[key].name.data, h[i].key.data) == 0)
+ {
+ if (hh[key].copy_handler(r, &h[i], hh[key].conf) != NGX_OK) {
+ ngx_http_upstream_finalize_request(r, u,
+ NGX_HTTP_INTERNAL_SERVER_ERROR);
+ return;
+ }
- rc = u->send_header(r);
+ continue;
+ }
+
+ if (ngx_http_upstream_copy_header_line(r, &h[i], 0) != NGX_OK) {
+ ngx_http_upstream_finalize_request(r, u,
+ NGX_HTTP_INTERNAL_SERVER_ERROR);
+ return;
+ }
+ }
+
+ rc = ngx_http_send_header(r);
if (rc == NGX_ERROR || rc > NGX_OK) {
ngx_http_upstream_finalize_request(r, u, rc);
@@ -820,20 +1065,27 @@ ngx_http_upstream_send_response(ngx_http_request_t *r, ngx_http_upstream_t *u)
p->send_timeout = clcf->send_timeout;
p->send_lowat = clcf->send_lowat;
- u->peer.connection->read->event_handler = ngx_http_upstream_process_body;
- r->connection->write->event_handler = ngx_http_upstream_process_body;
+ u->peer.connection->read->handler = ngx_http_upstream_process_body;
+ r->write_event_handler = ngx_http_upstream_process_downstream;
ngx_http_upstream_process_body(u->peer.connection->read);
}
static void
+ngx_http_upstream_process_downstream(ngx_http_request_t *r)
+{
+ ngx_http_upstream_process_body(r->connection->write);
+}
+
+
+static void
ngx_http_upstream_process_body(ngx_event_t *ev)
{
+ ngx_event_pipe_t *p;
ngx_connection_t *c;
ngx_http_request_t *r;
ngx_http_upstream_t *u;
- ngx_event_pipe_t *p;
c = ev->data;
r = c->data;
@@ -1046,11 +1298,6 @@ ngx_http_upstream_finalize_request(ngx_http_request_t *r,
rc = 0;
}
- if (u->saved_log_ctx) {
- r->connection->log->data = u->saved_log_ctx;
- r->connection->log->handler = u->saved_log_handler;
- }
-
if (u->pipe.temp_file) {
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"http upstream temp fd: %d",
@@ -1065,15 +1312,7 @@ ngx_http_upstream_finalize_request(ngx_http_request_t *r,
}
#endif
- if (u->pipe.temp_file) {
- r->file.fd = u->pipe.temp_file->file.fd;
-
-#if 0
- } else if (u->cache) {
- r->file.fd = u->cache->ctx.file.fd;
-#endif
- }
-
+ r->log_handler = u->saved_log_handler;
r->connection->log->action = "sending to client";
if (rc == 0 && r->main == NULL) {
@@ -1084,6 +1323,260 @@ ngx_http_upstream_finalize_request(ngx_http_request_t *r,
}
+static ngx_int_t
+ngx_http_upstream_process_header_line(ngx_http_request_t *r, ngx_table_elt_t *h,
+ ngx_uint_t offset)
+{
+ ngx_table_elt_t **ph;
+
+ ph = (ngx_table_elt_t **) ((char *) &r->upstream->headers_in + offset);
+
+ if (*ph == NULL) {
+ *ph = h;
+ }
+
+ return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_http_upstream_process_multi_header_lines(ngx_http_request_t *r,
+ ngx_table_elt_t *h, ngx_uint_t offset)
+{
+ ngx_array_t *pa;
+ ngx_table_elt_t **ph;
+
+ pa = (ngx_array_t *) ((char *) &r->upstream->headers_in + offset);
+
+ if (pa->elts == NULL) {
+ if (ngx_array_init(pa, r->pool, 2, sizeof(ngx_table_elt_t *)) != NGX_OK)
+ {
+ return NGX_ERROR;
+ }
+ }
+
+ ph = ngx_array_push(pa);
+ if (ph == NULL) {
+ return NGX_ERROR;
+ }
+
+ *ph = h;
+
+ return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_http_upstream_ignore_header_line(ngx_http_request_t *r, ngx_table_elt_t *h,
+ ngx_uint_t offset)
+{
+ return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_http_upstream_copy_header_line(ngx_http_request_t *r, ngx_table_elt_t *h,
+ ngx_uint_t offset)
+{
+ ngx_table_elt_t *ho;
+
+ ho = ngx_list_push(&r->headers_out.headers);
+ if (ho == NULL) {
+ return NGX_ERROR;
+ }
+
+ *ho = *h;
+
+ return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_http_upstream_conditional_copy_header_line(ngx_http_request_t *r,
+ ngx_table_elt_t *h, ngx_uint_t offset)
+{
+ ngx_flag_t *f;
+ ngx_table_elt_t *ho;
+
+ f = (ngx_flag_t *) ((char *) r->upstream->conf + offset);
+
+ if (*f == 0) {
+ return NGX_OK;
+ }
+
+ ho = ngx_list_push(&r->headers_out.headers);
+ if (ho == NULL) {
+ return NGX_ERROR;
+ }
+
+ *ho = *h;
+
+ return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_http_upstream_copy_multi_header_lines(ngx_http_request_t *r,
+ ngx_table_elt_t *h, ngx_uint_t offset)
+{
+ ngx_array_t *pa;
+ ngx_table_elt_t *ho, **ph;
+
+ pa = (ngx_array_t *) ((char *) &r->headers_out + offset);
+
+ if (pa->elts == NULL) {
+ if (ngx_array_init(pa, r->pool, 2, sizeof(ngx_table_elt_t *)) != NGX_OK)
+ {
+ return NGX_ERROR;
+ }
+ }
+
+ 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 = ho;
+
+ return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_http_upstream_copy_content_type(ngx_http_request_t *r, ngx_table_elt_t *h,
+ ngx_uint_t offset)
+{
+ r->headers_out.content_type = h->value;
+
+ return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_http_upstream_copy_content_length(ngx_http_request_t *r, ngx_table_elt_t *h,
+ ngx_uint_t offset)
+{
+ ngx_table_elt_t *ho;
+
+ ho = ngx_list_push(&r->headers_out.headers);
+ if (ho == NULL) {
+ return NGX_ERROR;
+ }
+
+ *ho = *h;
+
+ r->headers_out.content_length = ho;
+ r->headers_out.content_length_n = ngx_atoof(h->value.data, h->value.len);
+
+ return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_http_upstream_rewrite_location(ngx_http_request_t *r, ngx_table_elt_t *h,
+ ngx_uint_t offset)
+{
+ ngx_int_t rc;
+ ngx_table_elt_t *ho;
+
+ ho = ngx_list_push(&r->headers_out.headers);
+ if (ho == NULL) {
+ return NGX_ERROR;
+ }
+
+ *ho = *h;
+
+ if (r->upstream->rewrite_redirect) {
+ rc = r->upstream->rewrite_redirect(r, ho, 0);
+
+ if (rc == NGX_OK) {
+ r->headers_out.location = ho;
+
+ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "rewritten location: \"%V\"", &ho->value);
+ }
+
+ return rc;
+ }
+
+ /*
+ * 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()
+ */
+
+ return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_http_upstream_rewrite_refresh(ngx_http_request_t *r, ngx_table_elt_t *h,
+ ngx_uint_t offset)
+{
+ u_char *p;
+ ngx_int_t rc;
+ ngx_table_elt_t *ho;
+
+ ho = ngx_list_push(&r->headers_out.headers);
+ if (ho == NULL) {
+ return NGX_ERROR;
+ }
+
+ *ho = *h;
+
+ if (r->upstream->rewrite_redirect) {
+
+ p = (u_char *) ngx_strstr(ho->value.data, "url=");
+
+ if (p) {
+ rc = r->upstream->rewrite_redirect(r, ho, p + 4 - ho->value.data);
+
+ } else {
+ return NGX_OK;
+ }
+
+#if (NGX_DEBUG)
+ if (rc == NGX_OK) {
+ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "rewritten refresh: \"%V\"", &ho->value);
+ }
+#endif
+
+ return rc;
+ }
+
+ return NGX_OK;
+}
+
+
+#if (NGX_HTTP_GZIP)
+
+static ngx_int_t
+ngx_http_upstream_copy_content_encoding(ngx_http_request_t *r,
+ ngx_table_elt_t *h, ngx_uint_t offset)
+{
+ ngx_table_elt_t *ho;
+
+ ho = ngx_list_push(&r->headers_out.headers);
+ if (ho == NULL) {
+ return NGX_ERROR;
+ }
+
+ *ho = *h;
+
+ r->headers_out.content_encoding = ho;
+
+ return NGX_OK;
+}
+
+#endif
+
+
static size_t
ngx_http_upstream_log_status_getlen(ngx_http_request_t *r, uintptr_t data)
{
@@ -1131,51 +1624,45 @@ ngx_http_upstream_log_status(ngx_http_request_t *r, u_char *buf,
}
-u_char *
-ngx_http_upstream_log_error(ngx_log_t *log, u_char *buf, size_t len)
+static u_char *
+ngx_http_upstream_log_error(ngx_http_request_t *r, u_char *buf, size_t len)
{
u_char *p;
uintptr_t escape;
- ngx_http_log_ctx_t *ctx;
- ngx_http_request_t *r;
ngx_http_upstream_t *u;
ngx_peer_connection_t *peer;
- ctx = log->data;
- r = ctx->request;
u = r->upstream;
peer = &u->peer;
p = ngx_snprintf(buf, len,
- " while %s, client: %V, server: %V, URL: \"%V\","
+ ", server: %V, URL: \"%V\","
" upstream: %V%V%s%V",
- log->action,
- &r->connection->addr_text,
&r->server_name,
&r->unparsed_uri,
- &u->schema0,
+ &u->conf->schema,
&peer->peers->peer[peer->cur_peer].name,
peer->peers->peer[peer->cur_peer].uri_separator,
- &u->uri0);
+ &u->conf->uri);
len -= p - buf;
buf = p;
if (r->quoted_uri) {
- escape = 2 * ngx_escape_uri(NULL, r->uri.data + u->location0->len,
- r->uri.len - u->location0->len,
+ escape = 2 * ngx_escape_uri(NULL, r->uri.data + u->conf->location->len,
+ r->uri.len - u->conf->location->len,
NGX_ESCAPE_URI);
} else {
escape = 0;
}
if (escape) {
- if (len >= r->uri.len - u->location0->len + escape) {
+ if (len >= r->uri.len - u->conf->location->len + escape) {
- ngx_escape_uri(buf, r->uri.data + u->location0->len,
- r->uri.len - u->location0->len, NGX_ESCAPE_URI);
+ ngx_escape_uri(buf, r->uri.data + u->conf->location->len,
+ r->uri.len - u->conf->location->len, NGX_ESCAPE_URI);
- buf += r->uri.len - u->location0->len + escape;
- len -= r->uri.len - u->location0->len + escape;
+ buf += r->uri.len - u->conf->location->len + escape;
+ len -= r->uri.len - u->conf->location->len + escape;
if (r->args.len) {
p = ngx_snprintf(buf, len, "?%V", &r->args);
@@ -1186,19 +1673,19 @@ ngx_http_upstream_log_error(ngx_log_t *log, u_char *buf, size_t len)
return ngx_http_log_error_info(r, buf, len);
}
- p = ngx_palloc(r->pool, r->uri.len - u->location0->len + escape);
+ p = ngx_palloc(r->pool, r->uri.len - u->conf->location->len + escape);
if (p == NULL) {
return buf;
}
- ngx_escape_uri(p, r->uri.data + u->location0->len,
- r->uri.len - u->location0->len, NGX_ESCAPE_URI);
+ ngx_escape_uri(p, r->uri.data + u->conf->location->len,
+ r->uri.len - u->conf->location->len, NGX_ESCAPE_URI);
- p = ngx_cpymem(buf, p, r->uri.len - u->location0->len + escape);
+ p = ngx_cpymem(buf, p, r->uri.len - u->conf->location->len + escape);
} else {
- p = ngx_cpymem(buf, r->uri.data + u->location0->len,
- r->uri.len - u->location0->len);
+ p = ngx_cpymem(buf, r->uri.data + u->conf->location->len,
+ r->uri.len - u->conf->location->len);
}
len -= p - buf;
@@ -1232,3 +1719,43 @@ ngx_http_upstream_add_log_formats(ngx_conf_t *cf)
return NGX_OK;
}
+
+
+static void *
+ngx_http_upstream_create_main_conf(ngx_conf_t *cf)
+{
+ ngx_http_upstream_main_conf_t *umcf;
+
+ umcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_upstream_main_conf_t));
+ if (umcf == NULL) {
+ return NULL;
+ }
+
+ return umcf;
+}
+
+
+static char *
+ngx_http_core_init_main_conf(ngx_conf_t *cf, void *conf)
+{
+ ngx_http_upstream_main_conf_t *umcf = conf;
+
+ umcf->headers_in_hash.max_size = 100;
+ umcf->headers_in_hash.bucket_limit = 1;
+ umcf->headers_in_hash.bucket_size = sizeof(ngx_http_upstream_header_t);
+ umcf->headers_in_hash.name = "upstream_headers_in";
+
+ if (ngx_hash_init(&umcf->headers_in_hash, cf->pool,
+ ngx_http_upstream_headers_in, 0) != NGX_OK)
+ {
+ return NGX_CONF_ERROR;
+ }
+
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, cf->log, 0,
+ "http upstream headers_in hash size: %ui, "
+ "max buckets per entry: %ui",
+ umcf->headers_in_hash.hash_size,
+ umcf->headers_in_hash.min_buckets);
+
+ return NGX_CONF_OK;
+}
diff --git a/src/http/ngx_http_upstream.h b/src/http/ngx_http_upstream.h
index c1bc0d9e7..cf2aeaa0e 100644
--- a/src/http/ngx_http_upstream.h
+++ b/src/http/ngx_http_upstream.h
@@ -29,88 +29,141 @@
typedef struct {
- time_t bl_time;
- ngx_uint_t bl_state;
+ time_t bl_time;
+ ngx_uint_t bl_state;
- ngx_uint_t status;
- time_t time;
+ ngx_uint_t status;
+ time_t time;
- ngx_str_t *peer;
+ ngx_str_t *peer;
} ngx_http_upstream_state_t;
typedef struct {
- ngx_msec_t connect_timeout;
- ngx_msec_t send_timeout;
- ngx_msec_t read_timeout;
+ ngx_hash_t headers_in_hash;
+} ngx_http_upstream_main_conf_t;
- size_t send_lowat;
- size_t header_buffer_size;
- size_t busy_buffers_size;
- size_t max_temp_file_size;
- size_t temp_file_write_size;
- ngx_uint_t next_upstream;
+typedef struct {
+ ngx_msec_t connect_timeout;
+ ngx_msec_t send_timeout;
+ ngx_msec_t read_timeout;
+
+ size_t send_lowat;
+ size_t header_buffer_size;
+ size_t busy_buffers_size;
+ size_t max_temp_file_size;
+ size_t temp_file_write_size;
+
+ ngx_uint_t next_upstream;
+ ngx_uint_t method;
+
+ ngx_bufs_t bufs;
+
+ ngx_flag_t pass_request_headers;
+ ngx_flag_t pass_request_body;
- ngx_bufs_t bufs;
+ ngx_flag_t redirect_errors;
+ ngx_flag_t pass_unparsed_uri;
+ ngx_flag_t cyclic_temp_file;
- ngx_flag_t redirect_errors;
- ngx_flag_t pass_unparsed_uri;
- ngx_flag_t x_powered_by;
- ngx_flag_t cyclic_temp_file;
+ ngx_flag_t pass_x_powered_by;
+ ngx_flag_t pass_server;
+ ngx_flag_t pass_date;
+ ngx_flag_t pass_x_accel_expires;
- ngx_path_t *temp_path;
+ ngx_path_t *temp_path;
+
+ ngx_str_t schema;
+ ngx_str_t uri;
+ ngx_str_t *location;
+ ngx_str_t url; /* used in proxy_rewrite_location */
} ngx_http_upstream_conf_t;
-typedef struct ngx_http_upstream_s ngx_http_upstream_t;
+typedef struct {
+ ngx_str_t name;
+ ngx_http_header_handler_pt handler;
+ ngx_uint_t offset;
+ ngx_http_header_handler_pt copy_handler;
+ ngx_uint_t conf;
+} ngx_http_upstream_header_t;
+
+
+typedef struct {
+ ngx_list_t headers;
+
+ ngx_table_elt_t *status;
+ ngx_table_elt_t *date;
+ ngx_table_elt_t *server;
+ ngx_table_elt_t *connection;
+
+ ngx_table_elt_t *expires;
+ ngx_table_elt_t *etag;
+ ngx_table_elt_t *x_accel_expires;
+
+ ngx_table_elt_t *content_type;
+ ngx_table_elt_t *content_length;
+
+ ngx_table_elt_t *last_modified;
+ ngx_table_elt_t *location;
+ ngx_table_elt_t *accept_ranges;
+
+#if (NGX_HTTP_GZIP)
+ ngx_table_elt_t *content_encoding;
+#endif
+
+ ngx_array_t cache_control;
+} ngx_http_upstream_headers_in_t;
+
struct ngx_http_upstream_s {
- ngx_http_request_t *request;
+ ngx_http_request_t *request;
+
+ ngx_peer_connection_t peer;
- ngx_peer_connection_t peer;
+ ngx_event_pipe_t pipe;
- ngx_event_pipe_t pipe;
+ ngx_chain_t *request_bufs;
- ngx_output_chain_ctx_t output;
- ngx_chain_writer_ctx_t writer;
+ ngx_output_chain_ctx_t output;
+ ngx_chain_writer_ctx_t writer;
- ngx_http_upstream_conf_t *conf;
+ ngx_http_upstream_conf_t *conf;
- ngx_buf_t header_in;
+ ngx_http_upstream_headers_in_t headers_in;
- ngx_int_t (*create_request)(ngx_http_request_t *r);
- ngx_int_t (*reinit_request)(ngx_http_request_t *r);
- ngx_int_t (*process_header)(ngx_http_request_t *r);
- ngx_int_t (*send_header)(ngx_http_request_t *r);
- void (*abort_request)(ngx_http_request_t *r);
- void (*finalize_request)(ngx_http_request_t *r,
- ngx_int_t rc);
- ngx_uint_t method;
+ ngx_buf_t header_in;
- ngx_str_t schema0;
- ngx_str_t uri0;
- ngx_str_t *location0;
+ ngx_int_t (*create_request)(ngx_http_request_t *r);
+ ngx_int_t (*reinit_request)(ngx_http_request_t *r);
+ ngx_int_t (*process_header)(ngx_http_request_t *r);
+ void (*abort_request)(ngx_http_request_t *r);
+ void (*finalize_request)(ngx_http_request_t *r,
+ ngx_int_t rc);
+ ngx_int_t (*rewrite_redirect)(ngx_http_request_t *r,
+ ngx_table_elt_t *h, size_t prefix);
- ngx_http_log_ctx_t *log_ctx;
- ngx_log_handler_pt log_handler;
- ngx_http_log_ctx_t *saved_log_ctx;
- ngx_log_handler_pt saved_log_handler;
+ ngx_uint_t method;
- ngx_http_upstream_state_t *state;
- ngx_array_t states; /* of ngx_http_upstream_state_t */
+ ngx_http_log_handler_pt saved_log_handler;
- unsigned cachable:1;
+ ngx_http_upstream_state_t *state;
+ ngx_array_t states; /* of ngx_http_upstream_state_t */
- unsigned request_sent:1;
- unsigned header_sent:1;
+ unsigned cachable:1;
+ unsigned accel:1;
+
+ unsigned request_sent:1;
+ unsigned header_sent:1;
};
void ngx_http_upstream_init(ngx_http_request_t *r);
-u_char *ngx_http_upstream_log_error(ngx_log_t *log, u_char *buf, size_t len);
+extern ngx_module_t ngx_http_upstream_module;
+
extern char *ngx_http_upstream_header_errors[];
diff --git a/src/http/ngx_http_variables.c b/src/http/ngx_http_variables.c
index 154ee1352..488efcc05 100644
--- a/src/http/ngx_http_variables.c
+++ b/src/http/ngx_http_variables.c
@@ -10,66 +10,157 @@
#include <ngx_http.h>
-#define NGX_HTTP_VARS_HASH_PRIME 29
-
-#define ngx_http_vars_hash_key(key, vn) \
- { \
- ngx_uint_t n; \
- for (key = 0, n = 0; n < (vn)->len; n++) { \
- key += (vn)->data[n]; \
- } \
- key %= NGX_HTTP_VARS_HASH_PRIME; \
- }
-
-
+static ngx_http_variable_value_t *
+ ngx_http_variable_request(ngx_http_request_t *r, uintptr_t data);
static ngx_http_variable_value_t *
ngx_http_variable_header(ngx_http_request_t *r, uintptr_t data);
static ngx_http_variable_value_t *
ngx_http_variable_unknown_header(ngx_http_request_t *r, uintptr_t data);
static ngx_http_variable_value_t *
+ ngx_http_variable_host(ngx_http_request_t *r, uintptr_t data);
+static ngx_http_variable_value_t *
ngx_http_variable_remote_addr(ngx_http_request_t *r, uintptr_t data);
static ngx_http_variable_value_t *
- ngx_http_variable_uri(ngx_http_request_t *r, uintptr_t data);
+ ngx_http_variable_remote_port(ngx_http_request_t *r, uintptr_t data);
static ngx_http_variable_value_t *
- ngx_http_variable_query_string(ngx_http_request_t *r, uintptr_t data);
-
+ ngx_http_variable_server_addr(ngx_http_request_t *r, uintptr_t data);
+static ngx_http_variable_value_t *
+ ngx_http_variable_server_port(ngx_http_request_t *r, uintptr_t data);
+static ngx_http_variable_value_t *
+ ngx_http_variable_document_root(ngx_http_request_t *r, uintptr_t data);
+static ngx_http_variable_value_t *
+ ngx_http_variable_request_filename(ngx_http_request_t *r, uintptr_t data);
-static ngx_array_t *ngx_http_core_variables_hash;
+/*
+ * TODO:
+ * Apache CGI: AUTH_TYPE, PATH_INFO (null), PATH_TRANSLATED
+ * REMOTE_HOST (null), REMOTE_IDENT (null),
+ * SERVER_SOFTWARE
+ *
+ * Apache SSI: DATE_GMT, DOCUMENT_NAME, LAST_MODIFIED,
+ * USER_NAME (file owner)
+ */
-static ngx_http_core_variable_t ngx_http_core_variables[] = {
+static ngx_http_variable_t ngx_http_core_variables[] = {
- { ngx_string("HTTP_HOST"), ngx_http_variable_header,
- offsetof(ngx_http_headers_in_t, host) },
+ { ngx_string("http_host"), ngx_http_variable_header,
+ offsetof(ngx_http_request_t, headers_in.host), 0 },
- { ngx_string("HTTP_USER_AGENT"), ngx_http_variable_header,
- offsetof(ngx_http_headers_in_t, user_agent) },
+ { ngx_string("http_user_agent"), ngx_http_variable_header,
+ offsetof(ngx_http_request_t, headers_in.user_agent), 0 },
- { ngx_string("HTTP_REFERER"), ngx_http_variable_header,
- offsetof(ngx_http_headers_in_t, referer) },
+ { ngx_string("http_referer"), ngx_http_variable_header,
+ offsetof(ngx_http_request_t, headers_in.referer), 0 },
#if (NGX_HTTP_GZIP)
- { ngx_string("HTTP_VIA"), ngx_http_variable_header,
- offsetof(ngx_http_headers_in_t, via) },
+ { ngx_string("http_via"), ngx_http_variable_header,
+ offsetof(ngx_http_request_t, headers_in.via), 0 },
#endif
#if (NGX_HTTP_PROXY)
- { ngx_string("HTTP_X_FORWARDED_FOR"), ngx_http_variable_header,
- offsetof(ngx_http_headers_in_t, x_forwarded_for) },
+ { ngx_string("http_x_forwarded_for"), ngx_http_variable_header,
+ offsetof(ngx_http_request_t, headers_in.x_forwarded_for), 0 },
#endif
- { ngx_string("REMOTE_ADDR"), ngx_http_variable_remote_addr, 0 },
+ { ngx_string("content_length"), ngx_http_variable_header,
+ offsetof(ngx_http_request_t, headers_in.content_length), 0 },
+
+ { ngx_string("content_type"), ngx_http_variable_header,
+ offsetof(ngx_http_request_t, headers_in.content_type), 0 },
+
+ { ngx_string("host"), ngx_http_variable_host, 0, 0 },
+
+ { ngx_string("remote_addr"), ngx_http_variable_remote_addr, 0, 0 },
- { ngx_string("DOCUMENT_URI"), ngx_http_variable_uri, 0 },
+ { ngx_string("remote_port"), ngx_http_variable_remote_port, 0, 0 },
- { ngx_string("QUERY_STRING"), ngx_http_variable_query_string, 0 },
+ { ngx_string("server_addr"), ngx_http_variable_server_addr, 0, 0 },
- { ngx_null_string, NULL, 0 }
+ { ngx_string("server_port"), ngx_http_variable_server_port, 0, 0 },
+
+ { ngx_string("server_protocol"), ngx_http_variable_request,
+ offsetof(ngx_http_request_t, http_protocol), 0 },
+
+ { ngx_string("request_uri"), ngx_http_variable_request,
+ offsetof(ngx_http_request_t, unparsed_uri), 0 },
+
+ { ngx_string("document_uri"), ngx_http_variable_request,
+ offsetof(ngx_http_request_t, uri), 0 },
+
+ { ngx_string("document_root"), ngx_http_variable_document_root, 0, 0 },
+
+ { ngx_string("query_string"), ngx_http_variable_request,
+ offsetof(ngx_http_request_t, args),
+ NGX_HTTP_VAR_NOCACHABLE },
+
+ { ngx_string("request_filename"), ngx_http_variable_request_filename, 0,
+ NGX_HTTP_VAR_NOCACHABLE },
+
+ { ngx_string("server_name"), ngx_http_variable_request,
+ offsetof(ngx_http_request_t, server_name), 0 },
+
+ { ngx_string("request_method"), ngx_http_variable_request,
+ offsetof(ngx_http_request_t, method_name), 0 },
+
+ { ngx_string("remote_user"), ngx_http_variable_request,
+ offsetof(ngx_http_request_t, headers_in.user), 0 },
+
+ { ngx_null_string, NULL, 0, 0 }
};
ngx_http_variable_t *
-ngx_http_add_variable(ngx_conf_t *cf, ngx_str_t *name, ngx_uint_t set)
+ngx_http_add_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->all_variables.elts;
+ for (i = 0; i < cmcf->all_variables.nelts; i++) {
+ if (name->len != v[i].name.len
+ || ngx_strncasecmp(name->data, v[i].name.data, name->len) != 0)
+ {
+ continue;
+ }
+
+ if (!(v[i].flags & NGX_HTTP_VAR_CHANGABLE)) {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "the duplicate \"%V\" variable", name);
+ return NULL;
+ }
+
+ return &v[i];
+ }
+
+ v = ngx_array_push(&cmcf->all_variables);
+ if (v == NULL) {
+ return NULL;
+ }
+
+ v->name.len = name->len;
+ v->name.data = ngx_palloc(cf->pool, name->len);
+ if (v->name.data == NULL) {
+ return NULL;
+ }
+
+ for (i = 0; i < name->len; i++) {
+ v->name.data[i] = ngx_tolower(name->data[i]);
+ }
+
+ v->handler = NULL;
+ v->data = 0;
+ v->flags = flags;
+
+ return v;
+}
+
+
+ngx_int_t
+ngx_http_get_variable_index(ngx_conf_t *cf, ngx_str_t *name)
{
ngx_uint_t i;
ngx_http_variable_t *v;
@@ -83,7 +174,7 @@ ngx_http_add_variable(ngx_conf_t *cf, ngx_str_t *name, ngx_uint_t set)
if (ngx_array_init(&cmcf->variables, cf->pool, 4,
sizeof(ngx_http_variable_t)) == NGX_ERROR)
{
- return NULL;
+ return NGX_ERROR;
}
} else {
@@ -94,36 +185,30 @@ ngx_http_add_variable(ngx_conf_t *cf, ngx_str_t *name, ngx_uint_t set)
continue;
}
- if (set && v[i].handler) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "the duplicate \"%V\" variable", name);
- return NULL;
- }
-
- return &v[i];
+ return i;
}
}
v = ngx_array_push(&cmcf->variables);
if (v == NULL) {
- return NULL;
+ return NGX_ERROR;
}
v->name.len = name->len;
v->name.data = ngx_palloc(cf->pool, name->len);
if (v->name.data == NULL) {
- return NULL;
+ return NGX_ERROR;
}
for (i = 0; i < name->len; i++) {
- v->name.data[i] = ngx_toupper(name->data[i]);
+ v->name.data[i] = ngx_tolower(name->data[i]);
}
- v->index = cmcf->variables.nelts - 1;
v->handler = NULL;
v->data = 0;
+ v->flags = 0;
- return v;
+ return cmcf->variables.nelts - 1;
}
@@ -158,7 +243,9 @@ ngx_http_get_indexed_variable(ngx_http_request_t *r, ngx_uint_t index)
}
}
- r->variables[index] = vv;
+ if (!(v[index].flags & NGX_HTTP_VAR_NOCACHABLE)) {
+ r->variables[index] = vv;
+ }
return vv;
}
@@ -169,43 +256,56 @@ ngx_http_get_variable(ngx_http_request_t *r, ngx_str_t *name)
{
ngx_uint_t i, key;
ngx_http_variable_t *v;
- ngx_http_core_variable_t *cv;
ngx_http_core_main_conf_t *cmcf;
cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
- v = cmcf->variables.elts;
- for (i = 0; i < cmcf->variables.nelts; i++) {
- if (v[i].name.len != name->len) {
- continue;
- }
-
- if (ngx_strncmp(v[i].name.data, name->data, name->len) == 0) {
- return ngx_http_get_indexed_variable(r, v[i].index);
- }
+ key = 0;
+ for (i = 0; i < name->len; i++) {
+ key += name->data[i];
}
- ngx_http_vars_hash_key(key, name);
+ key %= cmcf->variables_hash.hash_size;
+ v = (ngx_http_variable_t *) cmcf->variables_hash.buckets;
- cv = ngx_http_core_variables_hash[key].elts;
- for (i = 0; i < ngx_http_core_variables_hash[key].nelts; i++) {
- if (cv[i].name.len != name->len) {
- continue;
- }
-
- if (ngx_strncmp(cv[i].name.data, name->data, name->len) == 0) {
- return cv[i].handler(r, cv[i].data);
- }
+ if (v[key].name.len == name->len
+ && ngx_strncmp(v[key].name.data, name->data, name->len) == 0)
+ {
+ return v[key].handler(r, v[key].data);
}
- if (ngx_strncmp(name->data, "HTTP_", 5) == 0) {
+ if (ngx_strncmp(name->data, "http_", 5) == 0) {
return ngx_http_variable_unknown_header(r, (uintptr_t) name);
}
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
"unknown \"%V\" variable", name);
- return NGX_HTTP_VARIABLE_NOT_FOUND;
+ return NGX_HTTP_VAR_NOT_FOUND;
+}
+
+
+static ngx_http_variable_value_t *
+ngx_http_variable_request(ngx_http_request_t *r, uintptr_t data)
+{
+ ngx_str_t *s;
+ ngx_http_variable_value_t *vv;
+
+ s = (ngx_str_t *) ((char *) r + data);
+
+ if (s->data == NULL) {
+ return NGX_HTTP_VAR_NOT_FOUND;
+ }
+
+ vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t));
+ if (vv == NULL) {
+ return NULL;
+ }
+
+ vv->value = 0;
+ vv->text = *s;
+
+ return vv;
}
@@ -215,10 +315,10 @@ ngx_http_variable_header(ngx_http_request_t *r, uintptr_t data)
ngx_table_elt_t *h;
ngx_http_variable_value_t *vv;
- h = *(ngx_table_elt_t **) ((char *) &r->headers_in + data);
+ h = *(ngx_table_elt_t **) ((char *) r + data);
if (h == NULL) {
- return NGX_HTTP_VARIABLE_NOT_FOUND;
+ return NGX_HTTP_VAR_NOT_FOUND;
}
vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t));
@@ -259,12 +359,11 @@ ngx_http_variable_unknown_header(ngx_http_request_t *r, uintptr_t data)
i = 0;
}
- for (n = 0; n + 5 < var->len && n < header[i].key.len; n++)
- {
+ for (n = 0; n + 5 < var->len && n < header[i].key.len; n++) {
ch = header[i].key.data[n];
- if (ch >= 'a' && ch <= 'z') {
- ch &= ~0x20;
+ if (ch >= 'A' && ch <= 'Z') {
+ ch |= 0x20;
} else if (ch == '-') {
ch = '_';
@@ -287,7 +386,31 @@ ngx_http_variable_unknown_header(ngx_http_request_t *r, uintptr_t data)
}
}
- return NGX_HTTP_VARIABLE_NOT_FOUND;
+ return NGX_HTTP_VAR_NOT_FOUND;
+}
+
+
+static ngx_http_variable_value_t *
+ngx_http_variable_host(ngx_http_request_t *r, uintptr_t data)
+{
+ ngx_http_variable_value_t *vv;
+
+ vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t));
+ if (vv == NULL) {
+ return NULL;
+ }
+
+ vv->value = 0;
+
+ if (r->headers_in.host) {
+ vv->text.len = r->headers_in.host_name_len;
+ vv->text.data = r->headers_in.host->value.data;
+
+ } else {
+ vv->text = r->server_name;
+ }
+
+ return vv;
}
@@ -309,8 +432,10 @@ ngx_http_variable_remote_addr(ngx_http_request_t *r, uintptr_t data)
static ngx_http_variable_value_t *
-ngx_http_variable_uri(ngx_http_request_t *r, uintptr_t data)
+ngx_http_variable_remote_port(ngx_http_request_t *r, uintptr_t data)
{
+ ngx_uint_t port;
+ struct sockaddr_in *sin;
ngx_http_variable_value_t *vv;
vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t));
@@ -319,14 +444,73 @@ ngx_http_variable_uri(ngx_http_request_t *r, uintptr_t data)
}
vv->value = 0;
- vv->text = r->uri;
+ vv->text.len = 0;
+
+ vv->text.data = ngx_palloc(r->pool, sizeof("65535") - 1);
+ if (vv->text.data == NULL) {
+ return NULL;
+ }
+
+ /* AF_INET only */
+
+ if (r->connection->sockaddr->sa_family == AF_INET) {
+ sin = (struct sockaddr_in *) r->connection->sockaddr;
+
+ port = ntohs(sin->sin_port);
+
+ if (port > 0 && port < 65536) {
+ vv->value = port;
+ vv->text.len = ngx_sprintf(vv->text.data, "%ui", port)
+ - vv->text.data;
+ }
+ }
+
+ return vv;
+}
+
+
+static ngx_http_variable_value_t *
+ngx_http_variable_server_addr(ngx_http_request_t *r, uintptr_t data)
+{
+ socklen_t len;
+ ngx_connection_t *c;
+ struct sockaddr_in sin;
+ ngx_http_variable_value_t *vv;
+
+ vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t));
+ if (vv == NULL) {
+ return NULL;
+ }
+
+ vv->value = 0;
+
+ vv->text.data = ngx_palloc(r->pool, INET_ADDRSTRLEN);
+ if (vv->text.data == NULL) {
+ return NULL;
+ }
+
+ c = r->connection;
+
+ if (r->in_addr == 0) {
+ len = sizeof(struct sockaddr_in);
+ if (getsockname(c->fd, (struct sockaddr *) &sin, &len) == -1) {
+ ngx_log_error(NGX_LOG_CRIT, c->log,
+ ngx_socket_errno, "getsockname() failed");
+ return NULL;
+ }
+
+ r->in_addr = sin.sin_addr.s_addr;
+ }
+
+ vv->text.len = ngx_inet_ntop(c->listening->family, &r->in_addr,
+ vv->text.data, INET_ADDRSTRLEN);
return vv;
}
static ngx_http_variable_value_t *
-ngx_http_variable_query_string(ngx_http_request_t *r, uintptr_t data)
+ngx_http_variable_server_port(ngx_http_request_t *r, uintptr_t data)
{
ngx_http_variable_value_t *vv;
@@ -335,85 +519,171 @@ ngx_http_variable_query_string(ngx_http_request_t *r, uintptr_t data)
return NULL;
}
+ vv->value = r->port;
+ vv->text.len = r->port_text->len - 1;
+ vv->text.data = r->port_text->data + 1;
+
+ return vv;
+}
+
+
+static ngx_http_variable_value_t *
+ngx_http_variable_document_root(ngx_http_request_t *r, uintptr_t data)
+{
+ ngx_http_core_loc_conf_t *clcf;
+ ngx_http_variable_value_t *vv;
+
+ vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t));
+ if (vv == NULL) {
+ return NULL;
+ }
+
+ clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
+
vv->value = 0;
- vv->text = r->args;
+ vv->text = clcf->root;
+
+ return vv;
+}
+
+
+static ngx_http_variable_value_t *
+ngx_http_variable_request_filename(ngx_http_request_t *r, uintptr_t data)
+{
+ u_char *p;
+ ngx_http_core_loc_conf_t *clcf;
+ ngx_http_variable_value_t *vv;
+
+ vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t));
+ if (vv == NULL) {
+ return NULL;
+ }
+
+ vv->value = 0;
+
+ clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
+
+ if (!clcf->alias) {
+ vv->text.len = clcf->root.len + r->uri.len;
+ vv->text.data = ngx_palloc(r->pool, vv->text.len);
+ if (vv->text.data == NULL) {
+ return NULL;
+ }
+
+ p = ngx_cpymem(vv->text.data, clcf->root.data, clcf->root.len);
+ ngx_memcpy(p, r->uri.data, r->uri.len + 1);
+
+ } else {
+ vv->text.len = clcf->root.len + r->uri.len + 2 - clcf->name.len;
+ vv->text.data = ngx_palloc(r->pool, vv->text.len);
+ if (vv->text.data == NULL) {
+ return NULL;
+ }
+
+ p = ngx_cpymem(vv->text.data, clcf->root.data, clcf->root.len);
+ ngx_memcpy(p, r->uri.data + clcf->name.len,
+ r->uri.len + 1 - clcf->name.len);
+ }
return vv;
}
ngx_int_t
-ngx_http_variables_init(ngx_cycle_t *cycle)
+ngx_http_variables_add_core_vars(ngx_conf_t *cf)
{
- ngx_uint_t i, j, key;
- ngx_http_variable_t *v;
- ngx_http_core_variable_t *cv, *vp;
+ ngx_http_variable_t *v, *cv;
ngx_http_core_main_conf_t *cmcf;
- ngx_http_core_variables_hash = ngx_palloc(cycle->pool,
- NGX_HTTP_VARS_HASH_PRIME
- * sizeof(ngx_array_t));
- if (ngx_http_core_variables_hash == NULL) {
+ cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
+
+ if (ngx_array_init(&cmcf->all_variables, cf->pool, 32,
+ sizeof(ngx_http_variable_t)) == NGX_ERROR)
+ {
return NGX_ERROR;
}
- for (i = 0; i < NGX_HTTP_VARS_HASH_PRIME; i++) {
- if (ngx_array_init(&ngx_http_core_variables_hash[i], cycle->pool, 4,
- sizeof(ngx_http_core_variable_t)) == NGX_ERROR)
- {
+ for (cv = ngx_http_core_variables; cv->name.len; cv++) {
+ v = ngx_array_push(&cmcf->all_variables);
+ if (v == NULL) {
return NGX_ERROR;
}
+
+ *v = *cv;
}
- for (cv = ngx_http_core_variables; cv->name.len; cv++) {
- ngx_http_vars_hash_key(key, &cv->name);
+ return NGX_OK;
+}
- vp = ngx_array_push(&ngx_http_core_variables_hash[key]);
- if (vp == NULL) {
- return NGX_ERROR;
- }
- *vp = *cv;
- }
+ngx_int_t
+ngx_http_variables_init_vars(ngx_conf_t *cf)
+{
+ ngx_uint_t i, n;
+ ngx_http_variable_t *v, *av;
+ ngx_http_core_main_conf_t *cmcf;
+ /* set the handlers for the indexed http variables */
- cmcf = ngx_http_cycle_get_module_main_conf(cycle, ngx_http_core_module);
+ cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
v = cmcf->variables.elts;
- for (i = 0; i < cmcf->variables.nelts; i++) {
+ av = cmcf->all_variables.elts;
- if (v[i].handler) {
- continue;
- }
-
- ngx_http_vars_hash_key(key, &v[i].name);
+ for (i = 0; i < cmcf->variables.nelts; i++) {
- cv = ngx_http_core_variables_hash[key].elts;
- for (j = 0; j < ngx_http_core_variables_hash[key].nelts; j++) {
- if (cv[j].name.len != v[i].name.len) {
- continue;
- }
+ for (n = 0; n < cmcf->all_variables.nelts; n++) {
- if (ngx_strncmp(cv[j].name.data, v[i].name.data, v[i].name.len)
- == 0)
+ if (v[i].name.len == av[n].name.len
+ && ngx_strncmp(v[i].name.data, av[n].name.data, v[i].name.len)
+ == 0)
{
- v[i].handler = cv[j].handler;
- v[i].data = cv[j].data;
- continue;
+ v[i].handler = av[n].handler;
+ v[i].data = av[n].data;
+ v[i].flags = av[n].flags;
+
+ goto next;
}
}
- if (ngx_strncmp(v[i].name.data, "HTTP_", 5) == 0) {
+ if (ngx_strncmp(v[i].name.data, "http_", 5) == 0) {
v[i].handler = ngx_http_variable_unknown_header;
v[i].data = (uintptr_t) &v[i].name;
+
continue;
}
- ngx_log_error(NGX_LOG_ERR, cycle->log, 0,
+ ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
"unknown \"%V\" variable", &v[i].name);
return NGX_ERROR;
+
+ next:
+ continue;
+ }
+
+ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, cf->log, 0,
+ "http variables: %ui", cmcf->variables.nelts);
+
+
+ /* init the all http variables hash */
+
+ cmcf->variables_hash.max_size = 500;
+ cmcf->variables_hash.bucket_limit = 1;
+ cmcf->variables_hash.bucket_size = sizeof(ngx_http_variable_t);
+ cmcf->variables_hash.name = "http variables";
+
+ if (ngx_hash_init(&cmcf->variables_hash, cf->pool,
+ cmcf->all_variables.elts, cmcf->all_variables.nelts) != NGX_OK)
+ {
+ return NGX_ERROR;
}
+ ngx_log_debug3(NGX_LOG_DEBUG_HTTP, cf->log, 0,
+ "http variables hash size: %ui for %ui values, "
+ "max buckets per entry: %ui",
+ cmcf->variables_hash.hash_size, cmcf->all_variables.nelts,
+ cmcf->variables_hash.min_buckets);
+
return NGX_OK;
}
diff --git a/src/http/ngx_http_variables.h b/src/http/ngx_http_variables.h
index bf80386cb..6624535aa 100644
--- a/src/http/ngx_http_variables.h
+++ b/src/http/ngx_http_variables.h
@@ -14,13 +14,13 @@
#include <ngx_http.h>
-#define NGX_HTTP_VARIABLE_NOT_FOUND (ngx_http_variable_value_t *) -1
+#define NGX_HTTP_VAR_NOT_FOUND (ngx_http_variable_value_t *) -1
-struct ngx_http_variable_value_s {
+typedef struct {
ngx_uint_t value;
ngx_str_t text;
-};
+} ngx_http_variable_value_t;
typedef struct ngx_http_variable_s ngx_http_variable_t;
@@ -28,30 +28,28 @@ typedef ngx_http_variable_value_t *
(*ngx_http_get_variable_pt) (ngx_http_request_t *r, uintptr_t data);
-struct ngx_http_variable_s {
- ngx_str_t name;
- ngx_uint_t index;
- ngx_http_get_variable_pt handler;
- uintptr_t data;
-};
+#define NGX_HTTP_VAR_CHANGABLE 1
+#define NGX_HTTP_VAR_NOCACHABLE 2
-typedef struct {
- ngx_str_t name;
+struct ngx_http_variable_s {
+ ngx_str_t name; /* must be first to build the hash */
ngx_http_get_variable_pt handler;
uintptr_t data;
-} ngx_http_core_variable_t;
+ ngx_uint_t flags;
+};
ngx_http_variable_t *ngx_http_add_variable(ngx_conf_t *cf, ngx_str_t *name,
- ngx_uint_t set);
-ngx_int_t ngx_http_get_variable_index(ngx_http_core_main_conf_t *cmcf,
- ngx_str_t *name);
+ ngx_uint_t flags);
+ngx_int_t ngx_http_get_variable_index(ngx_conf_t *cf, ngx_str_t *name);
ngx_http_variable_value_t *ngx_http_get_indexed_variable(ngx_http_request_t *r,
ngx_uint_t index);
ngx_http_variable_value_t *ngx_http_get_variable(ngx_http_request_t *r,
ngx_str_t *name);
-ngx_int_t ngx_http_variables_init(ngx_cycle_t *cycle);
+
+ngx_int_t ngx_http_variables_add_core_vars(ngx_conf_t *cf);
+ngx_int_t ngx_http_variables_init_vars(ngx_conf_t *cf);
#endif /* _NGX_HTTP_VARIABLES_H_INCLUDED_ */
diff --git a/src/http/ngx_http_write_filter_module.c b/src/http/ngx_http_write_filter_module.c
index a9526972b..e0f382847 100644
--- a/src/http/ngx_http_write_filter_module.c
+++ b/src/http/ngx_http_write_filter_module.c
@@ -10,16 +10,12 @@
#include <ngx_http.h>
-typedef struct {
- ngx_chain_t *out;
-} ngx_http_write_filter_ctx_t;
-
-
static ngx_int_t ngx_http_write_filter_init(ngx_cycle_t *cycle);
ngx_http_module_t ngx_http_write_filter_module_ctx = {
- NULL, /* pre conf */
+ NULL, /* preconfiguration */
+ NULL, /* postconfiguration */
NULL, /* create main configuration */
NULL, /* init main configuration */
@@ -33,7 +29,7 @@ ngx_http_module_t ngx_http_write_filter_module_ctx = {
ngx_module_t ngx_http_write_filter_module = {
- NGX_MODULE,
+ NGX_MODULE_V1,
&ngx_http_write_filter_module_ctx, /* module context */
NULL, /* module directives */
NGX_HTTP_MODULE, /* module type */
@@ -45,34 +41,20 @@ ngx_module_t ngx_http_write_filter_module = {
ngx_int_t
ngx_http_write_filter(ngx_http_request_t *r, ngx_chain_t *in)
{
- off_t size, sent;
- ngx_uint_t last, flush;
- ngx_chain_t *cl, *ln, **ll, *chain;
- ngx_connection_t *c;
- ngx_http_core_loc_conf_t *clcf;
- ngx_http_write_filter_ctx_t *ctx;
-
- ctx = ngx_http_get_module_ctx(r->main ? r->main : r,
- ngx_http_write_filter_module);
-
- if (ctx == NULL) {
-
- ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_write_filter_ctx_t));
- if (ctx == NULL) {
- return NGX_ERROR;
- }
-
- ngx_http_set_ctx(r, ctx, ngx_http_write_filter_module);
- }
+ off_t size, sent;
+ ngx_uint_t last, flush;
+ ngx_chain_t *cl, *ln, **ll, *chain;
+ ngx_connection_t *c;
+ ngx_http_core_loc_conf_t *clcf;
size = 0;
flush = 0;
last = 0;
- ll = &ctx->out;
+ ll = &r->out;
/* find the size, the flush point and the last link of the saved chain */
- for (cl = ctx->out; cl; cl = cl->next) {
+ for (cl = r->out; cl; cl = cl->next) {
ll = &cl->next;
ngx_log_debug7(NGX_LOG_DEBUG_EVENT, r->connection->log, 0,
@@ -174,11 +156,10 @@ ngx_http_write_filter(ngx_http_request_t *r, ngx_chain_t *in)
ngx_log_debug3(NGX_LOG_DEBUG_HTTP, c->log, 0,
"http write filter: l:%d f:%d s:%O", last, flush, size);
- clcf = ngx_http_get_module_loc_conf(r->main ? r->main : r,
- ngx_http_core_module);
+ clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
/*
- * avoid the output if there is no last buf, no flush point,
+ * avoid the output if there are no last buf, no flush point,
* there are the incoming bufs and the size of all bufs
* is smaller than "postpone_output" directive
*/
@@ -187,20 +168,30 @@ ngx_http_write_filter(ngx_http_request_t *r, ngx_chain_t *in)
return NGX_OK;
}
+ /*
+ * avoid the output if there are no incoming bufs but there are
+ * the postponed requests or data
+ */
+
+ if (in == NULL && r->postponed) {
+ return NGX_OK;
+ }
+
if (c->write->delayed) {
return NGX_AGAIN;
}
if (size == 0 && !c->buffered) {
if (last) {
+ r->out = NULL;
return NGX_OK;
}
if (flush) {
do {
- ctx->out = ctx->out->next;
+ r->out = r->out->next;
}
- while (ctx->out);
+ while (r->out);
return NGX_OK;
}
@@ -215,7 +206,7 @@ ngx_http_write_filter(ngx_http_request_t *r, ngx_chain_t *in)
sent = c->sent;
- chain = c->send_chain(c, ctx->out, clcf->limit_rate);
+ chain = c->send_chain(c, r->out, clcf->limit_rate);
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
"http write filter %p", chain);
@@ -231,13 +222,13 @@ ngx_http_write_filter(ngx_http_request_t *r, ngx_chain_t *in)
return NGX_ERROR;
}
- for (cl = ctx->out; cl && cl != chain; /* void */) {
+ for (cl = r->out; cl && cl != chain; /* void */) {
ln = cl;
cl = cl->next;
ngx_free_chain(r->pool, ln);
}
- ctx->out = chain;
+ r->out = chain;
if (chain || (last && c->buffered)) {
return NGX_AGAIN;
diff --git a/src/imap/ngx_imap.c b/src/imap/ngx_imap.c
index 7c1a42f8c..9fc5e2441 100644
--- a/src/imap/ngx_imap.c
+++ b/src/imap/ngx_imap.c
@@ -34,7 +34,7 @@ static ngx_core_module_t ngx_imap_module_ctx = {
ngx_module_t ngx_imap_module = {
- NGX_MODULE,
+ NGX_MODULE_V1,
&ngx_imap_module_ctx, /* module context */
ngx_imap_commands, /* module directives */
NGX_CORE_MODULE, /* module type */
diff --git a/src/imap/ngx_imap_handler.c b/src/imap/ngx_imap_handler.c
index 371d77f8e..f65db81f3 100644
--- a/src/imap/ngx_imap_handler.c
+++ b/src/imap/ngx_imap_handler.c
@@ -47,7 +47,7 @@ void ngx_imap_init_connection(ngx_connection_t *c)
return;
}
- c->read->event_handler = ngx_imap_init_session;
+ c->read->handler = ngx_imap_init_session;
ngx_add_timer(c->read, /* STUB */ 60000);
@@ -93,7 +93,7 @@ static void ngx_imap_init_session(ngx_event_t *rev)
return;
}
- c->read->event_handler = ngx_pop3_auth_state;
+ c->read->handler = ngx_pop3_auth_state;
ngx_pop3_auth_state(rev);
}
diff --git a/src/imap/ngx_imap_proxy.c b/src/imap/ngx_imap_proxy.c
index 451fb3770..2b6e30e3a 100644
--- a/src/imap/ngx_imap_proxy.c
+++ b/src/imap/ngx_imap_proxy.c
@@ -82,9 +82,9 @@ void ngx_imap_proxy_init(ngx_imap_session_t *s)
p->upstream.connection->data = s;
p->upstream.connection->pool = s->connection->pool;
- s->connection->read->event_handler = ngx_imap_proxy_block_read;
- p->upstream.connection->read->event_handler = ngx_imap_proxy_auth_handler;
- p->upstream.connection->write->event_handler = ngx_imap_proxy_dummy_handler;
+ s->connection->read->handler = ngx_imap_proxy_block_read;
+ p->upstream.connection->read->handler = ngx_imap_proxy_auth_handler;
+ p->upstream.connection->write->handler = ngx_imap_proxy_dummy_handler;
}
@@ -200,10 +200,10 @@ static void ngx_imap_proxy_auth_handler(ngx_event_t *rev)
s->proxy->buffer->pos = s->proxy->buffer->start;
s->proxy->buffer->last = s->proxy->buffer->start;
- s->connection->read->event_handler = ngx_imap_proxy_handler;
- s->connection->write->event_handler = ngx_imap_proxy_handler;
- rev->event_handler = ngx_imap_proxy_handler;
- c->write->event_handler = ngx_imap_proxy_handler;
+ s->connection->read->handler = ngx_imap_proxy_handler;
+ s->connection->write->handler = ngx_imap_proxy_handler;
+ rev->handler = ngx_imap_proxy_handler;
+ c->write->handler = ngx_imap_proxy_handler;
}
diff --git a/src/os/unix/ngx_channel.c b/src/os/unix/ngx_channel.c
index 853c5d6fd..c052b6022 100644
--- a/src/os/unix/ngx_channel.c
+++ b/src/os/unix/ngx_channel.c
@@ -137,7 +137,7 @@ ngx_int_t ngx_read_channel(ngx_socket_t s, ngx_channel_t *ch, size_t size,
if (ch->command == NGX_CMD_OPEN_CHANNEL) {
- if (cmsg.cm.cmsg_len < sizeof(cmsg)) {
+ if (cmsg.cm.cmsg_len < (socklen_t) sizeof(cmsg)) {
ngx_log_error(NGX_LOG_ALERT, log, 0,
"recvmsg() returned too small ancillary data");
return NGX_ERROR;
@@ -215,7 +215,7 @@ ngx_int_t ngx_add_channel_event(ngx_cycle_t *cycle, ngx_fd_t fd,
ev = (event == NGX_READ_EVENT) ? rev : wev;
- ev->event_handler = handler;
+ ev->handler = handler;
if (ngx_add_conn && (ngx_event_flags & NGX_USE_EPOLL_EVENT) == 0) {
if (ngx_add_conn(c) == NGX_ERROR) {
diff --git a/src/os/unix/ngx_freebsd_config.h b/src/os/unix/ngx_freebsd_config.h
index a61eeed7d..8d0e983fd 100644
--- a/src/os/unix/ngx_freebsd_config.h
+++ b/src/os/unix/ngx_freebsd_config.h
@@ -97,9 +97,6 @@ pid_t rfork_thread(int flags, void *stack, int (*func)(void *arg), void *arg);
#endif
-#define ngx_setproctitle setproctitle
-
-
extern char *malloc_options;
diff --git a/src/os/unix/ngx_linux_config.h b/src/os/unix/ngx_linux_config.h
index 29d8aae1b..5bad6451c 100644
--- a/src/os/unix/ngx_linux_config.h
+++ b/src/os/unix/ngx_linux_config.h
@@ -97,10 +97,5 @@ extern ssize_t sendfile(int s, int fd, int32_t *offset, size_t size);
#define NGX_HAVE_SELECT_CHANGE_TIMEOUT 1
#endif
-#ifndef NGX_SETPROCTITLE_USES_ENV
-#define NGX_SETPROCTITLE_USES_ENV 1
-#define NGX_SETPROCTITLE_PAD '\0'
-#endif
-
#endif /* _NGX_LINUX_CONFIG_H_INCLUDED_ */
diff --git a/src/os/unix/ngx_linux_init.c b/src/os/unix/ngx_linux_init.c
index 7f7be890a..6cb2449fa 100644
--- a/src/os/unix/ngx_linux_init.c
+++ b/src/os/unix/ngx_linux_init.c
@@ -73,8 +73,6 @@ ngx_os_init(ngx_log_t *log)
ngx_linux_rtsig_max = 0;
}
- ngx_init_setproctitle(log);
-
return ngx_posix_init(log);
}
diff --git a/src/os/unix/ngx_posix_config.h b/src/os/unix/ngx_posix_config.h
index 904060e76..0862726c3 100644
--- a/src/os/unix/ngx_posix_config.h
+++ b/src/os/unix/ngx_posix_config.h
@@ -102,13 +102,6 @@
#endif
-#if (NGX_HAVE_SETPROCTITLE)
-#define ngx_setproctitle setproctitle
-#else
-#define ngx_setproctitle(title)
-#endif
-
-
#define NGX_POSIX_IO 1
diff --git a/src/os/unix/ngx_posix_init.c b/src/os/unix/ngx_posix_init.c
index d48343b30..a66560acb 100644
--- a/src/os/unix/ngx_posix_init.c
+++ b/src/os/unix/ngx_posix_init.c
@@ -6,6 +6,7 @@
#include <ngx_config.h>
#include <ngx_core.h>
+#include <ngx_setproctitle.h>
ngx_int_t ngx_ncpu;
@@ -97,6 +98,8 @@ ngx_int_t ngx_posix_init(ngx_log_t *log)
ngx_signal_t *sig;
struct sigaction sa;
+ ngx_init_setproctitle(log);
+
ngx_pagesize = getpagesize();
if (ngx_ncpu == 0) {
diff --git a/src/os/unix/ngx_process.h b/src/os/unix/ngx_process.h
index 995e93ce2..b85c528d1 100644
--- a/src/os/unix/ngx_process.h
+++ b/src/os/unix/ngx_process.h
@@ -62,12 +62,6 @@ void ngx_debug_point(void);
#endif
-#if !defined(ngx_setproctitle)
-ngx_int_t ngx_init_setproctitle(ngx_log_t *log);
-void ngx_setproctitle(char *title);
-#endif
-
-
extern int ngx_argc;
extern char **ngx_argv;
extern char **ngx_os_argv;
diff --git a/src/os/unix/ngx_process_cycle.c b/src/os/unix/ngx_process_cycle.c
index 23589c997..ffa9dfec7 100644
--- a/src/os/unix/ngx_process_cycle.c
+++ b/src/os/unix/ngx_process_cycle.c
@@ -7,6 +7,7 @@
#include <ngx_config.h>
#include <ngx_core.h>
#include <ngx_event.h>
+#include <ngx_setproctitle.h>
#include <ngx_channel.h>
diff --git a/src/os/unix/ngx_send.c b/src/os/unix/ngx_send.c
index ecd136265..ffe6bcba2 100644
--- a/src/os/unix/ngx_send.c
+++ b/src/os/unix/ngx_send.c
@@ -63,7 +63,7 @@ ssize_t ngx_unix_send(ngx_connection_t *c, u_char *buf, size_t size)
} else {
wev->error = 1;
- ngx_connection_error(c, err, "recv() failed");
+ ngx_connection_error(c, err, "send() failed");
return NGX_ERROR;
}
}
diff --git a/src/os/unix/ngx_setproctitle.c b/src/os/unix/ngx_setproctitle.c
index 712c22c98..8ae643d9b 100644
--- a/src/os/unix/ngx_setproctitle.c
+++ b/src/os/unix/ngx_setproctitle.c
@@ -6,6 +6,7 @@
#include <ngx_config.h>
#include <ngx_core.h>
+#include <ngx_setproctitle.h>
#if (NGX_SETPROCTITLE_USES_ENV)
@@ -131,19 +132,4 @@ ngx_setproctitle(char *title)
"setproctitle: \"%s\"", ngx_os_argv[0]);
}
-
-#elif !defined(ngx_setproctitle)
-
-ngx_int_t
-ngx_init_setproctitle(ngx_log_t *log)
-{
- return NGX_OK;
-}
-
-void
-ngx_setproctitle(char *title)
-{
- return;
-}
-
-#endif
+#endif /* NGX_SETPROCTITLE_USES_ENV */
diff --git a/src/os/unix/ngx_setproctitle.h b/src/os/unix/ngx_setproctitle.h
new file mode 100644
index 000000000..107725a0a
--- /dev/null
+++ b/src/os/unix/ngx_setproctitle.h
@@ -0,0 +1,45 @@
+
+/*
+ * Copyright (C) Igor Sysoev
+ */
+
+
+#ifndef _NGX_SETPROCTITLE_H_INCLUDED_
+#define _NGX_SETPROCTITLE_H_INCLUDED_
+
+
+#if (NGX_HAVE_SETPROCTITLE)
+
+/* FreeBSD, NetBSD, OpenBSD */
+
+#define ngx_init_setproctitle(log)
+#define ngx_setproctitle setproctitle
+
+
+#elif !defined NGX_SETPROCTITLE_USES_ENV
+
+#define NGX_SETPROCTITLE_USES_ENV 1
+
+#if (NGX_SOLARIS)
+
+#define NGX_SETPROCTITLE_PAD ' '
+
+#elif (NGX_LINUX) || (NGX_DARWIN)
+
+#define NGX_SETPROCTITLE_PAD '\0'
+
+#endif
+
+ngx_int_t ngx_init_setproctitle(ngx_log_t *log);
+void ngx_setproctitle(char *title);
+
+
+#else /* !NGX_SETPROCTITLE_USES_ENV */
+
+#define ngx_init_setproctitle(log)
+#define ngx_setproctitle(title)
+
+#endif
+
+
+#endif /* _NGX_SETPROCTITLE_H_INCLUDED_ */
diff --git a/src/os/unix/ngx_solaris_config.h b/src/os/unix/ngx_solaris_config.h
index 088fbd023..437e50654 100644
--- a/src/os/unix/ngx_solaris_config.h
+++ b/src/os/unix/ngx_solaris_config.h
@@ -83,10 +83,4 @@
#endif
-#ifndef NGX_SETPROCTITLE_USES_ENV
-#define NGX_SETPROCTITLE_USES_ENV 1
-#define NGX_SETPROCTITLE_PAD ' '
-#endif
-
-
#endif /* _NGX_SOLARIS_CONFIG_H_INCLUDED_ */
diff --git a/src/os/unix/ngx_solaris_init.c b/src/os/unix/ngx_solaris_init.c
index 03072edad..9080eb20c 100644
--- a/src/os/unix/ngx_solaris_init.c
+++ b/src/os/unix/ngx_solaris_init.c
@@ -53,8 +53,6 @@ ngx_int_t ngx_os_init(ngx_log_t *log)
return NGX_ERROR;
}
- ngx_init_setproctitle(log);
-
return ngx_posix_init(log);
}
diff --git a/src/os/unix/ngx_time.c b/src/os/unix/ngx_time.c
index 20ec4644b..72137f952 100644
--- a/src/os/unix/ngx_time.c
+++ b/src/os/unix/ngx_time.c
@@ -29,3 +29,43 @@ void ngx_localtime(ngx_tm_t *tm)
tm->ngx_tm_mon++;
tm->ngx_tm_year += 1900;
}
+
+
+void ngx_libc_localtime(struct tm *tm)
+{
+#if (NGX_HAVE_LOCALTIME_R)
+ time_t now;
+
+ now = ngx_time();
+ localtime_r(&now, tm);
+
+#else
+ time_t now;
+ struct tm *t;
+
+ now = ngx_time();
+ t = localtime(&now);
+ *tm = *t;
+
+#endif
+}
+
+
+void ngx_libc_gmtime(struct tm *tm)
+{
+#if (NGX_HAVE_LOCALTIME_R)
+ time_t now;
+
+ now = ngx_time();
+ gmtime_r(&now, tm);
+
+#else
+ time_t now;
+ struct tm *t;
+
+ now = ngx_time();
+ t = gmtime(&now);
+ *tm = *t;
+
+#endif
+}
diff --git a/src/os/unix/ngx_time.h b/src/os/unix/ngx_time.h
index f257325d0..6e5a38ae2 100644
--- a/src/os/unix/ngx_time.h
+++ b/src/os/unix/ngx_time.h
@@ -54,6 +54,8 @@ typedef struct tm ngx_tm_t;
void ngx_localtime(ngx_tm_t *tm);
+void ngx_libc_localtime(struct tm *tm);
+void ngx_libc_gmtime(struct tm *tm);
#define ngx_gettimeofday(tp) gettimeofday(tp, NULL);
#define ngx_msleep(ms) usleep(ms * 1000)
diff --git a/src/os/unix/ngx_user.c b/src/os/unix/ngx_user.c
index fe2f79489..22eafd20e 100644
--- a/src/os/unix/ngx_user.c
+++ b/src/os/unix/ngx_user.c
@@ -27,11 +27,18 @@ ngx_crypt(ngx_pool_t *pool, u_char *key, u_char *salt, u_char **encrypted)
{
char *value;
size_t len;
+ ngx_err_t err;
struct crypt_data cd;
+ ngx_set_errno(0);
+
+ cd.initialized = 0;
+
value = crypt_r((char *) key, (char *) salt, &cd);
- if (value) {
+ err = ngx_errno;
+
+ if (err == 0) {
len = ngx_strlen(value);
*encrypted = ngx_palloc(pool, len);
@@ -41,6 +48,8 @@ ngx_crypt(ngx_pool_t *pool, u_char *key, u_char *salt, u_char **encrypted)
}
}
+ ngx_log_error(NGX_LOG_CRIT, pool->log, err, "crypt_r() failed");
+
return NGX_ERROR;
}
@@ -51,7 +60,7 @@ ngx_crypt(ngx_pool_t *pool, u_char *key, u_char *salt, u_char **encrypted)
{
char *value;
size_t len;
- ngx_int_t rc;
+ ngx_err_t err;
#if (NGX_THREADS && NGX_NONREENTRANT_CRYPT)
@@ -63,7 +72,7 @@ ngx_crypt(ngx_pool_t *pool, u_char *key, u_char *salt, u_char **encrypted)
#endif
- rc = NGX_ERROR;
+ ngx_set_errno(0);
value = crypt((char *) key, (char *) salt);
@@ -73,15 +82,23 @@ ngx_crypt(ngx_pool_t *pool, u_char *key, u_char *salt, u_char **encrypted)
*encrypted = ngx_palloc(pool, len);
if (*encrypted) {
ngx_memcpy(*encrypted, value, len + 1);
- rc = NGX_OK;
}
+
+#if (NGX_THREADS && NGX_NONREENTRANT_CRYPT)
+ ngx_mutex_unlock(ngx_crypt_mutex);
+#endif
+ return NGX_OK;
}
+ err = ngx_errno;
+
#if (NGX_THREADS && NGX_NONREENTRANT_CRYPT)
ngx_mutex_unlock(ngx_crypt_mutex);
#endif
- return rc;
+ ngx_log_error(NGX_LOG_CRIT, pool->log, err, "crypt() failed");
+
+ return NGX_ERROR;
}
#endif
diff --git a/src/os/win32/ngx_gui.c b/src/os/win32/ngx_gui.c
index 36d3c49d2..138d44a6b 100644
--- a/src/os/win32/ngx_gui.c
+++ b/src/os/win32/ngx_gui.c
@@ -11,7 +11,8 @@
#define NGX_MAX_TEXT 2048
-void ngx_cdecl ngx_message_box(char *title, ngx_uint_t type, ngx_err_t err,
+void __cdecl
+ngx_message_box(char *title, ngx_uint_t type, ngx_err_t err,
const char *fmt, ...)
{
va_list args;
diff --git a/src/os/win32/ngx_process_cycle.c b/src/os/win32/ngx_process_cycle.c
index 2251ff2df..7eabefe5c 100644
--- a/src/os/win32/ngx_process_cycle.c
+++ b/src/os/win32/ngx_process_cycle.c
@@ -12,7 +12,7 @@
static void *ngx_worker_thread_cycle(void *data);
static long __stdcall ngx_window_procedure(HWND window, u_int message,
- u_int wparam, long lparam);
+ u_int wparam, long lparam);
#if 0
ngx_pid_t ngx_new_binary;
@@ -45,7 +45,8 @@ sig_atomic_t ngx_change_binary;
static HMENU ngx_menu;
-void ngx_master_process_cycle(ngx_cycle_t *cycle)
+void
+ngx_master_process_cycle(ngx_cycle_t *cycle)
{
ngx_log_error(NGX_LOG_EMERG, cycle->log, 0, "master mode is not supported");
@@ -53,7 +54,8 @@ void ngx_master_process_cycle(ngx_cycle_t *cycle)
}
-void ngx_single_process_cycle(ngx_cycle_t *cycle)
+void
+ngx_single_process_cycle(ngx_cycle_t *cycle)
{
int rc;
ngx_int_t i;
@@ -165,7 +167,7 @@ void ngx_single_process_cycle(ngx_cycle_t *cycle)
if (ngx_system_tray_icon(window, NIM_ADD, tray, (u_char *) " nginx")
- == NGX_ERROR)
+ != NGX_OK)
{
ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
"Shell_NotifyIcon(NIM_ADD) failed");
@@ -200,7 +202,8 @@ void ngx_single_process_cycle(ngx_cycle_t *cycle)
}
-static void *ngx_worker_thread_cycle(void *data)
+static void *
+ngx_worker_thread_cycle(void *data)
{
ngx_cycle_t *cycle;
@@ -216,8 +219,8 @@ static void *ngx_worker_thread_cycle(void *data)
}
-static long __stdcall ngx_window_procedure(HWND window, u_int message,
- u_int wparam, long lparam)
+static long __stdcall
+ngx_window_procedure(HWND window, u_int message, u_int wparam, long lparam)
{
POINT mouse;
@@ -251,13 +254,13 @@ static long __stdcall ngx_window_procedure(HWND window, u_int message,
case WM_COMMAND:
if (wparam == NGX_WM_ABOUT) {
ngx_message_box("nginx", MB_OK, 0,
- NGINX_VER CRLF "(C) 2002-2004 Igor Sysoev");
+ NGINX_VER CRLF "(C) 2002-2005 Igor Sysoev");
return 0;
}
if (wparam == NGX_WM_EXIT) {
if (ngx_system_tray_icon(window, NIM_DELETE, NULL, NULL)
- == NGX_ERROR)
+ != NGX_OK)
{
ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, ngx_errno,
"Shell_NotifyIcon(NIM_DELETE) failed");
diff --git a/src/os/win32/ngx_time.c b/src/os/win32/ngx_time.c
index ca072029c..04a1af6a3 100644
--- a/src/os/win32/ngx_time.c
+++ b/src/os/win32/ngx_time.c
@@ -36,6 +36,28 @@ void ngx_gettimeofday(struct timeval *tp)
}
+void ngx_libc_localtime(struct tm *tm)
+{
+ time_t now;
+ struct tm *t;
+
+ now = ngx_time();
+ t = localtime(&now);
+ *tm = *t;
+}
+
+
+void ngx_libc_gmtime(struct tm *tm)
+{
+ time_t now;
+ struct tm *t;
+
+ now = ngx_time();
+ t = gmtime(&now);
+ *tm = *t;
+}
+
+
ngx_int_t ngx_gettimezone(void)
{
TIME_ZONE_INFORMATION tz;
diff --git a/src/os/win32/ngx_time.h b/src/os/win32/ngx_time.h
index 4cb984194..cc90c462a 100644
--- a/src/os/win32/ngx_time.h
+++ b/src/os/win32/ngx_time.h
@@ -42,6 +42,8 @@ typedef FILETIME ngx_mtime_t;
#define NGX_HAVE_GETTIMEZONE 1
ngx_int_t ngx_gettimezone(void);
+void ngx_libc_localtime(struct tm *tm);
+void ngx_libc_gmtime(struct tm *tm);
void ngx_gettimeofday(struct timeval *tp);
diff --git a/src/os/win32/ngx_win32_config.h b/src/os/win32/ngx_win32_config.h
index f49a16c96..a814acbdc 100644
--- a/src/os/win32/ngx_win32_config.h
+++ b/src/os/win32/ngx_win32_config.h
@@ -29,6 +29,14 @@
#include <stdlib.h>
#include <stdarg.h>
+#ifdef __WATCOMC__
+#define _TIME_T_DEFINED
+typedef long time_t;
+/* OpenWatcom defines time_t as "unsigned long" */
+#endif
+
+#include <time.h> /* localtime(), strftime() */
+
#ifdef _MSC_VER
@@ -51,11 +59,6 @@
/* FD_SET() and FD_CLR(): conditional expression is constant */
#pragma warning(disable:4127)
-#if 0
-/* assignment within conditional expression */
-#pragma warning(disable:4706)
-#endif
-
/* function 'ngx_handle_write_event' not inlined */
#pragma warning(disable:4710)
@@ -81,11 +84,6 @@
/* unreferenced formal parameter */
#pragma warn -8057
-#if 0
-/* assignment within conditional expression */
-#pragma warn -8060
-#endif
-
#endif
@@ -117,7 +115,6 @@ typedef unsigned __int64 uint64_t;
typedef u_int uintptr_t;
typedef int ssize_t;
-typedef long time_t;
typedef __int64 off_t;
typedef uint32_t in_addr_t;
typedef u_short in_port_t;