summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIgor Sysoev <igor@sysoev.ru>2008-11-20 17:30:53 +0000
committerJonathan Kolb <jon@b0g.us>2008-11-20 17:30:53 +0000
commit95268be18c7024d8c4b005a7fa623bd17f8ad219 (patch)
treec0fe834189ac5986df7d75ac74162c30e08043b4
parenta0e57793f889000af5cedff05b1912b7128e5c93 (diff)
downloadnginx-95268be18c7024d8c4b005a7fa623bd17f8ad219.tar.gz
Changes with nginx 0.6.33 20 Nov 2008v0.6.33
*) Feature: now nginx returns the 405 status code for POST method requesting a static file only if the file exists. *) Workaround: compatibility with glibc 2.3. Thanks to Eric Benson and Maxim Dounin. *) Bugfix: the resolver did not understand big DNS responses. Thanks to Zyb. *) Bugfix: in HTTPS mode requests might fail with the "bad write retry" error. *) Bugfix: the ngx_http_charset_module did not understand quoted charset name received from backend. *) Bugfix: if the "max_fails=0" parameter was used in upstream with several servers, then a worker process exited on a SIGFPE signal. Thanks to Maxim Dounin. *) Bugfix: the $r->header_in() method did not return value of the "Host", "User-Agent", and "Connection" request header lines; the bug had appeared in 0.6.32. *) Bugfix: a full response was returned for request method HEAD while redirection via an "error_page" directive. *) Bugfix: if a directory has search only rights and the first index file was absent, then nginx returned the 500 status code. *) Bugfix: of recursive error_page for 500 status code.
-rw-r--r--CHANGES39
-rw-r--r--CHANGES.ru37
-rw-r--r--src/core/nginx.c31
-rw-r--r--src/core/nginx.h2
-rw-r--r--src/core/ngx_conf_file.c18
-rw-r--r--src/core/ngx_cycle.c21
-rw-r--r--src/core/ngx_log.c2
-rw-r--r--src/core/ngx_resolver.c4
-rw-r--r--src/event/ngx_event_openssl.c16
-rw-r--r--src/http/modules/ngx_http_index_module.c13
-rw-r--r--src/http/modules/ngx_http_static_module.c18
-rw-r--r--src/http/modules/perl/nginx.pm2
-rw-r--r--src/http/ngx_http_request.c9
-rw-r--r--src/http/ngx_http_special_response.c19
-rw-r--r--src/http/ngx_http_upstream.c12
-rw-r--r--src/http/ngx_http_upstream_round_robin.c4
-rw-r--r--src/os/unix/ngx_files.h12
17 files changed, 196 insertions, 63 deletions
diff --git a/CHANGES b/CHANGES
index b2aeaa3bb..c982b00fe 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,4 +1,38 @@
+Changes with nginx 0.6.33 20 Nov 2008
+
+ *) Feature: now nginx returns the 405 status code for POST method
+ requesting a static file only if the file exists.
+
+ *) Workaround: compatibility with glibc 2.3.
+ Thanks to Eric Benson and Maxim Dounin.
+
+ *) Bugfix: the resolver did not understand big DNS responses.
+ Thanks to Zyb.
+
+ *) Bugfix: in HTTPS mode requests might fail with the "bad write retry"
+ error.
+
+ *) Bugfix: the ngx_http_charset_module did not understand quoted
+ charset name received from backend.
+
+ *) Bugfix: if the "max_fails=0" parameter was used in upstream with
+ several servers, then a worker process exited on a SIGFPE signal.
+ Thanks to Maxim Dounin.
+
+ *) Bugfix: the $r->header_in() method did not return value of the
+ "Host", "User-Agent", and "Connection" request header lines; the bug
+ had appeared in 0.6.32.
+
+ *) Bugfix: a full response was returned for request method HEAD while
+ redirection via an "error_page" directive.
+
+ *) Bugfix: if a directory has search only rights and the first index
+ file was absent, then nginx returned the 500 status code.
+
+ *) Bugfix: of recursive error_page for 500 status code.
+
+
Changes with nginx 0.6.32 07 Jul 2008
*) Change: the "none" parameter in the "ssl_session_cache" directive;
@@ -274,8 +308,7 @@ Changes with nginx 0.6.22 19 Dec 2007
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
+ IP-addresses only, then a "resolver" directive is not mandatory.
*) Bugfix: a segmentation fault might occur in worker process if a
"proxy_pass" directive with URI-part was used; the bug had appeared
@@ -1427,7 +1460,7 @@ Changes with nginx 0.3.55 28 Jul 2006
*) Bugfix: if the request contained "//" or "/./" and escaped symbols
after them, then the proxied request was sent unescaped.
- *) Bugfix: the $r->headers_in("Cookie") of the ngx_http_perl_module now
+ *) Bugfix: the $r->header_in("Cookie") of the ngx_http_perl_module now
returns all "Cookie" header lines.
*) Bugfix: a segmentation fault occurred if
diff --git a/CHANGES.ru b/CHANGES.ru
index 1711c1c2b..226912e2b 100644
--- a/CHANGES.ru
+++ b/CHANGES.ru
@@ -1,4 +1,39 @@
+Изменения в nginx 0.6.33 20.11.2008
+
+ *) Добавление: теперь nginx возвращает код 405 для метода POST при
+ запросе статического файла, только если файл существует.
+
+ *) Изменение: совместимость с glibc 2.3.
+ Спасибо Eric Benson и Максиму Дунину.
+
+ *) Исправление: resolver не понимал большие DNS-ответы.
+ Спасибо Zyb.
+
+ *) Исправление: при использовании HTTPS запросы могли завершаться с
+ ошибкой "bad write retry".
+
+ *) Исправление: модуль ngx_http_charset_module не понимал название
+ кодировки в кавычках, полученное от бэкенда.
+
+ *) Исправление: при использовании параметра max_fails=0 в upstream'е с
+ несколькими серверами рабочий процесс выходил по сигналу SIGFPE.
+ Спасибо Максиму Дунину.
+
+ *) Исправление: метод $r->header_in() не возвращал значения строк
+ "Host", "User-Agent", и "Connection" из заголовка запроса; ошибка
+ появилась в 0.6.32.
+
+ *) Исправление: при перенаправлении запроса с методом HEAD с помощью
+ директивы error_page возвращался полный ответ.
+
+ *) Исправление: если у каталога были права доступа только на поиск
+ файлов и первый индексный файл отсутствовал, то nginx возвращал
+ ошибку 500.
+
+ *) Исправление: рекурсивной error_page для 500 ошибки.
+
+
Изменения в nginx 0.6.32 07.07.2008
*) Изменение: параметр "none" в директиве ssl_session_cache; теперь
@@ -1461,7 +1496,7 @@
закодированные символы в виде "%XX", то проксируемый запрос
передавался незакодированным.
- *) Исправление: метод $r->headers_in("Cookie") модуля
+ *) Исправление: метод $r->header_in("Cookie") модуля
ngx_http_perl_module теперь возвращает все строки "Cookie" в
заголовке запроса.
diff --git a/src/core/nginx.c b/src/core/nginx.c
index 48e085ba3..28624db76 100644
--- a/src/core/nginx.c
+++ b/src/core/nginx.c
@@ -192,6 +192,8 @@ static char **ngx_os_environ;
int ngx_cdecl
main(int argc, char *const *argv)
{
+ char *p;
+ ssize_t n;
ngx_int_t i;
ngx_log_t *log;
ngx_cycle_t *cycle, init_cycle;
@@ -241,23 +243,30 @@ main(int argc, char *const *argv)
}
if (ngx_show_version) {
- ngx_write_fd(ngx_stderr_fileno, "nginx version: " NGINX_VER CRLF,
- sizeof("nginx version: " NGINX_VER CRLF) - 1);
+
+ p = "nginx version: " NGINX_VER CRLF;
+ n = sizeof("nginx version: " NGINX_VER CRLF) - 1;
+
+ if (ngx_write_fd(ngx_stderr_fileno, p, n) != n) {
+ return 1;
+ }
if (ngx_show_configure) {
#ifdef NGX_COMPILER
- ngx_write_fd(ngx_stderr_fileno, "built by " NGX_COMPILER CRLF,
- sizeof("built by " NGX_COMPILER CRLF) - 1);
-#endif
+ p = "built by " NGX_COMPILER CRLF;
+ n = sizeof("built by " NGX_COMPILER CRLF) - 1;
-#ifndef __WATCOMC__
+ if (ngx_write_fd(ngx_stderr_fileno, p, n) != n) {
+ return 1;
+ }
+#endif
- /* OpenWatcomC could not build the long NGX_CONFIGURE string */
+ p = "configure arguments: " NGX_CONFIGURE CRLF;
+ n = sizeof("configure arguments :" NGX_CONFIGURE CRLF) - 1;
- ngx_write_fd(ngx_stderr_fileno,
- "configure arguments: " NGX_CONFIGURE CRLF,
- sizeof("configure arguments :" NGX_CONFIGURE CRLF) - 1);
-#endif
+ if (ngx_write_fd(ngx_stderr_fileno, p, n) != n) {
+ return 1;
+ }
}
if (!ngx_test_config) {
diff --git a/src/core/nginx.h b/src/core/nginx.h
index edb570c49..65a2a34dc 100644
--- a/src/core/nginx.h
+++ b/src/core/nginx.h
@@ -8,7 +8,7 @@
#define _NGINX_H_INCLUDED_
-#define NGINX_VERSION "0.6.32"
+#define NGINX_VERSION "0.6.33"
#define NGINX_VER "nginx/" NGINX_VERSION
#define NGINX_VAR "NGINX"
diff --git a/src/core/ngx_conf_file.c b/src/core/ngx_conf_file.c
index 6efcd8b7d..54ae237f3 100644
--- a/src/core/ngx_conf_file.c
+++ b/src/core/ngx_conf_file.c
@@ -806,6 +806,7 @@ ngx_conf_open_file(ngx_cycle_t *cycle, ngx_str_t *name)
static void
ngx_conf_flush_files(ngx_cycle_t *cycle)
{
+ ssize_t n, len;
ngx_uint_t i;
ngx_list_part_t *part;
ngx_open_file_t *file;
@@ -826,11 +827,24 @@ ngx_conf_flush_files(ngx_cycle_t *cycle)
i = 0;
}
- if (file[i].buffer == NULL || file[i].pos - file[i].buffer == 0) {
+ len = file[i].pos - file[i].buffer;
+
+ if (file[i].buffer == NULL || len == 0) {
continue;
}
- ngx_write_fd(file[i].fd, file[i].buffer, file[i].pos - file[i].buffer);
+ n = ngx_write_fd(file[i].fd, file[i].buffer, len);
+
+ if (n == NGX_FILE_ERROR) {
+ ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
+ ngx_write_fd_n " to \"%s\" failed",
+ file[i].name.data);
+
+ } else if (n != len) {
+ ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
+ ngx_write_fd_n " to \"%s\" was incomplete: %z of %uz",
+ file[i].name.data, n, len);
+ }
}
}
diff --git a/src/core/ngx_cycle.c b/src/core/ngx_cycle.c
index 9cdbb2d95..f8c0d3e85 100644
--- a/src/core/ngx_cycle.c
+++ b/src/core/ngx_cycle.c
@@ -970,6 +970,7 @@ ngx_test_lockfile(u_char *file, ngx_log_t *log)
void
ngx_reopen_files(ngx_cycle_t *cycle, ngx_uid_t user)
{
+ ssize_t n, len;
ngx_fd_t fd;
ngx_uint_t i;
ngx_list_part_t *part;
@@ -993,9 +994,23 @@ ngx_reopen_files(ngx_cycle_t *cycle, ngx_uid_t user)
continue;
}
- if (file[i].buffer && file[i].pos - file[i].buffer != 0) {
- ngx_write_fd(file[i].fd, file[i].buffer,
- file[i].pos - file[i].buffer);
+ len = file[i].pos - file[i].buffer;
+
+ if (file[i].buffer && len != 0) {
+
+ n = ngx_write_fd(file[i].fd, file[i].buffer, len);
+
+ if (n == NGX_FILE_ERROR) {
+ ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
+ ngx_write_fd_n " to \"%s\" failed",
+ file[i].name.data);
+
+ } else if (n != len) {
+ ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
+ ngx_write_fd_n " to \"%s\" was incomplete: %z of %uz",
+ file[i].name.data, n, len);
+ }
+
file[i].pos = file[i].buffer;
}
diff --git a/src/core/ngx_log.c b/src/core/ngx_log.c
index 1059acf43..e3abcd780 100644
--- a/src/core/ngx_log.c
+++ b/src/core/ngx_log.c
@@ -158,7 +158,7 @@ ngx_log_error_core(ngx_uint_t level, ngx_log_t *log, ngx_err_t err,
ngx_linefeed(p);
- ngx_write_fd(log->file->fd, errstr, p - errstr);
+ (void) ngx_write_fd(log->file->fd, errstr, p - errstr);
}
diff --git a/src/core/ngx_resolver.c b/src/core/ngx_resolver.c
index a7fe056e6..2998bb2e0 100644
--- a/src/core/ngx_resolver.c
+++ b/src/core/ngx_resolver.c
@@ -1836,7 +1836,7 @@ ngx_resolver_copy(ngx_resolver_t *r, ngx_str_t *name, u_char *buf, u_char *src,
}
if (n & 0xc0) {
- n = (n & 0x3f << 8) + *p;
+ n = ((n & 0x3f) << 8) + *p;
p = &buf[n];
} else {
@@ -1886,7 +1886,7 @@ done:
}
} else {
- n = (n & 0x3f << 8) + *src;
+ n = ((n & 0x3f) << 8) + *src;
src = &buf[n];
n = *src++;
diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c
index 98f9a4d95..79b94144b 100644
--- a/src/event/ngx_event_openssl.c
+++ b/src/event/ngx_event_openssl.c
@@ -187,13 +187,6 @@ ngx_ssl_create(ngx_ssl_t *ssl, ngx_uint_t protocols, void *data)
SSL_CTX_set_options(ssl->ctx, ngx_ssl_protocols[protocols >> 1]);
}
- /*
- * we need this option because in ngx_ssl_send_chain()
- * we may switch to a buffered write and may copy leftover part of
- * previously unbuffered data to our internal buffer
- */
- SSL_CTX_set_mode(ssl->ctx, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
-
SSL_CTX_set_read_ahead(ssl->ctx, 1);
return NGX_OK;
@@ -776,14 +769,7 @@ ngx_ssl_send_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
ssize_t send, size;
ngx_buf_t *buf;
- if (!c->ssl->buffer
- || (in && in->next == NULL && !(c->buffered & NGX_SSL_BUFFERED)))
- {
- /*
- * we avoid a buffer copy if
- * we do not need to buffer the output
- * or the incoming buf is a single and our buffer is empty
- */
+ if (!c->ssl->buffer) {
while (in) {
if (ngx_buf_special(in->buf)) {
diff --git a/src/http/modules/ngx_http_index_module.c b/src/http/modules/ngx_http_index_module.c
index 6bfb04565..01e6cd59a 100644
--- a/src/http/modules/ngx_http_index_module.c
+++ b/src/http/modules/ngx_http_index_module.c
@@ -306,6 +306,19 @@ ngx_http_index_test_dir(ngx_http_request_t *r, ngx_http_core_loc_conf_t *clcf,
return ngx_http_index_error(r, dir.data, NGX_ENOENT);
}
+ if (of.err == NGX_EACCES) {
+
+ *last = c;
+
+ /*
+ * ngx_http_index_test_dir() is called after the first index
+ * file testing has returned an error distinct from NGX_EACCES.
+ * This means that directory searching is allowed.
+ */
+
+ return NGX_OK;
+ }
+
ngx_log_error(NGX_LOG_CRIT, r->connection->log, of.err,
ngx_open_file_n " \"%s\" failed", dir.data);
}
diff --git a/src/http/modules/ngx_http_static_module.c b/src/http/modules/ngx_http_static_module.c
index c4e688ffb..b8ad57336 100644
--- a/src/http/modules/ngx_http_static_module.c
+++ b/src/http/modules/ngx_http_static_module.c
@@ -58,7 +58,7 @@ ngx_http_static_handler(ngx_http_request_t *r)
ngx_open_file_info_t of;
ngx_http_core_loc_conf_t *clcf;
- if (!(r->method & (NGX_HTTP_GET|NGX_HTTP_HEAD))) {
+ if (!(r->method & (NGX_HTTP_GET|NGX_HTTP_HEAD|NGX_HTTP_POST))) {
return NGX_HTTP_NOT_ALLOWED;
}
@@ -71,12 +71,6 @@ ngx_http_static_handler(ngx_http_request_t *r)
return NGX_DECLINED;
}
- rc = ngx_http_discard_request_body(r);
-
- if (rc != NGX_OK) {
- return rc;
- }
-
log = r->connection->log;
/*
@@ -186,6 +180,16 @@ ngx_http_static_handler(ngx_http_request_t *r)
#endif
+ if (r->method & NGX_HTTP_POST) {
+ return NGX_HTTP_NOT_ALLOWED;
+ }
+
+ rc = ngx_http_discard_request_body(r);
+
+ if (rc != NGX_OK) {
+ return rc;
+ }
+
log->action = "sending response to client";
r->headers_out.status = NGX_HTTP_OK;
diff --git a/src/http/modules/perl/nginx.pm b/src/http/modules/perl/nginx.pm
index 4ae72d2ff..67751ca97 100644
--- 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.32';
+our $VERSION = '0.6.33';
require XSLoader;
XSLoader::load('nginx', $VERSION);
diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c
index 5258ad91f..aa61c5e62 100644
--- a/src/http/ngx_http_request.c
+++ b/src/http/ngx_http_request.c
@@ -74,15 +74,18 @@ static char *ngx_http_client_errors[] = {
ngx_http_header_t ngx_http_headers_in[] = {
- { ngx_string("Host"), 0, ngx_http_process_host },
+ { ngx_string("Host"), offsetof(ngx_http_headers_in_t, host),
+ ngx_http_process_host },
- { ngx_string("Connection"), 0, ngx_http_process_connection },
+ { ngx_string("Connection"), offsetof(ngx_http_headers_in_t, connection),
+ ngx_http_process_connection },
{ ngx_string("If-Modified-Since"),
offsetof(ngx_http_headers_in_t, if_modified_since),
ngx_http_process_unique_header_line },
- { ngx_string("User-Agent"), 0, ngx_http_process_user_agent },
+ { ngx_string("User-Agent"), offsetof(ngx_http_headers_in_t, user_agent),
+ ngx_http_process_user_agent },
{ ngx_string("Referer"), offsetof(ngx_http_headers_in_t, referer),
ngx_http_process_header_line },
diff --git a/src/http/ngx_http_special_response.c b/src/http/ngx_http_special_response.c
index 00b2251d8..f644e7812 100644
--- a/src/http/ngx_http_special_response.c
+++ b/src/http/ngx_http_special_response.c
@@ -327,7 +327,6 @@ static ngx_str_t ngx_http_get_name = { 3, (u_char *) "GET " };
ngx_int_t
ngx_http_special_response_handler(ngx_http_request_t *r, ngx_int_t error)
{
- ngx_int_t rc;
ngx_uint_t i, err;
ngx_http_err_page_t *err_page;
ngx_http_core_loc_conf_t *clcf;
@@ -335,12 +334,6 @@ ngx_http_special_response_handler(ngx_http_request_t *r, ngx_int_t error)
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"http special response: %d, \"%V\"", error, &r->uri);
- rc = ngx_http_discard_request_body(r);
-
- if (rc == NGX_HTTP_INTERNAL_SERVER_ERROR) {
- error = NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
r->err_status = error;
if (r->keepalive != 0) {
@@ -370,7 +363,7 @@ ngx_http_special_response_handler(ngx_http_request_t *r, ngx_int_t error)
clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
- if (!r->error_page && clcf->error_pages) {
+ if (!r->error_page && clcf->error_pages && r->uri_changes != 0) {
if (clcf->recursive_error_pages == 0) {
r->error_page = 1;
@@ -385,6 +378,10 @@ ngx_http_special_response_handler(ngx_http_request_t *r, ngx_int_t error)
}
}
+ if (ngx_http_discard_request_body(r) != NGX_OK) {
+ error = NGX_HTTP_INTERNAL_SERVER_ERROR;
+ }
+
if (clcf->msie_refresh
&& r->headers_in.msie
&& (error == NGX_HTTP_MOVED_PERMANENTLY
@@ -492,8 +489,10 @@ ngx_http_send_error_page(ngx_http_request_t *r, ngx_http_err_page_t *err_page)
if (uri->data[0] == '/') {
- r->method = NGX_HTTP_GET;
- r->method_name = ngx_http_get_name;
+ if (r->method != NGX_HTTP_HEAD) {
+ r->method = NGX_HTTP_GET;
+ r->method_name = ngx_http_get_name;
+ }
return ngx_http_internal_redirect(r, uri, args);
}
diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c
index 9ec861cfa..b18bf477f 100644
--- a/src/http/ngx_http_upstream.c
+++ b/src/http/ngx_http_upstream.c
@@ -2625,7 +2625,17 @@ ngx_http_upstream_copy_content_type(ngx_http_request_t *r, ngx_table_elt_t *h,
r->headers_out.content_type_len = last - h->value.data;
- r->headers_out.charset.len = h->value.data + h->value.len - p;
+ if (*p == '"') {
+ p++;
+ }
+
+ last = h->value.data + h->value.len;
+
+ if (*(last - 1) == '"') {
+ last--;
+ }
+
+ r->headers_out.charset.len = last - p;
r->headers_out.charset.data = p;
return NGX_OK;
diff --git a/src/http/ngx_http_upstream_round_robin.c b/src/http/ngx_http_upstream_round_robin.c
index 062137158..c6541a33c 100644
--- a/src/http/ngx_http_upstream_round_robin.c
+++ b/src/http/ngx_http_upstream_round_robin.c
@@ -645,7 +645,9 @@ ngx_http_upstream_free_round_robin_peer(ngx_peer_connection_t *pc, void *data,
peer->fails++;
peer->accessed = now;
- peer->current_weight -= peer->weight / peer->max_fails;
+ if (peer->max_fails) {
+ peer->current_weight -= peer->weight / peer->max_fails;
+ }
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, pc->log, 0,
"free rr peer failed: %ui %i",
diff --git a/src/os/unix/ngx_files.h b/src/os/unix/ngx_files.h
index a223b34e8..419f2fba0 100644
--- a/src/os/unix/ngx_files.h
+++ b/src/os/unix/ngx_files.h
@@ -68,7 +68,17 @@ ssize_t ngx_write_chain_to_file(ngx_file_t *file, ngx_chain_t *ce,
#define ngx_read_fd read
#define ngx_read_fd_n "read()"
-#define ngx_write_fd write
+/*
+ * we use inlined function instead of simple #define
+ * because glibc 2.3 sets warn_unused_result attribute for write()
+ * and in this case gcc 4.3 ignores (void) cast
+ */
+static ngx_inline ssize_t
+ngx_write_fd(ngx_fd_t fd, void *buf, size_t n)
+{
+ return write(fd, buf, n);
+}
+
#define ngx_write_fd_n "write()"
#define ngx_linefeed(p) *p++ = LF;