changeset 1804:d457a1576532

several changes in server_name: *) server_name_in_redirect directive and removal of the '*' stub *) use server address in redirect if host can not be detected *) ngx_http_server_addr() *) allow wildcard and regex names to be a main server_name *) DAV Destination header is tested against Host header
author Igor Sysoev <igor@sysoev.ru>
date Sat, 29 Dec 2007 15:30:39 +0000
parents 7405719e4848
children bb72f7518992
files src/http/modules/ngx_http_dav_module.c src/http/ngx_http_core_module.c src/http/ngx_http_core_module.h src/http/ngx_http_header_filter_module.c src/http/ngx_http_request.c
diffstat 5 files changed, 86 insertions(+), 43 deletions(-) [+]
line wrap: on
line diff
--- a/src/http/modules/ngx_http_dav_module.c
+++ b/src/http/modules/ngx_http_dav_module.c
@@ -491,15 +491,15 @@ ngx_http_dav_mkcol_handler(ngx_http_requ
 static ngx_int_t
 ngx_http_dav_copy_move_handler(ngx_http_request_t *r)
 {
-    u_char                   *p, *host, *last, ch;
-    size_t                    root;
+    u_char                   *p, *desthost, *last, ch;
+    size_t                    len, root;
     ngx_err_t                 err;
     ngx_int_t                 rc, depth;
     ngx_uint_t                overwrite, slash;
     ngx_str_t                 path, uri;
     ngx_tree_ctx_t            tree;
     ngx_file_info_t           fi;
-    ngx_table_elt_t          *dest, *over;
+    ngx_table_elt_t          *host, *dest, *over;
     ngx_http_dav_copy_ctx_t   copy;
 
     if (r->headers_in.content_length_n > 0) {
@@ -514,8 +514,12 @@ ngx_http_dav_copy_move_handler(ngx_http_
         return NGX_HTTP_BAD_REQUEST;
     }
 
-    if (dest->value.len < sizeof("http://") - 1 + r->server_name.len + 1) {
-        goto invalid_destination;
+    host = r->headers_in.host;
+
+    if (host == NULL) {
+        ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
+                      "client sent no \"Host\" header");
+        return NGX_HTTP_BAD_REQUEST;
     }
 
 #if (NGX_HTTP_SSL)
@@ -527,7 +531,7 @@ ngx_http_dav_copy_move_handler(ngx_http_
             goto invalid_destination;
         }
 
-        host = dest->value.data + sizeof("https://") - 1;
+        desthost = dest->value.data + sizeof("https://") - 1;
 
     } else
 #endif
@@ -538,10 +542,12 @@ ngx_http_dav_copy_move_handler(ngx_http_
             goto invalid_destination;
         }
 
-        host = dest->value.data + sizeof("http://") - 1;
+        desthost = dest->value.data + sizeof("http://") - 1;
     }
 
-    if (ngx_strncmp(host, r->server_name.data, r->server_name.len) != 0) {
+    len = r->headers_in.host_name_len;
+
+    if (ngx_strncmp(desthost, host->value.data, len) != 0) {
         ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
                       "Destination URI \"%V\" is handled by "
                       "different repository than the source URI",
@@ -552,7 +558,7 @@ ngx_http_dav_copy_move_handler(ngx_http_
 
     last = dest->value.data + dest->value.len;
 
-    for (p = host + r->server_name.len; p < last; p++) {
+    for (p = desthost + len; p < last; p++) {
         if (*p == '/') {
             goto destination_done;
         }
--- a/src/http/ngx_http_core_module.c
+++ b/src/http/ngx_http_core_module.c
@@ -439,6 +439,13 @@ static ngx_command_t  ngx_http_core_comm
       offsetof(ngx_http_core_loc_conf_t, reset_timedout_connection),
       NULL },
 
+    { ngx_string("server_name_in_redirect"),
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
+      ngx_conf_set_flag_slot,
+      NGX_HTTP_LOC_CONF_OFFSET,
+      offsetof(ngx_http_core_loc_conf_t, server_name_in_redirect),
+      NULL },
+
     { ngx_string("port_in_redirect"),
       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
       ngx_conf_set_flag_slot,
@@ -1471,6 +1478,38 @@ ngx_http_auth_basic_user(ngx_http_reques
 }
 
 
+ngx_int_t
+ngx_http_server_addr(ngx_http_request_t *r, ngx_str_t *s)
+{
+    socklen_t            len;
+    ngx_connection_t    *c;
+    struct sockaddr_in   sin;
+
+    /* AF_INET only */
+
+    c = r->connection;
+
+    if (r->in_addr == 0) {
+        len = sizeof(struct sockaddr_in);
+        if (getsockname(c->fd, (struct sockaddr *) &sin, &len) == -1) {
+            ngx_connection_error(c, ngx_socket_errno, "getsockname() failed");
+            return NGX_ERROR;
+        }
+
+        r->in_addr = sin.sin_addr.s_addr;
+    }
+
+    if (s == NULL) {
+        return NGX_OK;
+    }
+
+    s->len = ngx_inet_ntop(c->listening->family, &r->in_addr,
+                           s->data, INET_ADDRSTRLEN);
+
+    return NGX_OK;
+}
+
+
 #if (NGX_HTTP_GZIP)
 
 ngx_int_t
@@ -2652,6 +2691,7 @@ ngx_http_core_create_loc_conf(ngx_conf_t
     lcf->lingering_timeout = NGX_CONF_UNSET_MSEC;
     lcf->resolver_timeout = NGX_CONF_UNSET_MSEC;
     lcf->reset_timedout_connection = NGX_CONF_UNSET;
+    lcf->server_name_in_redirect = NGX_CONF_UNSET;
     lcf->port_in_redirect = NGX_CONF_UNSET;
     lcf->msie_padding = NGX_CONF_UNSET;
     lcf->msie_refresh = NGX_CONF_UNSET;
@@ -2863,6 +2903,8 @@ ngx_http_core_merge_loc_conf(ngx_conf_t 
 
     ngx_conf_merge_value(conf->reset_timedout_connection,
                               prev->reset_timedout_connection, 0);
+    ngx_conf_merge_value(conf->server_name_in_redirect,
+                              prev->server_name_in_redirect, 1);
     ngx_conf_merge_value(conf->port_in_redirect, prev->port_in_redirect, 1);
     ngx_conf_merge_value(conf->msie_padding, prev->msie_padding, 1);
     ngx_conf_merge_value(conf->msie_refresh, prev->msie_refresh, 0);
@@ -3078,20 +3120,6 @@ ngx_http_core_server_name(ngx_conf_t *cf
     ch = value[1].data[0];
 
     if (cscf->server_name.data == NULL && value[1].len) {
-        if (ngx_strchr(value[1].data, '*')) {
-            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
-                               "first server name \"%V\" must not be wildcard",
-                               &value[1]);
-            return NGX_CONF_ERROR;
-        }
-
-        if (value[1].data[0] == '~') {
-            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
-                               "first server name \"%V\" "
-                               "must not be regular expression", &value[1]);
-            return NGX_CONF_ERROR;
-        }
-
         name = value[1];
 
         if (ch == '.') {
@@ -3110,11 +3138,6 @@ ngx_http_core_server_name(ngx_conf_t *cf
 
         ch = value[i].data[0];
 
-        if (value[i].len == 1 && ch == '*') {
-            cscf->wildcard = 1;
-            continue;
-        }
-
         if (value[i].len == 0
             || (ch == '*' && (value[i].len < 3 || value[i].data[1] != '.'))
             || (ch == '.' && value[i].len < 2))
--- a/src/http/ngx_http_core_module.h
+++ b/src/http/ngx_http_core_module.h
@@ -131,7 +131,6 @@ typedef struct {
 
     unsigned                   regex_start:15;
     unsigned                   named_start:15;
-    unsigned                   wildcard:1;
 
     /* array of the ngx_http_listen_t, "listen" directive */
     ngx_array_t                listen;
@@ -294,6 +293,7 @@ struct ngx_http_core_loc_conf_s {
     ngx_flag_t    tcp_nopush;              /* tcp_nopush */
     ngx_flag_t    tcp_nodelay;             /* tcp_nodelay */
     ngx_flag_t    reset_timedout_connection; /* reset_timedout_connection */
+    ngx_flag_t    server_name_in_redirect; /* server_name_in_redirect */
     ngx_flag_t    port_in_redirect;        /* port_in_redirect */
     ngx_flag_t    msie_padding;            /* msie_padding */
     ngx_flag_t    msie_refresh;            /* msie_refresh */
@@ -352,6 +352,7 @@ ngx_int_t ngx_http_set_exten(ngx_http_re
 u_char *ngx_http_map_uri_to_path(ngx_http_request_t *r, ngx_str_t *name,
     size_t *root_length, size_t reserved);
 ngx_int_t ngx_http_auth_basic_user(ngx_http_request_t *r);
+ngx_int_t ngx_http_server_addr(ngx_http_request_t *r, ngx_str_t *s);
 #if (NGX_HTTP_GZIP)
 ngx_int_t ngx_http_gzip_ok(ngx_http_request_t *r);
 #endif
--- a/src/http/ngx_http_header_filter_module.c
+++ b/src/http/ngx_http_header_filter_module.c
@@ -153,12 +153,15 @@ ngx_http_header_filter(ngx_http_request_
 {
     u_char                    *p;
     size_t                     len;
+    ngx_str_t                  host;
     ngx_buf_t                 *b;
     ngx_uint_t                 status, i;
     ngx_chain_t                out;
     ngx_list_part_t           *part;
     ngx_table_elt_t           *header;
     ngx_http_core_loc_conf_t  *clcf;
+    /* AF_INET only */
+    u_char                     addr[INET_ADDRSTRLEN];
 
     r->header_sent = 1;
 
@@ -278,10 +281,25 @@ ngx_http_header_filter(ngx_http_request_
     {
         r->headers_out.location->hash = 0;
 
+        if (clcf->server_name_in_redirect) {
+            host = r->server_name;
+
+        } else if (r->headers_in.host) {
+            host.len = r->headers_in.host_name_len;
+            host.data = r->headers_in.host->value.data;
+
+        } else {
+            host.data = addr;
+
+            if (ngx_http_server_addr(r, &host) != NGX_OK) {
+                return NGX_ERROR;
+            }
+        }
+
 #if (NGX_HTTP_SSL)
         if (r->connection->ssl) {
             len += sizeof("Location: https://") - 1
-                   + r->server_name.len
+                   + host.len
                    + r->headers_out.location->value.len + 2;
 
             if (clcf->port_in_redirect && r->port != 443) {
@@ -292,13 +310,17 @@ ngx_http_header_filter(ngx_http_request_
 #endif
         {
             len += sizeof("Location: http://") - 1
-                   + r->server_name.len
+                   + host.len
                    + r->headers_out.location->value.len + 2;
 
             if (clcf->port_in_redirect && r->port != 80) {
                 len += r->port_text->len;
             }
         }
+
+    } else {
+        host.len = 0;
+        host.data = NULL;
     }
 
     if (r->chunked) {
@@ -428,10 +450,8 @@ ngx_http_header_filter(ngx_http_request_
         *b->last++ = CR; *b->last++ = LF;
     }
 
-    if (r->headers_out.location
-        && r->headers_out.location->value.len
-        && r->headers_out.location->value.data[0] == '/')
-    {
+    if (host.data) {
+
         p = b->last + sizeof("Location: ") - 1;
 
         b->last = ngx_cpymem(b->last, "Location: http",
@@ -444,7 +464,7 @@ ngx_http_header_filter(ngx_http_request_
 #endif
 
         *b->last++ = ':'; *b->last++ = '/'; *b->last++ = '/';
-        b->last = ngx_copy(b->last, r->server_name.data, r->server_name.len);
+        b->last = ngx_copy(b->last, host.data, host.len);
 
         if (clcf->port_in_redirect) {
 #if (NGX_HTTP_SSL)
--- a/src/http/ngx_http_request.c
+++ b/src/http/ngx_http_request.c
@@ -1515,13 +1515,6 @@ ngx_http_find_virtual_server(ngx_http_re
 
 #endif
 
-    cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
-
-    if (cscf->wildcard) {
-        r->server_name.len = len;
-        r->server_name.data = host;
-    }
-
     return;
 
 found: