# HG changeset patch # User Igor Sysoev # Date 1163538000 -10800 # Node ID 2e9c57a5e50a3a1201eb70889eb33adff014fe91 # Parent a13bad126e69ac4aed491d237ffa81e1f6a1063d 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. diff --git a/CHANGES b/CHANGES --- 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 diff --git a/CHANGES.ru b/CHANGES.ru --- 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 прокси diff --git a/auto/os/features b/auto/os/features --- 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 diff --git a/src/core/nginx.h b/src/core/nginx.h --- 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" diff --git a/src/event/ngx_event_pipe.c b/src/event/ngx_event_pipe.c --- 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; diff --git a/src/http/modules/ngx_http_addition_filter_module.c b/src/http/modules/ngx_http_addition_filter_module.c --- 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) { diff --git a/src/http/modules/ngx_http_autoindex_module.c b/src/http/modules/ngx_http_autoindex_module.c --- 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"; diff --git a/src/http/modules/ngx_http_proxy_module.c b/src/http/modules/ngx_http_proxy_module.c --- 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; } diff --git a/src/http/modules/perl/nginx.pm b/src/http/modules/perl/nginx.pm --- 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); diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c --- 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 } }; diff --git a/src/http/ngx_http_parse.c b/src/http/ngx_http_parse.c --- 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; } diff --git a/src/http/ngx_http_request.h b/src/http/ngx_http_request.h --- 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 diff --git a/src/http/ngx_http_request_body.c b/src/http/ngx_http_request_body.c --- 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) { diff --git a/src/http/ngx_http_script.c b/src/http/ngx_http_script.c --- 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); } } }