changeset 238:a528ae0fe909 NGINX_0_4_4

nginx 0.4.4 *) Feature: the $scheme variable. *) Feature: the "expires" directive supports the "max" parameter. *) Feature: the "include" directive supports the "*" mask. Thanks to Jonathan Dance. *) Bugfix: the "return" directive always overrode the "error_page" response code redirected by the "error_page" directive. *) Bugfix: a segmentation fault occurred if zero-length body was in PUT method. *) Bugfix: the redirect was changed incorrectly if the variables were used in the "proxy_redirect" directive.
author Igor Sysoev <http://sysoev.ru>
date Mon, 02 Oct 2006 00:00:00 +0400
parents 302a8e8b4ae7
children 4f355d4f0cfa
files CHANGES CHANGES.ru auto/options src/core/nginx.h src/core/ngx_conf_file.c src/http/modules/ngx_http_headers_filter_module.c src/http/modules/ngx_http_proxy_module.c src/http/modules/ngx_http_rewrite_module.c src/http/ngx_http_request.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_variables.c src/os/unix/ngx_files.c src/os/unix/ngx_files.h src/os/unix/ngx_freebsd_config.h src/os/unix/ngx_linux_config.h src/os/unix/ngx_posix_config.h src/os/unix/ngx_solaris_config.h
diffstat 19 files changed, 250 insertions(+), 24 deletions(-) [+]
line wrap: on
line diff
--- a/CHANGES
+++ b/CHANGES
@@ -1,4 +1,23 @@
 
+Changes with nginx 0.4.4                                         02 Oct 2006
+
+    *) Feature: the "scheme" variable.
+
+    *) Feature: the "expires" directive supports the "max" parameter.
+
+    *) Feature: the "include" directive supports the "*" mask.
+       Thanks to Jonathan Dance.
+
+    *) Bugfix: the "return" directive always overrode the "error_page" 
+       response code redirected by the "error_page" directive.
+
+    *) Bugfix: a segmentation fault occurred if zero-length body was in PUT 
+       method.
+
+    *) Bugfix: the redirect was changed incorrectly if the variables were 
+       used in the "proxy_redirect" directive.
+
+
 Changes with nginx 0.4.3                                         26 Sep 2006
 
     *) Change: now the 499 error could not be redirected using an 
--- a/CHANGES.ru
+++ b/CHANGES.ru
@@ -1,4 +1,23 @@
 
+Изменения в nginx 0.4.4                                           02.10.2006
+
+    *) Добавление: переменная scheme.
+
+    *) Добавление: директива expires поддерживает параметр max.
+
+    *) Добавление: директива include поддерживает маску "*".
+       Спасибо Jonathan Dance.
+
+    *) Исправление: директива return всегда изменяла код ответа, 
+       перенаправленного директивой error_page.
+
+    *) Исправление: происходил segmentation fault, если в методе PUT 
+       передавалось тело нулевой длины.
+
+    *) Исправление: при использовании переменных в директиве proxy_redirect 
+       редирект изменялся неверно.
+
+
 Изменения в nginx 0.4.3                                           26.09.2006
 
     *) Изменение: ошибку 499 теперь нельзя перенаправить с помощью 
--- a/auto/options
+++ b/auto/options
@@ -260,12 +260,14 @@ cat << END
   --without-http_auth_basic_module   disable ngx_http_auth_basic_module
   --without-http_autoindex_module    disable ngx_http_autoindex_module
   --without-http_geo_module          disable ngx_http_geo_module
+  --without-http_map_module          disable ngx_http_map_module
   --without-http_referer_module      disable ngx_http_referer_module
   --without-http_rewrite_module      disable ngx_http_rewrite_module
   --without-http_proxy_module        disable ngx_http_proxy_module
   --without-http_fastcgi_module      disable ngx_http_fastcgi_module
   --without-http_memcached_module    disable ngx_http_memcached_module
   --without-http_empty_gif_module    disable ngx_http_empty_gif_module
+  --without-http_browser_module      disable ngx_http_browser_module
 
   --with-http_perl_module            enable ngx_http_perl_module
   --with-perl_modules_path=PATH      set path to the perl modules
@@ -281,6 +283,7 @@ cat << END
   --without-http                     disable HTTP server
 
   --with-imap                        enable IMAP4/POP3 proxy module
+  --with-imap_ssl_module             enable ngx_imap_ssl_module
 
   --with-cc=PATH                     set path to C compiler
   --with-cpp=PATH                    set path to C preprocessor
--- a/src/core/nginx.h
+++ b/src/core/nginx.h
@@ -8,7 +8,7 @@
 #define _NGINX_H_INCLUDED_
 
 
-#define NGINX_VER          "nginx/0.4.3"
+#define NGINX_VER          "nginx/0.4.4"
 
 #define NGINX_VAR          "NGINX"
 #define NGX_OLDPID_EXT     ".oldbin"
--- a/src/core/ngx_conf_file.c
+++ b/src/core/ngx_conf_file.c
@@ -650,18 +650,52 @@ ngx_conf_read_token(ngx_conf_t *cf)
 static char *
 ngx_conf_include(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
 {
-    ngx_str_t  *value, file;
+    char        *rv;
+    ngx_int_t    n;
+    ngx_str_t   *value, file;
+    ngx_glob_t   gl;
 
     value = cf->args->elts;
     file = value[1];
 
+    ngx_log_debug1(NGX_LOG_DEBUG_CORE, cf->log, 0, "include %s", file.data);
+
     if (ngx_conf_full_name(cf->cycle, &file) == NGX_ERROR) {
         return NGX_CONF_ERROR;
     }
 
-    ngx_log_debug1(NGX_LOG_DEBUG_CORE, cf->log, 0, "include %s", file.data);
+    ngx_memzero(&gl, sizeof(ngx_glob_t));
+
+    gl.pattern = file.data;
+    gl.log = cf->log;
+
+    if (ngx_open_glob(&gl) != NGX_OK) {
+        ngx_conf_log_error(NGX_LOG_EMERG, cf, ngx_errno,
+                           ngx_open_glob_n " \"%s\" failed", file.data);
+        return NGX_CONF_ERROR;
+    }
+
+    rv = NGX_CONF_OK;
+
+    for ( ;; ) {
+        n = ngx_read_glob(&gl, &file);
 
-    return ngx_conf_parse(cf, &file);
+        if (n != NGX_OK) {
+            break;
+        }
+
+        ngx_log_debug1(NGX_LOG_DEBUG_CORE, cf->log, 0, "include %s", file.data);
+
+        rv = ngx_conf_parse(cf, &file);
+
+        if (rv != NGX_CONF_OK) {
+            break;
+        }
+    }
+
+    ngx_close_glob(&gl);
+
+    return rv;
 }
 
 
--- a/src/http/modules/ngx_http_headers_filter_module.c
+++ b/src/http/modules/ngx_http_headers_filter_module.c
@@ -26,6 +26,7 @@ typedef struct {
 #define NGX_HTTP_EXPIRES_UNSET   -2147483647
 #define NGX_HTTP_EXPIRES_OFF     -2147483646
 #define NGX_HTTP_EXPIRES_EPOCH   -2147483645
+#define NGX_HTTP_EXPIRES_MAX     -2147483644
 
 
 static void *ngx_http_headers_create_conf(ngx_conf_t *cf);
@@ -177,6 +178,13 @@ ngx_http_headers_filter(ngx_http_request
             cc->value.len = sizeof("no-cache") - 1;
             cc->value.data = (u_char *) "no-cache";
 
+        } else if (conf->expires == NGX_HTTP_EXPIRES_MAX) {
+            expires->value.data = (u_char *) "Thu, 31 Dec 2037 23:55:55 GMT";
+
+            /* 10 years */
+            cc->value.len = sizeof("max-age=315360000") - 1;
+            cc->value.data = (u_char *) "max-age=315360000";
+
         } else {
             expires->value.data = ngx_palloc(r->pool, len);
             if (expires->value.data == NULL) {
@@ -349,6 +357,11 @@ ngx_http_headers_expires(ngx_conf_t *cf,
         return NGX_CONF_OK;
     }
 
+    if (ngx_strcmp(value[1].data, "max") == 0) {
+        hcf->expires = NGX_HTTP_EXPIRES_MAX;
+        return NGX_CONF_OK;
+    }
+
     if (ngx_strcmp(value[1].data, "off") == 0) {
         hcf->expires = NGX_HTTP_EXPIRES_OFF;
         return NGX_CONF_OK;
--- a/src/http/modules/ngx_http_proxy_module.c
+++ b/src/http/modules/ngx_http_proxy_module.c
@@ -1397,8 +1397,11 @@ ngx_http_proxy_rewrite_redirect_vars(ngx
     e.ip = pr->replacement.vars.lengths;
     e.request = r;
 
-    for (len = prefix; *(uintptr_t *) e.ip; len += lcode(&e)) {
+    len = prefix + h->value.len - pr->redirect.len;
+
+    while (*(uintptr_t *) e.ip) {
         lcode = *(ngx_http_script_len_code_pt *) e.ip;
+        len += lcode(&e);
     }
 
     data = ngx_palloc(r->pool, len);
@@ -1418,6 +1421,9 @@ ngx_http_proxy_rewrite_redirect_vars(ngx
         code(&e);
     }
 
+    ngx_memcpy(e.pos, h->value.data + prefix + pr->redirect.len,
+               h->value.len - pr->redirect.len - prefix);
+
     h->value.len = len;
     h->value.data = data;
 
--- a/src/http/modules/ngx_http_rewrite_module.c
+++ b/src/http/modules/ngx_http_rewrite_module.c
@@ -178,7 +178,11 @@ ngx_http_rewrite_handler(ngx_http_reques
         code(e);
     }
 
-    return e->status;
+    if (r->err_status == 0) {
+        return e->status;
+    }
+
+    return r->err_status;
 }
 
 
--- a/src/http/ngx_http_request.h
+++ b/src/http/ngx_http_request.h
@@ -430,6 +430,7 @@ struct ngx_http_request_s {
     unsigned                          plain_http:1;
     unsigned                          chunked:1;
     unsigned                          header_only:1;
+    unsigned                          zero_body:1;
     unsigned                          keepalive:1;
     unsigned                          lingering_close:1;
     unsigned                          discard_body:1;
--- a/src/http/ngx_http_request_body.c
+++ b/src/http/ngx_http_request_body.c
@@ -34,6 +34,7 @@ ngx_http_read_client_request_body(ngx_ht
     ssize_t                    size;
     ngx_buf_t                 *b;
     ngx_chain_t               *cl, **next;
+    ngx_temp_file_t           *tf;
     ngx_http_request_body_t   *rb;
     ngx_http_core_loc_conf_t  *clcf;
 
@@ -49,7 +50,43 @@ ngx_http_read_client_request_body(ngx_ht
 
     r->request_body = rb;
 
-    if (r->headers_in.content_length_n <= 0) {
+    if (r->headers_in.content_length_n < 0) {
+        post_handler(r);
+        return NGX_OK;
+    }
+
+    clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
+
+    if (r->headers_in.content_length_n == 0) {
+
+        if (r->request_body_in_file_only) {
+            tf = ngx_pcalloc(r->pool, sizeof(ngx_temp_file_t));
+            if (tf == NULL) {
+                return NGX_HTTP_INTERNAL_SERVER_ERROR;
+            }
+
+            tf->file.fd = NGX_INVALID_FILE;
+            tf->file.log = r->connection->log;
+            tf->path = clcf->client_body_temp_path;
+            tf->pool = r->pool;
+            tf->warn = "a client request body is buffered to a temporary file";
+            tf->log_level = r->request_body_file_log_level;
+            tf->persistent = r->request_body_in_persistent_file;
+
+            if (r->request_body_file_group_access) {
+                tf->mode = 0660;
+            }
+
+            rb->temp_file = tf;
+
+            if (ngx_create_temp_file(&tf->file, tf->path, tf->pool,
+                                     tf->persistent, tf->mode)
+                != NGX_OK)
+            {
+                return NGX_HTTP_INTERNAL_SERVER_ERROR;
+            }
+        }
+
         post_handler(r);
         return NGX_OK;
     }
@@ -139,8 +176,6 @@ ngx_http_read_client_request_body(ngx_ht
         next = &rb->bufs;
     }
 
-    clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
-
     size = clcf->client_body_buffer_size;
     size += size >> 2;
 
--- a/src/http/ngx_http_script.c
+++ b/src/http/ngx_http_script.c
@@ -841,6 +841,7 @@ ngx_http_script_return_code(ngx_http_scr
 
     if (code->status == NGX_HTTP_NO_CONTENT) {
         e->request->header_only = 1;
+        e->request->zero_body = 1;
     }
 
     e->ip += sizeof(ngx_http_script_return_code_t) - sizeof(uintptr_t);
--- a/src/http/ngx_http_special_response.c
+++ b/src/http/ngx_http_special_response.c
@@ -455,25 +455,32 @@ ngx_http_special_response_handler(ngx_ht
 
     msie_padding = 0;
 
-    if (error_pages[err].len) {
-        r->headers_out.content_length_n = error_pages[err].len
-                                          + sizeof(error_tail) - 1;
+    if (!r->zero_body) {
+        if (error_pages[err].len) {
+            r->headers_out.content_length_n = error_pages[err].len
+                                              + sizeof(error_tail) - 1;
 
-        if (clcf->msie_padding
-            && r->headers_in.msie
-            && r->http_version >= NGX_HTTP_VERSION_10
-            && error >= NGX_HTTP_BAD_REQUEST
-            && error != NGX_HTTP_REQUEST_URI_TOO_LARGE)
-        {
-            r->headers_out.content_length_n += sizeof(ngx_http_msie_stub) - 1;
-            msie_padding = 1;
+            if (clcf->msie_padding
+                && r->headers_in.msie
+                && r->http_version >= NGX_HTTP_VERSION_10
+                && error >= NGX_HTTP_BAD_REQUEST
+                && error != NGX_HTTP_REQUEST_URI_TOO_LARGE)
+            {
+                r->headers_out.content_length_n +=
+                                                sizeof(ngx_http_msie_stub) - 1;
+                msie_padding = 1;
+            }
+
+            r->headers_out.content_type.len = sizeof("text/html") - 1;
+            r->headers_out.content_type.data = (u_char *) "text/html";
+
+        } else {
+            r->headers_out.content_length_n = -1;
         }
 
-        r->headers_out.content_type.len = sizeof("text/html") - 1;
-        r->headers_out.content_type.data = (u_char *) "text/html";
-
     } else {
-        r->headers_out.content_length_n = -1;
+        r->headers_out.content_length_n = 0;
+        err = 0;
     }
 
     if (r->headers_out.content_length) {
--- a/src/http/ngx_http_variables.c
+++ b/src/http/ngx_http_variables.c
@@ -36,6 +36,8 @@ static ngx_int_t ngx_http_variable_serve
     ngx_http_variable_value_t *v, uintptr_t data);
 static ngx_int_t ngx_http_variable_server_port(ngx_http_request_t *r,
     ngx_http_variable_value_t *v, uintptr_t data);
+static ngx_int_t ngx_http_variable_scheme(ngx_http_request_t *r,
+    ngx_http_variable_value_t *v, uintptr_t data);
 static ngx_int_t ngx_http_variable_document_root(ngx_http_request_t *r,
     ngx_http_variable_value_t *v, uintptr_t data);
 static ngx_int_t ngx_http_variable_request_filename(ngx_http_request_t *r,
@@ -122,6 +124,8 @@ static ngx_http_variable_t  ngx_http_cor
     { ngx_string("server_protocol"), NULL, ngx_http_variable_request,
       offsetof(ngx_http_request_t, http_protocol), 0, 0 },
 
+    { ngx_string("scheme"), NULL, ngx_http_variable_scheme, 0, 0, 0 },
+
     { ngx_string("request_uri"), NULL, ngx_http_variable_request,
       offsetof(ngx_http_request_t, unparsed_uri), 0, 0 },
 
@@ -772,6 +776,34 @@ ngx_http_variable_server_port(ngx_http_r
 
 
 static ngx_int_t
+ngx_http_variable_scheme(ngx_http_request_t *r,
+    ngx_http_variable_value_t *v, uintptr_t data)
+{
+#if (NGX_HTTP_SSL)
+
+    if (r->connection->ssl) {
+        v->len = sizeof("https") - 1;
+        v->valid = 1;
+        v->no_cachable = 0;
+        v->not_found = 0;
+        v->data = (u_char *) "https";
+
+        return NGX_OK;
+    }
+
+#endif
+
+    v->len = sizeof("http") - 1;
+    v->valid = 1;
+    v->no_cachable = 0;
+    v->not_found = 0;
+    v->data = (u_char *) "http";
+
+    return NGX_OK;
+}
+
+
+static ngx_int_t
 ngx_http_variable_document_root(ngx_http_request_t *r,
     ngx_http_variable_value_t *v, uintptr_t data)
 {
--- a/src/os/unix/ngx_files.c
+++ b/src/os/unix/ngx_files.c
@@ -253,6 +253,40 @@ ngx_open_dir(ngx_str_t *name, ngx_dir_t 
 }
 
 
+ngx_int_t
+ngx_open_glob(ngx_glob_t *gl)
+{
+    if (glob((char *) gl->pattern, 0, NULL, &gl->pglob) == 0) {
+        return NGX_OK;
+    }
+
+    return NGX_ERROR;
+}
+
+
+ngx_int_t
+ngx_read_glob(ngx_glob_t *gl, ngx_str_t *name)
+{
+    if (gl->n < gl->pglob.gl_pathc) {
+
+        name->len = (size_t) ngx_strlen(gl->pglob.gl_pathv[gl->n]);
+        name->data = (u_char *) gl->pglob.gl_pathv[gl->n];
+        gl->n++;
+
+        return NGX_OK;
+    }
+
+    return NGX_DONE;
+}
+
+
+void
+ngx_close_glob(ngx_glob_t *gl)
+{
+    globfree(&gl->pglob);
+}
+
+
 ngx_err_t
 ngx_trylock_fd(ngx_fd_t fd)
 {
--- a/src/os/unix/ngx_files.h
+++ b/src/os/unix/ngx_files.h
@@ -130,6 +130,20 @@ ngx_int_t ngx_open_dir(ngx_str_t *name, 
 #define ngx_de_mtime(dir)        (dir)->info.st_mtime
 
 
+typedef struct {
+    int         n;
+    glob_t      pglob;
+    u_char     *pattern;
+    ngx_log_t  *log;
+} ngx_glob_t;
+
+
+ngx_int_t ngx_open_glob(ngx_glob_t *gl);
+#define ngx_open_glob_n          "glob()"
+ngx_int_t ngx_read_glob(ngx_glob_t *gl, ngx_str_t *name);
+void ngx_close_glob(ngx_glob_t *gl);
+
+
 ngx_err_t ngx_trylock_fd(ngx_fd_t fd);
 ngx_err_t ngx_lock_fd(ngx_fd_t fd);
 ngx_err_t ngx_unlock_fd(ngx_fd_t fd);
--- a/src/os/unix/ngx_freebsd_config.h
+++ b/src/os/unix/ngx_freebsd_config.h
@@ -21,6 +21,7 @@
 #include <pwd.h>
 #include <grp.h>
 #include <dirent.h>
+#include <glob.h>
 
 #include <sys/filio.h>          /* FIONBIO */
 #include <sys/uio.h>
--- a/src/os/unix/ngx_linux_config.h
+++ b/src/os/unix/ngx_linux_config.h
@@ -27,6 +27,7 @@
 #include <pwd.h>
 #include <grp.h>
 #include <dirent.h>
+#include <glob.h>
 
 #include <sys/uio.h>
 #include <sys/stat.h>
--- a/src/os/unix/ngx_posix_config.h
+++ b/src/os/unix/ngx_posix_config.h
@@ -37,6 +37,7 @@
 #include <pwd.h>
 #include <grp.h>
 #include <dirent.h>
+#include <glob.h>
 
 #if (NGX_HAVE_SYS_FILIO_H)
 #include <sys/filio.h>          /* FIONBIO */
--- a/src/os/unix/ngx_solaris_config.h
+++ b/src/os/unix/ngx_solaris_config.h
@@ -25,6 +25,7 @@
 #include <pwd.h>
 #include <grp.h>
 #include <dirent.h>
+#include <glob.h>
 
 #include <sys/filio.h>          /* FIONBIO */
 #include <sys/uio.h>