diff options
Diffstat (limited to 'src/nxt_http_route.c')
-rw-r--r-- | src/nxt_http_route.c | 177 |
1 files changed, 108 insertions, 69 deletions
diff --git a/src/nxt_http_route.c b/src/nxt_http_route.c index cff69f96..606bf266 100644 --- a/src/nxt_http_route.c +++ b/src/nxt_http_route.c @@ -19,6 +19,7 @@ typedef enum { NXT_HTTP_ROUTE_ARGUMENT, NXT_HTTP_ROUTE_COOKIE, NXT_HTTP_ROUTE_SCHEME, + NXT_HTTP_ROUTE_QUERY, NXT_HTTP_ROUTE_SOURCE, NXT_HTTP_ROUTE_DESTINATION, } nxt_http_route_object_t; @@ -54,6 +55,7 @@ typedef struct { nxt_conf_value_t *arguments; nxt_conf_value_t *cookies; nxt_conf_value_t *scheme; + nxt_conf_value_t *query; nxt_conf_value_t *source; nxt_conf_value_t *destination; } nxt_http_route_match_conf_t; @@ -216,14 +218,12 @@ static nxt_int_t nxt_http_route_resolve(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, nxt_http_route_t *route); static nxt_int_t nxt_http_action_resolve(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, nxt_http_action_t *action); -static nxt_http_action_t *nxt_http_action_pass_var(nxt_task_t *task, +static nxt_http_action_t *nxt_http_pass_var(nxt_task_t *task, nxt_http_request_t *r, nxt_http_action_t *action); -static void nxt_http_action_pass_var_ready(nxt_task_t *task, void *obj, - void *data); -static void nxt_http_action_pass_var_error(nxt_task_t *task, void *obj, - void *data); -static nxt_int_t nxt_http_pass_find(nxt_task_t *task, nxt_mp_t *mp, - nxt_router_conf_t *rtcf, nxt_http_action_t *action); +static void nxt_http_pass_var_ready(nxt_task_t *task, void *obj, void *data); +static void nxt_http_pass_var_error(nxt_task_t *task, void *obj, void *data); +static nxt_int_t nxt_http_pass_find(nxt_mp_t *mp, nxt_router_conf_t *rtcf, + nxt_str_t *pass, nxt_http_action_t *action); static nxt_int_t nxt_http_route_find(nxt_http_routes_t *routes, nxt_str_t *name, nxt_http_action_t *action); @@ -249,6 +249,8 @@ static nxt_int_t nxt_http_route_test_argument(nxt_http_request_t *r, nxt_http_route_rule_t *rule, nxt_array_t *array); static nxt_int_t nxt_http_route_scheme(nxt_http_request_t *r, nxt_http_route_rule_t *rule); +static nxt_int_t nxt_http_route_query(nxt_http_request_t *r, + nxt_http_route_rule_t *rule); static nxt_int_t nxt_http_route_cookies(nxt_http_request_t *r, nxt_http_route_rule_t *rule); static nxt_array_t *nxt_http_route_cookies_parse(nxt_http_request_t *r); @@ -368,6 +370,12 @@ static nxt_conf_map_t nxt_http_route_match_conf[] = { }, { + nxt_string("query"), + NXT_CONF_MAP_PTR, + offsetof(nxt_http_route_match_conf_t, query), + }, + + { nxt_string("source"), NXT_CONF_MAP_PTR, offsetof(nxt_http_route_match_conf_t, source), @@ -566,6 +574,19 @@ nxt_http_route_match_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, test++; } + if (mtcf.query != NULL) { + rule = nxt_http_route_rule_create(task, mp, mtcf.query, 1, + NXT_HTTP_ROUTE_PATTERN_NOCASE, + NXT_HTTP_ROUTE_ENCODING_URI_PLUS); + if (rule == NULL) { + return NULL; + } + + rule->object = NXT_HTTP_ROUTE_QUERY; + test->rule = rule; + test++; + } + if (mtcf.source != NULL) { addr_rule = nxt_http_route_addr_rule_create(task, mp, mtcf.source); if (addr_rule == NULL) { @@ -652,7 +673,7 @@ nxt_http_action_init(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, { nxt_mp_t *mp; nxt_int_t ret; - nxt_str_t name, *string; + nxt_str_t pass; nxt_http_action_conf_t acf; nxt_memzero(&acf, sizeof(acf)); @@ -679,10 +700,10 @@ nxt_http_action_init(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, return nxt_http_proxy_init(mp, action, &acf); } - nxt_conf_get_string(acf.pass, &name); + nxt_conf_get_string(acf.pass, &pass); - string = nxt_str_dup(mp, &action->name, &name); - if (nxt_slow_path(string == NULL)) { + action->u.var = nxt_var_compile(&pass, mp, 0); + if (nxt_slow_path(action->u.var == NULL)) { return NXT_ERROR; } @@ -1372,7 +1393,7 @@ nxt_http_action_resolve(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, nxt_http_action_t *action) { nxt_int_t ret; - nxt_var_t *var; + nxt_str_t pass; if (action->handler != NULL) { if (action->fallback != NULL) { @@ -1382,20 +1403,17 @@ nxt_http_action_resolve(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, return NXT_OK; } - if (nxt_is_var(&action->name)) { - var = nxt_var_compile(&action->name, tmcf->router_conf->mem_pool); - if (nxt_slow_path(var == NULL)) { + if (nxt_var_is_const(action->u.var)) { + nxt_var_raw(action->u.var, &pass); + + ret = nxt_http_pass_find(tmcf->mem_pool, tmcf->router_conf, &pass, + action); + if (nxt_slow_path(ret != NXT_OK)) { return NXT_ERROR; } - action->u.var = var; - action->handler = nxt_http_action_pass_var; - return NXT_OK; - } - - ret = nxt_http_pass_find(task, tmcf->mem_pool, tmcf->router_conf, action); - if (nxt_slow_path(ret != NXT_OK)) { - return NXT_ERROR; + } else { + action->handler = nxt_http_pass_var; } return NXT_OK; @@ -1403,28 +1421,36 @@ nxt_http_action_resolve(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, static nxt_http_action_t * -nxt_http_action_pass_var(nxt_task_t *task, nxt_http_request_t *r, +nxt_http_pass_var(nxt_task_t *task, nxt_http_request_t *r, nxt_http_action_t *action) { - nxt_var_t *var; nxt_int_t ret; + nxt_str_t str; + nxt_var_t *var; + + var = action->u.var; + + nxt_var_raw(var, &str); + + nxt_debug(task, "http pass: \"%V\"", &str); ret = nxt_var_query_init(&r->var_query, r, r->mem_pool); if (nxt_slow_path(ret != NXT_OK)) { goto fail; } - var = action->u.var; - - action = nxt_mp_get(r->mem_pool, sizeof(nxt_http_action_t)); + action = nxt_mp_get(r->mem_pool, + sizeof(nxt_http_action_t) + sizeof(nxt_str_t)); if (nxt_slow_path(action == NULL)) { goto fail; } - nxt_var_query(task, r->var_query, var, &action->name); + action->u.pass = nxt_pointer_to(action, sizeof(nxt_http_action_t)); + + nxt_var_query(task, r->var_query, var, action->u.pass); nxt_var_query_resolve(task, r->var_query, action, - nxt_http_action_pass_var_ready, - nxt_http_action_pass_var_error); + nxt_http_pass_var_ready, + nxt_http_pass_var_error); return NULL; fail: @@ -1435,7 +1461,7 @@ fail: static void -nxt_http_action_pass_var_ready(nxt_task_t *task, void *obj, void *data) +nxt_http_pass_var_ready(nxt_task_t *task, void *obj, void *data) { nxt_int_t ret; nxt_router_conf_t *rtcf; @@ -1447,9 +1473,9 @@ nxt_http_action_pass_var_ready(nxt_task_t *task, void *obj, void *data) action = data; rtcf = r->conf->socket_conf->router_conf; - nxt_debug(task, "http pass lookup: %V", &action->name); + nxt_debug(task, "http pass lookup: %V", action->u.pass); - ret = nxt_http_pass_find(task, r->mem_pool, rtcf, action); + ret = nxt_http_pass_find(r->mem_pool, rtcf, action->u.pass, action); if (ret != NXT_OK) { status = (ret == NXT_DECLINED) ? NXT_HTTP_NOT_FOUND @@ -1464,7 +1490,7 @@ nxt_http_action_pass_var_ready(nxt_task_t *task, void *obj, void *data) static void -nxt_http_action_pass_var_error(nxt_task_t *task, void *obj, void *data) +nxt_http_pass_var_error(nxt_task_t *task, void *obj, void *data) { nxt_http_request_t *r; @@ -1475,13 +1501,13 @@ nxt_http_action_pass_var_error(nxt_task_t *task, void *obj, void *data) static nxt_int_t -nxt_http_pass_find(nxt_task_t *task, nxt_mp_t *mp, nxt_router_conf_t *rtcf, +nxt_http_pass_find(nxt_mp_t *mp, nxt_router_conf_t *rtcf, nxt_str_t *pass, nxt_http_action_t *action) { - nxt_int_t ret; - nxt_str_t segments[3]; + nxt_int_t ret; + nxt_str_t segments[3]; - ret = nxt_http_pass_segments(mp, &action->name, segments, 3); + ret = nxt_http_pass_segments(mp, pass, segments, 3); if (nxt_slow_path(ret != NXT_OK)) { return ret; } @@ -1587,18 +1613,24 @@ nxt_http_route_find(nxt_http_routes_t *routes, nxt_str_t *name, nxt_http_action_t * nxt_http_action_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, - nxt_str_t *name) + nxt_str_t *pass) { + nxt_mp_t *mp; nxt_int_t ret; nxt_http_action_t *action; - action = nxt_mp_alloc(tmcf->router_conf->mem_pool, - sizeof(nxt_http_action_t)); + mp = tmcf->router_conf->mem_pool; + + action = nxt_mp_alloc(mp, sizeof(nxt_http_action_t)); if (nxt_slow_path(action == NULL)) { return NULL; } - action->name = *name; + action->u.var = nxt_var_compile(pass, mp, 0); + if (nxt_slow_path(action->u.var == NULL)) { + return NULL; + } + action->handler = NULL; ret = nxt_http_action_resolve(task, tmcf, action); @@ -1623,8 +1655,6 @@ nxt_http_pass_application(nxt_task_t *task, nxt_router_conf_t *rtcf, return NULL; } - action->name = *name; - (void) nxt_router_application_init(rtcf, name, NULL, action); return action; @@ -1769,6 +1799,9 @@ nxt_http_route_rule(nxt_http_request_t *r, nxt_http_route_rule_t *rule) case NXT_HTTP_ROUTE_SCHEME: return nxt_http_route_scheme(r, rule); + case NXT_HTTP_ROUTE_QUERY: + return nxt_http_route_query(r, rule); + default: break; } @@ -2001,10 +2034,6 @@ nxt_http_route_arguments(nxt_http_request_t *r, nxt_http_route_rule_t *rule) { nxt_array_t *arguments; - if (r->args == NULL) { - return 0; - } - arguments = nxt_http_route_arguments_parse(r); if (nxt_slow_path(arguments == NULL)) { return -1; @@ -2018,10 +2047,9 @@ static nxt_array_t * nxt_http_route_arguments_parse(nxt_http_request_t *r) { size_t name_length; - u_char c, *p, *dst, *dst_start, *start, *end, *name; + u_char *p, *dst, *dst_start, *start, *end, *name; uint8_t d0, d1; uint32_t hash; - nxt_bool_t valid; nxt_array_t *args; nxt_http_name_value_t *nv; @@ -2035,7 +2063,6 @@ nxt_http_route_arguments_parse(nxt_http_request_t *r) } hash = NXT_HTTP_FIELD_HASH_INIT; - valid = 1; name = NULL; name_length = 0; @@ -2044,28 +2071,26 @@ nxt_http_route_arguments_parse(nxt_http_request_t *r) return NULL; } + r->args_decoded.start = dst_start; + start = r->args->start; end = start + r->args->length; for (p = start, dst = dst_start; p < end; p++, dst++) { - c = *p; - *dst = c; + *dst = *p; - switch (c) { + switch (*p) { case '=': - if (name != NULL) { - break; + if (name == NULL) { + name_length = dst - dst_start; + name = dst_start; + dst_start = dst + 1; } - name_length = dst - dst_start; - valid = (name_length != 0); - name = dst_start; - dst_start = dst + 1; - continue; case '&': - if (valid) { + if (name_length != 0 || dst != dst_start) { nv = nxt_http_route_argument(args, name, name_length, hash, dst_start, dst); if (nxt_slow_path(nv == NULL)) { @@ -2075,14 +2100,12 @@ nxt_http_route_arguments_parse(nxt_http_request_t *r) hash = NXT_HTTP_FIELD_HASH_INIT; name_length = 0; - valid = 1; name = NULL; dst_start = dst + 1; continue; case '+': - c = ' '; *dst = ' '; break; @@ -2100,18 +2123,19 @@ nxt_http_route_arguments_parse(nxt_http_request_t *r) } p += 2; - c = (d0 << 4) + d1; - *dst = c; + *dst = (d0 << 4) + d1; break; } if (name == NULL) { - hash = nxt_http_field_hash_char(hash, c); + hash = nxt_http_field_hash_char(hash, *dst); } } - if (valid) { + r->args_decoded.length = dst - r->args_decoded.start; + + if (name_length != 0 || dst != dst_start) { nv = nxt_http_route_argument(args, name, name_length, hash, dst_start, dst); if (nxt_slow_path(nv == NULL)) { @@ -2207,6 +2231,21 @@ nxt_http_route_scheme(nxt_http_request_t *r, nxt_http_route_rule_t *rule) static nxt_int_t +nxt_http_route_query(nxt_http_request_t *r, nxt_http_route_rule_t *rule) +{ + nxt_array_t *arguments; + + arguments = nxt_http_route_arguments_parse(r); + if (nxt_slow_path(arguments == NULL)) { + return -1; + } + + return nxt_http_route_test_rule(r, rule, r->args_decoded.start, + r->args_decoded.length); +} + + +static nxt_int_t nxt_http_route_cookies(nxt_http_request_t *r, nxt_http_route_rule_t *rule) { nxt_array_t *cookies; |