The server_name directive allows for selecting which "server" block should
be used to process a request; a "server" being a very convenient way to
group a set of directives and location blocks into a separate and distinct
configuration entity. Currently, server_name selects the server based on
the value of the Host: header alone, which can be overly constraining.
The attached patch extends server_name to allow the first directory element
to be used as part of the selection process. When there is at least one
server_name with a '/' character, at ngx_http_find_virtual_server() time an
initial lookup into the virtual_names hash is made using a combination of
hostname/topleveldirectory - if no match is found, the hostname only lookup
is performed (as before), thereby allowing for specific directories to be
broken out into their own server blocks
From a01fd492fb8935e9c9e0f4c703b9430c83c12590 Mon Sep 17 00:00:00 2001
From: Chris Newton <cnewton@netflix.com>
Date: Mon, 24 Jul 2023 19:32:03 +0000
Subject: [PATCH] virtual aliases
---
src/http/ngx_http.c | 2 ++
src/http/ngx_http.h | 1 +
src/http/ngx_http_core_module.c | 4 +--
src/http/ngx_http_request.c | 54 ++++++++++++++++++++++++++++-----
4 files changed, 51 insertions(+), 10 deletions(-)
diff --git a/src/http/ngx_http.c b/src/http/ngx_http.c
index d835f896e..54ad9cb9e 100644
--- a/src/http/ngx_http.c
+++ b/src/http/ngx_http.c
@@ -70,6 +70,7 @@ static ngx_int_t ngx_http_add_addrs6(ngx_conf_t *cf,
ngx_http_port_t *hport,
ngx_uint_t ngx_http_max_module;
+ngx_uint_t ngx_http_uses_complete_alias;
ngx_http_output_header_filter_pt ngx_http_top_header_filter;
ngx_http_output_body_filter_pt ngx_http_top_body_filter;
@@ -148,6 +149,7 @@ ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void
*conf)
ngx_http_max_module = ngx_count_modules(cf->cycle, NGX_HTTP_MODULE);
+ ngx_http_uses_complete_alias = 0;
/* the http main_conf context, it is the same in the all http contexts
*/
diff --git a/src/http/ngx_http.h b/src/http/ngx_http.h
index e06464ebd..935cecc0f 100644
--- a/src/http/ngx_http.h
+++ b/src/http/ngx_http.h
@@ -189,6 +189,7 @@ extern ngx_module_t ngx_http_module;
extern ngx_str_t ngx_http_html_default_types[];
+extern ngx_uint_t ngx_http_uses_complete_alias;
extern ngx_http_output_header_filter_pt ngx_http_top_header_filter;
extern ngx_http_output_body_filter_pt ngx_http_top_body_filter;
diff --git a/src/http/ngx_http_core_module.c
b/src/http/ngx_http_core_module.c
index 97a91aee2..3179d65a1 100644
--- a/src/http/ngx_http_core_module.c
+++ b/src/http/ngx_http_core_module.c
@@ -4380,9 +4380,7 @@ ngx_http_core_server_name(ngx_conf_t *cf,
ngx_command_t *cmd, void *conf)
}
if (ngx_strchr(value[i].data, '/')) {
- ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
- "server name \"%V\" has suspicious symbols",
- &value[i]);
+ ngx_http_uses_complete_alias = 1;
}
sn = ngx_array_push(&cscf->server_names);
diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c
index bd2be5eac..189500885 100644
--- a/src/http/ngx_http_request.c
+++ b/src/http/ngx_http_request.c
@@ -2227,6 +2227,7 @@ ngx_http_set_virtual_server(ngx_http_request_t *r,
ngx_str_t *host)
ngx_http_connection_t *hc;
ngx_http_core_loc_conf_t *clcf;
ngx_http_core_srv_conf_t *cscf;
+ ngx_str_t *find_host = host;
#if (NGX_SUPPRESS_WARN)
cscf = NULL;
@@ -2250,7 +2251,11 @@ ngx_http_set_virtual_server(ngx_http_request_t *r,
ngx_str_t *host)
return NGX_ERROR;
}
#endif
- return NGX_OK;
+ if (ngx_http_uses_complete_alias) {
+ find_host = hc->ssl_servername;
+ } else {
+ return NGX_OK;
+ }
}
}
@@ -2258,7 +2263,7 @@ ngx_http_set_virtual_server(ngx_http_request_t *r,
ngx_str_t *host)
rc = ngx_http_find_virtual_server(r->connection,
hc->addr_conf->virtual_names,
- host, r, &cscf);
+ find_host, r, &cscf);
if (rc == NGX_ERROR) {
ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
@@ -2275,14 +2280,19 @@ ngx_http_set_virtual_server(ngx_http_request_t *r,
ngx_str_t *host)
rc = NGX_OK;
}
- sscf = ngx_http_get_module_srv_conf(cscf->ctx,
ngx_http_ssl_module);
+ if (!ngx_http_uses_complete_alias
+ || hc->ssl_servername->len != host->len
+ || ngx_strncmp(hc->ssl_servername->data,
+ host->data, host->len) != 0) {
+ sscf = ngx_http_get_module_srv_conf(cscf->ctx,
ngx_http_ssl_module);
- if (sscf->verify) {
- ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
+ if (sscf->verify) {
+ ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
"client attempted to request the server name "
"different from the one that was negotiated");
- ngx_http_finalize_request(r, NGX_HTTP_MISDIRECTED_REQUEST);
- return NGX_ERROR;
+ ngx_http_finalize_request(r, NGX_HTTP_MISDIRECTED_REQUEST);
+ return NGX_ERROR;
+ }
}
}
@@ -2314,6 +2324,36 @@ ngx_http_find_virtual_server(ngx_connection_t *c,
return NGX_DECLINED;
}
+ if (r && r->uri.len > 1 && r->pool) {
+ ngx_str_t combined;
+ u_char *p;
+
+ p = (u_char *)ngx_strchr(&r->uri.data[1], '/');
+ if (p) {
+ ngx_uint_t alias_len = p - r->uri.data;
+ if (alias_len > r->uri.len) {
+ /* No '/' in the path, so use entire thing */
+ alias_len = r->uri.len;
+ }
+ combined.len = host->len + alias_len;
+
+ combined.data = ngx_pnalloc(r->pool, combined.len);
+ if (combined.data == NULL) {
+ return NGX_ERROR;
+ }
+ ngx_memcpy(&combined.data[0], host->data, host->len);
+ ngx_memcpy(&combined.data[host->len], r->uri.data, alias_len);
+
+ cscf = ngx_hash_find_combined(&virtual_names->names,
+ ngx_hash_key(combined.data,
combined.len),
+ combined.data, combined.len);
+ if (cscf) {
+ *cscfp = cscf;
+ return NGX_OK;
+ }
+ }
+ }
+
cscf = ngx_hash_find_combined(&virtual_names->names,
ngx_hash_key(host->data, host->len),
host->data, host->len);
--
2.40.1
*Chris Newton* (he/him/his)
Open Connect | Content Delivery Architecture M: 805.444.0573 |
cnewton@netflix.com
111 Albright Way | Los Gatos, CA 95032
https://maps.google.com/?q=111+Albright+Way%C2%A0%7C++Los+Gatos,+CA+95032&entry=gmail&source=g
_______________________________________________
nginx-devel mailing list
nginx-devel@nginx.org
https://mailman.nginx.org/mailman/listinfo/nginx-devel