path.len = e.pos - path.data;
- *e.pos++ = '\0';
+ *e.pos = '\0';
if (alias && ngx_strncmp(name, clcf->name.data, alias) == 0) {
ngx_memcpy(name, name + alias, len - alias);
ngx_int_t rc;
ngx_http_core_loc_conf_t *pclcf;
#if (NGX_PCRE)
- ngx_int_t n;
+ ngx_int_t n, len;
ngx_uint_t noregex;
ngx_http_core_loc_conf_t *clcf, **clcfp;
if (noregex == 0 && pclcf->regex_locations) {
+ len = 0;
+
for (clcfp = pclcf->regex_locations; *clcfp; clcfp++) {
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"test location: ~ \"%V\"", &(*clcfp)->name);
- n = ngx_regex_exec((*clcfp)->regex, &r->uri, NULL, 0);
+ if ((*clcfp)->captures) {
+
+ len = (NGX_HTTP_MAX_CAPTURES + 1) * 3;
+
+ if (r->captures == NULL) {
+ r->captures = ngx_palloc(r->pool, len * sizeof(int));
+ if (r->captures == NULL) {
+ return NGX_ERROR;
+ }
+ }
+ }
+
+ n = ngx_regex_exec((*clcfp)->regex, &r->uri, r->captures, len);
if (n == NGX_REGEX_NO_MATCHED) {
continue;
r->loc_conf = (*clcfp)->loc_conf;
+ r->ncaptures = len;
+ r->captures_data = r->uri.data;
+
/* look up nested locations */
rc = ngx_http_core_find_location(r);
return NULL;
}
- reserved += r->uri.len - alias + 1;
-
if (clcf->root_lengths == NULL) {
*root_length = clcf->root.len;
- path->len = clcf->root.len + reserved;
+ path->len = clcf->root.len + reserved + r->uri.len - alias + 1;
path->data = ngx_pnalloc(r->pool, path->len);
if (path->data == NULL) {
last = ngx_copy(path->data, clcf->root.data, clcf->root.len);
} else {
+ reserved += alias ? 1 : r->uri.len + 1;
+
if (ngx_http_script_run(r, path, clcf->root_lengths->elts, reserved,
clcf->root_values->elts)
== NULL)
*root_length = path->len - reserved;
last = path->data + *root_length;
+
+ if (alias) {
+ *last = '\0';
+ return last;
+ }
}
last = ngx_cpystrn(last, r->uri.data + alias, r->uri.len - alias + 1);
ngx_int_t
ngx_http_server_addr(ngx_http_request_t *r, ngx_str_t *s)
{
- socklen_t len;
- ngx_connection_t *c;
- u_char sa[NGX_SOCKADDRLEN];
+ socklen_t len;
+ ngx_uint_t addr;
+ ngx_connection_t *c;
+ u_char sa[NGX_SOCKADDRLEN];
+ struct sockaddr_in *sin;
+#if (NGX_HAVE_INET6)
+ ngx_uint_t i;
+ struct sockaddr_in6 *sin6;
+#endif
c = r->connection;
- if (c->local_sockaddr == NULL) {
+ switch (c->local_sockaddr->sa_family) {
+
+#if (NGX_HAVE_INET6)
+ case AF_INET6:
+ sin6 = (struct sockaddr_in6 *) c->local_sockaddr;
+
+ for (addr = 0, i = 0; addr == 0 && i < 16; i++) {
+ addr |= sin6->sin6_addr.s6_addr[i];
+ }
+
+ break;
+#endif
+
+ default: /* AF_INET */
+ sin = (struct sockaddr_in *) c->local_sockaddr;
+ addr = sin->sin_addr.s_addr;
+ break;
+ }
+
+ if (addr == 0) {
len = NGX_SOCKADDRLEN;
}
clcf->name = *regex;
+ clcf->captures = (ngx_regex_capture_count(clcf->regex) > 0);
return NGX_OK;
#if (NGX_PCRE)
sn->regex = NULL;
+ sn->captures = 0;
#endif
sn->core_srv_conf = conf;
sn->name.len = conf->server_name.len;
continue;
}
+ if (ngx_strncmp(value[n].data, "ipv6only=o", 10) == 0) {
+#if (NGX_HAVE_INET6 && defined IPV6_V6ONLY)
+ struct sockaddr *sa;
+
+ sa = (struct sockaddr *) ls->sockaddr;
+
+ if (sa->sa_family == AF_INET6) {
+
+ if (ngx_strcmp(&value[n].data[10], "n") == 0) {
+ ls->conf.ipv6only = 1;
+
+ } else if (ngx_strcmp(&value[n].data[10], "ff") == 0) {
+ ls->conf.ipv6only = 2;
+
+ } else {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "invalid ipv6only flags \"%s\"",
+ &value[n].data[9]);
+ return NGX_CONF_ERROR;
+ }
+
+ ls->conf.bind = 1;
+
+ } else {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "ipv6only is not supported "
+ "on addr \"%s\", ignored",
+ ls->conf.addr);
+ }
+
+ continue;
+#else
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "bind ipv6only is not supported "
+ "on this platform");
+ return NGX_CONF_ERROR;
+#endif
+ }
+
if (ngx_strcmp(value[n].data, "ssl") == 0) {
#if (NGX_HTTP_SSL)
ls->conf.ssl = 1;
#if (NGX_PCRE)
sn->regex = NULL;
+ sn->captures = 0;
#endif
sn->core_srv_conf = cscf;
sn->name = value[i];
return NGX_CONF_ERROR;
}
+ sn->captures = (ngx_regex_capture_count(sn->regex) > 0);
sn->name = value[i];
}
#else
return NGX_CONF_ERROR;
}
-#if (NGX_PCRE)
-
- if (lcf->regex && alias) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "the \"alias\" directive may not be used "
- "inside location given by regular expression");
-
- return NGX_CONF_ERROR;
- }
-
-#endif
-
value = cf->args->elts;
if (ngx_strstr(value[1].data, "$document_root")
n = ngx_http_script_variables_count(&lcf->root);
- if (n == 0) {
- return NGX_CONF_OK;
+ ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
+
+ if (n) {
+ sc.cf = cf;
+ sc.source = &lcf->root;
+ sc.lengths = &lcf->root_lengths;
+ sc.values = &lcf->root_values;
+ sc.variables = n;
+ sc.complete_lengths = 1;
+ sc.complete_values = 1;
+
+ if (ngx_http_script_compile(&sc) != NGX_OK) {
+ return NGX_CONF_ERROR;
+ }
}
- ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
+#if (NGX_PCRE)
- sc.cf = cf;
- sc.source = &lcf->root;
- sc.lengths = &lcf->root_lengths;
- sc.values = &lcf->root_values;
- sc.variables = n;
- sc.complete_lengths = 1;
- sc.complete_values = 1;
+ if (alias && lcf->regex
+ && (ngx_regex_capture_count(lcf->regex) <= 0 || sc.ncaptures == 0))
+ {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "the \"alias\" directive must use captures "
+ "inside location given by regular expression");
- if (ngx_http_script_compile(&sc) != NGX_OK) {
return NGX_CONF_ERROR;
}
+#endif
+
return NGX_CONF_OK;
}