# HG changeset patch # User Igor Sysoev # Date 1198942239 0 # Node ID d457a1576532352e73e2108a40978f72111ae84c # Parent 7405719e4848771fe003a4a250b500d7f12a2af8 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 diff --git a/src/http/modules/ngx_http_dav_module.c b/src/http/modules/ngx_http_dav_module.c --- 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; } 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 @@ -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)) diff --git a/src/http/ngx_http_core_module.h b/src/http/ngx_http_core_module.h --- 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 diff --git a/src/http/ngx_http_header_filter_module.c b/src/http/ngx_http_header_filter_module.c --- 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) diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c --- 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: