changeset 256:2e9c57a5e50a NGINX_0_4_13

nginx 0.4.13 *) Feature: the "proxy_pass" directive may be used inside the "limit_except" block. *) Feature: the "limit_except" directive supports all WebDAV methods. *) Bugfix: if the "add_before_body" directive was used without the "add_after_body" directive, then an response did not transferred complete. *) Bugfix: a large request body did not receive if the epoll method and the deferred accept() were used. *) Bugfix: a charset could not be set for ngx_http_autoindex_module responses; bug appeared in 0.3.50. *) Bugfix: the "[alert] zero size buf" error when FastCGI server was used; *) Bugfix: the --group= configuration parameter was ignored. Thanks to Thomas Moschny. *) Bugfix: the 50th subrequest in SSI response did not work; bug appeared in 0.3.50.
author Igor Sysoev <http://sysoev.ru>
date Wed, 15 Nov 2006 00:00:00 +0300
parents a13bad126e69
children 0e566ee1bcd5
files CHANGES CHANGES.ru auto/os/features src/core/nginx.h src/event/ngx_event_pipe.c src/http/modules/ngx_http_addition_filter_module.c src/http/modules/ngx_http_autoindex_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_parse.c src/http/ngx_http_request.h src/http/ngx_http_request_body.c src/http/ngx_http_script.c
diffstat 14 files changed, 239 insertions(+), 88 deletions(-) [+]
line wrap: on
line diff
--- a/CHANGES
+++ b/CHANGES
@@ -1,4 +1,31 @@
 
+Changes with nginx 0.4.13                                        15 Nov 2006
+
+    *) Feature: the "proxy_pass" directive may be used inside the 
+       "limit_expect" block.
+
+    *) Feature: the "limit_expect" directive supports all WebDAV methods.
+
+    *) Bugfix: if the "add_before_body" directive was used without the 
+       "add_after_body" directive, then an response did not transferred 
+       complete.
+
+    *) Bugfix: a large request body did not receive if the epoll method and 
+       the deferred accept() were used.
+
+    *) Bugfix: a charset could not be set for ngx_http_autoindex_module 
+       responses; bug appeared in 0.3.50.
+
+    *) Bugfix: the "[alert] zero size buf" error when FastCGI server was 
+       used;
+
+    *) Bugfix: the --group= configuration parameter was ignored.
+       Thanks to Thomas Moschny.
+
+    *) Bugfix: the 50th subrequest in SSI response did not work; bug 
+       appeared in 0.3.50.
+
+
 Changes with nginx 0.4.12                                        31 Oct 2006
 
     *) Feature: the ngx_http_perl_module supports the $r->variable method.
@@ -16,13 +43,13 @@ Changes with nginx 0.4.11               
     *) Feature: the ngx_http_perl_module supports the $r->allow_ranges 
        method.
 
-    *) Bugfix: if the APOP was enabledi in the POP3 proxy, then the 
+    *) Bugfix: if the APOP was enabled in the POP3 proxy, then the 
        USER/PASS commands might not work; bug appeared in 0.4.10.
 
 
 Changes with nginx 0.4.10                                        23 Oct 2006
 
-    *) Feature: the IMAP/POP3 proxy supports the APOP command.
+    *) Feature: the POP3 proxy supports the APOP command.
 
     *) Bugfix: if the select, poll or /dev/poll methods were used, then 
        while waiting authentication server response the IMAP/POP3 proxy 
--- a/CHANGES.ru
+++ b/CHANGES.ru
@@ -1,4 +1,30 @@
 
+Изменения в nginx 0.4.13                                          15.11.2006
+
+    *) Добавление: директиву proxy_pass можно использовать внутри блока 
+       limit_expect.
+
+    *) Добавление: директива limit_expect поддерживает все WebDAV методы.
+
+    *) Исправление: при использовании директивы add_before_body без 
+       директивы add_after_body ответ передавался не полностью.
+
+    *) Исправление: большое тело запроса не принималось, если 
+       использовались метод epoll и deferred accept().
+
+    *) Исправление: для ответов модуля ngx_http_autoindex_module не 
+       выставлялась кодировка; ошибка появилась в 0.3.50.
+
+    *) Исправление: ошибки "[alert] zero size buf" при работе с 
+       FastCGI-сервером;
+
+    *) Исправление: параметр конфигурации --group= игнорировался.
+       Спасибо Thomas Moschny.
+
+    *) Исправление: 50-й подзапрос в SSI ответе не работал; ошибка 
+       появилась в 0.3.50.
+
+
 Изменения в nginx 0.4.12                                          31.10.2006
 
     *) Добавление: модуль ngx_http_perl_module поддерживает метод 
@@ -23,7 +49,7 @@
 
 Изменения в nginx 0.4.10                                          23.10.2006
 
-    *) Добавление: IMAP/POP3 прокси поддерживает APOP.
+    *) Добавление: POP3 прокси поддерживает APOP.
 
     *) Исправление: при использовании методов select, poll и /dev/poll во 
        время ожидания ответа от сервера аутентификации IMAP/POP3 прокси 
--- a/auto/os/features
+++ b/auto/os/features
@@ -4,24 +4,25 @@
 
 NGX_USER=${NGX_USER:-nobody}
 
-if [ -z "$NGX_GROUP" -a $NGX_USER = nobody ] ; then
-    if grep nobody /etc/group 2>&1 >/dev/null; then
-        echo "checking for nobody group ... found"
-        NGX_GROUP=nobody
-    else
-        echo "checking for nobody group ... not found"
+if [ -z "$NGX_GROUP" ]; then
+    if [ $NGX_USER = nobody ]; then
+        if grep nobody /etc/group 2>&1 >/dev/null; then
+            echo "checking for nobody group ... found"
+            NGX_GROUP=nobody
+        else
+            echo "checking for nobody group ... not found"
 
-        if grep nogroup /etc/group 2>&1 >/dev/null; then
-            echo "checking for nogroup group ... found"
-            NGX_GROUP=nogroup
-        else
-            echo "checking for nogroup group ... not found"
-            NGX_GROUP=nobody
+            if grep nogroup /etc/group 2>&1 >/dev/null; then
+                echo "checking for nogroup group ... found"
+                NGX_GROUP=nogroup
+            else
+                echo "checking for nogroup group ... not found"
+                NGX_GROUP=nobody
+            fi
         fi
+    else
+        NGX_GROUP=$NGX_USER
     fi
-
-else
-    NGX_GROUP=$NGX_USER
 fi
 
 
--- a/src/core/nginx.h
+++ b/src/core/nginx.h
@@ -8,7 +8,7 @@
 #define _NGINX_H_INCLUDED_
 
 
-#define NGINX_VERSION      "0.4.12"
+#define NGINX_VERSION      "0.4.13"
 #define NGINX_VER          "nginx/" NGINX_VERSION
 
 #define NGINX_VAR          "NGINX"
