# HG changeset patch # User Igor Sysoev # Date 1186948092 0 # Node ID cb8b30ef3e7e3404d16ff0b727b39dab689c1036 # Parent 3c6da0610f19778024a332f336bbd2766c4d2504 regex in server_name diff --git a/src/http/ngx_http.c b/src/http/ngx_http.c --- a/src/http/ngx_http.c +++ b/src/http/ngx_http.c @@ -98,6 +98,9 @@ ngx_http_block(ngx_conf_t *cf, ngx_comma ngx_http_core_loc_conf_t *clcf; ngx_http_phase_handler_pt checker; ngx_http_core_main_conf_t *cmcf; +#if (NGX_PCRE) + ngx_uint_t regex; +#endif #if (NGX_WIN32) ngx_iocp_conf_t *iocpcf; #endif @@ -655,10 +658,21 @@ ngx_http_block(ngx_conf_t *cf, ngx_comma return NGX_CONF_ERROR; } +#if (NGX_PCRE) + regex = 0; +#endif + name = in_addr[a].names.elts; for (s = 0; s < in_addr[a].names.nelts; s++) { +#if (NGX_PCRE) + if (name[s].regex) { + regex++; + continue; + } +#endif + rc = ngx_hash_add_key(&ha, &name[s].name, name[s].core_srv_conf, NGX_HASH_WILDCARD_KEY); @@ -740,6 +754,27 @@ ngx_http_block(ngx_conf_t *cf, ngx_comma } ngx_destroy_pool(ha.temp_pool); + +#if (NGX_PCRE) + + if (regex == 0) { + continue; + } + + in_addr[a].nregex = regex; + in_addr[a].regex = ngx_palloc(cf->pool, + regex * sizeof(ngx_http_server_name_t)); + + if (in_addr[a].regex == NULL) { + return NGX_CONF_ERROR; + } + + for (i = 0, s = 0; s < in_addr[a].names.nelts; s++) { + if (name[s].regex) { + in_addr[a].regex[i++] = name[s]; + } + } +#endif } in_addr = in_port[p].addrs.elts; @@ -871,9 +906,13 @@ ngx_http_block(ngx_conf_t *cf, ngx_comma } hip->addrs[i].virtual_names = vn; - vn->hash = in_addr[i].hash; - vn->wc_head = in_addr[i].wc_head; - vn->wc_tail = in_addr[i].wc_tail; + vn->names.hash = in_addr[i].hash; + vn->names.wc_head = in_addr[i].wc_head; + vn->names.wc_tail = in_addr[i].wc_tail; +#if (NGX_PCRE) + vn->nregex = in_addr[i].nregex; + vn->regex = in_addr[i].regex; +#endif } if (done) { @@ -950,6 +989,10 @@ ngx_http_add_address(ngx_conf_t *cf, ngx in_addr->wc_head = NULL; in_addr->wc_tail = NULL; in_addr->names.elts = NULL; +#if (NGX_PCRE) + in_addr->nregex = 0; + in_addr->regex = NULL; +#endif in_addr->core_srv_conf = cscf; in_addr->default_server = lscf->conf.default_server; in_addr->bind = lscf->conf.bind; @@ -990,6 +1033,7 @@ ngx_http_add_names(ngx_conf_t *cf, ngx_h } server_names = cscf->server_names.elts; + for (i = 0; i < cscf->server_names.nelts; i++) { for (n = 0; n < server_names[i].name.len; n++) { @@ -1000,7 +1044,6 @@ ngx_http_add_names(ngx_conf_t *cf, ngx_h ngx_log_debug1(NGX_LOG_DEBUG_HTTP, cf->log, 0, "name: %V", &server_names[i].name); - name = ngx_array_push(&in_addr->names); if (name == NULL) { return NGX_ERROR; 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 @@ -2700,6 +2700,10 @@ ngx_http_core_server_name(ngx_conf_t *cf ngx_str_t *value, name; ngx_uint_t i; ngx_http_server_name_t *sn; +#if (NGX_PCRE) + ngx_str_t err; + u_char errstr[NGX_MAX_CONF_ERRSTR]; +#endif value = cf->args->elts; @@ -2713,6 +2717,13 @@ ngx_http_core_server_name(ngx_conf_t *cf 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 == '.') { @@ -2756,9 +2767,42 @@ ngx_http_core_server_name(ngx_conf_t *cf return NGX_CONF_ERROR; } +#if (NGX_PCRE) + sn->regex = NULL; +#endif + sn->core_srv_conf = cscf; sn->name.len = value[i].len; sn->name.data = value[i].data; - sn->core_srv_conf = cscf; + + if (value[i].data[0] != '~') { + continue; + } + +#if (NGX_PCRE) + err.len = NGX_MAX_CONF_ERRSTR; + err.data = errstr; + + value[i].len--; + value[i].data++; + + sn->regex = ngx_regex_compile(&value[i], NGX_REGEX_CASELESS, cf->pool, + &err); + + if (sn->regex == NULL) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%s", err.data); + return NGX_CONF_ERROR; + } + + sn->name.len = value[i].len; + sn->name.data = value[i].data; + +#else + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "the using of the regex \"%V\" " + "requires PCRE library", &value[i]); + + return NGX_CONF_ERROR; +#endif } return NGX_CONF_OK; 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 @@ -151,8 +151,10 @@ typedef struct { typedef struct { in_addr_t addr; + /* the default server configuration for this address:port */ ngx_http_core_srv_conf_t *core_srv_conf; + ngx_http_virtual_names_t *virtual_names; } ngx_http_in_addr_t; @@ -180,6 +182,12 @@ typedef struct { ngx_array_t names; /* array of ngx_http_server_name_t */ +#if (NGX_PCRE) + ngx_uint_t nregex; + ngx_http_server_name_t *regex; + +#endif + /* the default server configuration for this address:port */ ngx_http_core_srv_conf_t *core_srv_conf; @@ -190,10 +198,13 @@ typedef struct { } ngx_http_conf_in_addr_t; -typedef struct { +struct ngx_http_server_name_s { +#if (NGX_PCRE) + ngx_regex_t *regex; +#endif + ngx_http_core_srv_conf_t *core_srv_conf; /* virtual name server conf */ ngx_str_t name; - ngx_http_core_srv_conf_t *core_srv_conf; /* virtual name server conf */ -} ngx_http_server_name_t; +}; typedef struct { 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 @@ -1453,18 +1453,56 @@ static void ngx_http_find_virtual_server(ngx_http_request_t *r, u_char *host, size_t len, ngx_uint_t hash) { - ngx_http_virtual_names_t *vn; ngx_http_core_loc_conf_t *clcf; ngx_http_core_srv_conf_t *cscf; - - vn = r->virtual_names; - - cscf = ngx_hash_find_combined(vn, hash, host, len); +#if (NGX_PCRE) + ngx_int_t n; + ngx_uint_t i; + ngx_str_t name; + ngx_http_server_name_t *sn; +#endif + + cscf = ngx_hash_find_combined(&r->virtual_names->names, hash, host, len); if (cscf) { goto found; } +#if (NGX_PCRE) + + if (r->virtual_names->nregex) { + + name.len = len; + name.data = host; + + sn = r->virtual_names->regex; + + for (i = 0; i < r->virtual_names->nregex; i++) { + + n = ngx_regex_exec(sn[i].regex, &name, NULL, 0); + + if (n == NGX_REGEX_NO_MATCHED) { + continue; + } + + if (n < 0) { + ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, + ngx_regex_exec_n + " failed: %d on \"%V\" using \"%V\"", + n, &name, &sn[i].name); + return; + } + + /* match */ + + cscf = sn[i].core_srv_conf; + + goto found; + } + } + +#endif + cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module); if (cscf->wildcard) { diff --git a/src/http/ngx_http_request.h b/src/http/ngx_http_request.h --- a/src/http/ngx_http_request.h +++ b/src/http/ngx_http_request.h @@ -275,7 +275,15 @@ typedef struct { } ngx_http_connection_t; -typedef ngx_hash_combined_t ngx_http_virtual_names_t; +typedef struct ngx_http_server_name_s ngx_http_server_name_t; + + +typedef struct { + ngx_hash_combined_t names; + + ngx_uint_t nregex; + ngx_http_server_name_t *regex; +} ngx_http_virtual_names_t; typedef void (*ngx_http_cleanup_pt)(void *data);