Configuration: URI encoding in the "pass" option.
This is useful to escape "/" in path fragments. For example, in order
to reference the application named "foo/bar":
{
"pass": "applications/foo%2Fbar"
}
This commit is contained in:
@@ -1032,79 +1032,73 @@ static nxt_int_t
|
||||
nxt_conf_vldt_pass(nxt_conf_validation_t *vldt, nxt_conf_value_t *value,
|
||||
void *data)
|
||||
{
|
||||
u_char *p;
|
||||
nxt_str_t pass, first, second;
|
||||
nxt_str_t pass;
|
||||
nxt_int_t ret;
|
||||
nxt_str_t segments[2];
|
||||
|
||||
nxt_conf_get_string(value, &pass);
|
||||
|
||||
p = nxt_memchr(pass.start, '/', pass.length);
|
||||
ret = nxt_http_pass_segments(vldt->pool, &pass, segments, 2);
|
||||
|
||||
if (p != NULL) {
|
||||
first.length = p - pass.start;
|
||||
first.start = pass.start;
|
||||
if (ret != NXT_OK) {
|
||||
if (ret == NXT_DECLINED) {
|
||||
return nxt_conf_vldt_error(vldt, "Request \"pass\" value \"%V\" "
|
||||
"is invalid.", &pass);
|
||||
}
|
||||
|
||||
if (pass.length - first.length == 1) {
|
||||
return NXT_ERROR;
|
||||
}
|
||||
|
||||
if (nxt_str_eq(&segments[0], "applications", 12)) {
|
||||
|
||||
if (segments[1].length == 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
second.length = pass.length - first.length - 1;
|
||||
second.start = p + 1;
|
||||
value = nxt_conf_get_object_member(vldt->conf, &segments[0], NULL);
|
||||
|
||||
} else {
|
||||
first = pass;
|
||||
second.length = 0;
|
||||
}
|
||||
|
||||
if (nxt_str_eq(&first, "applications", 12)) {
|
||||
|
||||
if (second.length == 0) {
|
||||
if (value == NULL) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
value = nxt_conf_get_object_member(vldt->conf, &first, NULL);
|
||||
value = nxt_conf_get_object_member(value, &segments[1], NULL);
|
||||
|
||||
if (nxt_slow_path(value == NULL)) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
value = nxt_conf_get_object_member(value, &second, NULL);
|
||||
|
||||
if (nxt_slow_path(value == NULL)) {
|
||||
if (value == NULL) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
return NXT_OK;
|
||||
}
|
||||
|
||||
if (nxt_str_eq(&first, "upstreams", 9)) {
|
||||
if (nxt_str_eq(&segments[0], "upstreams", 9)) {
|
||||
|
||||
if (second.length == 0) {
|
||||
if (segments[1].length == 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
value = nxt_conf_get_object_member(vldt->conf, &first, NULL);
|
||||
value = nxt_conf_get_object_member(vldt->conf, &segments[0], NULL);
|
||||
|
||||
if (nxt_slow_path(value == NULL)) {
|
||||
if (value == NULL) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
value = nxt_conf_get_object_member(value, &second, NULL);
|
||||
value = nxt_conf_get_object_member(value, &segments[1], NULL);
|
||||
|
||||
if (nxt_slow_path(value == NULL)) {
|
||||
if (value == NULL) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
return NXT_OK;
|
||||
}
|
||||
|
||||
if (nxt_str_eq(&first, "routes", 6)) {
|
||||
value = nxt_conf_get_object_member(vldt->conf, &first, NULL);
|
||||
if (nxt_str_eq(&segments[0], "routes", 6)) {
|
||||
value = nxt_conf_get_object_member(vldt->conf, &segments[0], NULL);
|
||||
|
||||
if (nxt_slow_path(value == NULL)) {
|
||||
if (value == NULL) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (second.length == 0) {
|
||||
if (segments[1].length == 0) {
|
||||
if (nxt_conf_type(value) != NXT_CONF_ARRAY) {
|
||||
goto error;
|
||||
}
|
||||
@@ -1116,9 +1110,9 @@ nxt_conf_vldt_pass(nxt_conf_validation_t *vldt, nxt_conf_value_t *value,
|
||||
goto error;
|
||||
}
|
||||
|
||||
value = nxt_conf_get_object_member(value, &second, NULL);
|
||||
value = nxt_conf_get_object_member(value, &segments[1], NULL);
|
||||
|
||||
if (nxt_slow_path(value == NULL)) {
|
||||
if (value == NULL) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
|
||||
@@ -277,7 +277,10 @@ nxt_http_routes_t *nxt_http_routes_create(nxt_task_t *task,
|
||||
nxt_router_temp_conf_t *tmcf, nxt_conf_value_t *routes_conf);
|
||||
nxt_http_action_t *nxt_http_action_create(nxt_task_t *task,
|
||||
nxt_router_temp_conf_t *tmcf, nxt_str_t *name);
|
||||
void nxt_http_routes_resolve(nxt_task_t *task, nxt_router_temp_conf_t *tmcf);
|
||||
nxt_int_t nxt_http_routes_resolve(nxt_task_t *task,
|
||||
nxt_router_temp_conf_t *tmcf);
|
||||
nxt_int_t nxt_http_pass_segments(nxt_mp_t *mp, nxt_str_t *pass,
|
||||
nxt_str_t *segments, nxt_uint_t n);
|
||||
nxt_http_action_t *nxt_http_pass_application(nxt_task_t *task,
|
||||
nxt_router_temp_conf_t *tmcf, nxt_str_t *name);
|
||||
void nxt_http_routes_cleanup(nxt_task_t *task, nxt_http_routes_t *routes);
|
||||
|
||||
@@ -201,9 +201,9 @@ static nxt_int_t nxt_http_route_pattern_create(nxt_task_t *task, nxt_mp_t *mp,
|
||||
static u_char *nxt_http_route_pattern_copy(nxt_mp_t *mp, nxt_str_t *test,
|
||||
nxt_http_route_pattern_case_t pattern_case);
|
||||
|
||||
static void nxt_http_route_resolve(nxt_task_t *task,
|
||||
static nxt_int_t nxt_http_route_resolve(nxt_task_t *task,
|
||||
nxt_router_temp_conf_t *tmcf, nxt_http_route_t *route);
|
||||
static void nxt_http_action_resolve(nxt_task_t *task,
|
||||
static nxt_int_t nxt_http_action_resolve(nxt_task_t *task,
|
||||
nxt_router_temp_conf_t *tmcf, nxt_http_action_t *action);
|
||||
static void nxt_http_route_find(nxt_http_routes_t *routes, nxt_str_t *name,
|
||||
nxt_http_action_t *action);
|
||||
@@ -1097,9 +1097,10 @@ nxt_http_route_pattern_copy(nxt_mp_t *mp, nxt_str_t *test,
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
nxt_int_t
|
||||
nxt_http_routes_resolve(nxt_task_t *task, nxt_router_temp_conf_t *tmcf)
|
||||
{
|
||||
nxt_int_t ret;
|
||||
nxt_http_route_t **route, **end;
|
||||
nxt_http_routes_t *routes;
|
||||
|
||||
@@ -1110,75 +1111,128 @@ nxt_http_routes_resolve(nxt_task_t *task, nxt_router_temp_conf_t *tmcf)
|
||||
end = route + routes->items;
|
||||
|
||||
while (route < end) {
|
||||
nxt_http_route_resolve(task, tmcf, *route);
|
||||
ret = nxt_http_route_resolve(task, tmcf, *route);
|
||||
if (nxt_slow_path(ret != NXT_OK)) {
|
||||
return NXT_ERROR;
|
||||
}
|
||||
|
||||
route++;
|
||||
}
|
||||
}
|
||||
|
||||
return NXT_OK;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
static nxt_int_t
|
||||
nxt_http_route_resolve(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
|
||||
nxt_http_route_t *route)
|
||||
{
|
||||
nxt_int_t ret;
|
||||
nxt_http_route_match_t **match, **end;
|
||||
|
||||
match = &route->match[0];
|
||||
end = match + route->items;
|
||||
|
||||
while (match < end) {
|
||||
nxt_http_action_resolve(task, tmcf, &(*match)->action);
|
||||
ret = nxt_http_action_resolve(task, tmcf, &(*match)->action);
|
||||
if (nxt_slow_path(ret != NXT_OK)) {
|
||||
return NXT_ERROR;
|
||||
}
|
||||
|
||||
match++;
|
||||
}
|
||||
|
||||
return NXT_OK;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
static nxt_int_t
|
||||
nxt_http_action_resolve(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
|
||||
nxt_http_action_t *action)
|
||||
{
|
||||
nxt_str_t name;
|
||||
nxt_int_t ret;
|
||||
nxt_str_t segments[2];
|
||||
|
||||
if (action->handler != NULL) {
|
||||
if (action->handler == nxt_http_static_handler
|
||||
&& action->u.fallback != NULL)
|
||||
{
|
||||
nxt_http_action_resolve(task, tmcf, action->u.fallback);
|
||||
return nxt_http_action_resolve(task, tmcf, action->u.fallback);
|
||||
}
|
||||
|
||||
return;
|
||||
return NXT_OK;
|
||||
}
|
||||
|
||||
name = action->name;
|
||||
ret = nxt_http_pass_segments(tmcf->mem_pool, &action->name, segments, 2);
|
||||
if (nxt_slow_path(ret != NXT_OK)) {
|
||||
return NXT_ERROR;
|
||||
}
|
||||
|
||||
if (nxt_str_start(&name, "applications/", 13)) {
|
||||
name.length -= 13;
|
||||
name.start += 13;
|
||||
|
||||
nxt_router_listener_application(tmcf, &name, action);
|
||||
if (nxt_str_eq(&segments[0], "applications", 12)) {
|
||||
nxt_router_listener_application(tmcf, &segments[1], action);
|
||||
nxt_router_app_use(task, action->u.application, 1);
|
||||
|
||||
} else if (nxt_str_start(&name, "upstreams/", 10)) {
|
||||
name.length -= 10;
|
||||
name.start += 10;
|
||||
} else if (nxt_str_eq(&segments[0], "upstreams", 9)) {
|
||||
nxt_upstream_find(tmcf->router_conf->upstreams, &segments[1], action);
|
||||
|
||||
nxt_upstream_find(tmcf->router_conf->upstreams, &name, action);
|
||||
|
||||
} else if (nxt_str_start(&name, "routes", 6)) {
|
||||
|
||||
if (name.length == 6) {
|
||||
name.length = 0;
|
||||
name.start = NULL;
|
||||
|
||||
} else if (name.start[6] == '/') {
|
||||
name.length -= 7;
|
||||
name.start += 7;
|
||||
} else if (nxt_str_eq(&segments[0], "routes", 6)) {
|
||||
nxt_http_route_find(tmcf->router_conf->routes, &segments[1], action);
|
||||
}
|
||||
|
||||
nxt_http_route_find(tmcf->router_conf->routes, &name, action);
|
||||
return NXT_OK;
|
||||
}
|
||||
|
||||
|
||||
nxt_int_t
|
||||
nxt_http_pass_segments(nxt_mp_t *mp, nxt_str_t *pass, nxt_str_t *segments,
|
||||
nxt_uint_t n)
|
||||
{
|
||||
u_char *p;
|
||||
nxt_str_t rest;
|
||||
|
||||
if (nxt_slow_path(nxt_str_dup(mp, &rest, pass) == NULL)) {
|
||||
return NXT_ERROR;
|
||||
}
|
||||
|
||||
nxt_memzero(segments, n * sizeof(nxt_str_t));
|
||||
|
||||
do {
|
||||
p = nxt_memchr(rest.start, '/', rest.length);
|
||||
|
||||
if (p != NULL) {
|
||||
n--;
|
||||
|
||||
if (n == 0) {
|
||||
return NXT_DECLINED;
|
||||
}
|
||||
|
||||
segments->length = p - rest.start;
|
||||
segments->start = rest.start;
|
||||
|
||||
rest.length -= segments->length + 1;
|
||||
rest.start = p + 1;
|
||||
|
||||
} else {
|
||||
n = 0;
|
||||
*segments = rest;
|
||||
}
|
||||
|
||||
if (segments->length == 0) {
|
||||
return NXT_DECLINED;
|
||||
}
|
||||
|
||||
p = nxt_decode_uri(segments->start, segments->start, segments->length);
|
||||
if (p == NULL) {
|
||||
return NXT_DECLINED;
|
||||
}
|
||||
|
||||
segments->length = p - segments->start;
|
||||
segments++;
|
||||
|
||||
} while (n);
|
||||
|
||||
return NXT_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1793,6 +1793,11 @@ nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
|
||||
}
|
||||
}
|
||||
|
||||
ret = nxt_http_routes_resolve(task, tmcf);
|
||||
if (nxt_slow_path(ret != NXT_OK)) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
value = nxt_conf_get_path(conf, &access_log_path);
|
||||
|
||||
if (value != NULL) {
|
||||
@@ -1827,8 +1832,6 @@ nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
|
||||
tmcf->router_conf->access_log = access_log;
|
||||
}
|
||||
|
||||
nxt_http_routes_resolve(task, tmcf);
|
||||
|
||||
nxt_queue_add(&tmcf->deleting, &router->sockets);
|
||||
nxt_queue_init(&router->sockets);
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import os
|
||||
import shutil
|
||||
from urllib.parse import quote
|
||||
from unit.applications.proto import TestApplicationProto
|
||||
|
||||
|
||||
@@ -33,7 +34,9 @@ class TestApplicationNode(TestApplicationProto):
|
||||
|
||||
self._load_conf(
|
||||
{
|
||||
"listeners": {"*:7080": {"pass": "applications/" + script}},
|
||||
"listeners": {
|
||||
"*:7080": {"pass": "applications/" + quote(script, '')}
|
||||
},
|
||||
"applications": {
|
||||
script: {
|
||||
"type": "external",
|
||||
|
||||
Reference in New Issue
Block a user