--- a/src/event/ngx_event_pipe.c
+++ b/src/event/ngx_event_pipe.c
@@ -511,6 +511,7 @@ ngx_event_pipe_write_to_downstream(ngx_e
                 cl = p->out;
 
                 if (cl->buf->recycled
+                    && cl->buf->last_shadow
                     && bsize + cl->buf->last - cl->buf->pos > p->busy_size)
                 {
                     flush = 1;
@@ -525,6 +526,7 @@ ngx_event_pipe_write_to_downstream(ngx_e
                 cl = p->in;
 
                 if (cl->buf->recycled
+                    && cl->buf->last_shadow
                     && bsize + cl->buf->last - cl->buf->pos > p->busy_size)
                 {
                     flush = 1;
--- a/src/http/modules/ngx_http_addition_filter_module.c
+++ b/src/http/modules/ngx_http_addition_filter_module.c
@@ -152,6 +152,11 @@ ngx_http_addition_body_filter(ngx_http_r
         }
     }
 
+    if (conf->after_body.len == 0) {
+        ngx_http_set_ctx(r, NULL, ngx_http_addition_filter_module);
+        return ngx_http_next_body_filter(r, in);
+    }
+
     last = 0;
 
     for (cl = in; cl; cl = cl->next) {
--- a/src/http/modules/ngx_http_autoindex_module.c
+++ b/src/http/modules/ngx_http_autoindex_module.c
@@ -229,6 +229,7 @@ ngx_http_autoindex_handler(ngx_http_requ
     }
 
     r->headers_out.status = NGX_HTTP_OK;
+    r->headers_out.content_type_len = sizeof("text/html") - 1;
     r->headers_out.content_type.len = sizeof("text/html") - 1;
     r->headers_out.content_type.data = (u_char *) "text/html";
 
--- a/src/http/modules/ngx_http_proxy_module.c
+++ b/src/http/modules/ngx_http_proxy_module.c
@@ -135,7 +135,7 @@ static ngx_conf_bitmask_t  ngx_http_prox
 static ngx_command_t  ngx_http_proxy_commands[] = {
 
     { ngx_string("proxy_pass"),
-      NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_TAKE1,
+      NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_HTTP_LMT_CONF|NGX_CONF_TAKE1,
       ngx_http_proxy_pass,
       NGX_HTTP_LOC_CONF_OFFSET,
       0,
@@ -2207,8 +2207,9 @@ ngx_http_proxy_pass(ngx_conf_t *cf, ngx_
         if (plcf->upstream.uri.len) {
             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                                "\"proxy_pass\" may not have URI part in "
-                               "location given by regular expression or "
-                               "inside the \"if\" statement");
+                               "location given by regular expression, "
+                               "or inside the \"if\" statement, "
+                               "or inside the \"limit_except\" block");
             return NGX_CONF_ERROR;
         }
 
--- a/src/http/modules/perl/nginx.pm
+++ b/src/http/modules/perl/nginx.pm
@@ -17,7 +17,7 @@ our @EXPORT = qw(
     HTTP_SERVER_ERROR
 );
 
-our $VERSION = '0.4.12';
+our $VERSION = '0.4.13';
 
 require XSLoader;
 XSLoader::load('nginx', $VERSION);
--- a/src/http/ngx_http_core_module.c
+++ b/src/http/ngx_http_core_module.c
@@ -1298,6 +1298,7 @@ ngx_http_subrequest(ngx_http_request_t *
     if (r->main->subrequests == 0) {
         ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
                       "subrequests cycle while processing \"%V\"", uri);
+        r->main->subrequests = 1;
         return NGX_ERROR;
     }
 
@@ -1417,6 +1418,8 @@ ngx_http_subrequest(ngx_http_request_t *
         ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
                        "http subrequest done \"%V?%V\"", uri, &sr->args);
 
+        r->main->subrequests++;
+
         *psr = sr;
 
         if (sr->fast_subrequest) {
@@ -2661,9 +2664,19 @@ ngx_http_core_root(ngx_conf_t *cf, ngx_c
 
 
 static ngx_http_method_name_t  ngx_methods_names[] = {
-   { "GET",  (uint32_t) ~NGX_HTTP_GET },
-   { "HEAD", (uint32_t) ~NGX_HTTP_HEAD },
-   { "POST", (uint32_t) ~NGX_HTTP_POST },
+   { "GET",       (uint32_t) ~NGX_HTTP_GET },
+   { "HEAD",      (uint32_t) ~NGX_HTTP_HEAD },
+   { "POST",      (uint32_t) ~NGX_HTTP_POST },
+   { "PUT",       (uint32_t) ~NGX_HTTP_PUT },
+   { "DELETE",    (uint32_t) ~NGX_HTTP_DELETE },
+   { "MKCOL",     (uint32_t) ~NGX_HTTP_MKCOL },
+   { "COPY",      (uint32_t) ~NGX_HTTP_COPY },
+   { "MOVE",      (uint32_t) ~NGX_HTTP_MOVE },
+   { "OPTIONS",   (uint32_t) ~NGX_HTTP_OPTIONS },
+   { "PROPFIND" , (uint32_t) ~NGX_HTTP_PROPFIND },
+   { "PROPPATCH", (uint32_t) ~NGX_HTTP_PROPPATCH },
+   { "LOCK",      (uint32_t) ~NGX_HTTP_LOCK },
+   { "UNLOCK",    (uint32_t) ~NGX_HTTP_UNLOCK },
    { NULL, 0 }
 };
 
--- a/src/http/ngx_http_parse.c
+++ b/src/http/ngx_http_parse.c
@@ -94,23 +94,49 @@ ngx_http_parse_request_line(ngx_http_req
                 case 3:
                     if (m[0] == 'G' && m[1] == 'E' && m[2] == 'T') {
                         r->method = NGX_HTTP_GET;
+                        break;
+                    }
 
-                    } else if (m[0] == 'P' && m[1] == 'U' && m[2] == 'T') {
+                    if (m[0] == 'P' && m[1] == 'U' && m[2] == 'T') {
                         r->method = NGX_HTTP_PUT;
+                        break;
                     }
+
                     break;
 
                 case 4:
-                    if (m[0] == 'P' && m[1] == 'O'
-                        && m[2] == 'S' && m[3] == 'T')
-                    {
-                        r->method = NGX_HTTP_POST;
+                    if (m[1] == 'O') {
+
+                        if (m[0] == 'P' && m[2] == 'S' && m[3] == 'T') {
+                            r->method = NGX_HTTP_POST;
+                            break;
+                        }
+
+                        if (m[0] == 'C' && m[2] == 'P' && m[3] == 'Y') {
+                            r->method = NGX_HTTP_COPY;
+                            break;
+                        }
 
-                    } else if (m[0] == 'H' && m[1] == 'E'
-                               && m[2] == 'A' && m[3] == 'D')
-                    {
-                        r->method = NGX_HTTP_HEAD;
+                        if (m[0] == 'M' && m[2] == 'V' && m[3] == 'E') {
+                            r->method = NGX_HTTP_MOVE;
+                            break;
+                        }
+
+                        if (m[0] == 'L' && m[2] == 'C' && m[3] == 'K') {
+                            r->method = NGX_HTTP_LOCK;
+                            break;
+                        }
+
+                    } else {
+
+                        if (m[0] == 'H' && m[1] == 'E'
+                            && m[2] == 'A' && m[3] == 'D')
+                        {
+                            r->method = NGX_HTTP_HEAD;
+                            break;
+                        }
                     }
+
                     break;
 
                 case 5:
@@ -119,6 +145,7 @@ ngx_http_parse_request_line(ngx_http_req
                     {
                         r->method = NGX_HTTP_MKCOL;
                     }
+
                     break;
 
                 case 6:
@@ -126,7 +153,46 @@ ngx_http_parse_request_line(ngx_http_req
                         && m[3] == 'E' && m[4] == 'T' && m[5] == 'E')
                     {
                         r->method = NGX_HTTP_DELETE;
+                        break;
                     }
+
+                    if (m[0] == 'U' && m[1] == 'N' && m[2] == 'L'
+                        && m[3] == 'O' && m[4] == 'C' && m[5] == 'K')
+                    {
+                        r->method = NGX_HTTP_UNLOCK;
+                        break;
+                    }
+
+                    break;
+
+                case 7:
+                    if (m[0] == 'O' && m[1] == 'P'
+                        && m[2] == 'T' && m[3] == 'I'
+                        && m[4] == 'O' && m[5] == 'N' && m[6] == 'S')
+                    {
+                        r->method = NGX_HTTP_OPTIONS;
+                    }
+
+                    break;
+
+                case 8:
+                    if (m[0] == 'P' && m[1] == 'R'
+                        && m[2] == 'O' && m[3] == 'P' && m[4] == 'F'
+                        && m[5] == 'I' && m[6] == 'N' && m[7] == 'D')
+                    {
+                        r->method = NGX_HTTP_PROPFIND;
+                    }
+
+                    break;
+
+                case 9:
+                    if (m[0] == 'P' && m[1] == 'R' && m[2] == 'O'
+                        && m[3] == 'P' && m[4] == 'P' && m[5] == 'A'
+                        && m[6] == 'T' && m[7] == 'C' && m[8] == 'H')
+                    {
+                        r->method = NGX_HTTP_PROPPATCH;
+                    }
+
                     break;
                 }
 
--- a/src/http/ngx_http_request.h
+++ b/src/http/ngx_http_request.h
@@ -30,6 +30,13 @@
 #define NGX_HTTP_PUT                       0x0010
 #define NGX_HTTP_DELETE                    0x0020
 #define NGX_HTTP_MKCOL                     0x0040
+#define NGX_HTTP_COPY                      0x0080
+#define NGX_HTTP_MOVE                      0x0100
+#define NGX_HTTP_OPTIONS                   0x0200
+#define NGX_HTTP_PROPFIND                  0x0400
+#define NGX_HTTP_PROPPATCH                 0x0800
+#define NGX_HTTP_LOCK                      0x1000
+#define NGX_HTTP_UNLOCK                    0x2000
 
 #define NGX_HTTP_CONNECTION_CLOSE          1
 #define NGX_HTTP_CONNECTION_KEEP_ALIVE     2
--- a/src/http/ngx_http_request_body.c
+++ b/src/http/ngx_http_request_body.c
@@ -265,66 +265,72 @@ ngx_http_do_read_client_request_body(ngx
                    "http read client request body");
 
     for ( ;; ) {
-        if (rb->buf->last == rb->buf->end) {
+        for ( ;; ) {
+            if (rb->buf->last == rb->buf->end) {
+
+                if (ngx_http_write_request_body(r, rb->to_write) != NGX_OK) {
+                    return NGX_HTTP_INTERNAL_SERVER_ERROR;
+                }
 
-            if (ngx_http_write_request_body(r, rb->to_write) != NGX_OK) {
-                return NGX_HTTP_INTERNAL_SERVER_ERROR;
+                rb->to_write = rb->bufs->next ? rb->bufs->next : rb->bufs;
+                rb->buf->last = rb->buf->start;
+            }
+
+            size = rb->buf->end - rb->buf->last;
+
+            if ((off_t) size > rb->rest) {
+                size = (size_t) rb->rest;
             }
 
-            rb->to_write = rb->bufs->next ? rb->bufs->next : rb->bufs;
-            rb->buf->last = rb->buf->start;
-        }
+            n = c->recv(c, rb->buf->last, size);
+
+            ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
+                           "http client request body recv %z", n);
 
-        size = rb->buf->end - rb->buf->last;
+            if (n == NGX_AGAIN) {
+                break;
+            }
+
+            if (n == 0) {
+                ngx_log_error(NGX_LOG_INFO, c->log, 0,
+                              "client closed prematurely connection");
+            }
 
-        if ((off_t) size > rb->rest) {
-            size = (size_t) rb->rest;
+            if (n == 0 || n == NGX_ERROR) {
+                c->error = 1;
+                return NGX_HTTP_BAD_REQUEST;
+            }
+
+            rb->buf->last += n;
+            rb->rest -= n;
+            r->request_length += n;
+
+            if (rb->rest == 0) {
+                break;
+            }
+
+            if (rb->buf->last < rb->buf->end) {
+                break;
+            }
         }
 
-        n = c->recv(c, rb->buf->last, size);
-
         ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
-                       "http client request body recv %z", n);
-
-        if (n == NGX_AGAIN) {
-            break;
-        }
-
-        if (n == 0) {
-            ngx_log_error(NGX_LOG_INFO, c->log, 0,
-                          "client closed prematurely connection");
-        }
-
-        if (n == 0 || n == NGX_ERROR) {
-            c->error = 1;
-            return NGX_HTTP_BAD_REQUEST;
-        }
-
-        rb->buf->last += n;
-        rb->rest -= n;
-        r->request_length += n;
+                       "http client request body rest %uz", rb->rest);
 
         if (rb->rest == 0) {
             break;
         }
 
-        if (rb->buf->last < rb->buf->end) {
-            break;
-        }
-    }
-
-    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
-                   "http client request body rest %uz", rb->rest);
+        if (!c->read->ready) {
+            clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
+            ngx_add_timer(c->read, clcf->client_body_timeout);
 
-    if (rb->rest) {
-        clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
-        ngx_add_timer(c->read, clcf->client_body_timeout);
+            if (ngx_handle_read_event(c->read, 0) == NGX_ERROR) {
+                return NGX_HTTP_INTERNAL_SERVER_ERROR;
+            }
 
-        if (ngx_handle_read_event(c->read, 0) == NGX_ERROR) {
-            return NGX_HTTP_INTERNAL_SERVER_ERROR;
+            return NGX_AGAIN;
         }
-
-        return NGX_AGAIN;
     }
 
     if (c->read->timer_set) {
--- a/src/http/ngx_http_script.c
+++ b/src/http/ngx_http_script.c
@@ -423,10 +423,8 @@ ngx_http_script_copy_code(ngx_http_scrip
     e->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);
-    }
+    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
+                   "http script copy: \"%V\"", &e->buf);
 }
 
 
@@ -477,11 +475,9 @@ ngx_http_script_copy_var_code(ngx_http_s
         if (value && !value->not_found) {
             e->pos = ngx_copy(e->pos, value->data, value->len);
 
-            if (e->log) {
-                ngx_log_debug1(NGX_LOG_DEBUG_HTTP,
-                               e->request->connection->log, 0,
-                               "http script var: \"%V\"", &e->buf);
-            }
+            ngx_log_debug1(NGX_LOG_DEBUG_HTTP,
+                           e->request->connection->log, 0,
+                           "http script var: \"%V\"", &e->buf);
         }
     }
 }