changeset 354:583decdb82a4 NGINX_0_6_21

nginx 0.6.21 *) Change: if variable values used in a "proxy_pass" directive contain IP-addresses only, then a "resolver" directive is not mandatory. resolver *) Bugfix: a segmentation fault might occur in worker process if a "proxy_pass" directive with URI-part was used; bug appeared in 0.6.19. *) Bugfix: if resolver was used on platform that does not support kqueue, then nginx issued an alert "name is out of response". Thanks to Andrei Nigmatulin. *) Bugfix: if the $server_protocol was used in FastCGI parameters and a request line length was near to the "client_header_buffer_size" directive value, then nginx issued an alert "fastcgi: the request record is too big". *) Bugfix: if a plain text HTTP/0.9 version request was made to HTTPS server, then nginx returned usual response.
author Igor Sysoev <http://sysoev.ru>
date Mon, 03 Dec 2007 00:00:00 +0300
parents 4a470d9e2ea5
children 3ac45897a61c
files CHANGES CHANGES.ru auto/sources src/core/nginx.h src/core/ngx_inet.c src/core/ngx_inet.h src/core/ngx_queue.h src/core/ngx_rbtree.h src/core/ngx_resolver.c src/core/ngx_resolver.h src/event/modules/ngx_aio_module.c src/event/ngx_event.h src/http/modules/ngx_http_fastcgi_module.c src/http/modules/ngx_http_proxy_module.c src/http/modules/perl/nginx.pm src/http/ngx_http_core_module.c src/http/ngx_http_request.c src/http/ngx_http_special_response.c src/http/ngx_http_upstream.c src/mail/ngx_mail.h src/os/unix/ngx_freebsd_init.c src/os/unix/ngx_linux_init.c src/os/unix/ngx_os.h src/os/unix/ngx_posix_init.c src/os/unix/ngx_recv.c src/os/unix/ngx_send.c src/os/unix/ngx_solaris_init.c src/os/unix/ngx_udp_recv.c
diffstat 28 files changed, 267 insertions(+), 447 deletions(-) [+]
line wrap: on
line diff
--- a/CHANGES
+++ b/CHANGES
@@ -1,4 +1,27 @@
 
+Changes with nginx 0.6.21                                        03 Dec 2007
+
+    *) Change: if variable values used in a "proxy_pass" directive contain 
+       IP-addresses only, then a "resolver" directive is not mandatory. 
+       resolver
+
+    *) Bugfix: a segmentation fault might occur in worker process if a 
+       "proxy_pass" directive with URI-part was used; bug appeared in 
+       0.6.19.
+
+    *) Bugfix: if resolver was used on platform that does not support 
+       kqueue, then nginx issued an alert "name is out of response".
+       Thanks to Andrei Nigmatulin.
+
+    *) Bugfix: if the $server_protocol was used in FastCGI parameters and a 
+       request line length was near to the "client_header_buffer_size" 
+       directive value, then nginx issued an alert "fastcgi: the request 
+       record is too big".
+
+    *) Bugfix: if a plain text HTTP/0.9 version request was made to HTTPS 
+       server, then nginx returned usual response.
+
+
 Changes with nginx 0.6.20                                        28 Nov 2007
 
     *) Bugfix: a segmentation fault might occur in worker process if a 
@@ -372,185 +395,6 @@ Changes with nginx 0.6.0                
        support the "www.example.*" wildcards.
 
 
-Changes with nginx 0.5.33                                        07 Nov 2007
-
-    *) Change: now by default the "echo" SSI command uses entity encoding.
-
-    *) Feature: the "encoding" parameter in the "echo" SSI command.
-
-    *) Change: mail proxy was split on three modules: pop3, imap and smtp.
-
-    *) Feature: the --without-mail_pop3_module, --without-mail_imap_module, 
-       and --without-mail_smtp_module configuration parameters.
-
-    *) Feature: the "smtp_greeting_delay" and "smtp_client_buffer" 
-       directives of the ngx_mail_smtp_module.
-
-    *) Feature: the "server_name" and "valid_referers" directives support 
-       regular expressions.
-
-    *) Feature: the "server_name", "map", and "valid_referers" directives 
-       support the "www.example.*" wildcards.
-
-    *) Bugfix: sub_filter did not work with empty substitution.
-
-    *) Bugfix: in sub_filter parsing.
-
-    *) Bugfix: a worker process may got caught in an endless loop, if the 
-       memcached was used.
-
-    *) Bugfix: nginx supported low case only "close" and "keep-alive" 
-       values in the "Connection" request header line; bug appeared in 
-       0.5.32.
-
-    *) Bugfix: nginx could not start on Solaris if the shared PCRE library 
-       located in non-standard place was used.
-
-
-Changes with nginx 0.5.32                                        24 Sep 2007
-
-    *) Change: now nginx tries to set the "worker_priority", 
-       "worker_rlimit_nofile", "worker_rlimit_core", and 
-       "worker_rlimit_sigpending" without super-user privileges.
-
-    *) Change: now nginx escapes space and "%" in request to a mail proxy 
-       authentication server.
-
-    *) Change: now nginx escapes "%" in $memcached_key variable.
-
-    *) Change: the special make target "upgrade1" was defined for online 
-       upgrade of 0.1.x versions.
-
-    *) Feature: the "add_header Last-Modified ..." directive changes the 
-       "Last-Modified" response header line.
-
-    *) Feature: the mail proxy supports AUTHENTICATE in IMAP mode.
-       Thanks to Maxim Dounin.
-
-    *) Feature: the mail proxy supports STARTTLS in SMTP mode.
-       Thanks to Maxim Dounin.
-
-    *) Bugfix: nginx did not close directory file on HEAD request if 
-       autoindex was used.
-       Thanks to Arkadiusz Patyk.
-
-    *) Bugfix: the "proxy_hide_header" and "fastcgi_hide_header" directives 
-       did not hide response header lines whose name was longer than 32 
-       characters.
-       Thanks to Manlio Perillo.
-
-    *) Bugfix: active connection counter always increased if mail proxy was 
-       used.
-
-    *) Bugfix: if backend returned response header only using non-buffered 
-       proxy, then nginx closed backend connection on timeout.
-
-    *) Bugfix: nginx did not support several "Connection" request header 
-       lines.
-
-    *) Bugfix: a charset set by the "charset" directive was not appended to 
-       the "Content-Type" header set by $r->send_http_header().
-
-    *) Bugfix: a segmentation fault might occur in worker process if 
-       /dev/poll method was used.
-
-    *) Bugfix: nginx did not work on FreeBSD/sparc64.
-
-    *) Bugfix: a segmentation fault occurred in worker process if invalid 
-       address was set in the "auth_http" directive.
-
-    *) Bugfix: now nginx uses default listen backlog value 511 on all 
-       platforms except FreeBSD.
-       Thanks to Jiang Hong.
-
-    *) Bugfix: now Solaris sendfilev() is not used to transfer the client 
-       request body to FastCGI-server via the unix domain socket.
-
-    *) Bugfix: if the same host without specified port was used as backend 
-       for HTTP and HTTPS, then nginx used only one port - 80 or 443.
-
-    *) Bugfix: the "proxy_ignore_client_abort" and 
-       "fastcgi_ignore_client_abort" directives did not work; bug appeared 
-       in 0.5.13.
-
-
-Changes with nginx 0.5.31                                        15 Aug 2007
-
-    *) Feature: named locations.
-
-    *) Feature: the "proxy_store" and "fastcgi_store" directives.
-
-    *) Feature: the "proxy_store_access" and "fastcgi_store_access" 
-       directives.
-
-
-Changes with nginx 0.5.30                                        30 Jul 2007
-
-    *) Feature: the $args variable can be set with the "set" directive.
-
-    *) Feature: the $is_args variable.
-
-    *) Bugfix: if a client has closed connection to mail proxy then nginx 
-       might not close connection to backend.
-
-    *) Bugfix: now nginx escapes space in $memcached_key variable.
-
-    *) Bugfix: a segmentation fault might occur in worker process when the 
-       HTTPS protocol was used in the "proxy_pass" directive.
-
-    *) Bugfix: the perl $$ variable value in ngx_http_perl_module was equal 
-       to the master process identification number.
-
-    *) Bugfix: fix building on Solaris/amd64 by Sun Studio 11 and early 
-       versions; bug appeared in 0.5.29.
-
-
-Changes with nginx 0.5.29                                        23 Jul 2007
-
-    *) Feature: $nginx_version variable.
-       Thanks to Nick S. Grechukh.
-
-    *) Bugfix: if the FastCGI header was split in records, then nginx 
-       passed garbage in the header to a client.
-
-    *) Bugfix: Sun Studio compatibility on Solaris/amd64 and 
-       Solaris/sparc64.
-       Thanks to Jiang Hong and Andrei Nigmatulin.
-
-    *) Bugfix: of minor potential bugs.
-       Thanks to Coverity's Scan.
-
-
-Changes with nginx 0.5.28                                        17 Jul 2007
-
-    *) Security: the "msie_refresh" directive allowed XSS.
-       Thanks to Maxim Boguk.
-
-    *) Bugfix: a segmentation fault might occur in worker process if the 
-       "auth_http_header" directive was used.
-       Thanks to Maxim Dounin.
-
-    *) Bugfix: a segmentation fault occurred in worker process if the 
-       CRAM-MD5 authentication method was used, but it was not enabled.
-
-    *) Bugfix: a segmentation fault might occur in worker process if the 
-       eventport method was used.
-
-
-Changes with nginx 0.5.27                                        09 Jul 2007
-
-    *) Bugfix: if remote SSI subrequest was used, then posterior local file 
-       subrequest might transferred to client in wrong order.
-
-    *) Bugfix: large SSI inclusions buffered in temporary files were 
-       truncated.
-
-
-Changes with nginx 0.5.26                                        17 Jun 2007
-
-    *) Bugfix: in SSI parsing.
-
-
 Changes with nginx 0.5.25                                        11 Jun 2007
 
     *) Bugfix: nginx could not be built with the 
--- a/CHANGES.ru
+++ b/CHANGES.ru
@@ -1,4 +1,27 @@
 
