diff options
author | Valentin Bartenev <vbart@nginx.com> | 2020-05-14 13:15:00 +0300 |
---|---|---|
committer | Valentin Bartenev <vbart@nginx.com> | 2020-05-14 13:15:00 +0300 |
commit | 0174c971b5ec0d604e4e9becfa41e0bc31179e57 (patch) | |
tree | 8d0c0c41b10cc290084676aac836c1dd2313410b /src | |
parent | d803ec39bc75622194802d249edc11fedc8e2441 (diff) | |
download | unit-0174c971b5ec0d604e4e9becfa41e0bc31179e57.tar.gz unit-0174c971b5ec0d604e4e9becfa41e0bc31179e57.tar.bz2 |
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"
}
Diffstat (limited to 'src')
-rw-r--r-- | src/nxt_conf_validation.c | 60 | ||||
-rw-r--r-- | src/nxt_http.h | 5 | ||||
-rw-r--r-- | src/nxt_http_route.c | 112 | ||||
-rw-r--r-- | src/nxt_router.c | 7 |
4 files changed, 119 insertions, 65 deletions
diff --git a/src/nxt_conf_validation.c b/src/nxt_conf_validation.c index bc03bdfb..476fc97b 100644 --- a/src/nxt_conf_validation.c +++ b/src/nxt_conf_validation.c @@ -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); - - if (p != NULL) { - first.length = p - pass.start; - first.start = pass.start; + ret = nxt_http_pass_segments(vldt->pool, &pass, segments, 2); - if (pass.length - first.length == 1) { - goto error; + if (ret != NXT_OK) { + if (ret == NXT_DECLINED) { + return nxt_conf_vldt_error(vldt, "Request \"pass\" value \"%V\" " + "is invalid.", &pass); } - second.length = pass.length - first.length - 1; - second.start = p + 1; - - } else { - first = pass; - second.length = 0; + return NXT_ERROR; } - if (nxt_str_eq(&first, "applications", 12)) { + if (nxt_str_eq(&segments[0], "applications", 12)) { - 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, "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; } diff --git a/src/nxt_http.h b/src/nxt_http.h index 841f5b40..6f593cd2 100644 --- a/src/nxt_http.h +++ b/src/nxt_http.h @@ -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); diff --git a/src/nxt_http_route.c b/src/nxt_http_route.c index ca43c060..bb6e9dc9 100644 --- a/src/nxt_http_route.c +++ b/src/nxt_http_route.c @@ -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; - - if (nxt_str_start(&name, "applications/", 13)) { - name.length -= 13; - name.start += 13; + ret = nxt_http_pass_segments(tmcf->mem_pool, &action->name, segments, 2); + if (nxt_slow_path(ret != NXT_OK)) { + return NXT_ERROR; + } - 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_eq(&segments[0], "routes", 6)) { + nxt_http_route_find(tmcf->router_conf->routes, &segments[1], action); + } - } else if (nxt_str_start(&name, "routes", 6)) { + return NXT_OK; +} - if (name.length == 6) { - name.length = 0; - name.start = NULL; - } else if (name.start[6] == '/') { - name.length -= 7; - name.start += 7; - } +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; - nxt_http_route_find(tmcf->router_conf->routes, &name, action); + 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; } diff --git a/src/nxt_router.c b/src/nxt_router.c index 93b750a0..a699effc 100644 --- a/src/nxt_router.c +++ b/src/nxt_router.c @@ -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); |