summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIgor Sysoev <igor@sysoev.ru>2005-05-12 14:59:46 +0000
committerJonathan Kolb <jon@b0g.us>2005-05-12 14:59:46 +0000
commit4b4c1f681d5475900d89e99d87e15388044e3f5b (patch)
treea0115d1c387749651805317929adbc1bfa359b06
parent67f93c257afca7699d999a2441165d261dbe75a9 (diff)
downloadnginx-0.1.29.tar.gz
Changes with nginx 0.1.29 12 May 2005v0.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" is 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_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; bug 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--CHANGES89
-rw-r--r--CHANGES.ru90
-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--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_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_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.c1934
-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_cache.c628
-rw-r--r--src/http/modules/proxy/ngx_http_proxy_handler.c1509
-rw-r--r--src/http/modules/proxy/ngx_http_proxy_handler.h272
-rw-r--r--src/http/modules/proxy/ngx_http_proxy_header.c206
-rw-r--r--src/http/modules/proxy/ngx_http_proxy_parse.c216
-rw-r--r--src/http/modules/proxy/ngx_http_proxy_upstream.c1646
-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/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
115 files changed, 7504 insertions, 8396 deletions
diff --git a/CHANGES b/CHANGES
index 26f9114d9..10c36f767 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,4 +1,91 @@
+Changes with nginx 0.1.29 12 May 2005
+
+ *) 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" is
+ 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_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; bug 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.
+
+
Changes with nginx 0.1.28 08 Apr 2005
*) Bugfix: nginx hogs CPU while proxing the huge files.
@@ -180,7 +267,7 @@ Changes with nginx 0.1.18 09 Feb 2005
Changes with nginx 0.1.17 03 Feb 2005
- *) Feature: the ngx_http_rewrite_module was rewritten from the scratch.
+ *) Change: the ngx_http_rewrite_module was rewritten from the scratch.
Now it is possible to redirect, to return the error codes, to check
the variables and referrers. The directives can be used inside
locations. The redirect directive was canceled.
diff --git a/CHANGES.ru b/CHANGES.ru
index 800785c85..f93650c11 100644
--- a/CHANGES.ru
+++ b/CHANGES.ru
@@ -1,4 +1,92 @@
+Изменения в nginx 0.1.29 12.05.2005
+
+ *) Добавление: модуль ngx_http_ssi_module поддерживает команду include
+ virtual.
+
+ *) Добавление: модуль ngx_http_ssi_module поддерживает условную команду
+ вида 'if expr="$NAME"' и команды else и endif. Допускается только
+ один уровень вложенности.
+
+ *) Добавление: модуль ngx_http_ssi_module поддерживает две переменные
+ DATE_LOCAL и DATE_GMT и команду config timefmt.
+
+ *) Добавление: директива ssi_ignore_recycled_buffers.
+
+ *) Исправление: если переменная QUERY_STRING не была определена, то в
+ команде echo не ставилось значение по умолчанию.
+
+ *) Изменение: модуль ngx_http_proxy_module полностью переписан.
+
+ *) Добавление: директивы proxy_redirect, proxy_pass_request_headers,
+ proxy_pass_request_body и proxy_method.
+
+ *) Добавление: директива proxy_set_header. Директива proxy_x_var
+ упразднена и должна быть заменена директивой proxy_set_header.
+
+ *) Изменение: директива proxy_preserve_host упразднена и должна быть
+ заменена директивами "proxy_set_header Host $host" и "proxy_redirect
+ off" или директивой "proxy_set_header Host $host:$proxy_port" и
+ соответствующими ей директивами proxy_redirect.
+
+ *) Изменение: директива proxy_set_x_real_ip упразднена и должна быть
+ заменена директивой "proxy_set_header X-Real-IP $remote_addr".
+
+ *) Изменение: директива proxy_add_x_forwarded_for упразднена и должна
+ быть заменена директивой
+ "proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for".
+
+ *) Изменение: директива proxy_set_x_url упразднена и должна быть
+ заменена директивой
+ "proxy_set_header X-URL http://$host:$server_port$request_uri".
+
+ *) Добавление: директива fastcgi_param.
+
+ *) Изменение: директивы fastcgi_set_var и fastcgi_params упразднены и
+ должны быть замены директивами fastcgi_param.
+
+ *) Добавление: директива index может использовать переменные.
+
+ *) Добавление: директива index может быть указана на уровне http и
+ server.
+
+ *) Изменение: только последний параметр в директиве index может быть
+ абсолютным.
+
+ *) Добавление: в директиве rewrite могут использоваться переменные.
+
+ *) Добавление: директива internal.
+
+ *) Добавление: переменные CONTENT_LENGTH, CONTENT_TYPE, REMOTE_PORT,
+ SERVER_ADDR, SERVER_PORT, SERVER_PROTOCOL, DOCUMENT_ROOT,
+ SERVER_NAME, REQUEST_METHOD, REQUEST_URI и REMOTE_USER.
+
+ *) Изменение: nginx теперь передаёт неверные строки в заголовках
+ запроса клиента и ответа бэкенда.
+
+ *) Исправление: если бэкенд долго не передавал ответ и send_timeout был
+ меньше, чем proxy_read_timeout, то клиенту возвращался ответ 408.
+
+ *) Исправление: если бэкенд передавал неверную строку в заголовке
+ ответа, то происходил segmentation fault; ошибка появилась в 0.1.26.
+
+ *) Исправление: при использовании отказоустойчивой конфигурации в
+ FastCGI мог происходить segmentation fault.
+
+ *) Исправление: директива expires не удаляла уже установленные строки
+ заголовка "Expires" и "Cache-Control".
+
+ *) Исправление: nginx не учитывал завершающую точку в строке заголовка
+ запроса "Host".
+
+ *) Исправление: модуль ngx_http_auth_module не работал на Linux.
+
+ *) Исправление: директива rewrite неверно работала, если в запросе
+ присутствовали аргументы.
+
+ *) Исправление: nginx не собирался на MacOS X.
+
+
Изменения в nginx 0.1.28 08.04.2005
*) Исправление: при проксировании больших файлов nginx сильно нагружал
@@ -181,7 +269,7 @@
Изменения в nginx 0.1.17 03.02.2005
- *) Добавление: модуль ngx_http_rewrite_module полностью переписан.
+ *) Изменение: модуль ngx_http_rewrite_module полностью переписан.
Теперь можно делать редиректы, возвращать коды ошибок и проверять
переменные и рефереры. Эти директивы можно использовать внутри
location. Директива redirect упразднена.
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/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_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_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
new file mode 100644
index 000000000..5504610e6
--- /dev/null
+++ b/src/http/modules/ngx_http_proxy_module.c
@@ -0,0 +1,1934 @@
+
+/*
+ * Copyright (C) Igor Sysoev
+ */
+
+
+#include <ngx_config.h>
+#include <ngx_core.h>
+#include <ngx_event.h>
+#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_peers_t *peers;
+
+ ngx_array_t *headers_set_len;
+ ngx_array_t *headers_set;
+ ngx_hash_t *headers_set_hash;
+
+ ngx_array_t *headers_source;
+ ngx_array_t *headers_names;
+
+ ngx_array_t *redirects;
+
+ ngx_str_t host_header;
+ ngx_str_t port_text;
+
+ ngx_flag_t redirect;
+} ngx_http_proxy_loc_conf_t;
+
+
+typedef struct {
+ ngx_uint_t status;
+ ngx_uint_t status_count;
+ u_char *status_start;
+ u_char *status_end;
+} ngx_http_proxy_ctx_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 void ngx_http_proxy_abort_request(ngx_http_request_t *r);
+static void ngx_http_proxy_finalize_request(ngx_http_request_t *r,
+ ngx_int_t rc);
+
+static ngx_http_variable_value_t *
+ ngx_http_proxy_host_variable(ngx_http_request_t *r, uintptr_t data);
+static ngx_http_variable_value_t *
+ ngx_http_proxy_port_variable(ngx_http_request_t *r, uintptr_t data);
+static ngx_http_variable_value_t *
+ 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_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_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 };
+
+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 },
+ { ngx_string("timeout"), NGX_HTTP_UPSTREAM_FT_TIMEOUT },
+ { ngx_string("invalid_header"), NGX_HTTP_UPSTREAM_FT_INVALID_HEADER },
+ { ngx_string("http_500"), NGX_HTTP_UPSTREAM_FT_HTTP_500 },
+ { ngx_string("http_404"), NGX_HTTP_UPSTREAM_FT_HTTP_404 },
+ { ngx_null_string, 0 }
+};
+
+
+static ngx_command_t ngx_http_proxy_commands[] = {
+
+ { ngx_string("proxy_pass"),
+ NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+ ngx_http_proxy_pass,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ 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,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ offsetof(ngx_http_proxy_loc_conf_t, upstream.connect_timeout),
+ NULL },
+
+ { ngx_string("proxy_send_timeout"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+ ngx_conf_set_msec_slot,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ offsetof(ngx_http_proxy_loc_conf_t, upstream.send_timeout),
+ NULL },
+
+ { ngx_string("proxy_send_lowat"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+ ngx_conf_set_size_slot,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ offsetof(ngx_http_proxy_loc_conf_t, upstream.send_lowat),
+ &ngx_http_proxy_lowat_post },
+
+ { 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.redirect_errors),
+ NULL },
+
+ { 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, upstream.pass_unparsed_uri),
+ NULL },
+
+ { 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, headers_source),
+ NULL },
+
+ { 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, upstream.method),
+ ngx_http_proxy_set_methods },
+
+ { 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,
+ offsetof(ngx_http_proxy_loc_conf_t, upstream.pass_request_headers),
+ NULL },
+
+ { 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, upstream.pass_request_body),
+ NULL },
+
+ { ngx_string("proxy_header_buffer_size"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+ ngx_conf_set_size_slot,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ offsetof(ngx_http_proxy_loc_conf_t, upstream.header_buffer_size),
+ NULL },
+
+ { ngx_string("proxy_read_timeout"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+ ngx_conf_set_msec_slot,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ offsetof(ngx_http_proxy_loc_conf_t, upstream.read_timeout),
+ NULL },
+
+ { ngx_string("proxy_buffers"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE2,
+ ngx_conf_set_bufs_slot,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ offsetof(ngx_http_proxy_loc_conf_t, upstream.bufs),
+ NULL },
+
+ { ngx_string("proxy_busy_buffers_size"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+ ngx_conf_set_size_slot,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ offsetof(ngx_http_proxy_loc_conf_t, upstream.busy_buffers_size),
+ NULL },
+
+ { ngx_string("proxy_temp_path"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1234,
+ ngx_conf_set_path_slot,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ offsetof(ngx_http_proxy_loc_conf_t, upstream.temp_path),
+ (void *) ngx_garbage_collector_temp_handler },
+
+ { ngx_string("proxy_max_temp_file_size"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+ ngx_conf_set_size_slot,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ offsetof(ngx_http_proxy_loc_conf_t, upstream.max_temp_file_size),
+ NULL },
+
+ { ngx_string("proxy_temp_file_write_size"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+ ngx_conf_set_size_slot,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ offsetof(ngx_http_proxy_loc_conf_t, upstream.temp_file_write_size),
+ NULL },
+
+ { ngx_string("proxy_next_upstream"),
+ 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_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, 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, upstream.pass_x_accel_expires),
+ NULL },
+
+ ngx_null_command
+};
+
+
+ngx_http_module_t ngx_http_proxy_module_ctx = {
+ ngx_http_proxy_add_variables, /* preconfiguration */
+ NULL, /* postconfiguration */
+
+ NULL, /* create main configuration */
+ NULL, /* init main configuration */
+
+ NULL, /* create server configuration */
+ NULL, /* merge server configuration */
+
+ ngx_http_proxy_create_loc_conf, /* create location configration */
+ ngx_http_proxy_merge_loc_conf /* merge location configration */
+};
+
+
+ngx_module_t ngx_http_proxy_module = {
+ NGX_MODULE_V1,
+ &ngx_http_proxy_module_ctx, /* module context */
+ ngx_http_proxy_commands, /* module directives */
+ NGX_HTTP_MODULE, /* module type */
+ NULL, /* init module */
+ NULL /* init process */
+};
+
+
+static ngx_str_t ngx_http_proxy_methods[] = {
+ ngx_string("GET "),
+ ngx_string("HEAD "),
+ ngx_string("POST ")
+};
+
+
+static char ngx_http_proxy_version[] = " HTTP/1.0" CRLF;
+
+
+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 }
+};
+
+
+static ngx_http_variable_t ngx_http_proxy_vars[] = {
+
+ { ngx_string("proxy_host"), ngx_http_proxy_host_variable, 0,
+ NGX_HTTP_VAR_CHANGABLE },
+
+ { 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 },
+
+#if 0
+ { ngx_string("proxy_add_via"), NULL, 0, 0 },
+#endif
+
+ { ngx_null_string, NULL, 0, 0 }
+};
+
+
+#if (NGX_PCRE)
+static ngx_str_t ngx_http_proxy_uri = ngx_string("/");
+#endif
+
+
+static ngx_int_t
+ngx_http_proxy_handler(ngx_http_request_t *r)
+{
+ ngx_int_t rc;
+ ngx_http_upstream_t *u;
+ ngx_http_proxy_loc_conf_t *plcf;
+
+ plcf = ngx_http_get_module_loc_conf(r, ngx_http_proxy_module);
+
+ u = ngx_pcalloc(r->pool, sizeof(ngx_http_upstream_t));
+ if (u == NULL) {
+ return NGX_HTTP_INTERNAL_SERVER_ERROR;
+ }
+
+ u->peer.log = r->connection->log;
+ u->peer.log_error = NGX_ERROR_ERR;
+ u->peer.peers = plcf->peers;
+ u->peer.tries = plcf->peers->number;
+#if (NGX_THREADS)
+ u->peer.lock = &r->connection->lock;
+#endif
+
+ u->output.tag = (ngx_buf_tag_t) &ngx_http_proxy_module;
+
+ u->conf = &plcf->upstream;
+
+ u->create_request = ngx_http_proxy_create_request;
+ u->reinit_request = ngx_http_proxy_reinit_request;
+ 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;
+
+ if (plcf->redirects) {
+ u->rewrite_redirect = ngx_http_proxy_rewrite_redirect;
+ }
+
+ u->pipe.input_filter = ngx_event_pipe_copy_input_filter;
+
+ u->accel = 1;
+
+ r->upstream = u;
+
+ rc = ngx_http_read_client_request_body(r, ngx_http_upstream_init);
+
+ if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
+ return rc;
+ }
+
+ return NGX_DONE;
+}
+
+
+static ngx_int_t
+ngx_http_proxy_create_request(ngx_http_request_t *r)
+{
+ 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;
+
+ plcf = ngx_http_get_module_loc_conf(r, ngx_http_proxy_module);
+
+ len = sizeof(ngx_http_proxy_version) - 1 + sizeof(CRLF) - 1;
+
+ if (u->method) {
+ len += ngx_http_proxy_methods[u->method - 1].len + u->conf->uri.len;
+ } else {
+ 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 + loc_len,
+ r->uri.len - loc_len, NGX_ESCAPE_URI);
+ }
+
+ len += r->uri.len - loc_len + escape + sizeof("?") - 1 + r->args.len;
+ }
+
+ ngx_memzero(&e, sizeof(ngx_http_script_engine_t));
+
+ le.ip = plcf->headers_set_len->elts;
+ le.request = r;
+
+ 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);
+ }
+
+
+ hh = (ngx_str_t *) plcf->headers_set_hash->buckets;
+
+ if (plcf->upstream.pass_request_headers) {
+ part = &r->headers_in.headers.part;
+ header = part->elts;
+
+ for (i = 0; /* void */; i++) {
+
+ if (i >= part->nelts) {
+ if (part->next == NULL) {
+ break;
+ }
+
+ part = part->next;
+ header = part->elts;
+ i = 0;
+ }
+
+ 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;
+ }
+
+ 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;
+ }
+
+ cl = ngx_alloc_chain_link(r->pool);
+ if (cl == NULL) {
+ return NGX_ERROR;
+ }
+
+ cl->buf = b;
+
+
+ /* the request line */
+
+ if (u->method) {
+ b->last = ngx_cpymem(b->last,
+ 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 + 1);
+ }
+
+ 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 + 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 + loc_len,
+ r->uri.len - loc_len);
+ }
+
+ if (r->args.len > 0) {
+ *b->last++ = '?';
+ b->last = ngx_cpymem(b->last, r->args.data, r->args.len);
+ }
+ }
+
+ b->last = ngx_cpymem(b->last, ngx_http_proxy_version,
+ sizeof(ngx_http_proxy_version) - 1);
+
+
+ e.ip = plcf->headers_set->elts;
+ e.pos = b->last;
+ e.request = r;
+
+ 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;
+
+
+ if (plcf->upstream.pass_request_headers) {
+ part = &r->headers_in.headers.part;
+ header = part->elts;
+
+ for (i = 0; /* void */; i++) {
+
+ if (i >= part->nelts) {
+ if (part->next == NULL) {
+ break;
+ }
+
+ part = part->next;
+ header = part->elts;
+ i = 0;
+ }
+
+ 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;
+ }
+
+ b->last = ngx_cpymem(b->last, header[i].key.data,
+ header[i].key.len);
+
+ *b->last++ = ':'; *b->last++ = ' ';
+
+ b->last = ngx_cpymem(b->last, header[i].value.data,
+ header[i].value.len);
+
+ *b->last++ = 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);
+ }
+ }
+
+ /* add "\r\n" at the header end */
+ *b->last++ = CR; *b->last++ = LF;
+
+#if (NGX_DEBUG)
+ {
+ ngx_str_t s;
+
+ s.len = b->last - b->pos;
+ s.data = b->pos;
+ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "http proxy header:\n\"%V\"", &s);
+ }
+#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;
+}
+
+
+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_status_line(ngx_http_request_t *r)
+{
+ 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_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)
+{
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "abort http proxy request");
+
+ return;
+}
+
+
+static void
+ngx_http_proxy_finalize_request(ngx_http_request_t *r, ngx_int_t rc)
+{
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "finalize http proxy request");
+
+ return;
+}
+
+
+static ngx_http_variable_value_t *
+ngx_http_proxy_host_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;
+ }
+
+ plcf = ngx_http_get_module_loc_conf(r, ngx_http_proxy_module);
+
+ vv->value = 0;
+ vv->text = plcf->host_header;
+
+ return vv;
+}
+
+
+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;
+ }
+
+ plcf = ngx_http_get_module_loc_conf(r, ngx_http_proxy_module);
+
+ vv->value = 0;
+ vv->text = plcf->port_text;
+
+ return vv;
+}
+
+
+static ngx_http_variable_value_t *
+ngx_http_proxy_add_x_forwarded_for_variable(ngx_http_request_t *r,
+ uintptr_t data)
+{
+ u_char *p;
+ ngx_http_variable_value_t *vv;
+
+ vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t));
+ if (vv == NULL) {
+ return NULL;
+ }
+
+ 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);
+
+ 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);
+
+ 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;
+}
+
+
+static void *
+ngx_http_proxy_create_loc_conf(ngx_conf_t *cf)
+{
+ ngx_http_proxy_loc_conf_t *conf;
+
+ conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_proxy_loc_conf_t));
+ if (conf == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ /*
+ * set by ngx_pcalloc():
+ *
+ * conf->upstream.bufs.num = 0;
+ * 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;
+ conf->upstream.send_timeout = NGX_CONF_UNSET_MSEC;
+ conf->upstream.read_timeout = NGX_CONF_UNSET_MSEC;
+
+ conf->upstream.send_lowat = NGX_CONF_UNSET_SIZE;
+ conf->upstream.header_buffer_size = NGX_CONF_UNSET_SIZE;
+ 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;
+
+ /* "proxy_cyclic_temp_file" is disabled */
+ conf->upstream.cyclic_temp_file = 0;
+
+ 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->redirect = NGX_CONF_UNSET;
+
+ return conf;
+}
+
+
+static char *
+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;
+
+ 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);
+
+ ngx_conf_merge_msec_value(conf->upstream.send_timeout,
+ prev->upstream.send_timeout, 60000);
+
+ ngx_conf_merge_msec_value(conf->upstream.read_timeout,
+ prev->upstream.read_timeout, 60000);
+
+ ngx_conf_merge_size_value(conf->upstream.send_lowat,
+ prev->upstream.send_lowat, 0);
+
+ ngx_conf_merge_size_value(conf->upstream.header_buffer_size,
+ prev->upstream.header_buffer_size,
+ (size_t) ngx_pagesize);
+
+ ngx_conf_merge_bufs_value(conf->upstream.bufs, prev->upstream.bufs,
+ 8, ngx_pagesize);
+
+ if (conf->upstream.bufs.num < 2) {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "there must be at least 2 \"proxy_buffers\"");
+ return NGX_CONF_ERROR;
+ }
+
+
+ size = conf->upstream.header_buffer_size;
+ if (size < conf->upstream.bufs.size) {
+ size = conf->upstream.bufs.size;
+ }
+
+
+ ngx_conf_merge_size_value(conf->upstream.busy_buffers_size,
+ prev->upstream.busy_buffers_size,
+ NGX_CONF_UNSET_SIZE);
+
+ if (conf->upstream.busy_buffers_size == NGX_CONF_UNSET_SIZE) {
+ conf->upstream.busy_buffers_size = 2 * size;
+
+ } else if (conf->upstream.busy_buffers_size < size) {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "\"proxy_busy_buffers_size\" must be equal or bigger than "
+ "maximum of the value of \"proxy_header_buffer_size\" and "
+ "one of the \"proxy_buffers\"");
+
+ return NGX_CONF_ERROR;
+
+ } else if (conf->upstream.busy_buffers_size
+ > (conf->upstream.bufs.num - 1) * conf->upstream.bufs.size)
+ {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "\"proxy_busy_buffers_size\" must be less than "
+ "the size of all \"proxy_buffers\" minus one buffer");
+
+ return NGX_CONF_ERROR;
+ }
+
+
+ ngx_conf_merge_size_value(conf->upstream.temp_file_write_size,
+ prev->upstream.temp_file_write_size,
+ NGX_CONF_UNSET_SIZE);
+
+ if (conf->upstream.temp_file_write_size == NGX_CONF_UNSET_SIZE) {
+ conf->upstream.temp_file_write_size = 2 * size;
+
+ } else if (conf->upstream.temp_file_write_size < size) {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "\"proxy_temp_file_write_size\" must be equal or bigger than "
+ "maximum of the value of \"proxy_header_buffer_size\" and "
+ "one of the \"proxy_buffers\"");
+
+ return NGX_CONF_ERROR;
+ }
+
+
+ ngx_conf_merge_size_value(conf->upstream.max_temp_file_size,
+ prev->upstream.max_temp_file_size,
+ NGX_CONF_UNSET_SIZE);
+
+ if (conf->upstream.max_temp_file_size == NGX_CONF_UNSET_SIZE) {
+
+ conf->upstream.max_temp_file_size = 1024 * 1024 * 1024;
+
+ } else if (conf->upstream.max_temp_file_size != 0
+ && conf->upstream.max_temp_file_size < size)
+ {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "\"fastcgi_max_temp_file_size\" must be equal to zero to disable "
+ "the temporary files usage or must be equal or bigger than "
+ "maximum of the value of \"fastcgi_header_buffer_size\" and "
+ "one of the \"fastcgi_buffers\"");
+
+ return NGX_CONF_ERROR;
+ }
+
+ ngx_conf_merge_bitmask_value(conf->upstream.next_upstream,
+ prev->upstream.next_upstream,
+ (NGX_CONF_BITMASK_SET
+ |NGX_HTTP_UPSTREAM_FT_ERROR
+ |NGX_HTTP_UPSTREAM_FT_TIMEOUT));
+
+ 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->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;
+ }
+
+ 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;
+ }
+ }
+
+
+ if (conf->peers == NULL) {
+ conf->peers = prev->peers;
+ conf->upstream = prev->upstream;
+ }
+
+ 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) {
+ return NGX_CONF_OK;
+ }
+
+
+ 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_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;
+ }
+ }
+
+ 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;
+ }
+
+
+ src = conf->headers_source->elts;
+
+ 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;
+ }
+
+ *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 = src[i].key;
+
+ 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;
+ }
+
+ copy->code = (ngx_http_script_code_pt)
+ ngx_http_script_copy_len_code;
+ copy->len = src[i].key.len + sizeof(": ") - 1
+ + src[i].value.len + sizeof(CRLF) - 1;
+
+
+ size = (sizeof(ngx_http_script_copy_code_t)
+ + src[i].key.len + sizeof(": ") - 1
+ + src[i].value.len + sizeof(CRLF) - 1
+ + sizeof(uintptr_t) - 1)
+ & ~(sizeof(uintptr_t) - 1);
+
+ copy = ngx_array_push_n(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;
+
+ p = (u_char *) copy + sizeof(ngx_http_script_copy_code_t);
+
+ p = ngx_cpymem(p, src[i].key.data, src[i].key.len);
+ *p++ = ':'; *p++ = ' ';
+ p = ngx_cpymem(p, src[i].value.data, src[i].value.len);
+ *p++ = CR; *p = LF;
+
+ } else {
+ copy = ngx_array_push_n(conf->headers_set_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 + sizeof(": ") - 1;
+
+
+ size = (sizeof(ngx_http_script_copy_code_t)
+ + src[i].key.len + sizeof(": ") - 1 + sizeof(uintptr_t) - 1)
+ & ~(sizeof(uintptr_t) - 1);
+
+ copy = ngx_array_push_n(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;
+
+ p = (u_char *) copy + sizeof(ngx_http_script_copy_code_t);
+ p = ngx_cpymem(p, src[i].key.data, src[i].key.len);
+ *p++ = ':'; *p = ' ';
+
+
+ ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
+
+ sc.cf = cf;
+ sc.source = &src[i].value;
+ sc.lengths = &conf->headers_set_len;
+ sc.values = &conf->headers_set;
+
+ if (ngx_http_script_compile(&sc) != NGX_OK) {
+ return NGX_CONF_ERROR;
+ }
+
+
+ copy = ngx_array_push_n(conf->headers_set_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 = sizeof(CRLF) - 1;
+
+
+ size = (sizeof(ngx_http_script_copy_code_t)
+ + sizeof(CRLF) - 1 + sizeof(uintptr_t) - 1)
+ & ~(sizeof(uintptr_t) - 1);
+
+ 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 = sizeof(CRLF) - 1;
+
+ p = (u_char *) copy + sizeof(ngx_http_script_copy_code_t);
+ *p++ = CR; *p = LF;
+ }
+
+ code = ngx_array_push_n(conf->headers_set_len, sizeof(uintptr_t));
+ if (code == NULL) {
+ return NGX_CONF_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;
+ }
+
+ code = ngx_array_push_n(conf->headers_set_len, sizeof(uintptr_t));
+ if (code == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ *code = (uintptr_t) NULL;
+
+
+ conf->headers_set_hash = ngx_pcalloc(cf->pool, sizeof(ngx_hash_t));
+ if (conf->headers_set_hash == 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";
+
+ 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_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_CONF_OK;
+}
+
+
+static char *
+ngx_http_proxy_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
+{
+ ngx_http_proxy_loc_conf_t *plcf = conf;
+
+ ngx_uint_t i;
+ ngx_str_t *value, *url;
+ 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;
+
+ url = &value[1];
+
+ if (ngx_strncasecmp(url->data, "http://", 7) != 0) {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid URL prefix");
+ return NGX_CONF_ERROR;
+ }
+
+ if (ngx_strncasecmp(url->data + 7, "unix:", 5) == 0) {
+
+#if (NGX_HAVE_UNIX_DOMAIN)
+
+ ngx_memzero(&unix_upstream, sizeof(ngx_unix_domain_upstream_t));
+
+ unix_upstream.name = *url;
+ unix_upstream.url.len = url->len - 7;
+ unix_upstream.url.data = url->data + 7;
+ unix_upstream.uri_part = 1;
+
+ plcf->peers = ngx_unix_upstream_parse(cf, &unix_upstream);
+ if (plcf->peers == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ plcf->peers->peer[0].uri_separator = ":";
+
+ 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,
+ "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 = *url;
+ inet_upstream.url.len = url->len - 7;
+ inet_upstream.url.data = url->data + 7;
+ inet_upstream.default_port_value = 80;
+ inet_upstream.uri_part = 1;
+
+ plcf->peers = ngx_inet_upstream_parse(cf, &inet_upstream);
+ if (plcf->peers == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ for (i = 0; i < plcf->peers->number; i++) {
+ plcf->peers->peer[i].uri_separator = ":";
+ }
+
+ 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)
+ plcf->upstream.location = clcf->regex ? &ngx_http_proxy_uri : &clcf->name;
+#else
+ plcf->upstream.location = &clcf->name;
+#endif
+
+ plcf->upstream.url = *url;
+
+ if (clcf->name.data[clcf->name.len - 1] == '/') {
+ clcf->auto_redirect = 1;
+ }
+
+ return NGX_CONF_OK;
+}
+
+
+static char *
+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;
+}
+
+
+static char *
+ngx_http_proxy_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,
+ "\"proxy_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,
+ "\"proxy_send_lowat\" is not supported, ignored");
+
+ *np = 0;
+
+#endif
+
+ 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_cache.c b/src/http/modules/proxy/ngx_http_proxy_cache.c
deleted file mode 100644
index 86b8424c6..000000000
--- a/src/http/modules/proxy/ngx_http_proxy_cache.c
+++ /dev/null
@@ -1,628 +0,0 @@
-
-/*
- * Copyright (C) Igor Sysoev
- */
-
-
-#include <ngx_config.h>
-#include <ngx_core.h>
-#include <ngx_http.h>
-#include <ngx_http_proxy_handler.h>
-
-
-static int ngx_http_proxy_process_cached_response(ngx_http_proxy_ctx_t *p,
- int rc);
-static int ngx_http_proxy_process_cached_header(ngx_http_proxy_ctx_t *p);
-static void ngx_http_proxy_cache_look_complete_request(ngx_http_proxy_ctx_t *p);
-
-
-int ngx_http_proxy_get_cached_response(ngx_http_proxy_ctx_t *p)
-{
- char *last;
- ngx_http_request_t *r;
- ngx_http_proxy_cache_t *c;
- ngx_http_proxy_upstream_conf_t *u;
-
- r = p->request;
-
- if (!(c = ngx_pcalloc(r->pool, sizeof(ngx_http_proxy_cache_t)))) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- p->cache = c;
-
- c->ctx.file.fd = NGX_INVALID_FILE;
- c->ctx.file.log = r->connection->log;
- c->ctx.path = p->lcf->cache_path;
-
- u = p->lcf->upstream;
-
- c->ctx.key.len = u->url.len + r->uri.len - u->location->len + r->args.len;
- if (!(c->ctx.key.data = ngx_palloc(r->pool, c->ctx.key.len + 1))) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- last = ngx_cpymem(c->ctx.key.data, u->url.data, u->url.len);
-
- last = ngx_cpymem(last, r->uri.data + u->location->len,
- r->uri.len - u->location->len);
-
- if (r->args.len > 0) {
- *(last++) = '?';
- last = ngx_cpymem(last, r->args.data, r->args.len);
- }
- *last = '\0';
-
- p->header_in = ngx_create_temp_hunk(r->pool, p->lcf->header_buffer_size);
- if (p->header_in == NULL) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
- p->header_in->tag = (ngx_hunk_tag_t) &ngx_http_proxy_module;
-
- c->ctx.buf = p->header_in;
- c->ctx.log = r->connection->log;
-
- return ngx_http_proxy_process_cached_response(p,
- ngx_http_cache_get_file(r, &c->ctx));
-}
-
-
-static int ngx_http_proxy_process_cached_response(ngx_http_proxy_ctx_t *p,
- int rc)
-{
- if (rc == NGX_OK) {
- p->state->cache_state = NGX_HTTP_PROXY_CACHE_HIT;
- p->header_in->pos = p->header_in->start + p->cache->ctx.header_size;
-
- if (ngx_http_proxy_process_cached_header(p) == NGX_ERROR) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- p->valid_header_in = 1;
-
- return ngx_http_proxy_send_cached_response(p);
- }
-
- if (rc == NGX_HTTP_CACHE_STALE) {
- p->state->cache_state = NGX_HTTP_PROXY_CACHE_EXPR;
-
- } else if (rc == NGX_HTTP_CACHE_AGED) {
- p->state->cache_state = NGX_HTTP_PROXY_CACHE_AGED;
- }
-
- if (rc == NGX_HTTP_CACHE_STALE || rc == NGX_HTTP_CACHE_AGED) {
- p->state->expired = ngx_time() - p->cache->ctx.expires;
- p->header_in->pos = p->header_in->start + p->cache->ctx.header_size;
-
- if (ngx_http_proxy_process_cached_header(p) == NGX_ERROR) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- p->header_in->pos = p->header_in->start + p->cache->ctx.header_size;
- p->header_in->last = p->header_in->pos;
-
- p->stale = 1;
- p->valid_header_in = 1;
-
- } else if (rc == NGX_DECLINED) {
- p->state->cache_state = NGX_HTTP_PROXY_CACHE_MISS;
- p->header_in->pos = p->header_in->start + p->cache->ctx.header_size;
- p->header_in->last = p->header_in->pos;
- }
-
- if (p->lcf->busy_lock) {
- p->try_busy_lock = 1;
-
- p->header_in->pos = p->header_in->start;
- p->header_in->last = p->header_in->start;
-
- p->busy_lock.time = 0;
- p->busy_lock.event = p->request->connection->read;
- p->busy_lock.event_handler = ngx_http_proxy_busy_lock_handler;
- p->busy_lock.md5 = p->cache->ctx.md5;
-
- ngx_http_proxy_cache_busy_lock(p);
- return NGX_DONE;
- }
-
- return ngx_http_proxy_request_upstream(p);
-}
-
-
-static int ngx_http_proxy_process_cached_header(ngx_http_proxy_ctx_t *p)
-{
- int rc, i;
- ngx_table_elt_t *h;
- ngx_http_request_t *r;
- ngx_http_proxy_cache_t *c;
-
- rc = ngx_http_proxy_parse_status_line(p);
-
- c = p->cache;
- r = p->request;
-
- if (rc == NGX_AGAIN) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "\"proxy_header_buffer_size\" "
- "is too small to read header from \"%s\"",
- c->ctx.file.name.data);
- return NGX_ERROR;
- }
-
- if (rc == NGX_HTTP_PROXY_PARSE_NO_HEADER) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "no valid HTTP/1.0 header in \"%s\"",
- c->ctx.file.name.data);
- return NGX_ERROR;
- }
-
- /* rc == NGX_OK */
-
- c->status = p->status;
- c->status_line.len = p->status_end - p->status_start;
- c->status_line.data = ngx_palloc(r->pool, c->status_line.len + 1);
- if (c->status_line.data == NULL) {
- return NGX_ERROR;
- }
-
- /* reset for the possible parsing the upstream header */
-
- p->status = 0;
- p->status_count = 0;
-
- ngx_cpystrn(c->status_line.data, p->status_start, c->status_line.len + 1);
-
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http cache status %ui \"%V\"",
- c->status, &c->status_line);
-
- /* TODO: ngx_init_table */
- c->headers_in.headers = ngx_create_table(r->pool, 20);
-
- for ( ;; ) {
- rc = ngx_http_parse_header_line(r, p->header_in);
-
- if (rc == NGX_OK) {
-
- /* a header line has been parsed successfully */
-
- h = ngx_http_add_header(&c->headers_in, ngx_http_proxy_headers_in);
- if (h == NULL) {
- return NGX_ERROR;
- }
-
- 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_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);
-
- for (i = 0; ngx_http_proxy_headers_in[i].name.len != 0; i++) {
- if (ngx_http_proxy_headers_in[i].name.len != h->key.len) {
- continue;
- }
-
- if (ngx_strcasecmp(ngx_http_proxy_headers_in[i].name.data,
- h->key.data) == 0)
- {
- *((ngx_table_elt_t **) ((char *) &c->headers_in
- + ngx_http_proxy_headers_in[i].offset)) = h;
- break;
- }
- }
-
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http cache header: \"%V: %V\"", &h->key, &h->value);
-
- continue;
-
- } else 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 cache header done");
-
- c->ctx.file_start = p->header_in->pos - p->header_in->start;
-
- return NGX_OK;
-
- } else if (rc == NGX_HTTP_PARSE_INVALID_HEADER) {
-
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "invalid header in \"%s\"",
- c->ctx.file.name.data);
- return NGX_ERROR;
- }
-
- /* rc == NGX_AGAIN || rc == NGX_HTTP_PARSE_TOO_LONG_HEADER */
-
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "\"proxy_header_buffer_size\" "
- "is too small to read header from \"%s\"",
- c->ctx.file.name.data);
- return NGX_ERROR;
- }
-}
-
-
-void ngx_http_proxy_cache_busy_lock(ngx_http_proxy_ctx_t *p)
-{
- int rc, ft_type;
-
- rc = ngx_http_busy_lock_cachable(p->lcf->busy_lock, &p->busy_lock,
- p->try_busy_lock);
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, p->request->connection->log, 0,
- "http cache busy lock cachable: %d", rc);
-
- if (rc == NGX_OK) {
- if (p->try_busy_lock) {
- p->busy_locked = 1;
- p->header_in->pos = p->header_in->start + p->cache->ctx.header_size;
- p->header_in->last = p->header_in->pos;
-
- ngx_http_proxy_request_upstream(p);
- return;
- }
-
- ngx_http_proxy_cache_look_complete_request(p);
- return;
- }
-
- p->try_busy_lock = 0;
-
- if (p->cache->ctx.file.fd != NGX_INVALID_FILE
- && !p->cache->ctx.file.info_valid)
- {
- if (ngx_fd_info(p->cache->ctx.file.fd, &p->cache->ctx.file.info)
- == NGX_FILE_ERROR)
- {
- ngx_log_error(NGX_LOG_CRIT, p->request->connection->log, ngx_errno,
- ngx_fd_info_n " \"%s\" failed",
- p->cache->ctx.file.name.data);
- ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR);
- return;
- }
-
- p->cache->ctx.file.info_valid = 1;
- }
-
- if (rc == NGX_AGAIN) {
-
- if ((ngx_event_flags & (NGX_USE_CLEAR_EVENT|NGX_USE_KQUEUE_EVENT))
- && !p->request->connection->write->active)
- {
- /*
- * kqueue allows to detect when client closes prematurely
- * connection
- */
-
- p->request->connection->write->event_handler =
- ngx_http_proxy_check_broken_connection;
-
- if (ngx_add_event(p->request->connection->write, NGX_WRITE_EVENT,
- NGX_CLEAR_EVENT) == NGX_ERROR)
- {
- ngx_http_proxy_finalize_request(p,
- NGX_HTTP_INTERNAL_SERVER_ERROR);
- return;
- }
- }
-
- return;
- }
-
- ngx_http_busy_unlock(p->lcf->busy_lock, &p->busy_lock);
-
- if (rc == NGX_DONE) {
- ft_type = NGX_HTTP_PROXY_FT_BUSY_LOCK;
-
- } else {
- /* rc == NGX_ERROR */
- ft_type = NGX_HTTP_PROXY_FT_MAX_WAITING;
- }
-
- if (p->stale && (p->lcf->use_stale & ft_type)) {
- ngx_http_proxy_finalize_request(p,
- ngx_http_proxy_send_cached_response(p));
- return;
- }
-
- p->state->status = NGX_HTTP_SERVICE_UNAVAILABLE;
- ngx_http_proxy_finalize_request(p, NGX_HTTP_SERVICE_UNAVAILABLE);
-}
-
-
-static void ngx_http_proxy_cache_look_complete_request(ngx_http_proxy_ctx_t *p)
-{
- int rc;
- ngx_http_cache_ctx_t *ctx;
-
- if (!(ctx = ngx_pcalloc(p->request->pool, sizeof(ngx_http_cache_ctx_t)))) {
- ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR);
- return;
- }
-
- *ctx = p->cache->ctx;
-
- rc = ngx_http_cache_open_file(ctx, ngx_file_uniq(&p->cache->ctx.file.info));
-
- if (rc == NGX_DECLINED || rc == NGX_HTTP_CACHE_THE_SAME) {
- p->try_busy_lock = 1;
- p->busy_lock.time = 0;
- ngx_http_proxy_cache_busy_lock(p);
- return;
- }
-
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, p->request->connection->log, 0,
- "http cache old fd:%d, new fd:%d",
- p->cache->ctx.file.fd, ctx->file.fd);
-
- if (p->cache->ctx.file.fd != NGX_INVALID_FILE) {
- if (ngx_close_file(p->cache->ctx.file.fd) == NGX_FILE_ERROR) {
- ngx_log_error(NGX_LOG_ALERT, p->request->connection->log, ngx_errno,
- ngx_close_file_n " \"%s\" failed",
- p->cache->ctx.file.name.data);
- }
- }
-
- p->cache->ctx = *ctx;
-
- p->status = 0;
- p->status_count = 0;
-
- ngx_http_proxy_finalize_request(p,
- ngx_http_proxy_process_cached_response(p, rc));
-}
-
-
-int ngx_http_proxy_send_cached_response(ngx_http_proxy_ctx_t *p)
-{
- int rc, len, i;
- off_t rest;
- ngx_hunk_t *h0, *h1;
- ngx_chain_t out[2];
- ngx_http_request_t *r;
-
- r = p->request;
-
- r->headers_out.status = p->cache->status;
-
-#if 0
- r->headers_out.content_length_n = -1;
- r->headers_out.content_length = NULL;
-#endif
-
- /* copy an cached header to r->headers_out */
-
- if (ngx_http_proxy_copy_header(p, &p->cache->headers_in) == NGX_ERROR) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- /* we need to allocate all before the header would be sent */
-
- len = p->header_in->end - (p->header_in->start + p->cache->ctx.file_start);
-
- h0 = NULL;
- h1 = NULL;
-
- if (len) {
- if (!((h0 = ngx_calloc_hunk(r->pool)))) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- if (!((h0->file = ngx_pcalloc(r->pool, sizeof(ngx_file_t))))) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
- }
-
- if (len < p->cache->ctx.length) {
- if (!((h1 = ngx_calloc_hunk(r->pool)))) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- if (!((h1->file = ngx_pcalloc(r->pool, sizeof(ngx_file_t))))) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
- }
-
- rc = ngx_http_send_header(r);
-
- /* NEEDED ??? */ p->header_sent = 1;
-
- if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) {
- return rc;
- }
-
- rest = p->cache->ctx.length;
-
- if (len) {
- if (p->valid_header_in) {
- h0->pos = p->header_in->start + p->cache->ctx.file_start;
-
- if (len > p->cache->ctx.length) {
- h0->last = h0->pos + p->cache->ctx.length;
-
- } else {
- h0->last = p->header_in->end;
- }
-
- h0->type = NGX_HUNK_IN_MEMORY|NGX_HUNK_TEMP;
- }
-
- h0->type |= NGX_HUNK_FILE;
- h0->file_pos = p->cache->ctx.file_start;
-
- h0->file->fd = p->cache->ctx.file.fd;
- h0->file->log = r->connection->log;
-
- if (len > p->cache->ctx.length) {
- h0->file_last = h0->file_pos + p->cache->ctx.length;
- rest = 0;
-
- } else {
- h0->file_last = h0->file_pos + len;
- rest -= len;
- }
-
- out[0].hunk = h0;
- out[0].next = &out[1];
- i = 0;
-
- } else {
- i = -1;
- }
-
- if (rest) {
- h1->file_pos = p->cache->ctx.file_start + len;
- h1->file_last = h1->file_pos + rest;
- h1->type = NGX_HUNK_FILE;
-
- h1->file->fd = p->cache->ctx.file.fd;
- h1->file->log = r->connection->log;
-
- out[++i].hunk = h1;
- }
-
- out[i].next = NULL;
- if (!r->main) {
- out[i].hunk->type |= NGX_HUNK_LAST;
- }
-
- r->file.fd = p->cache->ctx.file.fd;
-
- return ngx_http_output_filter(r, out);
-}
-
-
-int ngx_http_proxy_is_cachable(ngx_http_proxy_ctx_t *p)
-{
- time_t date, last_modified, expires, t;
- ngx_http_proxy_headers_in_t *h;
-
- switch (p->upstream->status) {
- case NGX_HTTP_OK:
- case NGX_HTTP_MOVED_PERMANENTLY:
- case NGX_HTTP_MOVED_TEMPORARILY:
- break;
-
-#if 0
- case NGX_HTTP_NOT_MODIFIED:
- return 1;
-#endif
-
- default:
- return 0;
- }
-
- h = &p->upstream->headers_in;
-
- date = NGX_ERROR;
- if (h->date) {
- date = ngx_http_parse_time(h->date->value.data, h->date->value.len);
- }
- if (date == NGX_ERROR) {
- date = ngx_time();
- }
- p->cache->ctx.date = date;
-
- last_modified = NGX_ERROR;
- if (h->last_modified) {
- last_modified = ngx_http_parse_time(h->last_modified->value.data,
- h->last_modified->value.len);
- p->cache->ctx.last_modified = last_modified;
- }
-
- if (h->x_accel_expires) {
- expires = ngx_atoi(h->x_accel_expires->value.data,
- h->x_accel_expires->value.len);
- if (expires != NGX_ERROR) {
- p->state->reason = NGX_HTTP_PROXY_CACHE_XAE;
- p->state->expires = expires;
- p->cache->ctx.expires = date + expires;
- return (expires > 0);
- }
- }
-
- if (!p->lcf->ignore_expires) {
-
- /* TODO: Cache-Control: no-cache, max-age= */
-
- if (h->expires) {
- expires = ngx_http_parse_time(h->expires->value.data,
- h->expires->value.len);
- if (expires != NGX_ERROR) {
- p->state->reason = NGX_HTTP_PROXY_CACHE_EXP;
- p->state->expires = expires - date;
- p->cache->ctx.expires = expires;
- return (date < expires);
- }
- }
- }
-
- if (p->upstream->status == NGX_HTTP_MOVED_PERMANENTLY) {
- p->state->reason = NGX_HTTP_PROXY_CACHE_MVD;
- p->state->expires = /* STUB: 1 hour */ 60 * 60;
- p->cache->ctx.expires = /* STUB: 1 hour */ 60 * 60;
- return 1;
- }
-
- if (p->upstream->status == NGX_HTTP_MOVED_TEMPORARILY) {
- return 1;
- }
-
- if (last_modified != NGX_ERROR && p->lcf->lm_factor > 0) {
-
- /* FIXME: time_t == int_64_t, we can use fpu */
-
- p->state->reason = NGX_HTTP_PROXY_CACHE_LMF;
- t = (time_t)
- ((((int64_t) (date - last_modified)) * p->lcf->lm_factor) / 100);
- p->state->expires = t;
- p->cache->ctx.expires = ngx_time() + t;
- return 1;
- }
-
- if (p->lcf->default_expires > 0) {
- p->state->reason = NGX_HTTP_PROXY_CACHE_PDE;
- p->state->expires = p->lcf->default_expires;
- p->cache->ctx.expires = ngx_time() + p->lcf->default_expires;
- return 1;
- }
-
- return 0;
-}
-
-
-int ngx_http_proxy_update_cache(ngx_http_proxy_ctx_t *p)
-{
- ngx_event_pipe_t *ep;
-
- if (p->cache == NULL) {
- return NGX_OK;
- }
-
- ep = p->upstream->event_pipe;
-
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, p->request->connection->log, 0,
- "http cache update len: %O:%O",
- p->cache->ctx.length, ep->read_length);
-
- if (p->cache->ctx.length == -1) {
- /* TODO: test rc */
- ngx_write_file(&ep->temp_file->file,
- (char *) &ep->read_length, sizeof(off_t),
- offsetof(ngx_http_cache_header_t, length));
- }
-
- return ngx_http_cache_update_file(p->request, &p->cache->ctx,
- &ep->temp_file->file.name);
-}
diff --git a/src/http/modules/proxy/ngx_http_proxy_handler.c b/src/http/modules/proxy/ngx_http_proxy_handler.c
deleted file mode 100644
index 12d417176..000000000
--- a/src/http/modules/proxy/ngx_http_proxy_handler.c
+++ /dev/null
@@ -1,1509 +0,0 @@
-
-/*
- * Copyright (C) Igor Sysoev
- */
-
-
-#include <ngx_config.h>
-#include <ngx_core.h>
-#include <ngx_http.h>
-#include <ngx_http_proxy_handler.h>
-
-
-static ngx_int_t ngx_http_proxy_handler(ngx_http_request_t *r);
-#if 0
-static ngx_int_t ngx_http_proxy_cache_get(ngx_http_proxy_ctx_t *p);
-#endif
-
-static size_t ngx_http_proxy_log_proxy_state_getlen(ngx_http_request_t *r,
- uintptr_t data);
-static u_char *ngx_http_proxy_log_proxy_state(ngx_http_request_t *r,
- u_char *buf,
- ngx_http_log_op_t *op);
-
-#if 0
-static u_char *ngx_http_proxy_log_cache_state(ngx_http_request_t *r,
- u_char *buf, uintptr_t data);
-static u_char *ngx_http_proxy_log_reason(ngx_http_request_t *r, u_char *buf,
- uintptr_t data);
-#endif
-
-static ngx_int_t ngx_http_proxy_add_log_formats(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_set_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);
-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 } ;
-
-
-static ngx_conf_bitmask_t next_upstream_masks[] = {
- { ngx_string("error"), NGX_HTTP_PROXY_FT_ERROR },
- { ngx_string("timeout"), NGX_HTTP_PROXY_FT_TIMEOUT },
- { ngx_string("invalid_header"), NGX_HTTP_PROXY_FT_INVALID_HEADER },
- { ngx_string("http_500"), NGX_HTTP_PROXY_FT_HTTP_500 },
- { ngx_string("http_404"), NGX_HTTP_PROXY_FT_HTTP_404 },
- { ngx_null_string, 0 }
-};
-
-
-static ngx_conf_bitmask_t use_stale_masks[] = {
- { ngx_string("error"), NGX_HTTP_PROXY_FT_ERROR },
- { ngx_string("timeout"), NGX_HTTP_PROXY_FT_TIMEOUT },
- { ngx_string("invalid_header"), NGX_HTTP_PROXY_FT_INVALID_HEADER },
- { ngx_string("http_500"), NGX_HTTP_PROXY_FT_HTTP_500 },
- { ngx_string("busy_lock"), NGX_HTTP_PROXY_FT_BUSY_LOCK },
- { ngx_string("max_waiting"), NGX_HTTP_PROXY_FT_MAX_WAITING },
- { ngx_null_string, 0 }
-};
-
-
-static ngx_conf_num_bounds_t ngx_http_proxy_lm_factor_bounds = {
- ngx_conf_check_num_bounds, 0, 100
-};
-
-
-static ngx_command_t ngx_http_proxy_commands[] = {
-
- { ngx_string("proxy_pass"),
- NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_http_proxy_set_pass,
- 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,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_proxy_loc_conf_t, connect_timeout),
- NULL },
-
- { ngx_string("proxy_send_timeout"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_msec_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_proxy_loc_conf_t, send_timeout),
- NULL },
-
- { ngx_string("proxy_send_lowat"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_size_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_proxy_loc_conf_t, send_lowat),
- &ngx_http_proxy_lowat_post },
-
- { ngx_string("proxy_preserve_host"),
- 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),
- NULL },
-
- { 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, 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_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_proxy_loc_conf_t, set_x_url),
- 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_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_proxy_loc_conf_t, set_x_real_ip),
- NULL },
-
- { 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_HTTP_LOC_CONF_OFFSET,
- 0,
- NULL },
-
- { ngx_string("proxy_add_x_forwarded_for"),
- 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),
- NULL },
-
- { ngx_string("proxy_header_buffer_size"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_size_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_proxy_loc_conf_t, header_buffer_size),
- NULL },
-
- { ngx_string("proxy_read_timeout"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_msec_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_proxy_loc_conf_t, read_timeout),
- NULL },
-
- { ngx_string("proxy_buffers"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE2,
- ngx_conf_set_bufs_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_proxy_loc_conf_t, bufs),
- NULL },
-
- { ngx_string("proxy_busy_buffers_size"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_size_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_proxy_loc_conf_t, busy_buffers_size),
- NULL },
-
-#if 0
-
- { ngx_string("proxy_cache_path"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1234,
- ngx_conf_set_path_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_proxy_loc_conf_t, cache_path),
- (void *) ngx_http_cache_cleaner_handler },
-
-#endif
-
- { ngx_string("proxy_temp_path"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1234,
- ngx_conf_set_path_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_proxy_loc_conf_t, temp_path),
- (void *) ngx_garbage_collector_temp_handler },
-
- { ngx_string("proxy_max_temp_file_size"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_size_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_proxy_loc_conf_t, max_temp_file_size),
- NULL },
-
- { ngx_string("proxy_temp_file_write_size"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_size_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_proxy_loc_conf_t, temp_file_write_size),
- NULL },
-
- { ngx_string("proxy_cache"),
- 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, cache),
- NULL },
-
-
- { ngx_string("proxy_busy_lock"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE13,
- ngx_http_set_busy_lock_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_proxy_loc_conf_t, busy_lock),
- 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),
- 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),
- NULL },
-
- { ngx_string("proxy_ignore_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, ignore_expires),
- NULL },
-
- { ngx_string("proxy_lm_factor"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_num_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_proxy_loc_conf_t, lm_factor),
- &ngx_http_proxy_lm_factor_bounds },
-
- { ngx_string("proxy_default_expires"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_sec_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_proxy_loc_conf_t, default_expires),
- NULL },
-
- { ngx_string("proxy_next_upstream"),
- 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_proxy_loc_conf_t, next_upstream),
- &next_upstream_masks },
-
- { ngx_string("proxy_use_stale"),
- 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_proxy_loc_conf_t, use_stale),
- &use_stale_masks },
-
- ngx_null_command
-};
-
-
-ngx_http_module_t ngx_http_proxy_module_ctx = {
- ngx_http_proxy_add_log_formats, /* pre conf */
-
- NULL, /* create main configuration */
- NULL, /* init main configuration */
-
- NULL, /* create server configuration */
- NULL, /* merge server configuration */
-
- ngx_http_proxy_create_loc_conf, /* create location configration */
- ngx_http_proxy_merge_loc_conf /* merge location configration */
-};
-
-
-ngx_module_t ngx_http_proxy_module = {
- NGX_MODULE,
- &ngx_http_proxy_module_ctx, /* module context */
- ngx_http_proxy_commands, /* module directives */
- NGX_HTTP_MODULE, /* module type */
- NULL, /* init module */
- NULL /* init process */
-};
-
-
-
-static ngx_http_log_op_name_t ngx_http_proxy_log_fmt_ops[] = {
- { ngx_string("proxy"), 0, NULL,
- ngx_http_proxy_log_proxy_state_getlen,
- ngx_http_proxy_log_proxy_state },
-
-#if 0
- { ngx_string("proxy_cache_state"), 0, ngx_http_proxy_log_cache_state },
- { ngx_string("proxy_reason"), 0, ngx_http_proxy_log_reason },
-#endif
-
- { ngx_null_string, 0, NULL, NULL, NULL }
-};
-
-
-
-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("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) },
-
- { ngx_null_string, 0 }
-};
-
-
-static ngx_str_t cache_states[] = {
- ngx_string("PASS"),
- ngx_string("BYPASS"),
- ngx_string("AUTH"),
- ngx_string("PGNC"),
- ngx_string("MISS"),
- ngx_string("EXPR"),
- ngx_string("AGED"),
- ngx_string("HIT")
-};
-
-
-static ngx_str_t cache_reasons[] = {
- ngx_string("BPS"),
- ngx_string("XAE"),
- ngx_string("CTL"),
- ngx_string("EXP"),
- ngx_string("MVD"),
- ngx_string("LMF"),
- ngx_string("PDE")
-};
-
-
-#if (NGX_PCRE)
-static ngx_str_t ngx_http_proxy_uri = ngx_string("/");
-#endif
-
-
-static ngx_int_t ngx_http_proxy_handler(ngx_http_request_t *r)
-{
- ngx_http_proxy_ctx_t *p;
-
- 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);
-
-
- p->lcf = ngx_http_get_module_loc_conf(r, ngx_http_proxy_module);
- p->request = r;
-
- /* TODO: we currently support reverse proxy only */
- p->accel = 1;
-
- if (ngx_array_init(&p->states, r->pool, p->lcf->peers->number,
- sizeof(ngx_http_proxy_state_t)) == NGX_ERROR)
- {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- p->state = ngx_array_push(&p->states);
- if (p->state == NULL) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- ngx_memzero(p->state, sizeof(ngx_http_proxy_state_t));
-
-#if 0
-
- if (!p->lcf->cache
- || (r->method != NGX_HTTP_GET && r->method != NGX_HTTP_HEAD))
- {
- p->state->cache_state = NGX_HTTP_PROXY_CACHE_PASS;
-
- } else if (r->bypass_cache) {
- p->state->cache_state = NGX_HTTP_PROXY_CACHE_BYPASS;
-
- } else if (r->headers_in.authorization) {
- p->state->cache_state = NGX_HTTP_PROXY_CACHE_AUTH;
-
- } else if (r->no_cache) {
- p->state->cache_state = NGX_HTTP_PROXY_CACHE_PGNC;
- p->cachable = 1;
-
- } else {
- p->cachable = 1;
- }
-
-
- if (p->state->cache_state != 0) {
- return ngx_http_proxy_request_upstream(p);
- }
-
- return ngx_http_proxy_cache_get(p);
-
-#else
-
- p->state->cache_state = NGX_HTTP_PROXY_CACHE_PASS;
-
- return ngx_http_proxy_request_upstream(p);
-
-#endif
-}
-
-
-#if 0
-
-static ngx_int_t ngx_http_proxy_cache_get(ngx_http_proxy_ctx_t *p)
-{
- u_char *last;
- ngx_http_request_t *r;
- ngx_http_cache_ctx_t ctx;
- ngx_http_proxy_upstream_conf_t *u;
-
- r = p->request;
- u = p->lcf->upstream;
-
- ctx.key.len = u->url.len + r->uri.len - u->location->len + r->args.len;
- ctx.key.data = ngx_palloc(r->pool, ctx.key.len);
- if (ctx.key.data == NULL) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- last = ngx_cpymem(ctx.key.data, u->url.data, u->url.len);
-
- last = ngx_cpymem(last, r->uri.data + u->location->len,
- r->uri.len - u->location->len);
-
- if (r->args.len > 0) {
- *(last++) = '?';
- last = ngx_cpymem(last, r->args.data, r->args.len);
- }
-
- p->header_in = ngx_create_temp_buf(r->pool, p->lcf->header_buffer_size);
- if (p->header_in == NULL) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
- p->header_in->tag = (ngx_buf_tag_t) &ngx_http_proxy_module;
-
- ctx.buf = p->header_in;
- ctx.path = p->lcf->cache_path;
- ctx.file = 1;
- ctx.primary = 1;
-
- ngx_http_cache_get(r, &ctx);
-
- return ngx_http_proxy_request_upstream(p);
-}
-
-#endif
-
-
-void ngx_http_proxy_check_broken_connection(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,
- "http proxy check client, write event:%d", ev->write);
-
-#if (NGX_HAVE_KQUEUE)
-
- if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) {
-
- if (!ev->pending_eof) {
- return;
- }
-
- c = ev->data;
- r = c->data;
- p = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
-
- ev->eof = 1;
-
- if (ev->kq_errno) {
- ev->error = 1;
- }
-
- if (!p->cachable && p->upstream->peer.connection) {
- ngx_log_error(NGX_LOG_INFO, ev->log, ev->kq_errno,
- "kevent() reported that client closed "
- "prematurely connection, "
- "so upstream connection is closed too");
- ngx_http_proxy_finalize_request(p, NGX_HTTP_CLIENT_CLOSED_REQUEST);
- return;
- }
-
- ngx_log_error(NGX_LOG_INFO, ev->log, ev->kq_errno,
- "kevent() reported that client closed "
- "prematurely connection");
-
- if (p->upstream == NULL || p->upstream->peer.connection == NULL) {
- ngx_http_proxy_finalize_request(p, NGX_HTTP_CLIENT_CLOSED_REQUEST);
- }
-
- return;
- }
-
-#endif
-
- c = ev->data;
- r = c->data;
- p = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
-
- n = recv(c->fd, buf, 1, MSG_PEEK);
-
- err = ngx_socket_errno;
-
- /*
- * we do not need to disable the write event because
- * that event has NGX_USE_CLEAR_EVENT type
- */
-
- if (ev->write && (n >= 0 || err == NGX_EAGAIN)) {
- return;
- }
-
- if ((ngx_event_flags & NGX_USE_LEVEL_EVENT) && ev->active) {
- if (ngx_del_event(ev, NGX_READ_EVENT, 0) == NGX_ERROR) {
- ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR);
- }
- }
-
- if (n > 0) {
- return;
- }
-
- ev->eof = 1;
-
- if (n == -1) {
- if (err == NGX_EAGAIN) {
- return;
- }
-
- ev->error = 1;
-
- } else {
- /* n == 0 */
- err = 0;
- }
-
- if (!p->cachable && p->upstream->peer.connection) {
- ngx_log_error(NGX_LOG_INFO, ev->log, err,
- "client closed prematurely connection, "
- "so upstream connection is closed too");
- ngx_http_proxy_finalize_request(p, NGX_HTTP_CLIENT_CLOSED_REQUEST);
- return;
- }
-
- ngx_log_error(NGX_LOG_INFO, ev->log, err,
- "client closed prematurely connection");
-
- if (p->upstream == NULL || p->upstream->peer.connection == NULL) {
- ngx_http_proxy_finalize_request(p, NGX_HTTP_CLIENT_CLOSED_REQUEST);
- }
-}
-
-
-void ngx_http_proxy_busy_lock_handler(ngx_event_t *rev)
-{
- ngx_connection_t *c;
- ngx_http_request_t *r;
- ngx_http_proxy_ctx_t *p;
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0, "http proxy busy lock");
-
- c = rev->data;
- r = c->data;
- p = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
- p->action = "waiting upstream in busy lock";
-
- if (p->request->connection->write->eof) {
- ngx_http_busy_unlock(p->lcf->busy_lock, &p->busy_lock);
- ngx_http_proxy_finalize_request(p, NGX_HTTP_CLIENT_CLOSED_REQUEST);
- return;
- }
-
- if (rev->timedout) {
- rev->timedout = 0;
- p->busy_lock.time++;
- p->state->bl_time = p->busy_lock.time;
-
-#if (NGX_HTTP_FILE_CACHE)
-
- if (p->state->cache_state < NGX_HTTP_PROXY_CACHE_MISS) {
- ngx_http_proxy_upstream_busy_lock(p);
-
- } else {
- ngx_http_proxy_cache_busy_lock(p);
- }
-#else
-
- ngx_http_proxy_upstream_busy_lock(p);
-
-#endif
-
- return;
- }
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0,
- "http proxy: client sent while busy lock");
-
- /*
- * TODO: kevent() notify about error, otherwise we need to
- * call ngx_peek(): recv(MSG_PEEK) to get errno. THINK about aio.
- * if there's no error we need to disable event.
- */
-
-#if 0
-#if (NGX_HAVE_KQUEUE)
-
- if ((ngx_event_flags & NGX_USE_KQUEUE_EVENT) && rev->kq_eof) {
- ngx_http_busy_unlock(p->lcf->busy_lock, &p->busy_lock);
-
- ngx_del_timer(rev);
-
- ngx_log_error(NGX_LOG_ERR, c->log, rev->kq_errno,
- "client() closed connection");
-
- if (ngx_del_event(rev, NGX_READ_EVENT, NGX_CLOSE_EVENT) == NGX_ERROR) {
- ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR);
- return;
- }
-
- ngx_http_proxy_finalize_request(p, NGX_HTTP_CLIENT_CLOSED_REQUEST);
- return;
- }
-
-#endif
-#endif
-
-}
-
-
-void ngx_http_proxy_finalize_request(ngx_http_proxy_ctx_t *p, int rc)
-{
- ngx_http_request_t *r;
-
- r = p->request;
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "finalize http proxy request");
-
- if (p->upstream && p->upstream->peer.connection) {
- ngx_http_proxy_close_connection(p);
- }
-
- if (p->header_sent
- && (rc == NGX_ERROR || rc >= NGX_HTTP_SPECIAL_RESPONSE))
- {
- rc = 0;
- }
-
- if (p->saved_ctx) {
- r->connection->log->data = p->saved_ctx;
- r->connection->log->handler = p->saved_handler;
- }
-
- if (p->upstream && p->upstream->event_pipe) {
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http proxy temp fd: %d",
- p->upstream->event_pipe->temp_file->file.fd);
- }
-
- if (p->cache) {
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http proxy cache fd: %d",
- 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);
- }
-
- ngx_http_finalize_request(r, rc);
-}
-
-
-void ngx_http_proxy_close_connection(ngx_http_proxy_ctx_t *p)
-{
- ngx_socket_t fd;
- ngx_connection_t *c;
-
- c = p->upstream->peer.connection;
- p->upstream->peer.connection = NULL;
-
- if (p->lcf->busy_lock) {
- p->lcf->busy_lock->busy--;
- }
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
- "http proxy close connection: %d", c->fd);
-
- if (c->fd == -1) {
-#if 0
- ngx_log_error(NGX_LOG_ALERT, c->log, 0, "connection already closed");
-#endif
- return;
- }
-
- if (c->read->timer_set) {
- ngx_del_timer(c->read);
- }
-
- if (c->write->timer_set) {
- ngx_del_timer(c->write);
- }
-
- /* TODO: move connection to the connection pool */
-
- if (ngx_del_conn) {
- ngx_del_conn(c, NGX_CLOSE_EVENT);
-
- } else {
- if (c->read->active || c->read->disabled) {
- ngx_del_event(c->read, NGX_READ_EVENT, NGX_CLOSE_EVENT);
- }
-
- if (c->write->active || c->read->disabled) {
- ngx_del_event(c->write, NGX_WRITE_EVENT, NGX_CLOSE_EVENT);
- }
- }
-
- /*
- * we have to clean the connection information before the closing
- * because another thread may reopen the same file descriptor
- * before we clean the connection
- */
-
- if (ngx_mutex_lock(ngx_posted_events_mutex) == NGX_OK) {
-
- if (c->read->prev) {
- ngx_delete_posted_event(c->read);
- }
-
- if (c->write->prev) {
- ngx_delete_posted_event(c->write);
- }
-
- c->read->closed = 1;
- c->write->closed = 1;
-
- ngx_mutex_unlock(ngx_posted_events_mutex);
- }
-
- fd = c->fd;
- c->fd = (ngx_socket_t) -1;
- c->data = NULL;
-
- if (ngx_close_socket(fd) == -1) {
- ngx_log_error(NGX_LOG_ALERT, c->log, ngx_socket_errno,
- ngx_close_socket_n " failed");
- }
-}
-
-
-u_char *ngx_http_proxy_log_error(ngx_log_t *log, u_char *buf, size_t len)
-{
- u_char *p;
- ngx_int_t escape;
- ngx_http_request_t *r;
- ngx_peer_connection_t *peer;
- ngx_http_proxy_log_ctx_t *ctx;
- ngx_http_proxy_upstream_conf_t *uc;
-
- ctx = log->data;
- r = ctx->proxy->request;
- uc = ctx->proxy->lcf->upstream;
- peer = &ctx->proxy->upstream->peer;
-
- p = ngx_snprintf(buf, len,
- " while %s, client: %V, server: %V, URL: \"%V\","
- " upstream: http://%V%s%V",
- ctx->proxy->action,
- &r->connection->addr_text,
- &r->server_name,
- &r->unparsed_uri,
- &peer->peers->peer[peer->cur_peer].name,
- ctx->proxy->lcf->upstream->uri_separator,
- &ctx->proxy->lcf->upstream->uri);
- len -= p - buf;
- buf = p;
-
- if (ctx->proxy->lcf->pass_unparsed_uri && r->valid_unparsed_uri) {
- p = ngx_cpymem(buf, r->unparsed_uri.data + 1, r->unparsed_uri.len - 1);
- len -= p - buf;
-
- return ngx_http_log_error_info(r, p, len);
- }
-
- if (r->quoted_uri) {
- escape = 2 * ngx_escape_uri(NULL, r->uri.data + uc->location->len,
- r->uri.len - uc->location->len,
- NGX_ESCAPE_URI);
- } else {
- escape = 0;
- }
-
- if (escape) {
- if (len >= r->uri.len - uc->location->len + escape) {
-
- ngx_escape_uri(buf, r->uri.data + uc->location->len,
- r->uri.len - uc->location->len, NGX_ESCAPE_URI);
-
- buf += r->uri.len - uc->location->len + escape;
- len -= r->uri.len - uc->location->len + escape;
-
- if (r->args.len) {
- p = ngx_snprintf(buf, len, "?%V", &r->args);
- len -= p - buf;
- buf = p;
- }
-
- return ngx_http_log_error_info(r, buf, len);
- }
-
- p = ngx_palloc(r->pool, r->uri.len - uc->location->len + escape);
- if (p == NULL) {
- return buf;
- }
-
- ngx_escape_uri(p, r->uri.data + uc->location->len,
- r->uri.len - uc->location->len, NGX_ESCAPE_URI);
-
- p = ngx_cpymem(buf, p, r->uri.len - uc->location->len + escape);
-
- } else {
- p = ngx_cpymem(buf, r->uri.data + uc->location->len,
- r->uri.len - uc->location->len);
- }
-
- len -= p - buf;
- buf = p;
-
- if (r->args.len) {
- p = ngx_snprintf(buf, len, "?%V", &r->args);
- len -= p - buf;
- buf = p;
- }
-
- return ngx_http_log_error_info(r, buf, len);
-}
-
-
-static size_t ngx_http_proxy_log_proxy_state_getlen(ngx_http_request_t *r,
- uintptr_t data)
-{
- ngx_http_proxy_ctx_t *p;
-
- p = ngx_http_get_module_err_ctx(r, ngx_http_proxy_module);
-
- if (p == NULL) {
- return 1;
- }
-
- return p->states.nelts * /* STUB */ 100;
-}
-
-
-static u_char *ngx_http_proxy_log_proxy_state(ngx_http_request_t *r,
- u_char *buf,
- ngx_http_log_op_t *op)
-{
- ngx_uint_t i;
- ngx_http_proxy_ctx_t *p;
- ngx_http_proxy_state_t *state;
-
- p = ngx_http_get_module_err_ctx(r, ngx_http_proxy_module);
-
- if (p == NULL) {
- *buf = '-';
- return buf + 1;
- }
-
- i = 0;
- state = p->states.elts;
-
- for ( ;; ) {
- if (state[i].cache_state == 0) {
- *buf++ = '-';
-
- } else {
- buf = ngx_cpymem(buf, cache_states[state[i].cache_state - 1].data,
- cache_states[state[i].cache_state - 1].len);
- }
-
- *buf++ = '/';
-
- if (state[i].expired == 0) {
- *buf++ = '-';
-
- } else {
- buf = ngx_sprintf(buf, "%T", state[i].expired);
- }
-
- *buf++ = '/';
-
- if (state[i].bl_time == 0) {
- *buf++ = '-';
-
- } else {
- buf = ngx_sprintf(buf, "%T", state[i].bl_time);
- }
-
- *buf++ = '/';
-
- *buf++ = '*';
-
- *buf++ = ' ';
-
- if (state[i].status == 0) {
- *buf++ = '-';
-
- } else {
- buf = ngx_sprintf(buf, "%ui", state[i].status);
- }
-
- *buf++ = '/';
-
- if (state[i].reason == 0) {
- *buf++ = '-';
-
- } else {
- buf = ngx_cpymem(buf, cache_reasons[state[i].reason - 1].data,
- cache_reasons[state[i].reason - 1].len);
- }
-
- *buf++ = '/';
-
- if (state[i].reason < NGX_HTTP_PROXY_CACHE_XAE) {
- *buf++ = '-';
-
- } else {
- buf = ngx_sprintf(buf, "%T", state[i].expires);
- }
-
- *buf++ = ' ';
- *buf++ = '*';
-
- if (++i == p->states.nelts) {
- return buf;
- }
-
- *buf++ = ',';
- *buf++ = ' ';
- }
-}
-
-
-#if 0
-
-static u_char *ngx_http_proxy_log_cache_state(ngx_http_request_t *r,
- u_char *buf, uintptr_t data)
-{
- ngx_uint_t i;
- ngx_http_proxy_ctx_t *p;
- ngx_http_proxy_state_t *state;
-
- p = ngx_http_get_module_err_ctx(r, ngx_http_proxy_module);
-
- if (p == NULL || p->state->cache_state == 0) {
- if (buf == NULL) {
- return (u_char *) 1;
- }
-
- *buf = '-';
- return buf + 1;
- }
-
- if (buf == NULL) {
- /* find the request line length */
- return (u_char *) (p->states.nelts * sizeof("BYPASS") - 1);
- }
-
- i = 0;
- state = p->states.elts;
-
- for ( ;; ) {
- buf = ngx_cpymem(buf, cache_states[state[i].cache_state - 1].data,
- cache_states[state[i].cache_state - 1].len);
-
- if (++i == p->states.nelts) {
- return buf;
- }
-
- *buf++ = ',';
- *buf++ = ' ';
- }
-}
-
-
-static u_char *ngx_http_proxy_log_reason(ngx_http_request_t *r, u_char *buf,
- uintptr_t data)
-{
- ngx_uint_t i;
- ngx_http_proxy_ctx_t *p;
- ngx_http_proxy_state_t *state;
-
- p = ngx_http_get_module_err_ctx(r, ngx_http_proxy_module);
-
- if (p == NULL || p->state->reason == 0) {
- if (buf == NULL) {
- return (u_char *) 1;
- }
-
- *buf = '-';
- return buf + 1;
- }
-
- if (buf == NULL) {
- /* find the request line length */
- return (u_char *) (p->states.nelts * sizeof("BPS") - 1);
- }
-
- i = 0;
- state = p->states.elts;
-
- for ( ;; ) {
- buf = ngx_cpymem(buf, cache_reasons[state[i].reason - 1].data,
- cache_reasons[state[i].reason - 1].len);
-
- if (++i == p->states.nelts) {
- return buf;
- }
-
- *buf++ = ',';
- *buf++ = ' ';
- }
-}
-
-#endif
-
-
-static ngx_int_t ngx_http_proxy_add_log_formats(ngx_conf_t *cf)
-{
- ngx_http_log_op_name_t *op;
-
- 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;
- }
- }
-
- op->run = (ngx_http_log_op_run_pt) ngx_http_proxy_log_fmt_ops;
-
- return NGX_OK;
-}
-
-
-static void *ngx_http_proxy_create_loc_conf(ngx_conf_t *cf)
-{
- ngx_http_proxy_loc_conf_t *conf;
-
- conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_proxy_loc_conf_t));
- if (conf == NULL) {
- return NGX_CONF_ERROR;
- }
-
- /*
- * set by ngx_pcalloc():
- *
- * conf->bufs.num = 0;
- * conf->path = NULL;
- * conf->next_upstream = 0;
- * conf->use_stale = 0;
- * conf->upstreams = NULL;
- * conf->peers = NULL;
- * conf->cache_path = NULL;
- * conf->temp_path = NULL;
- * conf->x_vars;
- * conf->busy_lock = NULL;
- */
-
- conf->connect_timeout = NGX_CONF_UNSET_MSEC;
- conf->send_timeout = NGX_CONF_UNSET_MSEC;
- conf->send_lowat = NGX_CONF_UNSET_SIZE;
-
- conf->pass_unparsed_uri = NGX_CONF_UNSET;
- 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->header_buffer_size = NGX_CONF_UNSET_SIZE;
- conf->read_timeout = NGX_CONF_UNSET_MSEC;
- conf->busy_buffers_size = NGX_CONF_UNSET_SIZE;
-
- conf->max_temp_file_size = NGX_CONF_UNSET_SIZE;
- conf->temp_file_write_size = NGX_CONF_UNSET_SIZE;
-
- /* "proxy_cyclic_temp_file" is disabled */
- conf->cyclic_temp_file = 0;
-
- conf->cache = NGX_CONF_UNSET;
-
- conf->pass_server = NGX_CONF_UNSET;
- conf->pass_x_accel_expires = NGX_CONF_UNSET;
- conf->ignore_expires = NGX_CONF_UNSET;
- conf->lm_factor = NGX_CONF_UNSET;
- conf->default_expires = NGX_CONF_UNSET;
-
- return conf;
-}
-
-
-static char *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_conf_merge_msec_value(conf->connect_timeout,
- prev->connect_timeout, 60000);
- 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_value(conf->pass_unparsed_uri, prev->pass_unparsed_uri, 0);
-
- if (conf->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_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);
-
- ngx_conf_merge_msec_value(conf->read_timeout, prev->read_timeout, 60000);
-
- ngx_conf_merge_size_value(conf->header_buffer_size,
- prev->header_buffer_size, (size_t) ngx_pagesize);
-
- ngx_conf_merge_bufs_value(conf->bufs, prev->bufs, 8, ngx_pagesize);
-
- if (conf->bufs.num < 2) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "there must be at least 2 \"proxy_buffers\"");
- return NGX_CONF_ERROR;
- }
-
- size = conf->header_buffer_size;
- if (size < conf->bufs.size) {
- size = conf->bufs.size;
- }
-
-
- ngx_conf_merge_size_value(conf->busy_buffers_size,
- prev->busy_buffers_size, NGX_CONF_UNSET_SIZE);
-
- if (conf->busy_buffers_size == NGX_CONF_UNSET_SIZE) {
- conf->busy_buffers_size = 2 * size;
-
- } else if (conf->busy_buffers_size < size) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "\"proxy_busy_buffers_size\" must be equal or bigger than "
- "maximum of the value of \"proxy_header_buffer_size\" and "
- "one of the \"proxy_buffers\"");
-
- return NGX_CONF_ERROR;
-
- } else if (conf->busy_buffers_size > (conf->bufs.num - 1) * conf->bufs.size)
- {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "\"proxy_busy_buffers_size\" must be less than "
- "the size of all \"proxy_buffers\" minus one buffer");
-
- return NGX_CONF_ERROR;
- }
-
-
- ngx_conf_merge_size_value(conf->temp_file_write_size,
- prev->temp_file_write_size, NGX_CONF_UNSET_SIZE);
-
- if (conf->temp_file_write_size == NGX_CONF_UNSET_SIZE) {
- conf->temp_file_write_size = 2 * size;
-
- } else if (conf->temp_file_write_size < size) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "\"proxy_temp_file_write_size\" must be equal or bigger than "
- "maximum of the value of \"proxy_header_buffer_size\" and "
- "one of the \"proxy_buffers\"");
-
- return NGX_CONF_ERROR;
- }
-
-
- ngx_conf_merge_size_value(conf->max_temp_file_size,
- prev->max_temp_file_size, NGX_CONF_UNSET_SIZE);
-
- if (conf->max_temp_file_size == NGX_CONF_UNSET_SIZE) {
-
- /*
- * "proxy_max_temp_file_size" is set to 1G for reverse proxy,
- * it should be much less in the generic proxy
- */
-
- conf->max_temp_file_size = 1024 * 1024 * 1024;
-
-#if 0
- conf->max_temp_file_size = 2 * size;
-#endif
-
-
- } else if (conf->max_temp_file_size != 0
- && conf->max_temp_file_size < size)
- {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "\"proxy_max_temp_file_size\" must be equal to zero to disable "
- "the temporary files usage or must be equal or bigger than "
- "maximum of the value of \"proxy_header_buffer_size\" and "
- "one of the \"proxy_buffers\"");
-
- return NGX_CONF_ERROR;
- }
-
-
- ngx_conf_merge_bitmask_value(conf->next_upstream, prev->next_upstream,
- (NGX_CONF_BITMASK_SET
- |NGX_HTTP_PROXY_FT_ERROR
- |NGX_HTTP_PROXY_FT_TIMEOUT));
-
- ngx_conf_merge_bitmask_value(conf->use_stale, prev->use_stale,
- NGX_CONF_BITMASK_SET);
-
-#if 0
- ngx_conf_merge_path_value(conf->cache_path, prev->cache_path,
- NGX_HTTP_PROXY_CACHE_PATH, 1, 2, 0,
- ngx_garbage_collector_temp_handler, cf);
-#endif
-
- ngx_conf_merge_path_value(conf->temp_path, prev->temp_path,
- NGX_HTTP_PROXY_TEMP_PATH, 1, 2, 0,
- ngx_garbage_collector_temp_handler, cf);
-
- ngx_conf_merge_value(conf->cache, prev->cache, 0);
-
-
- /* conf->cache must be merged */
-
- if (conf->busy_lock == NULL) {
- conf->busy_lock = prev->busy_lock;
- }
-
- if (conf->busy_lock && conf->cache && conf->busy_lock->md5 == NULL) {
-
- /* ngx_calloc_shared() */
- conf->busy_lock->md5_mask =
- ngx_pcalloc(cf->pool, (conf->busy_lock->max_busy + 7) / 8);
- if (conf->busy_lock->md5_mask == NULL) {
- return NGX_CONF_ERROR;
- }
-
- /* 16 bytes are 128 bits of the md5 */
-
- /* ngx_alloc_shared() */
- conf->busy_lock->md5 = ngx_palloc(cf->pool,
- 16 * conf->busy_lock->max_busy);
- if (conf->busy_lock->md5 == NULL) {
- return NGX_CONF_ERROR;
- }
- }
-
-
- ngx_conf_merge_value(conf->pass_server, prev->pass_server, 0);
- ngx_conf_merge_value(conf->pass_x_accel_expires,
- prev->pass_x_accel_expires, 0);
- ngx_conf_merge_value(conf->ignore_expires, prev->ignore_expires, 0);
- ngx_conf_merge_value(conf->lm_factor, prev->lm_factor, 0);
- ngx_conf_merge_sec_value(conf->default_expires, prev->default_expires, 0);
-
- if (conf->x_vars == NULL) {
- conf->x_vars = prev->x_vars;
- }
-
- if (conf->peers == NULL) {
- conf->peers = prev->peers;
- conf->upstream = prev->upstream;
- }
-
- return NULL;
-}
-
-
-static char *ngx_http_proxy_set_pass(ngx_conf_t *cf, ngx_command_t *cmd,
- void *conf)
-{
- ngx_http_proxy_loc_conf_t *lcf = conf;
-
- ngx_str_t *value, *url;
- 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;
-
- url = &value[1];
-
- if (ngx_strncasecmp(url->data, "http://", 7) != 0) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid URL prefix");
- return NGX_CONF_ERROR;
- }
-
- lcf->upstream = ngx_pcalloc(cf->pool,
- sizeof(ngx_http_proxy_upstream_conf_t));
- if (lcf->upstream == NULL) {
- return NGX_CONF_ERROR;
- }
-
- lcf->upstream->url = *url;
-
- if (ngx_strncasecmp(url->data + 7, "unix:", 5) == 0) {
-
-#if (NGX_HAVE_UNIX_DOMAIN)
-
- ngx_memzero(&unix_upstream, sizeof(ngx_unix_domain_upstream_t));
-
- unix_upstream.name = *url;
- unix_upstream.url.len = url->len - 7;
- 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) {
- return NGX_CONF_ERROR;
- }
-
- lcf->upstream->host_header.len = sizeof("localhost") - 1;
- lcf->upstream->host_header.data = (u_char *) "localhost";
- lcf->upstream->uri = unix_upstream.uri;
- lcf->upstream->uri_separator = ":";
- lcf->upstream->default_port = 1;
-
-#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 = *url;
- inet_upstream.url.len = url->len - 7;
- inet_upstream.url.data = url->data + 7;
- inet_upstream.default_port_value = 80;
- inet_upstream.uri_part = 1;
-
- lcf->peers = ngx_inet_upstream_parse(cf, &inet_upstream);
- if (lcf->peers == NULL) {
- return NGX_CONF_ERROR;
- }
-
- lcf->upstream->host_header = inet_upstream.host_header;
- lcf->upstream->port_text = inet_upstream.port_text;
- lcf->upstream->uri = inet_upstream.uri;
- lcf->upstream->uri_separator = "";
- lcf->upstream->default_port = inet_upstream.default_port;
- }
-
- clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
-
- clcf->handler = ngx_http_proxy_handler;
-
-#if (NGX_PCRE)
- lcf->upstream->location = clcf->regex ? &ngx_http_proxy_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_proxy_set_x_var(ngx_conf_t *cf, ngx_command_t *cmd,
- void *conf)
-{
- ngx_http_proxy_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->x_vars == NULL) {
- lcf->x_vars = ngx_array_create(cf->pool, 4,
- sizeof(ngx_http_variable_t *));
- if (lcf->x_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->x_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_proxy_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,
- "\"proxy_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,
- "\"proxy_send_lowat\" is not supported, ignored");
-
- *np = 0;
-
-#endif
-
- return NGX_CONF_OK;
-}
diff --git a/src/http/modules/proxy/ngx_http_proxy_handler.h b/src/http/modules/proxy/ngx_http_proxy_handler.h
deleted file mode 100644
index 2c9210f9c..000000000
--- a/src/http/modules/proxy/ngx_http_proxy_handler.h
+++ /dev/null
@@ -1,272 +0,0 @@
-
-/*
- * Copyright (C) Igor Sysoev
- */
-
-
-#ifndef _NGX_HTTP_PROXY_HANDLER_H_INCLUDED_
-#define _NGX_HTTP_PROXY_HANDLER_H_INCLUDED_
-
-
-#include <ngx_config.h>
-#include <ngx_core.h>
-#include <ngx_event.h>
-#include <ngx_event_connect.h>
-#include <ngx_event_pipe.h>
-#include <ngx_http.h>
-
-
-typedef enum {
- NGX_HTTP_PROXY_CACHE_PASS = 1,
- NGX_HTTP_PROXY_CACHE_BYPASS,
- NGX_HTTP_PROXY_CACHE_AUTH,
- NGX_HTTP_PROXY_CACHE_PGNC,
- NGX_HTTP_PROXY_CACHE_MISS,
- NGX_HTTP_PROXY_CACHE_EXPR,
- NGX_HTTP_PROXY_CACHE_AGED,
- NGX_HTTP_PROXY_CACHE_HIT
-} ngx_http_proxy_state_e;
-
-
-typedef enum {
- NGX_HTTP_PROXY_CACHE_BPS = 1,
- NGX_HTTP_PROXY_CACHE_XAE,
- NGX_HTTP_PROXY_CACHE_CTL,
- NGX_HTTP_PROXY_CACHE_EXP,
- NGX_HTTP_PROXY_CACHE_MVD,
- NGX_HTTP_PROXY_CACHE_LMF,
- NGX_HTTP_PROXY_CACHE_PDE
-} ngx_http_proxy_reason_e;
-
-
-typedef struct {
- ngx_str_t url;
- ngx_str_t host;
- ngx_str_t uri;
- ngx_str_t host_header;
- ngx_str_t port_text;
- ngx_str_t *location;
-
- char *uri_separator;
-
- in_port_t port;
-
- unsigned default_port:1;
-} ngx_http_proxy_upstream_conf_t;
-
-
-typedef struct {
- 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_msec_t connect_timeout;
- ngx_msec_t send_timeout;
- ngx_msec_t read_timeout;
- time_t default_expires;
-
- ngx_int_t lm_factor;
-
- ngx_uint_t next_upstream;
- ngx_uint_t use_stale;
-
- ngx_bufs_t bufs;
-
- ngx_flag_t cyclic_temp_file;
- ngx_flag_t cache;
- 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_unparsed_uri;
- ngx_flag_t pass_server;
- ngx_flag_t pass_x_accel_expires;
- ngx_flag_t ignore_expires;
-
- ngx_path_t *cache_path;
- ngx_path_t *temp_path;
-
- ngx_array_t *x_vars;
-
- ngx_http_busy_lock_t *busy_lock;
-
- ngx_http_proxy_upstream_conf_t *upstream;
- ngx_peers_t *peers;
-} ngx_http_proxy_loc_conf_t;
-
-
-/*
- * "EXPR/10/5/- 200/EXP/60 4"
- * "MISS/-/-/B 503/-/- -"
- * "EXPR/10/20/SB HIT/-/- -"
- * "EXPR/10/15/NB HIT/-/- -"
- */
-
-typedef struct {
- ngx_http_proxy_state_e cache_state;
- time_t expired;
- time_t bl_time;
- ngx_uint_t bl_state;
-
- ngx_uint_t status;
- ngx_http_proxy_reason_e reason;
- time_t time;
- time_t expires;
-
- ngx_str_t *peer;
-} ngx_http_proxy_state_t;
-
-
-typedef struct {
- ngx_list_t headers;
-#if 0
- ngx_table_t headers; /* it must be first field */
-#endif
-
- ngx_table_elt_t *date;
- ngx_table_elt_t *server;
-
- 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;
-
-
-typedef struct {
- ngx_http_cache_t ctx;
- ngx_uint_t status;
- ngx_str_t status_line;
-
- ngx_http_proxy_headers_in_t headers_in;
-} ngx_http_proxy_cache_t;
-
-
-typedef struct {
- ngx_peer_connection_t peer;
- ngx_uint_t status;
- ngx_str_t status_line;
- ngx_uint_t method;
-
- ngx_output_chain_ctx_t *output_chain_ctx;
- ngx_event_pipe_t *event_pipe;
-
- ngx_http_proxy_headers_in_t headers_in;
-} ngx_http_proxy_upstream_t;
-
-
-typedef struct ngx_http_proxy_ctx_s ngx_http_proxy_ctx_t;
-
-struct ngx_http_proxy_ctx_s {
- ngx_http_request_t *request;
- ngx_http_proxy_loc_conf_t *lcf;
- ngx_http_proxy_upstream_t *upstream;
- ngx_http_proxy_cache_t *cache;
-
- ngx_buf_t *header_in;
-
- ngx_http_busy_lock_ctx_t busy_lock;
-
- unsigned accel:1;
-
- unsigned cachable:1;
- unsigned stale:1;
- unsigned try_busy_lock:1;
- unsigned busy_locked:1;
- unsigned valid_header_in:1;
-
- unsigned request_sent:1;
- unsigned header_sent:1;
-
-
- /* used to parse an upstream HTTP header */
- ngx_uint_t status;
- u_char *status_start;
- u_char *status_end;
- ngx_uint_t status_count;
- ngx_uint_t parse_state;
-
- ngx_http_proxy_state_t *state;
- ngx_array_t states; /* of ngx_http_proxy_state_t */
-
- /*
- * we declare "action" as "char *" because the actions are usually
- * the static strings and in the "u_char *" case we have to override
- * all the time their types
- */
-
- char *action;
- ngx_http_log_ctx_t *saved_ctx;
- ngx_log_handler_pt saved_handler;
-};
-
-
-typedef struct {
- ngx_uint_t connection;
- ngx_http_proxy_ctx_t *proxy;
-} ngx_http_proxy_log_ctx_t;
-
-
-#define NGX_HTTP_PROXY_PARSE_NO_HEADER 30
-
-
-#define NGX_HTTP_PROXY_FT_ERROR 0x02
-#define NGX_HTTP_PROXY_FT_TIMEOUT 0x04
-#define NGX_HTTP_PROXY_FT_INVALID_HEADER 0x08
-#define NGX_HTTP_PROXY_FT_HTTP_500 0x10
-#define NGX_HTTP_PROXY_FT_HTTP_404 0x20
-#define NGX_HTTP_PROXY_FT_BUSY_LOCK 0x40
-#define NGX_HTTP_PROXY_FT_MAX_WAITING 0x80
-
-
-int ngx_http_proxy_request_upstream(ngx_http_proxy_ctx_t *p);
-
-#if (NGX_HTTP_FILE_CACHE)
-
-int ngx_http_proxy_get_cached_response(ngx_http_proxy_ctx_t *p);
-int ngx_http_proxy_send_cached_response(ngx_http_proxy_ctx_t *p);
-int ngx_http_proxy_is_cachable(ngx_http_proxy_ctx_t *p);
-int ngx_http_proxy_update_cache(ngx_http_proxy_ctx_t *p);
-
-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_busy_lock_handler(ngx_event_t *rev);
-void ngx_http_proxy_upstream_busy_lock(ngx_http_proxy_ctx_t *p);
-
-u_char *ngx_http_proxy_log_error(ngx_log_t *log, u_char *buf, size_t len);
-void ngx_http_proxy_finalize_request(ngx_http_proxy_ctx_t *p, int rc);
-void ngx_http_proxy_close_connection(ngx_http_proxy_ctx_t *p);
-
-int ngx_http_proxy_parse_status_line(ngx_http_proxy_ctx_t *p);
-int ngx_http_proxy_copy_header(ngx_http_proxy_ctx_t *p,
- ngx_http_proxy_headers_in_t *headers_in);
-
-
-
-extern ngx_module_t ngx_http_proxy_module;
-extern ngx_http_header_t ngx_http_proxy_headers_in[];
-
-
-
-#endif /* _NGX_HTTP_PROXY_HANDLER_H_INCLUDED_ */
diff --git a/src/http/modules/proxy/ngx_http_proxy_header.c b/src/http/modules/proxy/ngx_http_proxy_header.c
deleted file mode 100644
index a46ff9e2a..000000000
--- a/src/http/modules/proxy/ngx_http_proxy_header.c
+++ /dev/null
@@ -1,206 +0,0 @@
-
-/*
- * Copyright (C) Igor Sysoev
- */
-
-
-#include <ngx_config.h>
-#include <ngx_core.h>
-#include <ngx_http.h>
-#include <ngx_http_proxy_handler.h>
-
-
-static int ngx_http_proxy_rewrite_location_header(ngx_http_proxy_ctx_t *p,
- ngx_table_elt_t *loc);
-
-int ngx_http_proxy_copy_header(ngx_http_proxy_ctx_t *p,
- ngx_http_proxy_headers_in_t *headers_in)
-{
- ngx_uint_t i;
- ngx_list_part_t *part;
- ngx_table_elt_t *ho, *h;
- ngx_http_request_t *r;
-
- r = p->request;
-
- 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->connection) {
- continue;
- }
-
- if (&h[i] == headers_in->x_pad) {
- continue;
- }
-
- if (p->accel) {
- if (&h[i] == headers_in->date
- || &h[i] == headers_in->accept_ranges) {
- continue;
- }
-
- if (&h[i] == headers_in->x_accel_expires
- && !p->lcf->pass_x_accel_expires)
- {
- continue;
- }
-
- if (&h[i] == headers_in->server && !p->lcf->pass_server) {
- continue;
- }
-
- if (&h[i] == headers_in->location) {
- if (ngx_http_proxy_rewrite_location_header(p, &h[i])
- == NGX_ERROR)
- {
- return NGX_ERROR;
- }
-
- 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_ERROR;
- }
-
- *ho = h[i];
-
- if (&h[i] == headers_in->expires) {
- r->headers_out.expires = ho;
- continue;
- }
-
- if (&h[i] == headers_in->cache_control) {
- r->headers_out.cache_control = ho;
- continue;
- }
-
- if (&h[i] == headers_in->etag) {
- r->headers_out.etag = ho;
- continue;
- }
-
-#if (NGX_HTTP_GZIP)
- if (&h[i] == headers_in->content_encoding) {
- r->headers_out.content_encoding = ho;
- continue;
- }
-#endif
-
- if (&h[i] == headers_in->last_modified) {
- r->headers_out.last_modified = ho;
- /* TODO: update r->headers_out.last_modified_time */
- continue;
- }
-
- /*
- * ngx_http_header_filter() passes the following headers as is
- * and does not handle them specially if they are set:
- * r->headers_out.server,
- * r->headers_out.date,
- * r->headers_out.content_length
- */
-
- if (&h[i] == headers_in->server) {
- r->headers_out.server = ho;
- continue;
- }
-
- if (&h[i] == headers_in->date) {
- r->headers_out.date = ho;
- continue;
- }
-
- 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_OK;
-}
-
-
-static int ngx_http_proxy_rewrite_location_header(ngx_http_proxy_ctx_t *p,
- ngx_table_elt_t *loc)
-{
- u_char *last;
- ngx_table_elt_t *location;
- ngx_http_request_t *r;
- ngx_http_proxy_upstream_conf_t *uc;
-
- r = p->request;
- uc = p->lcf->upstream;
-
- location = ngx_list_push(&r->headers_out.headers);
- if (location == NULL) {
- return NGX_ERROR;
- }
-
- if (p->lcf->preserve_host
- || uc->url.len > loc->value.len
- || ngx_rstrncmp(loc->value.data, uc->url.data, uc->url.len) != 0)
- {
-
- /*
- * 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()
- */
-
- *location = *loc;
- return NGX_OK;
- }
-
- /* TODO: proxy_reverse */
-
- r->headers_out.location = location;
-
- location->key.len = 0;
- location->key.data = NULL;
-
- location->value.len = uc->location->len
- + (loc->value.len - uc->url.len) + 1;
- location->value.data = ngx_palloc(r->pool, location->value.len);
- if (location->value.data == NULL) {
- return NGX_ERROR;
- }
-
- last = ngx_cpymem(location->value.data,
- uc->location->data, uc->location->len);
-
- ngx_cpystrn(last, loc->value.data + uc->url.len,
- loc->value.len - uc->url.len + 1);
-
- return NGX_OK;
-}
diff --git a/src/http/modules/proxy/ngx_http_proxy_parse.c b/src/http/modules/proxy/ngx_http_proxy_parse.c
deleted file mode 100644
index c10cf4924..000000000
--- a/src/http/modules/proxy/ngx_http_proxy_parse.c
+++ /dev/null
@@ -1,216 +0,0 @@
-
-/*
- * Copyright (C) Igor Sysoev
- */
-
-
-#include <ngx_config.h>
-#include <ngx_core.h>
-#include <ngx_http.h>
-#include <ngx_http_proxy_handler.h>
-
-
-int ngx_http_proxy_parse_status_line(ngx_http_proxy_ctx_t *p)
-{
- u_char ch;
- u_char *pos;
- 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,
- sw_done
- } state;
-
- state = p->parse_state;
- pos = p->header_in->pos;
-
- while (pos < p->header_in->last && state < sw_done) {
- 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 - 3;
- }
-
- 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:
- state = sw_done;
- break;
- 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:
- state = sw_done;
- break;
- }
- break;
-
- /* end of request line */
- case sw_almost_done:
- p->status_end = pos - 2;
- switch (ch) {
- case LF:
- state = sw_done;
- break;
- default:
- return NGX_HTTP_PROXY_PARSE_NO_HEADER;
- }
- break;
-
- /* suppress warning */
- case sw_done:
- break;
- }
- }
-
- p->header_in->pos = pos;
-
- if (state == sw_done) {
- if (p->status_end == NULL) {
- p->status_end = pos - 1;
- }
-
- p->parse_state = sw_start;
- return NGX_OK;
- }
-
- p->parse_state = state;
- return NGX_AGAIN;
-}
diff --git a/src/http/modules/proxy/ngx_http_proxy_upstream.c b/src/http/modules/proxy/ngx_http_proxy_upstream.c
deleted file mode 100644
index 107aba3df..000000000
--- a/src/http/modules/proxy/ngx_http_proxy_upstream.c
+++ /dev/null
@@ -1,1646 +0,0 @@
-
-/*
- * Copyright (C) Igor Sysoev
- */
-
-
-#include <ngx_config.h>
-#include <ngx_core.h>
-#include <ngx_event.h>
-#include <ngx_event_connect.h>
-#include <ngx_event_pipe.h>
-#include <ngx_http.h>
-#include <ngx_http_proxy_handler.h>
-
-
-static ngx_chain_t *ngx_http_proxy_create_request(ngx_http_proxy_ctx_t *p);
-static void ngx_http_proxy_init_upstream(ngx_http_request_t *r);
-static void ngx_http_proxy_reinit_upstream(ngx_http_proxy_ctx_t *p);
-static void ngx_http_proxy_connect(ngx_http_proxy_ctx_t *p);
-static void ngx_http_proxy_send_request(ngx_http_proxy_ctx_t *p);
-static void ngx_http_proxy_send_request_handler(ngx_event_t *wev);
-static void ngx_http_proxy_dummy_handler(ngx_event_t *wev);
-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_body(ngx_event_t *ev);
-static void ngx_http_proxy_next_upstream(ngx_http_proxy_ctx_t *p,
- ngx_uint_t ft_type);
-
-
-static ngx_str_t http_methods[] = {
- ngx_string("GET "),
- ngx_string("HEAD "),
- ngx_string("POST ")
-};
-
-
-static char *upstream_header_errors[] = {
- "upstream sent invalid header",
- "upstream sent too long header line"
-};
-
-
-static char http_version[] = " HTTP/1.0" CRLF;
-static char host_header[] = "Host: ";
-static char x_url_header[] = "X-URL: http";
-static char x_real_ip_header[] = "X-Real-IP: ";
-static char x_forwarded_for_header[] = "X-Forwarded-For: ";
-static char connection_close_header[] = "Connection: close" CRLF;
-
-
-int ngx_http_proxy_request_upstream(ngx_http_proxy_ctx_t *p)
-{
- int rc;
- ngx_http_request_t *r;
- ngx_http_proxy_upstream_t *u;
-
- r = p->request;
-
- u = ngx_pcalloc(r->pool, sizeof(ngx_http_proxy_upstream_t));
- if (u == NULL) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- p->upstream = u;
-
- u->peer.log_error = NGX_ERROR_ERR;
- u->peer.peers = p->lcf->peers;
- u->peer.tries = p->lcf->peers->number;
-#if (NGX_THREADS)
- u->peer.lock = &r->connection->lock;
-#endif
-
- u->method = r->method;
-
- rc = ngx_http_read_client_request_body(r, ngx_http_proxy_init_upstream);
-
- if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
- return rc;
- }
-
- return NGX_DONE;
-}
-
-
-static ngx_chain_t *ngx_http_proxy_create_request(ngx_http_proxy_ctx_t *p)
-{
- size_t len;
- ngx_uint_t i, escape, *index;
- ngx_buf_t *b;
- ngx_chain_t *chain;
- ngx_list_part_t *part;
- ngx_table_elt_t *header;
- ngx_http_request_t *r;
- ngx_http_variable_t *var;
- ngx_http_variable_value_t *value;
- ngx_http_core_main_conf_t *cmcf;
- ngx_http_proxy_upstream_conf_t *uc;
-
- r = p->request;
- uc = p->lcf->upstream;
-
-#if (NGX_SUPPRESS_WARN)
- var = NULL;
- index = NULL;
-#endif
-
- escape = 0;
-
- if (p->upstream->method) {
- len = http_methods[p->upstream->method - 1].len + uc->uri.len;
-
- } else {
- len = r->method_name.len + uc->uri.len;
- }
-
- if (p->lcf->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 + uc->location->len,
- r->uri.len - uc->location->len,
- NGX_ESCAPE_URI);
- }
-
- len += r->uri.len - uc->location->len + escape
- + sizeof("?") - 1 + r->args.len;
- }
-
- len += sizeof(http_version) - 1
- + sizeof(connection_close_header) - 1
- + sizeof(CRLF) - 1;
-
-
- if (p->lcf->set_x_url) {
- len += sizeof(x_url_header) - 1
- + sizeof("s://") - 1
- + r->port_text->len
- + r->unparsed_uri.len
- + sizeof(CRLF) - 1;
-
- if (r->headers_in.host) {
- len += r->headers_in.host_name_len;
-
- } else {
- len += r->server_name.len;
- }
-
- }
-
-
- if (p->lcf->preserve_host) {
- if (r->headers_in.host) {
- len += sizeof(host_header) - 1
- + r->headers_in.host_name_len + sizeof(":") - 1
- + uc->port_text.len + sizeof(CRLF) - 1;
-
- } else {
- len += sizeof(host_header) - 1
- + r->server_name.len + sizeof(":") - 1
- + uc->port_text.len + sizeof(CRLF) - 1;
- }
-
- } else {
- len += sizeof(host_header) - 1 + uc->host_header.len
- + sizeof(CRLF) - 1;
- }
-
-
- if (p->lcf->set_x_real_ip) {
- len += sizeof(x_real_ip_header) - 1 + INET_ADDRSTRLEN - 1
- + sizeof(CRLF) - 1;
- }
-
-
- if (p->lcf->add_x_forwarded_for) {
- if (r->headers_in.x_forwarded_for) {
- len += sizeof(x_forwarded_for_header) - 1
- + r->headers_in.x_forwarded_for->value.len
- + sizeof(", ") - 1 + INET_ADDRSTRLEN - 1 + sizeof(CRLF) - 1;
-
- } else {
- len += sizeof(x_forwarded_for_header) - 1 + INET_ADDRSTRLEN - 1
- + sizeof(CRLF) - 1;
- }
- }
-
-
- if (p->lcf->x_vars) {
- cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
-
- var = cmcf->variables.elts;
- index = p->lcf->x_vars->elts;
-
- for (i = 0; i < p->lcf->x_vars->nelts; i++) {
-
- value = ngx_http_get_indexed_variable(r, index[i]);
- if (value == NULL) {
- continue;
- }
-
- if (value->text.len) {
- len += sizeof("X-") - 1 + var[index[i]].name.len
- + sizeof(": ") - 1 + value->text.len + sizeof(CRLF) - 1;
- }
- }
- }
-
-
- part = &r->headers_in.headers.part;
- header = part->elts;
-
- for (i = 0; /* void */; i++) {
-
- if (i >= part->nelts) {
- if (part->next == NULL) {
- break;
- }
-
- part = part->next;
- header = part->elts;
- i = 0;
- }
-
- if (&header[i] == r->headers_in.host) {
- continue;
- }
-
- if (&header[i] == r->headers_in.connection) {
- continue;
- }
-
- len += header[i].key.len + sizeof(": ") - 1
- + header[i].value.len + sizeof(CRLF) - 1;
- }
-
-#if (NGX_DEBUG)
- len++;
-#endif
-
- b = ngx_create_temp_buf(r->pool, len);
- if (b == NULL) {
- return NULL;
- }
-
- chain = ngx_alloc_chain_link(r->pool);
- if (chain == NULL) {
- return NULL;
- }
-
- chain->buf = b;
- chain->next = NULL;
-
-
- /* the request line */
-
- if (p->upstream->method) {
- b->last = ngx_cpymem(b->last,
- 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, uc->uri.data, uc->uri.len);
-
- if (p->lcf->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 + uc->location->len,
- r->uri.len - uc->location->len, NGX_ESCAPE_URI);
- b->last += r->uri.len - uc->location->len + escape;
-
- } else {
- b->last = ngx_cpymem(b->last, r->uri.data + uc->location->len,
- r->uri.len - uc->location->len);
- }
-
- if (r->args.len > 0) {
- *b->last++ = '?';
- b->last = ngx_cpymem(b->last, r->args.data, r->args.len);
- }
- }
-
- b->last = ngx_cpymem(b->last, http_version, sizeof(http_version) - 1);
-
-
- /* the "Connection: close" header */
-
- b->last = ngx_cpymem(b->last, connection_close_header,
- sizeof(connection_close_header) - 1);
-
-
- /* the "Host" header */
-
- b->last = ngx_cpymem(b->last, host_header, sizeof(host_header) - 1);
-
- if (p->lcf->preserve_host) {
- if (r->headers_in.host) {
- b->last = ngx_cpymem(b->last, r->headers_in.host->value.data,
- r->headers_in.host_name_len);
- } else {
- b->last = ngx_cpymem(b->last, r->server_name.data,
- r->server_name.len);
- }
-
- if (!uc->default_port) {
- *b->last++ = ':';
- b->last = ngx_cpymem(b->last, uc->port_text.data,
- uc->port_text.len);
- }
-
- } else {
- b->last = ngx_cpymem(b->last, uc->host_header.data,
- uc->host_header.len);
- }
- *b->last++ = CR; *b->last++ = LF;
-
-
- /* the "X-URL" header */
-
- if (p->lcf->set_x_url) {
-
- b->last = ngx_cpymem(b->last, x_url_header,
- sizeof(x_url_header) - 1);
-
-#if (NGX_OPENSSL)
-
- if (r->connection->ssl) {
- *b->last++ = 's';
- }
-
-#endif
-
- *b->last++ = ':'; *b->last++ = '/'; *b->last++ = '/';
-
- if (r->headers_in.host) {
- b->last = ngx_cpymem(b->last, r->headers_in.host->value.data,
- r->headers_in.host_name_len);
- } else {
- b->last = ngx_cpymem(b->last, r->server_name.data,
- r->server_name.len);
- }
-
- b->last = ngx_cpymem(b->last, r->port_text->data, r->port_text->len);
- b->last = ngx_cpymem(b->last, r->unparsed_uri.data,
- r->unparsed_uri.len);
-
- *b->last++ = CR; *b->last++ = LF;
- }
-
-
- /* the "X-Real-IP" header */
-
- if (p->lcf->set_x_real_ip) {
- b->last = ngx_cpymem(b->last, x_real_ip_header,
- sizeof(x_real_ip_header) - 1);
- b->last = ngx_cpymem(b->last, r->connection->addr_text.data,
- r->connection->addr_text.len);
- *b->last++ = CR; *b->last++ = LF;
- }
-
-
- /* the "X-Forwarded-For" header */
-
- if (p->lcf->add_x_forwarded_for) {
- if (r->headers_in.x_forwarded_for) {
- b->last = ngx_cpymem(b->last, x_forwarded_for_header,
- sizeof(x_forwarded_for_header) - 1);
-
- b->last = ngx_cpymem(b->last,
- r->headers_in.x_forwarded_for->value.data,
- r->headers_in.x_forwarded_for->value.len);
-
- *b->last++ = ','; *b->last++ = ' ';
-
- } else {
- b->last = ngx_cpymem(b->last, x_forwarded_for_header,
- sizeof(x_forwarded_for_header) - 1);
- }
-
- b->last = ngx_cpymem(b->last, r->connection->addr_text.data,
- r->connection->addr_text.len);
- *b->last++ = CR; *b->last++ = LF;
- }
-
-
- if (p->lcf->x_vars) {
- for (i = 0; i < p->lcf->x_vars->nelts; i++) {
-
- value = ngx_http_get_indexed_variable(r, index[i]);
- if (value == NULL) {
- continue;
- }
-
- if (value->text.len == 0) {
- continue;
- }
-
- *b->last++ = 'X'; *b->last++ = '-';
-
- b->last = ngx_cpymem(b->last, var[index[i]].name.data,
- var[index[i]].name.len);
-
- *b->last++ = ':'; *b->last++ = ' ';
-
- b->last = ngx_cpymem(b->last, value->text.data, value->text.len);
-
- *b->last++ = CR; *b->last++ = LF;
- }
- }
-
-
- part = &r->headers_in.headers.part;
- header = part->elts;
-
- for (i = 0; /* void */; i++) {
-
- if (i >= part->nelts) {
- if (part->next == NULL) {
- break;
- }
-
- part = part->next;
- header = part->elts;
- i = 0;
- }
-
- if (&header[i] == r->headers_in.host) {
- continue;
- }
-
- if (&header[i] == r->headers_in.connection) {
- continue;
- }
-
- if (&header[i] == r->headers_in.keep_alive) {
- continue;
- }
-
- if (&header[i] == r->headers_in.x_forwarded_for
- && p->lcf->add_x_forwarded_for)
- {
- continue;
- }
-
- if (&header[i] == r->headers_in.x_real_ip && p->lcf->set_x_real_ip) {
- continue;
- }
-
- if (&header[i] == r->headers_in.x_url && p->lcf->set_x_url) {
- continue;
- }
-
- b->last = ngx_cpymem(b->last, header[i].key.data, header[i].key.len);
-
- *b->last++ = ':'; *b->last++ = ' ';
-
- b->last = ngx_cpymem(b->last, header[i].value.data,
- header[i].value.len);
-
- *b->last++ = 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);
- }
-
- /* add "\r\n" at the header end */
- *b->last++ = CR; *b->last++ = LF;
-
-#if (NGX_DEBUG)
- *b->last = '\0';
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http proxy header:\n\"%s\"", b->pos);
-#endif
-
- return chain;
-}
-
-
-static void ngx_http_proxy_init_upstream(ngx_http_request_t *r)
-{
-
- ngx_chain_t *cl;
- ngx_http_proxy_ctx_t *p;
- ngx_output_chain_ctx_t *output;
- ngx_chain_writer_ctx_t *writer;
- ngx_http_proxy_log_ctx_t *ctx;
-
- p = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http proxy init upstream, client timer: %d",
- r->connection->read->timer_set);
-
- if (r->connection->read->timer_set) {
- ngx_del_timer(r->connection->read);
- }
-
- r->connection->read->event_handler = ngx_http_proxy_check_broken_connection;
-
- if (ngx_event_flags & NGX_USE_CLEAR_EVENT) {
-
- r->connection->write->event_handler =
- ngx_http_proxy_check_broken_connection;
-
- if (!r->connection->write->active) {
- if (ngx_add_event(r->connection->write, NGX_WRITE_EVENT,
- NGX_CLEAR_EVENT) == NGX_ERROR)
- {
- ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
- return;
- }
- }
- }
-
-
- cl = ngx_http_proxy_create_request(p);
- if (cl == NULL) {
- ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
- return;
- }
-
- if (r->request_body->bufs) {
- cl->next = r->request_body->bufs;
- }
-
- r->request_body->bufs = cl;
-
- ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_proxy_log_ctx_t));
- if (ctx == NULL) {
- ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR);
- return;
- }
- ctx->connection = r->connection->number;
- ctx->proxy = p;
-
- p->upstream->peer.log = r->connection->log;
- p->saved_ctx = r->connection->log->data;
- p->saved_handler = r->connection->log->handler;
- r->connection->log->data = ctx;
- r->connection->log->handler = ngx_http_proxy_log_error;
- p->action = "connecting to upstream";
-
- output = ngx_pcalloc(r->pool, sizeof(ngx_output_chain_ctx_t));
- if (output == NULL) {
- ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR);
- return;
- }
-
- p->upstream->output_chain_ctx = output;
-
- output->sendfile = r->connection->sendfile;
- output->pool = r->pool;
- output->bufs.num = 1;
- output->tag = (ngx_buf_tag_t) &ngx_http_proxy_module;
- output->output_filter = ngx_chain_writer;
-
- writer = ngx_palloc(r->pool, sizeof(ngx_chain_writer_ctx_t));
- if (writer == NULL) {
- ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR);
- return;
- }
-
- output->filter_ctx = writer;
- writer->pool = r->pool;
-
-#if 0
- if (p->lcf->busy_lock && p->busy_lock == NULL) {
-#else
- if (p->lcf->busy_lock && !p->busy_locked) {
-#endif
- ngx_http_proxy_upstream_busy_lock(p);
- } else {
- ngx_http_proxy_connect(p);
- }
-}
-
-
-static void ngx_http_proxy_reinit_upstream(ngx_http_proxy_ctx_t *p)
-{
- ngx_chain_t *cl;
- ngx_output_chain_ctx_t *output;
- ngx_http_proxy_state_e state;
-
- /* reinit the request chain */
-
- for (cl = p->request->request_body->bufs; cl; cl = cl->next) {
- cl->buf->pos = cl->buf->start;
- cl->buf->file_pos = 0;
- }
-
- /* reinit the ngx_output_chain() context */
-
- output = p->upstream->output_chain_ctx;
-
- output->buf = NULL;
- output->in = NULL;
- output->free = NULL;
- output->busy = NULL;
-
- /* reinit r->header_in buffer */
-
- if (p->header_in) {
- if (p->cache) {
- p->header_in->pos = p->header_in->start + p->cache->ctx.header_size;
- p->header_in->last = p->header_in->pos;
-
- } else {
- p->header_in->pos = p->header_in->start;
- p->header_in->last = p->header_in->start;
- }
- }
-
- /* add one more state */
-
- state = p->state->cache_state;
-
- p->state = ngx_array_push(&p->states);
- if (p->state == NULL) {
- ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR);
- return;
- }
-
- ngx_memzero(p->state, sizeof(ngx_http_proxy_state_t));
-
- p->state->cache_state = state;
-
- p->status = 0;
- p->status_count = 0;
-}
-
-
-#if 0
-
-void ngx_http_proxy_upstream_busy_lock(ngx_http_proxy_ctx_t *p)
-{
- ngx_int_t rc;
-
- rc = ngx_event_busy_lock(p->lcf->busy_lock, p->busy_lock);
-
- if (rc == NGX_AGAIN) {
- return;
- }
-
- if (rc == NGX_OK) {
- ngx_http_proxy_connect(p);
- return;
- }
-
- if (rc == NGX_ERROR) {
- p->state->status = NGX_HTTP_INTERNAL_SERVER_ERROR;
- ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR);
- return;
- }
-
- /* rc == NGX_BUSY */
-
-#if (NGX_HTTP_CACHE)
-
- if (p->busy_lock->timer) {
- ft_type = NGX_HTTP_PROXY_FT_MAX_WAITING;
- } else {
- ft_type = NGX_HTTP_PROXY_FT_BUSY_LOCK;
- }
-
- if (p->stale && (p->lcf->use_stale & ft_type)) {
- ngx_http_proxy_finalize_request(p,
- ngx_http_proxy_send_cached_response(p));
- return;
- }
-
-#endif
-
- p->state->status = NGX_HTTP_SERVICE_UNAVAILABLE;
- ngx_http_proxy_finalize_request(p, NGX_HTTP_SERVICE_UNAVAILABLE);
-}
-
-#endif
-
-
-#if 1
-
-void ngx_http_proxy_upstream_busy_lock(ngx_http_proxy_ctx_t *p)
-{
- ngx_int_t rc;
-#if (NGX_HTTP_CACHE)
- ngx_int_t ft_type;
-#endif
-
- if (p->busy_lock.time == 0) {
- p->busy_lock.event = p->request->connection->read;
- p->busy_lock.event_handler = ngx_http_proxy_busy_lock_handler;
- }
-
- rc = ngx_http_busy_lock(p->lcf->busy_lock, &p->busy_lock);
-
- if (rc == NGX_AGAIN) {
- return;
- }
-
- if (rc == NGX_OK) {
- ngx_http_proxy_connect(p);
- return;
- }
-
- ngx_http_busy_unlock(p->lcf->busy_lock, &p->busy_lock);
-
-#if (NGX_HTTP_CACHE)
-
- if (rc == NGX_DONE) {
- ft_type = NGX_HTTP_PROXY_FT_BUSY_LOCK;
-
- } else {
- /* rc == NGX_ERROR */
- ft_type = NGX_HTTP_PROXY_FT_MAX_WAITING;
- }
-
- if (p->stale && (p->lcf->use_stale & ft_type)) {
- ngx_http_proxy_finalize_request(p,
- ngx_http_proxy_send_cached_response(p));
- return;
- }
-
-#endif
-
- p->state->status = NGX_HTTP_SERVICE_UNAVAILABLE;
- ngx_http_proxy_finalize_request(p, NGX_HTTP_SERVICE_UNAVAILABLE);
-}
-
-#endif
-
-
-static void ngx_http_proxy_connect(ngx_http_proxy_ctx_t *p)
-{
- ngx_int_t rc;
- ngx_connection_t *c;
- ngx_http_request_t *r;
- ngx_output_chain_ctx_t *output;
- ngx_chain_writer_ctx_t *writer;
-
- p->action = "connecting to upstream";
-
- p->request->connection->single_connection = 0;
-
- rc = ngx_event_connect_peer(&p->upstream->peer);
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, p->request->connection->log, 0,
- "http proxy connect: %i", rc);
-
- if (rc == NGX_ERROR) {
- ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR);
- return;
- }
-
- p->state->peer =
- &p->upstream->peer.peers->peer[p->upstream->peer.cur_peer].name;
-
- if (rc == NGX_CONNECT_ERROR) {
- ngx_http_proxy_next_upstream(p, NGX_HTTP_PROXY_FT_ERROR);
- return;
- }
-
- r = p->request;
- 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->sendfile = r->connection->sendfile;
-
- c->pool = r->pool;
- c->read->log = c->write->log = c->log = r->connection->log;
-
- /* init or reinit the ngx_output_chain() and ngx_chain_writer() contexts */
-
- output = p->upstream->output_chain_ctx;
- writer = output->filter_ctx;
- writer->out = NULL;
- writer->last = &writer->out;
- writer->connection = c;
- writer->limit = 0;
-
- if (p->request_sent) {
- ngx_http_proxy_reinit_upstream(p);
- }
-
- if (r->request_body->buf) {
- if (r->request_body->temp_file) {
-
- output->free = ngx_alloc_chain_link(r->pool);
- if (output->free == NULL) {
- ngx_http_proxy_finalize_request(p,
- NGX_HTTP_INTERNAL_SERVER_ERROR);
- return;
- }
-
- output->free->buf = r->request_body->buf;
- output->free->next = NULL;
- output->allocated = 1;
-
- r->request_body->buf->pos = r->request_body->buf->start;
- r->request_body->buf->last = r->request_body->buf->start;
- r->request_body->buf->tag = (ngx_buf_tag_t) &ngx_http_proxy_module;
-
- } else {
- r->request_body->buf->pos = r->request_body->buf->start;
- }
- }
-
- p->request_sent = 0;
-
- if (rc == NGX_AGAIN) {
- ngx_add_timer(c->write, p->lcf->connect_timeout);
- return;
- }
-
- /* rc == NGX_OK */
-
-#if 0 /* test only, see below about "post aio operation" */
-
- if (c->read->ready) {
- /* post aio operation */
- ngx_http_proxy_process_upstream_status_line(c->read);
-#if 0
- return;
-#endif
- }
-
-#endif
-
- ngx_http_proxy_send_request(p);
-}
-
-
-static void ngx_http_proxy_send_request(ngx_http_proxy_ctx_t *p)
-{
- int rc;
- ngx_connection_t *c;
-
- c = p->upstream->peer.connection;
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
- "http proxy send request");
-
-#if (NGX_HAVE_KQUEUE)
-
- if ((ngx_event_flags & NGX_USE_KQUEUE_EVENT)
- && !p->request_sent
- && c->write->pending_eof)
- {
- ngx_log_error(NGX_LOG_ERR, c->log, c->write->kq_errno,
- "connect() failed");
-
- ngx_http_proxy_next_upstream(p, NGX_HTTP_PROXY_FT_ERROR);
- return;
- }
-
-#endif
-
- p->action = "sending request to upstream";
-
- rc = ngx_output_chain(p->upstream->output_chain_ctx,
- p->request_sent ? NULL:
- p->request->request_body->bufs);
-
- p->request_sent = 1;
-
- if (rc == NGX_ERROR) {
- ngx_http_proxy_next_upstream(p, NGX_HTTP_PROXY_FT_ERROR);
- return;
- }
-
- if (c->write->timer_set) {
- ngx_del_timer(c->write);
- }
-
- if (rc == NGX_AGAIN) {
- ngx_add_timer(c->write, p->lcf->send_timeout);
-
- if (ngx_handle_write_event(c->write, p->lcf->send_lowat) == NGX_ERROR) {
- ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR);
- return;
- }
-
- return;
- }
-
- /* rc == NGX_OK */
-
- if (c->tcp_nopush == NGX_TCP_NOPUSH_SET) {
- if (ngx_tcp_push(c->fd) == NGX_ERROR) {
- ngx_log_error(NGX_LOG_CRIT, c->log,
- ngx_socket_errno,
- ngx_tcp_push_n " failed");
- ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR);
- return;
- }
-
- c->tcp_nopush = NGX_TCP_NOPUSH_UNSET;
- return;
- }
-
- ngx_add_timer(c->read, p->lcf->read_timeout);
-
-#if 1
- if (c->read->ready) {
-
- /* post aio operation */
-
- /*
- * although we can post aio operation just in the end
- * of ngx_http_proxy_connect() CHECK IT !!!
- * it's better to do here because we postpone header buffer allocation
- */
-
- ngx_http_proxy_process_upstream_status_line(c->read);
- return;
- }
-#endif
-
- c->write->event_handler = ngx_http_proxy_dummy_handler;
-
- if (ngx_handle_level_write_event(c->write) == NGX_ERROR) {
- ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR);
- return;
- }
-}
-
-
-static void ngx_http_proxy_send_request_handler(ngx_event_t *wev)
-{
- ngx_connection_t *c;
- ngx_http_proxy_ctx_t *p;
-
- c = wev->data;
- p = c->data;
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, wev->log, 0,
- "http proxy send request handler");
-
- if (wev->timedout) {
- p->action = "sending request to upstream";
- ngx_http_proxy_next_upstream(p, NGX_HTTP_PROXY_FT_TIMEOUT);
- return;
- }
-
- if (p->request->connection->write->eof
- && (!p->cachable || !p->request_sent))
- {
- ngx_http_proxy_finalize_request(p, NGX_HTTP_CLIENT_CLOSED_REQUEST);
- return;
- }
-
- ngx_http_proxy_send_request(p);
-}
-
-
-static void ngx_http_proxy_dummy_handler(ngx_event_t *wev)
-{
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, wev->log, 0, "http proxy dummy handler");
-}
-
-
-static void ngx_http_proxy_process_upstream_status_line(ngx_event_t *rev)
-{
- int rc;
- ssize_t n;
- ngx_connection_t *c;
- ngx_http_proxy_ctx_t *p;
-
- c = rev->data;
- p = c->data;
- p->action = "reading upstream status line";
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0,
- "http proxy process status line");
-
- if (rev->timedout) {
- ngx_http_proxy_next_upstream(p, NGX_HTTP_PROXY_FT_TIMEOUT);
- return;
- }
-
- if (p->header_in == NULL) {
- p->header_in = ngx_create_temp_buf(p->request->pool,
- p->lcf->header_buffer_size);
- if (p->header_in == NULL) {
- ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR);
- return;
- }
- p->header_in->tag = (ngx_buf_tag_t) &ngx_http_proxy_module;
-
- if (p->cache) {
- p->header_in->pos += p->cache->ctx.header_size;
- p->header_in->last = p->header_in->pos;
- }
- }
-
- n = ngx_http_proxy_read_upstream_header(p);
-
- if (n == NGX_AGAIN) {
- return;
- }
-
- if (n == 0) {
- ngx_log_error(NGX_LOG_ERR, rev->log, 0,
- "upstream prematurely closed connection");
- }
-
- if (n == NGX_ERROR || n == 0) {
- ngx_http_proxy_next_upstream(p, NGX_HTTP_PROXY_FT_ERROR);
- return;
- }
-
- p->valid_header_in = 0;
-
- p->upstream->peer.cached = 0;
-
- rc = ngx_http_proxy_parse_status_line(p);
-
- if (rc == NGX_AGAIN) {
- if (p->header_in->pos == p->header_in->end) {
- ngx_log_error(NGX_LOG_ERR, rev->log, 0,
- "upstream sent too long status line");
- ngx_http_proxy_next_upstream(p, NGX_HTTP_PROXY_FT_INVALID_HEADER);
- }
- return;
- }
-
- if (rc == NGX_HTTP_PROXY_PARSE_NO_HEADER) {
- ngx_log_error(NGX_LOG_ERR, rev->log, 0,
- "upstream sent no valid HTTP/1.0 header");
-
- if (p->accel) {
- ngx_http_proxy_next_upstream(p, NGX_HTTP_PROXY_FT_INVALID_HEADER);
-
- } else {
- p->request->http_version = NGX_HTTP_VERSION_9;
- p->upstream->status = NGX_HTTP_OK;
- ngx_http_proxy_send_response(p);
- }
-
- return;
- }
-
- /* rc == NGX_OK */
-
- p->upstream->status = p->status;
- p->state->status = p->status;
-
- if (p->status == NGX_HTTP_INTERNAL_SERVER_ERROR) {
-
- if (p->upstream->peer.tries > 1
- && (p->lcf->next_upstream & NGX_HTTP_PROXY_FT_HTTP_500))
- {
- ngx_http_proxy_next_upstream(p, NGX_HTTP_PROXY_FT_HTTP_500);
- return;
- }
-
-#if (NGX_HTTP_CACHE)
-
- if (p->upstream->peer.tries == 0
- && p->stale
- && (p->lcf->use_stale & NGX_HTTP_PROXY_FT_HTTP_500))
- {
- ngx_http_proxy_finalize_request(p,
- ngx_http_proxy_send_cached_response(p));
-
- return;
- }
-
-#endif
- }
-
- if (p->status == NGX_HTTP_NOT_FOUND
- && p->upstream->peer.tries > 1
- && p->lcf->next_upstream & NGX_HTTP_PROXY_FT_HTTP_404)
- {
- ngx_http_proxy_next_upstream(p, NGX_HTTP_PROXY_FT_HTTP_404);
- return;
- }
-
- /* TODO: "proxy_error_page" */
-
- p->upstream->status_line.len = p->status_end - p->status_start;
- p->upstream->status_line.data = ngx_palloc(p->request->pool,
- p->upstream->status_line.len + 1);
- if (p->upstream->status_line.data == NULL) {
- ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR);
- return;
- }
- ngx_cpystrn(p->upstream->status_line.data, p->status_start,
- p->upstream->status_line.len + 1);
-
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, rev->log, 0,
- "http proxy status %ui \"%V\"",
- p->upstream->status, &p->upstream->status_line);
-
-
- /* init or reinit the p->upstream->headers_in.headers table */
-
- if (p->upstream->headers_in.headers.part.elts) {
- p->upstream->headers_in.headers.part.nelts = 0;
- p->upstream->headers_in.headers.part.next = NULL;
- p->upstream->headers_in.headers.last =
- &p->upstream->headers_in.headers.part;
-
- ngx_memzero(&p->upstream->headers_in.date,
- sizeof(ngx_http_proxy_headers_in_t) - sizeof(ngx_list_t));
-
- } else {
- if (ngx_list_init(&p->upstream->headers_in.headers, p->request->pool,
- 20, sizeof(ngx_table_elt_t)) == NGX_ERROR)
- {
- ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR);
- return;
- }
- }
-
-
- c->read->event_handler = ngx_http_proxy_process_upstream_headers;
- ngx_http_proxy_process_upstream_headers(rev);
-}
-
-
-static void ngx_http_proxy_process_upstream_headers(ngx_event_t *rev)
-{
- int i, rc;
- ssize_t n;
- ngx_table_elt_t *h;
- ngx_connection_t *c;
- ngx_http_request_t *r;
- ngx_http_proxy_ctx_t *p;
-
- c = rev->data;
- p = c->data;
- r = p->request;
- p->action = "reading upstream headers";
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0,
- "http proxy process header line");
-
- if (rev->timedout) {
- ngx_http_proxy_next_upstream(p, NGX_HTTP_PROXY_FT_TIMEOUT);
- return;
- }
-
- rc = NGX_AGAIN;
-
- for ( ;; ) {
- if (rc == NGX_AGAIN) {
- n = ngx_http_proxy_read_upstream_header(p);
-
- if (n == 0) {
- ngx_log_error(NGX_LOG_ERR, rev->log, 0,
- "upstream prematurely closed connection");
- }
-
- if (n == NGX_ERROR || n == 0) {
- ngx_http_proxy_next_upstream(p, NGX_HTTP_PROXY_FT_ERROR);
- return;
- }
-
- if (n == NGX_AGAIN) {
- return;
- }
- }
-
- rc = ngx_http_parse_header_line(p->request, p->header_in);
-
- if (rc == NGX_OK) {
-
- /* a header line has been parsed successfully */
-
- h = ngx_list_push(&p->upstream->headers_in.headers);
- if (h == NULL) {
- ngx_http_proxy_finalize_request(p,
- NGX_HTTP_INTERNAL_SERVER_ERROR);
- return;
- }
-
- 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(p->request->pool,
- h->key.len + 1 + h->value.len + 1);
- if (h->key.data == NULL) {
- ngx_http_proxy_finalize_request(p,
- NGX_HTTP_INTERNAL_SERVER_ERROR);
- return;
- }
-
- 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);
-
- for (i = 0; ngx_http_proxy_headers_in[i].name.len != 0; i++) {
- if (ngx_http_proxy_headers_in[i].name.len != h->key.len) {
- continue;
- }
-
- if (ngx_strcasecmp(ngx_http_proxy_headers_in[i].name.data,
- h->key.data) == 0)
- {
- *((ngx_table_elt_t **) ((char *) &p->upstream->headers_in
- + ngx_http_proxy_headers_in[i].offset)) = h;
- break;
- }
- }
-
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
- "http proxy header: \"%V: %V\"", &h->key, &h->value);
-
- continue;
-
- } else if (rc == NGX_HTTP_PARSE_HEADER_DONE) {
-
- /* a whole header has been parsed successfully */
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
- "http proxy header done");
-
- /* TODO: hook to process the upstream header */
-
-#if (NGX_HTTP_CACHE)
-
- if (p->cachable) {
- p->cachable = ngx_http_proxy_is_cachable(p);
- }
-
-#endif
-
- ngx_http_proxy_send_response(p);
- return;
-
- } else if (rc != NGX_AGAIN) {
-
- /* there was error while a header line parsing */
-
- ngx_log_error(NGX_LOG_ERR, rev->log, 0,
- upstream_header_errors[rc - NGX_HTTP_PARSE_HEADER_ERROR]);
-
- ngx_http_proxy_next_upstream(p, NGX_HTTP_PROXY_FT_INVALID_HEADER);
- return;
- }
-
- /* rc == NGX_AGAIN: a header line parsing is still not complete */
-
- if (p->header_in->last == p->header_in->end) {
- ngx_log_error(NGX_LOG_ERR, rev->log, 0,
- "upstream sent too big header");
-
- ngx_http_proxy_next_upstream(p, NGX_HTTP_PROXY_FT_INVALID_HEADER);
- return;
- }
- }
-}
-
-
-static ssize_t ngx_http_proxy_read_upstream_header(ngx_http_proxy_ctx_t *p)
-{
- ssize_t n;
- ngx_event_t *rev;
-
- rev = p->upstream->peer.connection->read;
-
- n = p->header_in->last - p->header_in->pos;
-
- if (n > 0) {
- return n;
- }
-
- n = ngx_recv(p->upstream->peer.connection, p->header_in->last,
- p->header_in->end - p->header_in->last);
-
- if (n == NGX_AGAIN) {
-#if 0
- ngx_add_timer(rev, p->lcf->read_timeout);
-#endif
-
- if (ngx_handle_read_event(rev, 0) == NGX_ERROR) {
- ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR);
- return NGX_ERROR;
- }
-
- return NGX_AGAIN;
- }
-
- if (n == 0) {
- ngx_log_error(NGX_LOG_ERR, rev->log, 0,
- "upstream closed prematurely connection");
- }
-
- if (n == 0 || n == NGX_ERROR) {
- return NGX_ERROR;
- }
-
- p->header_in->last += n;
-
- return n;
-}
-
-
-static void ngx_http_proxy_send_response(ngx_http_proxy_ctx_t *p)
-{
- int rc;
- ngx_event_pipe_t *ep;
- ngx_http_request_t *r;
- ngx_http_cache_header_t *header;
- ngx_http_core_loc_conf_t *clcf;
-
- r = p->request;
-
- r->headers_out.status = p->upstream->status;
- r->headers_out.status_line = p->upstream->status_line;
-
-#if 0
- r->headers_out.content_length_n = -1;
- r->headers_out.content_length = NULL;
-#endif
-
- /* copy an upstream header to r->headers_out */
-
- if (ngx_http_proxy_copy_header(p, &p->upstream->headers_in) == NGX_ERROR) {
- ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR);
- return;
- }
-
- /* TODO: preallocate event_pipe bufs, look "Content-Length" */
-
- rc = ngx_http_send_header(r);
-
- if (rc == NGX_ERROR || rc > NGX_OK) {
- ngx_http_proxy_finalize_request(p, rc);
- return;
- }
-
- p->header_sent = 1;
-
- if (p->cache && p->cache->ctx.file.fd != NGX_INVALID_FILE) {
- if (ngx_close_file(p->cache->ctx.file.fd) == NGX_FILE_ERROR) {
- ngx_log_error(NGX_LOG_ALERT, r->connection->log, ngx_errno,
- ngx_close_file_n " \"%s\" failed",
- p->cache->ctx.file.name.data);
- }
- }
-
- if (p->cachable) {
- header = (ngx_http_cache_header_t *) p->header_in->start;
-
- header->expires = p->cache->ctx.expires;
- header->last_modified = p->cache->ctx.last_modified;
- header->date = p->cache->ctx.date;
- header->length = r->headers_out.content_length_n;
- p->cache->ctx.length = r->headers_out.content_length_n;
-
- header->key_len = p->cache->ctx.key0.len;
- ngx_memcpy(&header->key, p->cache->ctx.key0.data, header->key_len);
- header->key[header->key_len] = LF;
- }
-
- ep = ngx_pcalloc(r->pool, sizeof(ngx_event_pipe_t));
- if (ep == NULL) {
- ngx_http_proxy_finalize_request(p, 0);
- return;
- }
-
- p->upstream->event_pipe = ep;
-
- ep->input_filter = ngx_event_pipe_copy_input_filter;
- ep->output_filter = (ngx_event_pipe_output_filter_pt)
- ngx_http_output_filter;
- ep->output_ctx = r;
- ep->tag = (ngx_buf_tag_t) &ngx_http_proxy_module;
- ep->bufs = p->lcf->bufs;
- ep->busy_size = p->lcf->busy_buffers_size;
- ep->upstream = p->upstream->peer.connection;
- ep->downstream = r->connection;
- ep->pool = r->pool;
- ep->log = r->connection->log;
-
- ep->cachable = p->cachable;
-
- ep->temp_file = ngx_pcalloc(r->pool, sizeof(ngx_temp_file_t));
- if (ep->temp_file == NULL) {
- ngx_http_proxy_finalize_request(p, 0);
- return;
- }
-
- ep->temp_file->file.fd = NGX_INVALID_FILE;
- ep->temp_file->file.log = r->connection->log;
- ep->temp_file->path = p->lcf->temp_path;
- ep->temp_file->pool = r->pool;
-
- if (p->cachable) {
- ep->temp_file->persistent = 1;
- } else {
- ep->temp_file->warn = "an upstream response is buffered "
- "to a temporary file";
- }
-
- ep->max_temp_file_size = p->lcf->max_temp_file_size;
- ep->temp_file_write_size = p->lcf->temp_file_write_size;
-
- ep->preread_bufs = ngx_alloc_chain_link(r->pool);
- if (ep->preread_bufs == NULL) {
- ngx_http_proxy_finalize_request(p, 0);
- return;
- }
- ep->preread_bufs->buf = p->header_in;
- ep->preread_bufs->next = NULL;
- p->header_in->recycled = 1;
-
- ep->preread_size = p->header_in->last - p->header_in->pos;
-
- if (p->cachable) {
- ep->buf_to_file = ngx_calloc_buf(r->pool);
- if (ep->buf_to_file == NULL) {
- ngx_http_proxy_finalize_request(p, 0);
- return;
- }
- ep->buf_to_file->pos = p->header_in->start;
- ep->buf_to_file->last = p->header_in->pos;
- ep->buf_to_file->temporary = 1;
- }
-
- if (ngx_event_flags & NGX_USE_AIO_EVENT) {
- /* the posted aio operation can currupt a shadow buffer */
- ep->single_buf = 1;
- }
-
- /* TODO: ep->free_bufs = 0 if use ngx_create_chain_of_bufs() */
- ep->free_bufs = 1;
-
- /*
- * event_pipe would do p->header_in->last += ep->preread_size
- * as though these bytes were read.
- */
- p->header_in->last = p->header_in->pos;
-
- if (p->lcf->cyclic_temp_file) {
-
- /*
- * we need to disable the use of sendfile() if we use cyclic temp file
- * because the writing a new data can interfere with sendfile()
- * that uses the same kernel file pages (at least on FreeBSD)
- */
-
- ep->cyclic_temp_file = 1;
- r->connection->sendfile = 0;
-
- } else {
- ep->cyclic_temp_file = 0;
- }
-
- clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
-
- ep->read_timeout = p->lcf->read_timeout;
- 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;
-
- ngx_http_proxy_process_body(p->upstream->peer.connection->read);
-
- return;
-}
-
-
-static void ngx_http_proxy_process_body(ngx_event_t *ev)
-{
- ngx_connection_t *c;
- ngx_http_request_t *r;
- ngx_http_proxy_ctx_t *p;
- ngx_event_pipe_t *ep;
-
- c = ev->data;
-
- if (ev->write) {
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ev->log, 0,
- "http proxy process downstream");
- r = c->data;
- p = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
- p->action = "sending to client";
-
- } else {
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ev->log, 0,
- "http proxy process upstream");
- p = c->data;
- p->action = "reading upstream body";
- }
-
- ep = p->upstream->event_pipe;
-
- if (ev->timedout) {
- if (ev->write) {
- ep->downstream_error = 1;
- ngx_log_error(NGX_LOG_ERR, c->log, NGX_ETIMEDOUT,
- "client timed out");
-
- } else {
- ep->upstream_error = 1;
- ngx_log_error(NGX_LOG_ERR, c->log, NGX_ETIMEDOUT,
- "upstream timed out");
- }
-
- } else {
- if (ngx_event_pipe(ep, ev->write) == NGX_ABORT) {
- ngx_http_proxy_finalize_request(p, 0);
- return;
- }
- }
-
- if (p->upstream->peer.connection) {
-
-#if (NGX_HTTP_FILE_CACHE)
-
- if (ep->upstream_done && p->cachable) {
- if (ngx_http_proxy_update_cache(p) == NGX_ERROR) {
- ngx_http_busy_unlock(p->lcf->busy_lock, &p->busy_lock);
- ngx_http_proxy_finalize_request(p, 0);
- return;
- }
-
- } else if (ep->upstream_eof && p->cachable) {
-
- /* TODO: check length & update cache */
-
- if (ngx_http_proxy_update_cache(p) == NGX_ERROR) {
- ngx_http_busy_unlock(p->lcf->busy_lock, &p->busy_lock);
- ngx_http_proxy_finalize_request(p, 0);
- return;
- }
- }
-
-#endif
-
- if (ep->upstream_done || ep->upstream_eof || ep->upstream_error) {
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ev->log, 0,
- "http proxy upstream exit: %p", ep->out);
- ngx_http_busy_unlock(p->lcf->busy_lock, &p->busy_lock);
- ngx_http_proxy_finalize_request(p, 0);
- return;
- }
- }
-
- if (ep->downstream_error) {
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ev->log, 0,
- "http proxy downstream error");
- if (!p->cachable && p->upstream->peer.connection) {
- ngx_http_proxy_finalize_request(p, 0);
- }
- }
-}
-
-
-static void ngx_http_proxy_next_upstream(ngx_http_proxy_ctx_t *p,
- ngx_uint_t ft_type)
-{
- ngx_uint_t status;
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, p->request->connection->log, 0,
- "http proxy next upstream: %ui", ft_type);
-
- ngx_http_busy_unlock(p->lcf->busy_lock, &p->busy_lock);
-
- if (ft_type != NGX_HTTP_PROXY_FT_HTTP_404) {
- ngx_event_connect_peer_failed(&p->upstream->peer);
- }
-
- if (ft_type == NGX_HTTP_PROXY_FT_TIMEOUT) {
- ngx_log_error(NGX_LOG_ERR, p->request->connection->log, NGX_ETIMEDOUT,
- "upstream timed out");
- }
-
- if (p->upstream->peer.cached && ft_type == NGX_HTTP_PROXY_FT_ERROR) {
- status = 0;
-
- } else {
- switch(ft_type) {
- case NGX_HTTP_PROXY_FT_TIMEOUT:
- status = NGX_HTTP_GATEWAY_TIME_OUT;
- break;
-
- case NGX_HTTP_PROXY_FT_HTTP_500:
- status = NGX_HTTP_INTERNAL_SERVER_ERROR;
- break;
-
- case NGX_HTTP_PROXY_FT_HTTP_404:
- status = NGX_HTTP_NOT_FOUND;
- break;
-
- /*
- * NGX_HTTP_PROXY_FT_BUSY_LOCK and NGX_HTTP_PROXY_FT_MAX_WAITING
- * never reach here
- */
-
- default:
- status = NGX_HTTP_BAD_GATEWAY;
- }
- }
-
- if (p->upstream->peer.connection) {
- ngx_http_proxy_close_connection(p);
- }
-
- if (p->request->connection->write->eof) {
- ngx_http_proxy_finalize_request(p, NGX_HTTP_CLIENT_CLOSED_REQUEST);
- return;
- }
-
- if (status) {
- p->state->status = status;
-
- if (p->upstream->peer.tries == 0 || !(p->lcf->next_upstream & ft_type))
- {
-
-#if (NGX_HTTP_CACHE)
-
- if (p->stale && (p->lcf->use_stale & ft_type)) {
- ngx_http_proxy_finalize_request(p,
- ngx_http_proxy_send_cached_response(p));
- return;
- }
-
-#endif
-
- ngx_http_proxy_finalize_request(p, status);
- return;
- }
- }
-
- if (p->lcf->busy_lock && !p->busy_locked) {
- ngx_http_proxy_upstream_busy_lock(p);
- } else {
- ngx_http_proxy_connect(p);
- }
-}
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/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