+Изменения в nginx 0.6.21                                          03.12.2007
+
+    *) Изменение: если в значениях переменных директивы proxy_pass 
+       используются только IP-адреса, то указывать resolver не нужно.
+
+    *) Исправление: при использовании директивы proxy_pass c URI-частью в 
+       рабочем процессе мог произойти segmentation fault; ошибка появилась 
+       в 0.6.19.
+
+    *) Исправление: если resolver использовался на платформах, не 
+       поддерживающих метод kqueue, то nginx выдавал alert "name is out of 
+       response".
+       Спасибо Андрею Нигматулину.
+
+    *) Исправление: При использовании переменной $server_protocol в 
+       FastCGI-параметрах и запросе, длина которого была близка к значению 
+       директивы client_header_buffer_size, nginx выдавал alert "fastcgi: 
+       the request record is too big".
+
+    *) Исправление: при обычном запросе версии HTTP/0.9 к HTTPS серверу 
+       nginx возвращал обычный ответ.
+
+
 Изменения в nginx 0.6.20                                          28.11.2007
 
     *) Исправление: при использовании директивы proxy_pass c URI-частью в 
@@ -382,193 +405,6 @@
        поддерживают маски вида "www.example.*".
 
 
-Изменения в nginx 0.5.33                                          07.11.2007
-
-    *) Изменение: теперь по умолчанию команда SSI echo использует 
-       кодирование entity.
-
-    *) Добавление: параметр encoding в команде SSI echo.
-
-    *) Изменение: почтовый прокси-сервер разделён на три модуля: pop3, imap 
-       и smtp.
-
-    *) Добавление: параметры конфигурации --without-mail_pop3_module, 
-       --without-mail_imap_module и --without-mail_smtp_module.
-
-    *) Добавление: директивы smtp_greeting_delay и smtp_client_buffer 
-       модуля ngx_mail_smtp_module.
-
-    *) Добавление: директивы server_name и valid_referers поддерживают 
-       регулярные выражения.
-
-    *) Добавление: директивы "server_name", "map", and "valid_referers" 
-       поддерживают маски вида "www.example.*".
-
-    *) Исправление: sub_filter не работал с пустой строкой замены.
-
-    *) Исправление: в парсинге sub_filter.
-
-    *) Исправление: рабочий процесс мог зациклиться при использовании 
-       memcached.
-
-    *) Исправление: nginx распознавал параметры "close" и "keep-alive" в 
-       строке "Connection" в заголовке запроса только, если они были в 
-       нижнем регистре; ошибка появилась в 0.5.32.
-
-    *) Исправление: при использовании разделяемой библиотеки PCRE, 
-       расположенной в нестандартном месте, nginx не запускался на Solaris.
-
-
-Изменения в nginx 0.5.32                                          24.09.2007
-
-    *) Изменение: теперь nginx пытается установить директивы 
-       worker_priority, worker_rlimit_nofile, worker_rlimit_core, 
-       worker_rlimit_sigpending без привилегий root'а.
-
-    *) Изменение: теперь nginx экранирует символы пробела и "%" при 
-       передаче запроса серверу аутентификации почтового прокси-сервера.
-
-    *) Изменение: теперь nginx экранирует символ "%" в переменной 
-       $memcached_key.
-
-    *) Изменение: для обновления на лету версий 0.1.x создан специальный 
-       сценарий make upgrade1.
-
-    *) Добавление: директива "add_header Last-Modified ..." меняет строку 
-       "Last-Modified" в заголовке ответа.
-
-    *) Добавление: почтовый прокси-сервер поддерживает AUTHENTICATE в 
-       режиме IMAP.
-       Спасибо Максиму Дунину.
-
-    *) Добавление: почтовый прокси-сервер поддерживает STARTTLS в режиме 
-       SMTP.
-       Спасибо Максиму Дунину.
-
-    *) Исправление: nginx не закрывал файл каталога для запроса HEAD, если 
-       использовался autoindex
-       Спасибо Arkadiusz Patyk.
-
-    *) Исправление: директивы proxy_hide_header и fastcgi_hide_header не 
-       скрывали строки заголовка ответа с именем больше 32 символов.
-       Спасибо Manlio Perillo.
-
-    *) Исправление: счётчик активных соединений всегда рос при 
-       использовании почтового прокси-сервера.
-
-    *) Исправление: если бэкенд возвращал только заголовок ответа при 
-       небуферизированном проксировании, то nginx закрывал соединение с 
-       бэкендом по таймауту.
-
-    *) Исправление: nginx не поддерживал несколько строк "Connection" в 
-       заголовке запроса.
-
-    *) Исправление: В строку заголовка ответа "Content-Type", указанную в 
-       методе $r->send_http_header(), не добавлялась кодировка, указанная в 
-       директиве charset.
-
-    *) Исправление: при использовании метода /dev/poll в рабочем процессе 
-       мог произойти segmentation fault.
-
-    *) Исправление: nginx не работал на FreeBSD/sparc64.
-
-    *) Исправление: если в директиве auth_http был задан неправильный 
-       адрес, то в рабочем процессе происходил segmentation fault.
-
-    *) Исправление: теперь по умолчанию nginx использует значение 511 для 
-       listen backlog на всех платформах, кроме FreeBSD.
-       Спасибо Jiang Hong.
-
-    *) Исправление: sendfilev() в Solaris теперь не используется при 
-       передаче тела запроса FastCGI-серверу через unix domain сокет.
-
-    *) Исправление: при использовании одного хоста в качестве бэкендов для 
-       протоколов HTTP и HTTPS без явного указания портов, nginx 
-       использовал только один порт - 80 или 443.
-
-    *) Исправление: директивы proxy_ignore_client_abort и 
-       fastcgi_ignore_client_abort не работали; ошибка появилась в 0.5.13.
-
-
-Изменения в nginx 0.5.31                                          15.08.2007
-
-    *) Добавление: именованные location'ы.
-
-    *) Добавление: директивы proxy_store и fastcgi_store.
-
-    *) Добавление: директивы proxy_store_access и fastcgi_store_access.
-
-
-Изменения в nginx 0.5.30                                          30.07.2007
-
-    *) Добавление: переменную $args можно устанавливать с помощью set.
-
-    *) Добавление: переменная $is_args.
-
-    *) Исправление: если клиент в почтовом прокси-сервере закрывал 
-       соединение, то nginx мог не закрывать соединение с бэкендом.
-
-    *) Исправление: теперь nginx экранирует пробел в переменной 
-       $memcached_key.
-
-    *) Исправление: при использовании протокола HTTPS в директиве 
-       proxy_pass в рабочем процессе мог произойти segmentation fault.
-
-    *) Исправление: значение perl'овой переменной $$ модуля 
-       ngx_http_perl_module было равно номеру главного процесса.
-
-    *) Исправление: nginx не собирался на Solaris/amd64 Sun Studio 11 и 
-       более ранними версиями; ошибка появилась в 0.5.29.
-
-
-Изменения в nginx 0.5.29                                          23.07.2007
-
-    *) Добавление: переменная $nginx_version.
-       Спасибо Николаю Гречуху.
-
-    *) Исправление: если заголовок ответа был разделён в FastCGI-записях, 
-       то nginx передавал клиенту мусор в таких заголовках.
-
-    *) Исправление: совместимость с Sun Studio на Solaris/amd64 и 
-       Solaris/sparc64.
-       Спасибо Jiang Hong и Андрею Нигматулину.
-
-    *) Исправление: незначительных потенциальных ошибок.
-       Спасибо Coverity's Scan.
-
-
-Изменения в nginx 0.5.28                                          17.07.2007
-
-    *) Безопасность: при использовании директивы msie_refresh был возможен 
-       XSS.
-       Спасибо Максиму Богуку.
-
-    *) Исправление: при использовании директивы auth_http_header в рабочем 
-       процессе мог произойти segmentation fault.
-       Спасибо Максиму Дунину.
-
-    *) Исправление: если использовался метод аутентификации CRAM-MD5, но он 
-       не был разрешён, то в рабочем процессе происходил segmentation fault.
-
-    *) Исправление: в рабочем процессе мог произойти segmentation fault, 
-       если использовался метод eventport.
-
-
-Изменения в nginx 0.5.27                                          09.07.2007
-
-    *) Исправление: при использовании удалённого подзапроса в SSI 
-       последующий подзапрос локального файла мог отдаваться клиенту в 
-       неверном порядке.
-
-    *) Исправление: большие включения в SSI, сохранённые во временные 
-       файлы, передавались не полностью.
-
-
-Изменения в nginx 0.5.26                                          17.06.2007
-
-    *) Исправление: в парсинге SSI.
-
-
 Изменения в nginx 0.5.25                                          11.06.2007
 
     *) Исправление: nginx не собирался с параметром 
--- a/auto/sources
+++ b/auto/sources
@@ -164,6 +164,7 @@ UNIX_SRCS="$CORE_SRCS $EVENT_SRCS \
             src/os/unix/ngx_socket.c \
             src/os/unix/ngx_recv.c \
             src/os/unix/ngx_readv_chain.c \
+            src/os/unix/ngx_udp_recv.c \
             src/os/unix/ngx_send.c \
             src/os/unix/ngx_writev_chain.c \
             src/os/unix/ngx_channel.c \
@@ -229,6 +230,7 @@ WIN32_SRCS="$CORE_SRCS $EVENT_SRCS \
             src/os/win32/ngx_socket.c \
             src/os/win32/ngx_wsarecv.c \
             src/os/win32/ngx_wsarecv_chain.c \
+            src/os/win32/ngx_udp_wsarecv.c \
             src/os/win32/ngx_wsasend_chain.c \
             src/os/win32/ngx_win32_init.c \
             src/os/win32/ngx_user.c \
--- a/src/core/nginx.h
+++ b/src/core/nginx.h
@@ -8,7 +8,7 @@
 #define _NGINX_H_INCLUDED_
 
 
-#define NGINX_VERSION      "0.6.20"
+#define NGINX_VERSION      "0.6.21"
 #define NGINX_VER          "nginx/" NGINX_VERSION
 
 #define NGINX_VAR          "NGINX"
--- a/src/core/ngx_inet.c
+++ b/src/core/ngx_inet.c
@@ -417,6 +417,9 @@ ngx_parse_url(ngx_pool_t *pool, ngx_url_
             return NGX_ERROR;
         }
 
