changeset 222:dd6c66b5b0e2 NGINX_0_3_58

nginx 0.3.58 *) Feature: the "error_page" directive supports the variables. *) Change: now the procfs interface instead of sysctl is used on Linux. *) Change: now the "Content-Type" header line is inherited from first response when the "X-Accel-Redirect" was used. *) Bugfix: the "error_page" directive did not redirect the 413 error. *) Bugfix: the trailing "?" did not remove old arguments if no new arguments were added to a rewritten URI. *) Bugfix: nginx could not run on 64-bit FreeBSD 7.0-CURRENT.
author Igor Sysoev <http://sysoev.ru>
date Mon, 14 Aug 2006 00:00:00 +0400
parents 52ac9a089ea5
children c3b6f8ef140b
files CHANGES CHANGES.ru src/core/nginx.h src/http/modules/ngx_http_fastcgi_module.c src/http/modules/ngx_http_proxy_module.c src/http/modules/perl/nginx.xs src/http/modules/perl/ngx_http_perl_module.c src/http/ngx_http_core_module.c src/http/ngx_http_core_module.h src/http/ngx_http_request_body.c src/http/ngx_http_script.c src/http/ngx_http_special_response.c src/http/ngx_http_upstream.c src/os/unix/ngx_freebsd.h src/os/unix/ngx_freebsd_init.c src/os/unix/ngx_linux_init.c
diffstat 16 files changed, 189 insertions(+), 83 deletions(-) [+]
line wrap: on
line diff
--- a/CHANGES
+++ b/CHANGES
@@ -1,4 +1,21 @@
 
+Changes with nginx 0.3.58                                        14 Aug 2006
+
+    *) Feature: the "error_page" directive supports the variables.
+
+    *) Change: now the procfs interface instead of sysctl is used on Linux.
+
+    *) Change: now the "Content-Type" header line is inherited from first 
+       response when the "X-Accel-Redirect" was used.
+
+    *) Bugfix: the "error_page" directive did not redirect the 413 error.
+
+    *) Bugfix: the trailing "?" did not remove old arguments if no new 
+       arguments were added to a rewritten URI.
+
+    *) Bugfix: nginx could not run on 64-bit FreeBSD 7.0-CURRENT.
+
+
 Changes with nginx 0.3.57                                        09 Aug 2006
 
     *) Feature: the $ssl_client_serial variable.
--- a/CHANGES.ru
+++ b/CHANGES.ru
@@ -1,4 +1,22 @@
 
+Изменения в nginx 0.3.58                                          14.08.2006
+
+    *) Добавление: директива error_page поддерживает переменные.
+
+    *) Изменение: теперь на Linux используется интерфейс procfs вместо 
+       sysctl.
+
+    *) Изменение: теперь при использовании "X-Accel-Redirect" строка 
+       "Content-Type" наследуется из первоначального ответа.
+
+    *) Исправление: директива error_page не перенаправляла ошибку 413.
+
+    *) Исправление: завершающий "?" не удалял старые аргументы, если в 
+       переписанном URI не было новых аргументов.
+
+    *) Исправление: nginx не запускался на 64-битной FreeBSD 7.0-CURRENT.
+
+
 Изменения в nginx 0.3.57                                          09.08.2006
 
     *) Добавление: переменная $ssl_client_serial.
--- a/src/core/nginx.h
+++ b/src/core/nginx.h
@@ -8,7 +8,7 @@
 #define _NGINX_H_INCLUDED_
 
 
-#define NGINX_VER          "nginx/0.3.57"
+#define NGINX_VER          "nginx/0.3.58"
 
 #define NGINX_VAR          "NGINX"
 #define NGX_OLDPID_EXT     ".oldbin"
--- a/src/http/modules/ngx_http_fastcgi_module.c
+++ b/src/http/modules/ngx_http_fastcgi_module.c
@@ -2056,7 +2056,7 @@ ngx_http_fastcgi_lowat_check(ngx_conf_t 
 #if (NGX_FREEBSD)
     ssize_t *np = data;
 
-    if (*np >= ngx_freebsd_net_inet_tcp_sendspace) {
+    if ((u_long) *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)",
--- a/src/http/modules/ngx_http_proxy_module.c
+++ b/src/http/modules/ngx_http_proxy_module.c
@@ -2343,7 +2343,7 @@ ngx_http_proxy_lowat_check(ngx_conf_t *c
 #if (NGX_FREEBSD)
     ssize_t *np = data;
 
-    if (*np >= ngx_freebsd_net_inet_tcp_sendspace) {
+    if ((u_long) *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)",
--- a/src/http/modules/perl/nginx.xs
+++ b/src/http/modules/perl/nginx.xs
@@ -116,10 +116,8 @@ send_http_header(r, ...)
         }
 
     } else {
-        if (r->headers_out.content_type.len == 0) {
-            if (ngx_http_set_content_type(r) != NGX_OK) {
-                XSRETURN_EMPTY;
-            }
+        if (ngx_http_set_content_type(r) != NGX_OK) {
+            XSRETURN_EMPTY;
         }
     }
 
--- a/src/http/modules/perl/ngx_http_perl_module.c
+++ b/src/http/modules/perl/ngx_http_perl_module.c
@@ -226,13 +226,6 @@ ngx_http_perl_handle_request(ngx_http_re
 
     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "perl handler");
 
-    /* mod_perl's content handler assumes that content type was already set */
-
-    if (ngx_http_set_content_type(r) != NGX_OK) {
-        ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
-        return;
-    }
-
     ctx = ngx_http_get_module_ctx(r, ngx_http_perl_module);
 
     if (ctx == NULL) {
--- a/src/http/ngx_http_core_module.c
+++ b/src/http/ngx_http_core_module.c
@@ -700,6 +700,7 @@ ngx_http_find_location_config(ngx_http_r
                    r->headers_in.content_length_n, clcf->client_max_body_size);
 
     if (r->headers_in.content_length_n != -1
+        && !r->discard_body
         && clcf->client_max_body_size
         && clcf->client_max_body_size < r->headers_in.content_length_n)
     {
@@ -929,6 +930,10 @@ ngx_http_set_content_type(ngx_http_reque
     ngx_uint_t                 i, hash;
     ngx_http_core_loc_conf_t  *clcf;
 
+    if (r->headers_out.content_type.len) {
+        return NGX_OK;
+    }
+
     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
 
     if (r->exten.len) {
@@ -2688,10 +2693,12 @@ ngx_http_core_error_page(ngx_conf_t *cf,
 {
     ngx_http_core_loc_conf_t *lcf = conf;
 
-    ngx_int_t             overwrite;
-    ngx_uint_t            i, n;
-    ngx_str_t            *value;
-    ngx_http_err_page_t  *err;
+    ngx_int_t                   overwrite;
+    ngx_str_t                  *value, uri;
+    ngx_uint_t                  i, n, nvar;
+    ngx_array_t                *uri_lengths, *uri_values;
+    ngx_http_err_page_t        *err;
+    ngx_http_script_compile_t   sc;
 
     if (lcf->error_pages == NULL) {
         lcf->error_pages = ngx_array_create(cf->pool, 4,
@@ -2732,6 +2739,28 @@ ngx_http_core_error_page(ngx_conf_t *cf,
         n = 1;
     }
 
+    uri = value[cf->args->nelts - 1];
+    uri_lengths = NULL;
+    uri_values = NULL;
+
+    nvar = ngx_http_script_variables_count(&uri);
+
+    if (nvar) {
+        ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
+
+        sc.cf = cf;
+        sc.source = &uri;
+        sc.lengths = &uri_lengths;
+        sc.values = &uri_values;
+        sc.variables = nvar;
+        sc.complete_lengths = 1;
+        sc.complete_values = 1;
+
+        if (ngx_http_script_compile(&sc) != NGX_OK) {
+            return NGX_CONF_ERROR;
+        }
+    }
+
     for (i = 1; i < cf->args->nelts - n; i++) {
         err = ngx_array_push(lcf->error_pages);
         if (err == NULL) {
@@ -2755,7 +2784,9 @@ ngx_http_core_error_page(ngx_conf_t *cf,
 
         err->overwrite = (overwrite >= 0) ? overwrite : err->status;
 
-        err->uri = value[cf->args->nelts - 1];
+        err->uri = uri;
+        err->uri_lengths = uri_lengths;
+        err->uri_values = uri_values;
     }
 
     return NGX_CONF_OK;
@@ -2838,7 +2869,7 @@ ngx_http_core_lowat_check(ngx_conf_t *cf
 #if (NGX_FREEBSD)
     ssize_t *np = data;
 
-    if (*np >= ngx_freebsd_net_inet_tcp_sendspace) {
+    if ((u_long) *np >= ngx_freebsd_net_inet_tcp_sendspace) {
         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                            "\"send_lowat\" must be less than %d "
                            "(sysctl net.inet.tcp.sendspace)",
--- a/src/http/ngx_http_core_module.h
+++ b/src/http/ngx_http_core_module.h
@@ -171,9 +171,11 @@ typedef struct {
 
 
 typedef struct {
-    ngx_int_t     status;
-    ngx_int_t     overwrite;
-    ngx_str_t     uri;
+    ngx_int_t                  status;
+    ngx_int_t                  overwrite;
+    ngx_str_t                  uri;
+    ngx_array_t               *uri_lengths;
+    ngx_array_t               *uri_values;
 } ngx_http_err_page_t;
 
 
--- a/src/http/ngx_http_request_body.c
+++ b/src/http/ngx_http_request_body.c
@@ -405,7 +405,7 @@ ngx_http_discard_body(ngx_http_request_t
     ssize_t       size;
     ngx_event_t  *rev;
 
-    if (r != r->main) {
+    if (r != r->main || r->discard_body) {
         return NGX_OK;
     }
 
--- a/src/http/ngx_http_script.c
+++ b/src/http/ngx_http_script.c
@@ -792,6 +792,10 @@ ngx_http_script_regex_end_code(ngx_http_
 
     } else {
         e->buf.len = e->pos - e->buf.data;
+
+        if (!code->add_args) {
+            r->args.len = 0;
+        }
     }
 
     if (e->log) {
--- a/src/http/ngx_http_special_response.c
+++ b/src/http/ngx_http_special_response.c
@@ -295,8 +295,9 @@ ngx_int_t
 ngx_http_special_response_handler(ngx_http_request_t *r, ngx_int_t error)
 {
     ngx_int_t                  rc;
+    ngx_buf_t                 *b;
+    ngx_str_t                 *uri;
     ngx_uint_t                 i, err, msie_padding;
-    ngx_buf_t                 *b;
     ngx_chain_t               *out, *cl;
     ngx_http_err_page_t       *err_page;
     ngx_http_core_loc_conf_t  *clcf;
@@ -349,9 +350,20 @@ ngx_http_special_response_handler(ngx_ht
 
                 r->method = NGX_HTTP_GET;
 
-                if (err_page[i].uri.data[0] == '/') {
-                    return ngx_http_internal_redirect(r, &err_page[i].uri,
-                                                      NULL);
+                uri = &err_page[i].uri;
+
+                if (err_page[i].uri_lengths) {
+                    if (ngx_http_script_run(r, uri,
+                                            err_page[i].uri_lengths->elts, 0,
+                                            err_page[i].uri_values->elts)
+                        == NULL)
+                    {
+                        return NGX_ERROR;
+                    }
+                }
+
+                if (uri->data[0] == '/') {
+                    return ngx_http_internal_redirect(r, uri, NULL);
                 }
 
                 r->headers_out.location =
@@ -364,10 +376,10 @@ ngx_http_special_response_handler(ngx_ht
                     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 = err_page[i].uri;
+                    r->headers_out.location->value = *uri;
 
                 } else {
-                    error = NGX_HTTP_INTERNAL_SERVER_ERROR;
+                    return NGX_ERROR;
                 }
             }
         }
--- a/src/http/ngx_http_upstream.c
+++ b/src/http/ngx_http_upstream.c
@@ -110,7 +110,7 @@ ngx_http_upstream_header_t  ngx_http_ups
     { 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, 0 },
+                 ngx_http_upstream_copy_content_type, 0, 1 },
 
     { ngx_string("Content-Length"),
                  ngx_http_upstream_process_header_line,
--- a/src/os/unix/ngx_freebsd.h
+++ b/src/os/unix/ngx_freebsd.h
@@ -11,10 +11,10 @@
 ngx_chain_t *ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in,
     off_t limit);
 
-extern int ngx_freebsd_kern_osreldate;
-extern int ngx_freebsd_hw_ncpu;
-extern int ngx_freebsd_net_inet_tcp_sendspace;
-extern int ngx_freebsd_kern_ipc_zero_copy_send;
+extern int     ngx_freebsd_kern_osreldate;
+extern int     ngx_freebsd_hw_ncpu;
+extern u_long  ngx_freebsd_net_inet_tcp_sendspace;
+extern int     ngx_freebsd_kern_ipc_zero_copy_send;
 
 extern ngx_uint_t ngx_freebsd_sendfile_nbytes_bug;
 extern ngx_uint_t ngx_freebsd_use_tcp_nopush;
--- a/src/os/unix/ngx_freebsd_init.c
+++ b/src/os/unix/ngx_freebsd_init.c
@@ -9,18 +9,18 @@
 
 
 /* FreeBSD 3.0 at least */
-char ngx_freebsd_kern_ostype[16];
-char ngx_freebsd_kern_osrelease[128];
-int ngx_freebsd_kern_osreldate;
-int ngx_freebsd_hw_ncpu;
-int ngx_freebsd_net_inet_tcp_sendspace;
-int ngx_freebsd_kern_ipc_somaxconn;
+char    ngx_freebsd_kern_ostype[16];
+char    ngx_freebsd_kern_osrelease[128];
+int     ngx_freebsd_kern_osreldate;
+int     ngx_freebsd_hw_ncpu;
+int     ngx_freebsd_kern_ipc_somaxconn;
+u_long  ngx_freebsd_net_inet_tcp_sendspace;
 
 /* FreeBSD 4.9 */
-int ngx_freebsd_machdep_hlt_logical_cpus;
+int     ngx_freebsd_machdep_hlt_logical_cpus;
 
 /* FreeBSD 5.0 */
-int ngx_freebsd_kern_ipc_zero_copy_send;
+int     ngx_freebsd_kern_ipc_zero_copy_send;
 
 
 ngx_uint_t ngx_freebsd_sendfile_nbytes_bug;
@@ -43,7 +43,7 @@ static ngx_os_io_t ngx_freebsd_io = {
 
 typedef struct {
     char        *name;
-    int         *value;
+    void        *value;
     size_t       size;
     ngx_uint_t   exists;
 } sysctl_t;
@@ -52,23 +52,23 @@ typedef struct {
 sysctl_t sysctls[] = {
     { "hw.ncpu",
       &ngx_freebsd_hw_ncpu,
-      sizeof(int), 0 },
+      sizeof(ngx_freebsd_hw_ncpu), 0 },
 
     { "machdep.hlt_logical_cpus",
       &ngx_freebsd_machdep_hlt_logical_cpus,
-      sizeof(int), 0 },
+      sizeof(ngx_freebsd_machdep_hlt_logical_cpus), 0 },
 
     { "net.inet.tcp.sendspace",
       &ngx_freebsd_net_inet_tcp_sendspace,
-      sizeof(int), 0 },
+      sizeof(ngx_freebsd_net_inet_tcp_sendspace), 0 },
 
     { "kern.ipc.somaxconn",
       &ngx_freebsd_kern_ipc_somaxconn,
-      sizeof(int), 0 },
+      sizeof(ngx_freebsd_kern_ipc_somaxconn), 0 },
 
     { "kern.ipc.zero_copy.send",
       &ngx_freebsd_kern_ipc_zero_copy_send,
-      sizeof(int), 0 },
+      sizeof(ngx_freebsd_kern_ipc_zero_copy_send), 0 },
 
     { NULL, NULL, 0, 0 }
 };
@@ -177,11 +177,10 @@ ngx_os_specific_init(ngx_log_t *log)
 
 
     for (i = 0; sysctls[i].name; i++) {
-        *sysctls[i].value = 0;
         size = sysctls[i].size;
 
         if (sysctlbyname(sysctls[i].name, sysctls[i].value, &size, NULL, 0)
-                                                                          == 0)
+            == 0)
         {
             sysctls[i].exists = 1;
             continue;
@@ -193,12 +192,6 @@ ngx_os_specific_init(ngx_log_t *log)
             continue;
         }
 
-#if 0
-        if (sysctls[i].value == &ngx_freebsd_machdep_hlt_logical_cpus) {
-            continue;
-        }
-#endif
-
         ngx_log_error(NGX_LOG_ALERT, log, err,
                       "sysctlbyname(%s) failed", sysctls[i].name);
         return NGX_ERROR;
@@ -206,15 +199,12 @@ ngx_os_specific_init(ngx_log_t *log)
 
     if (ngx_freebsd_machdep_hlt_logical_cpus) {
         ngx_ncpu = ngx_freebsd_hw_ncpu / 2;
+
     } else {
         ngx_ncpu = ngx_freebsd_hw_ncpu;
     }
 
-    if (version < 600008) {
-        somaxconn = 32767;
-    } else {
-        somaxconn = 65535;
-    }
+    somaxconn = version < 600008 ? 32676 : 65535;
 
     if (ngx_freebsd_kern_ipc_somaxconn > somaxconn) {
         ngx_log_error(NGX_LOG_ALERT, log, 0,
@@ -234,6 +224,7 @@ ngx_os_specific_init(ngx_log_t *log)
 void
 ngx_os_specific_status(ngx_log_t *log)
 {
+    u_long      value;
     ngx_uint_t  i;
 
     ngx_log_error(NGX_LOG_NOTICE, log, 0, "OS: %s %s",
@@ -251,8 +242,15 @@ ngx_os_specific_status(ngx_log_t *log)
 
     for (i = 0; sysctls[i].name; i++) {
         if (sysctls[i].exists) {
-            ngx_log_error(NGX_LOG_NOTICE, log, 0, "%s: %d",
-                          sysctls[i].name, *sysctls[i].value);
+            if (sysctls[i].size == sizeof(long)) {
+                value = *(long *) sysctls[i].value;
+
+            } else {
+                value = *(int *) sysctls[i].value;
+            }
+
+            ngx_log_error(NGX_LOG_NOTICE, log, 0, "%s: %l",
+                          sysctls[i].name, value);
         }
     }
 }
--- a/src/os/unix/ngx_linux_init.c
+++ b/src/os/unix/ngx_linux_init.c
@@ -8,10 +8,14 @@
 #include <ngx_core.h>
 
 
-char ngx_linux_kern_ostype[50];
-char ngx_linux_kern_osrelease[20];
+static ngx_int_t ngx_linux_procfs(char *name, char *buf, size_t len,
+    ngx_log_t *log);
+
 
-int ngx_linux_rtsig_max;
+char  ngx_linux_kern_ostype[50];
+char  ngx_linux_kern_osrelease[20];
+
+int   ngx_linux_rtsig_max;
 
 
 static ngx_os_io_t ngx_linux_io = {
@@ -35,35 +39,31 @@ ngx_os_specific_init(ngx_log_t *log)
     size_t     len;
     ngx_err_t  err;
 
-    name[0] = CTL_KERN;
-    name[1] = KERN_OSTYPE;
-    len = sizeof(ngx_linux_kern_ostype);
-
-    if (sysctl(name, 2, ngx_linux_kern_ostype, &len, NULL, 0) == -1) {
-        ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
-                      "sysctl(KERN_OSTYPE) failed");
+    if (ngx_linux_procfs("/proc/sys/kernel/ostype",
+                         ngx_linux_kern_ostype,
+                         sizeof(ngx_linux_kern_ostype), log)
+        == -1)
+    {
         return NGX_ERROR;
     }
 
-    /* name[0] = CTL_KERN; */
-    name[1] = KERN_OSRELEASE;
-    len = sizeof(ngx_linux_kern_osrelease);
-
-    if (sysctl(name, 2, ngx_linux_kern_osrelease, &len, NULL, 0) == -1) {
-        ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
-                      "sysctl(KERN_OSRELEASE) failed");
+    if (ngx_linux_procfs("/proc/sys/kernel/osrelease",
+                         ngx_linux_kern_osrelease,
+                         sizeof(ngx_linux_kern_osrelease), log)
+        == -1)
+    {
         return NGX_ERROR;
     }
 
 
-    /* name[0] = CTL_KERN; */
+    name[0] = CTL_KERN;
     name[1] = KERN_RTSIGMAX;
     len = sizeof(ngx_linux_rtsig_max);
 
     if (sysctl(name, 2, &ngx_linux_rtsig_max, &len, NULL, 0) == -1) {
         err = ngx_errno;
 
-        if (err != NGX_ENOTDIR) {
+        if (err != NGX_ENOTDIR && err != NGX_ENOSYS) {
             ngx_log_error(NGX_LOG_ALERT, log, err,
                           "sysctl(KERN_RTSIGMAX) failed");
 
@@ -89,3 +89,36 @@ ngx_os_specific_status(ngx_log_t *log)
     ngx_log_error(NGX_LOG_NOTICE, log, 0, "sysctl(KERN_RTSIGMAX): %d",
                   ngx_linux_rtsig_max);
 }
+
+
+static ngx_int_t
+ngx_linux_procfs(char *name, char *buf, size_t len, ngx_log_t *log)
+{
+    int       n;
+    ngx_fd_t  fd;
+
+    fd = open(name, O_RDONLY);
+
+    if (fd == NGX_INVALID_FILE) {
+        ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
+                      "open(\"%s\") failed", name);
+
+        return NGX_ERROR;
+    }
+
+    n = read(fd, buf, len);
+
+    if (n == -1) {
+        ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
+                      "read(\"%s\") failed", name);
+
+    } else {
+        if (buf[n - 1] == '\n') {
+            buf[--n] = '\0';
+        }
+    }
+
+    ngx_close_file(fd);
+
+    return n;
+}