+        u->port_text.len = port_len;
+        u->port_text.data = port_start;
+
     } else {
         port = ngx_atoi(p, len);
 
--- a/src/core/ngx_inet.h
+++ b/src/core/ngx_inet.h
@@ -35,6 +35,7 @@ typedef struct {
 
     ngx_str_t         url;
     ngx_str_t         host;
+    ngx_str_t         port_text;
     ngx_str_t         uri;
 
     in_port_t         port;
--- a/src/core/ngx_queue.h
+++ b/src/core/ngx_queue.h
@@ -20,6 +20,11 @@ struct ngx_queue_s {
 };
 
 
+#define ngx_queue_init(q)                                                     \
+    (q)->prev = q;                                                            \
+    (q)->next = q;
+
+
 #define ngx_queue_empty(h)                                                    \
     (h == (h)->prev)
 
--- a/src/core/ngx_rbtree.h
+++ b/src/core/ngx_rbtree.h
@@ -40,6 +40,13 @@ struct ngx_rbtree_s {
 };
 
 
+#define ngx_rbtree_init(tree, s, i)                                           \
+    ngx_rbtree_sentinel_init(s);                                              \
+    (tree)->root = s;                                                         \
+    (tree)->sentinel = s;                                                     \
+    (tree)->insert = i
+
+
 void ngx_rbtree_insert(ngx_thread_volatile ngx_rbtree_t *tree,
     ngx_rbtree_node_t *node);
 void ngx_rbtree_delete(ngx_thread_volatile ngx_rbtree_t *tree,
--- a/src/core/ngx_resolver.c
+++ b/src/core/ngx_resolver.c
@@ -99,47 +99,28 @@ ngx_resolver_create(ngx_peer_addr_t *add
         return NULL;
     }
 
-    uc = ngx_calloc(sizeof(ngx_udp_connection_t), log);
-    if (uc == NULL) {
-        return NULL;
-    }
-
     r->event = ngx_calloc(sizeof(ngx_event_t), log);
     if (r->event == NULL) {
         return NULL;
     }
 
-    ngx_rbtree_sentinel_init(&r->name_sentinel);
-
-    r->name_rbtree.root = &r->name_sentinel;
-    r->name_rbtree.sentinel = &r->name_sentinel;
-    r->name_rbtree.insert = ngx_resolver_rbtree_insert_value;
-
-    ngx_rbtree_sentinel_init(&r->addr_sentinel);
-
-    r->addr_rbtree.root = &r->addr_sentinel;
-    r->addr_rbtree.sentinel = &r->addr_sentinel;
-    r->addr_rbtree.insert = ngx_rbtree_insert_value;
-
-    r->name_resend_queue.prev = &r->name_resend_queue;
-    r->name_resend_queue.next = &r->name_resend_queue;
-
-    r->addr_resend_queue.prev = &r->addr_resend_queue;
-    r->addr_resend_queue.next = &r->addr_resend_queue;
-
-    r->name_expire_queue.prev = &r->name_expire_queue;
-    r->name_expire_queue.next = &r->name_expire_queue;
-
-    r->addr_expire_queue.prev = &r->addr_expire_queue;
-    r->addr_expire_queue.next = &r->addr_expire_queue;
+    ngx_rbtree_init(&r->name_rbtree, &r->name_sentinel,
+                    ngx_resolver_rbtree_insert_value);
+
+    ngx_rbtree_init(&r->addr_rbtree, &r->addr_sentinel,
+                    ngx_rbtree_insert_value);
+
+    ngx_queue_init(&r->name_resend_queue);
+    ngx_queue_init(&r->addr_resend_queue);
+
+    ngx_queue_init(&r->name_expire_queue);
+    ngx_queue_init(&r->addr_expire_queue);
 
     r->event->handler = ngx_resolver_resend_handler;
     r->event->data = r;
     r->event->log = log;
     r->ident = -1;
 
-    r->udp_connection = uc;
-
     r->resend_timeout = 5;
     r->expire = 30;
     r->valid = 300;
@@ -147,10 +128,19 @@ ngx_resolver_create(ngx_peer_addr_t *add
     r->log = log;
     r->log_level = NGX_LOG_ALERT;
 
-    uc->sockaddr = addr->sockaddr;
-    uc->socklen = addr->socklen;
-    uc->server = addr->name;
-    uc->log = log;
+    if (addr) {
+        uc = ngx_calloc(sizeof(ngx_udp_connection_t), log);
+        if (uc == NULL) {
+            return NULL;
+        }
+
+        r->udp_connection = uc;
+
+        uc->sockaddr = addr->sockaddr;
+        uc->socklen = addr->socklen;
+        uc->server = addr->name;
+        uc->log = log;
+    }
 
     return r;
 }
@@ -177,6 +167,10 @@ ngx_resolve_start(ngx_resolver_t *r, ngx
         }
     }
 
+    if (r->udp_connection == NULL) {
+        return NGX_NO_RESOLVER;
+    }
+
     ctx = ngx_resolver_calloc(r, sizeof(ngx_resolver_ctx_t));
 
     if (ctx) {
@@ -748,7 +742,7 @@ ngx_resolver_resend_handler(ngx_event_t 
     /* lock addr mutex */
 
     atimer = ngx_resolver_resend(r, &r->addr_rbtree, &r->addr_resend_queue);
-       
+
     /* unlock addr mutex */
 
     if (ntimer == 0) {
@@ -832,9 +826,9 @@ ngx_resolver_read_response(ngx_event_t *
     c = rev->data;
 
     do {
-        n = ngx_recv(c, buf, NGX_RESOLVER_UDP_SIZE);
-
-        if (n == -1) {
+        n = ngx_udp_recv(c, buf, NGX_RESOLVER_UDP_SIZE);
+
+        if (n < 0) {
             return;
         }
 
--- a/src/core/ngx_resolver.h
+++ b/src/core/ngx_resolver.h
@@ -26,6 +26,9 @@
 #define NGX_RESOLVE_TIMEDOUT  NGX_ETIMEDOUT
 
 
+#define NGX_NO_RESOLVER       (void *) -1
+
+
 typedef struct {
     ngx_connection_t         *connection;
     struct sockaddr          *sockaddr;
--- a/src/event/modules/ngx_aio_module.c
+++ b/src/event/modules/ngx_aio_module.c
@@ -28,6 +28,7 @@ static ngx_int_t ngx_aio_process_events(
 ngx_os_io_t ngx_os_aio = {
     ngx_aio_read,
     ngx_aio_read_chain,
+    NULL,
     ngx_aio_write,
     ngx_aio_write_chain,
     0
--- a/src/event/ngx_event.h
+++ b/src/event/ngx_event.h
@@ -429,6 +429,7 @@ extern ngx_os_io_t  ngx_io;
 
 #define ngx_recv             ngx_io.recv
 #define ngx_recv_chain       ngx_io.recv_chain
+#define ngx_udp_recv         ngx_io.udp_recv
 #define ngx_send             ngx_io.send
 #define ngx_send_chain       ngx_io.send_chain
 
--- a/src/http/modules/ngx_http_fastcgi_module.c
+++ b/src/http/modules/ngx_http_fastcgi_module.c
@@ -553,7 +553,7 @@ ngx_http_fastcgi_create_request(ngx_http
 
     if (len > 65535) {
         ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
-                      "fastcgi: the request record is too big");
+                      "fastcgi request record is too big: %uz", len);
         return NGX_ERROR;
     }
 
--- a/src/http/modules/ngx_http_proxy_module.c
+++ b/src/http/modules/ngx_http_proxy_module.c
@@ -675,7 +675,8 @@ ngx_http_proxy_create_request(ngx_http_r
                                         r->uri.len - loc_len, NGX_ESCAPE_URI);
         }
 
-        len += r->uri.len - loc_len + escape + sizeof("?") - 1 + r->args.len;
+        len += ctx->vars.uri.len + r->uri.len - loc_len + escape
+               + sizeof("?") - 1 + r->args.len;
     }
 
     ngx_http_script_flush_no_cacheable_variables(r, plcf->flushes);
@@ -2323,7 +2324,7 @@ ngx_http_proxy_pass(ngx_conf_t *cf, ngx_
         sc.variables = n;
         sc.complete_lengths = 1;
         sc.complete_values = 1;
-        
+
         if (ngx_http_script_compile(&sc) != NGX_OK) {
             return NGX_CONF_ERROR;
         }
@@ -2645,8 +2646,6 @@ static ngx_int_t
 ngx_http_proxy_set_vars(ngx_pool_t *pool, ngx_url_t *u,
     ngx_http_proxy_vars_t *v)
 {
-    u_char  *p;
-
     if (!u->unix_socket) {
         if (u->no_port || u->port == u->default_port) {
             v->host_header = u->host;
@@ -2661,16 +2660,9 @@ ngx_http_proxy_set_vars(ngx_pool_t *pool
             }
 
         } else {
-            p = ngx_palloc(pool, u->host.len + sizeof(":65536") - 1);
-            if (p == NULL) {
-                return NGX_ERROR;
-            }
-
-            v->host_header.len = ngx_sprintf(p, "%V:%d", &u->host, u->port) - p;
-            v->host_header.data = p;
-
-            v->port.len = v->host_header.len - u->host.len - 1;
-            v->port.data = p + u->host.len + 1;
+            v->host_header.len = u->host.len + 1 + u->port_text.len;
+            v->host_header.data = u->host.data;
+            v->port = u->port_text;
         }
 
     } else {
--- a/src/http/modules/perl/nginx.pm
+++ b/src/http/modules/perl/nginx.pm
@@ -47,7 +47,7 @@ our @EXPORT = qw(
     HTTP_INSUFFICIENT_STORAGE
 );
 
-our $VERSION = '0.6.20';
+our $VERSION = '0.6.21';
 
 require XSLoader;
 XSLoader::load('nginx', $VERSION);
--- a/src/http/ngx_http_core_module.c
+++ b/src/http/ngx_http_core_module.c
@@ -69,7 +69,7 @@ static char *ngx_http_core_keepalive(ngx
     void *conf);
 static char *ngx_http_core_internal(ngx_conf_t *cf, ngx_command_t *cmd,
     void *conf);
-static char * ngx_http_core_resolver(ngx_conf_t *cf, ngx_command_t *cmd,
+static char *ngx_http_core_resolver(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);
@@ -2594,6 +2594,13 @@ ngx_http_core_merge_loc_conf(ngx_conf_t 
 
     if (conf->resolver == NULL) {
         conf->resolver = prev->resolver;
+
+        if (conf->resolver == NULL) {
+            conf->resolver = ngx_resolver_create(NULL, cf->cycle->new_log);
+            if (conf->resolver == NULL) {
+                return NGX_OK;
+            }
+        }
     }
 
     ngx_conf_merge_path_value(conf->client_body_temp_path,
@@ -3393,6 +3400,8 @@ ngx_http_core_resolver(ngx_conf_t *cf, n
 
     value = cf->args->elts;
 
+    ngx_memzero(&u, sizeof(ngx_url_t));
+
     u.host = value[1];
     u.port = 53;
 
--- a/src/http/ngx_http_request.c
+++ b/src/http/ngx_http_request.c
@@ -1154,6 +1154,10 @@ ngx_http_alloc_large_header_buffer(ngx_h
             r->args_start = new + (r->args_start - old);
         }
 
+        if (r->http_protocol.data) {
+            r->http_protocol.data = new + (r->http_protocol.data - old);
+        }
+
     } else {
         r->header_name_start = new;
         r->header_name_end = new + (r->header_name_end - old);
@@ -1335,13 +1339,6 @@ ngx_http_process_request_header(ngx_http
         return NGX_ERROR;
     }
 
-    if (r->plain_http) {
-        ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
-                      "client sent plain HTTP request to HTTPS port");
-        ngx_http_finalize_request(r, NGX_HTTP_TO_HTTPS);
-        return NGX_ERROR;
-    }
-
     if (r->headers_in.connection_type == NGX_HTTP_CONNECTION_KEEP_ALIVE) {
         if (r->headers_in.keep_alive) {
             r->headers_in.keep_alive_n =
@@ -1409,6 +1406,13 @@ ngx_http_process_request(ngx_http_reques
 
     c = r->connection;
 
+    if (r->plain_http) {
+        ngx_log_error(NGX_LOG_INFO, c->log, 0,
+                      "client sent plain HTTP request to HTTPS port");
+        ngx_http_finalize_request(r, NGX_HTTP_TO_HTTPS);
+        return;
+    }
+
 #if (NGX_HTTP_SSL)
 
     if (c->ssl) {
--- a/src/http/ngx_http_special_response.c
+++ b/src/http/ngx_http_special_response.c
@@ -307,7 +307,7 @@ static ngx_str_t ngx_http_error_pages[] 
     ngx_string(ngx_http_error_495_page), /* 495, https certificate error */
     ngx_string(ngx_http_error_496_page), /* 496, https no certificate */
     ngx_string(ngx_http_error_497_page), /* 497, http to https */
-    ngx_string(ngx_http_error_404_page), /* 498, invalid host name */
+    ngx_string(ngx_http_error_404_page), /* 498, canceled */
     ngx_null_string,                     /* 499, client has closed connection */
 
     ngx_string(ngx_http_error_500_page),
--- a/src/http/ngx_http_upstream.c
+++ b/src/http/ngx_http_upstream.c
@@ -398,13 +398,6 @@ ngx_http_upstream_init(ngx_http_request_
             }
         }
 
-        if (clcf->resolver == NULL) {
-            ngx_log_error(NGX_LOG_ERR, c->log, 0,
-                          "no resolver defined to resolve %V", host);
-            ngx_http_finalize_request(r, NGX_HTTP_BAD_GATEWAY);
-            return;
-        }
-
         temp.name = *host;
 
         ctx = ngx_resolve_start(clcf->resolver, &temp);
@@ -413,6 +406,14 @@ ngx_http_upstream_init(ngx_http_request_
             return;
         }
 
+        if (ctx == NGX_NO_RESOLVER) {
+            ngx_log_error(NGX_LOG_ERR, c->log, 0,
+                          "no resolver defined to resolve %V", host);
+
+            ngx_http_finalize_request(r, NGX_HTTP_BAD_GATEWAY);
+            return;
+        }
+
         ctx->name = *host;
         ctx->type = NGX_RESOLVE_A;
         ctx->handler = ngx_http_upstream_resolve_handler;
--- a/src/mail/ngx_mail.h
+++ b/src/mail/ngx_mail.h
@@ -102,7 +102,7 @@ typedef enum {
     ngx_pop3_auth_login_password,
     ngx_pop3_auth_plain,
     ngx_pop3_auth_cram_md5
-} ngx_po3_state_e;
+} ngx_pop3_state_e;
 
 
 typedef enum {
--- a/src/os/unix/ngx_freebsd_init.c
+++ b/src/os/unix/ngx_freebsd_init.c
@@ -30,6 +30,7 @@ ngx_uint_t ngx_freebsd_use_tcp_nopush;
 static ngx_os_io_t ngx_freebsd_io = {
     ngx_unix_recv,
     ngx_readv_chain,
+    ngx_udp_unix_recv,
     ngx_unix_send,
 #if (NGX_HAVE_SENDFILE)
     ngx_freebsd_sendfile_chain,
--- a/src/os/unix/ngx_linux_init.c
+++ b/src/os/unix/ngx_linux_init.c
@@ -17,6 +17,7 @@ int   ngx_linux_rtsig_max;
 static ngx_os_io_t ngx_linux_io = {
     ngx_unix_recv,
     ngx_readv_chain,
+    ngx_udp_unix_recv,
     ngx_unix_send,
 #if (NGX_HAVE_SENDFILE)
     ngx_linux_sendfile_chain,
--- a/src/os/unix/ngx_os.h
+++ b/src/os/unix/ngx_os.h
@@ -25,6 +25,7 @@ typedef ngx_chain_t *(*ngx_send_chain_pt
 typedef struct {
     ngx_recv_pt        recv;
     ngx_recv_chain_pt  recv_chain;
+    ngx_recv_pt        udp_recv;
     ngx_send_pt        send;
     ngx_send_chain_pt  send_chain;
     ngx_uint_t         flags;
@@ -41,6 +42,7 @@ ngx_int_t ngx_daemon(ngx_log_t *log);
 
 ssize_t ngx_unix_recv(ngx_connection_t *c, u_char *buf, size_t size);
 ssize_t ngx_readv_chain(ngx_connection_t *c, ngx_chain_t *entry);
+ssize_t ngx_udp_unix_recv(ngx_connection_t *c, u_char *buf, size_t size);
 ssize_t ngx_unix_send(ngx_connection_t *c, u_char *buf, size_t size);
 ngx_chain_t *ngx_writev_chain(ngx_connection_t *c, ngx_chain_t *in,
     off_t limit);
--- a/src/os/unix/ngx_posix_init.c
+++ b/src/os/unix/ngx_posix_init.c
@@ -21,6 +21,7 @@ struct rlimit  rlmt;
 ngx_os_io_t ngx_os_io = {
     ngx_unix_recv,
     ngx_readv_chain,
+    ngx_udp_unix_recv,
     NULL,
     ngx_writev_chain,
     0
--- a/src/os/unix/ngx_recv.c
+++ b/src/os/unix/ngx_recv.c
@@ -11,7 +11,8 @@
 
 #if (NGX_HAVE_KQUEUE)
 
-ssize_t ngx_unix_recv(ngx_connection_t *c, u_char *buf, size_t size)
+ssize_t
+ngx_unix_recv(ngx_connection_t *c, u_char *buf, size_t size)
 {
     ssize_t       n;
     ngx_err_t     err;
@@ -77,12 +78,6 @@ ssize_t ngx_unix_recv(ngx_connection_t *
                      * even if kqueue reported about available data
                      */
 
-#if 0
-                    ngx_log_error(NGX_LOG_ALERT, c->log, 0,
-                                  "recv() returned 0 while kevent() reported "
-                                  "%d available bytes", rev->available);
-#endif
-
                     rev->eof = 1;
                     rev->available = 0;
                 }
@@ -126,7 +121,8 @@ ssize_t ngx_unix_recv(ngx_connection_t *
 
 #else /* ! NGX_HAVE_KQUEUE */
 
-ssize_t ngx_unix_recv(ngx_connection_t *c, u_char *buf, size_t size)
+ssize_t
+ngx_unix_recv(ngx_connection_t *c, u_char *buf, size_t size)
 {
     ssize_t       n;
     ngx_err_t     err;
--- a/src/os/unix/ngx_send.c
+++ b/src/os/unix/ngx_send.c
@@ -9,7 +9,8 @@
 #include <ngx_event.h>
 
 
-ssize_t ngx_unix_send(ngx_connection_t *c, u_char *buf, size_t size)
+ssize_t
+ngx_unix_send(ngx_connection_t *c, u_char *buf, size_t size)
 {
     ssize_t       n;
     ngx_err_t     err;
--- a/src/os/unix/ngx_solaris_init.c
+++ b/src/os/unix/ngx_solaris_init.c
@@ -16,6 +16,7 @@ char ngx_solaris_version[50];
 static ngx_os_io_t ngx_solaris_io = {
     ngx_unix_recv,
     ngx_readv_chain,
+    ngx_udp_unix_recv,
     ngx_unix_send,
 #if (NGX_HAVE_SENDFILE)
     ngx_solaris_sendfilev_chain,
new file mode 100644
--- /dev/null
+++ b/src/os/unix/ngx_udp_recv.c
@@ -0,0 +1,114 @@
+
+/*
+ * Copyright (C) Igor Sysoev
+ */
+
+
+#include <ngx_config.h>
+#include <ngx_core.h>
+#include <ngx_event.h>
+
+
+#if (NGX_HAVE_KQUEUE)
+
+ssize_t
+ngx_udp_unix_recv(ngx_connection_t *c, u_char *buf, size_t size)
+{
+    ssize_t       n;
+    ngx_err_t     err;
+    ngx_event_t  *rev;
+
+    rev = c->read;
+
+    do {
+        n = recv(c->fd, buf, size, 0);
+
+        ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
+                       "recv: fd:%d %d of %d", c->fd, n, size);
+
+        if (n >= 0) {
+            if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) {
+                rev->available -= n;
+
+                /*
+                 * rev->available may be negative here because some additional
+                 * bytes may be received between kevent() and recv()
+                 */
+
+                if (rev->available <= 0) {
+                    rev->ready = 0;
+                    rev->available = 0;
+                }
+            }
+
+            return n;
+        }
+
+        err = ngx_socket_errno;
+
+        if (err == NGX_EAGAIN || err == NGX_EINTR) {
+            ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err,
+                           "recv() not ready");
+            n = NGX_AGAIN;
+
+        } else {
+            n = ngx_connection_error(c, err, "recv() failed");
+            break;
+        }
+
+    } while (err == NGX_EINTR);
+
+    rev->ready = 0;
+
+    if (n == NGX_ERROR){
+        rev->error = 1;
+    }
+
+    return n;
+}
+
+#else /* ! NGX_HAVE_KQUEUE */
+
+ssize_t
+ngx_udp_unix_recv(ngx_connection_t *c, u_char *buf, size_t size)
+{
+    ssize_t       n;
+    ngx_err_t     err;
+    ngx_event_t  *rev;
+
+    rev = c->read;
+
+    do {
+        n = recv(c->fd, buf, size, 0);
+
+        ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
+                       "recv: fd:%d %d of %d", c->fd, n, size);
+
+        if (n >= 0) {
+            return n;
+        }
+
+        err = ngx_socket_errno;
+
+        if (err == NGX_EAGAIN || err == NGX_EINTR) {
+            ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err,
+                           "recv() not ready");
+            n = NGX_AGAIN;
+
+        } else {
+            n = ngx_connection_error(c, err, "recv() failed");
+            break;
+        }
+
+    } while (err == NGX_EINTR);
+
+    rev->ready = 0;
+
+    if (n == NGX_ERROR){
+        rev->error = 1;
+    }
+
+    return n;
+}
+
+#endif /* NGX_HAVE_KQUEUE */