diff options
-rw-r--r-- | auto/sources | 1 | ||||
-rw-r--r-- | docs/changes.xml | 6 | ||||
-rw-r--r-- | src/nxt_conf_validation.c | 18 | ||||
-rw-r--r-- | src/nxt_http.h | 7 | ||||
-rw-r--r-- | src/nxt_http_parse.c | 4 | ||||
-rw-r--r-- | src/nxt_http_parse.h | 1 | ||||
-rw-r--r-- | src/nxt_http_request.c | 9 | ||||
-rw-r--r-- | src/nxt_http_rewrite.c | 104 | ||||
-rw-r--r-- | src/nxt_http_route.c | 20 | ||||
-rw-r--r-- | src/nxt_tstr.c | 7 | ||||
-rw-r--r-- | src/nxt_tstr.h | 1 |
11 files changed, 167 insertions, 11 deletions
diff --git a/auto/sources b/auto/sources index f74985b9..9a7ff010 100644 --- a/auto/sources +++ b/auto/sources @@ -92,6 +92,7 @@ NXT_LIB_SRCS=" \ src/nxt_http_error.c \ src/nxt_http_route.c \ src/nxt_http_route_addr.c \ + src/nxt_http_rewrite.c \ src/nxt_http_return.c \ src/nxt_http_static.c \ src/nxt_http_proxy.c \ diff --git a/docs/changes.xml b/docs/changes.xml index 740a51a5..6c89fa15 100644 --- a/docs/changes.xml +++ b/docs/changes.xml @@ -34,6 +34,12 @@ NGINX Unit updated to 1.30.0. <change type="feature"> <para> +basic URI rewrite support. +</para> +</change> + +<change type="feature"> +<para> added conditional logging of route selection for HTTP requests. </para> </change> diff --git a/src/nxt_conf_validation.c b/src/nxt_conf_validation.c index 9059b2b3..c9aac790 100644 --- a/src/nxt_conf_validation.c +++ b/src/nxt_conf_validation.c @@ -669,6 +669,16 @@ static nxt_conf_vldt_object_t nxt_conf_vldt_match_members[] = { }; +static nxt_conf_vldt_object_t nxt_conf_vldt_action_common_members[] = { + { + .name = nxt_string("rewrite"), + .type = NXT_CONF_VLDT_STRING, + }, + + NXT_CONF_VLDT_END +}; + + static nxt_conf_vldt_object_t nxt_conf_vldt_pass_action_members[] = { { .name = nxt_string("pass"), @@ -677,7 +687,7 @@ static nxt_conf_vldt_object_t nxt_conf_vldt_pass_action_members[] = { .flags = NXT_CONF_VLDT_TSTR, }, - NXT_CONF_VLDT_END + NXT_CONF_VLDT_NEXT(nxt_conf_vldt_action_common_members) }; @@ -692,7 +702,7 @@ static nxt_conf_vldt_object_t nxt_conf_vldt_return_action_members[] = { .flags = NXT_CONF_VLDT_TSTR, }, - NXT_CONF_VLDT_END + NXT_CONF_VLDT_NEXT(nxt_conf_vldt_action_common_members) }; @@ -736,7 +746,7 @@ static nxt_conf_vldt_object_t nxt_conf_vldt_share_action_members[] = { #endif }, - NXT_CONF_VLDT_END + NXT_CONF_VLDT_NEXT(nxt_conf_vldt_action_common_members) }; @@ -747,7 +757,7 @@ static nxt_conf_vldt_object_t nxt_conf_vldt_proxy_action_members[] = { .validator = nxt_conf_vldt_proxy, }, - NXT_CONF_VLDT_END + NXT_CONF_VLDT_NEXT(nxt_conf_vldt_action_common_members) }; diff --git a/src/nxt_http.h b/src/nxt_http.h index d7bbaf02..08e1fcbe 100644 --- a/src/nxt_http.h +++ b/src/nxt_http.h @@ -226,6 +226,7 @@ typedef struct nxt_http_route_addr_rule_s nxt_http_route_addr_rule_t; typedef struct { + nxt_conf_value_t *rewrite; nxt_conf_value_t *pass; nxt_conf_value_t *ret; nxt_conf_value_t *location; @@ -253,6 +254,7 @@ struct nxt_http_action_s { nxt_str_t *pass; } u; + nxt_tstr_t *rewrite; nxt_http_action_t *fallback; }; @@ -378,6 +380,11 @@ nxt_int_t nxt_upstreams_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, nxt_int_t nxt_upstreams_joint_create(nxt_router_temp_conf_t *tmcf, nxt_upstream_t ***upstream_joint); +nxt_int_t nxt_http_rewrite_init(nxt_router_conf_t *rtcf, + nxt_http_action_t *action, nxt_http_action_conf_t *acf); +nxt_int_t nxt_http_rewrite(nxt_task_t *task, nxt_http_request_t *r, + nxt_http_action_t *action); + nxt_int_t nxt_http_return_init(nxt_router_conf_t *rtcf, nxt_http_action_t *action, nxt_http_action_conf_t *acf); diff --git a/src/nxt_http_parse.c b/src/nxt_http_parse.c index 439993df..50cbda2b 100644 --- a/src/nxt_http_parse.c +++ b/src/nxt_http_parse.c @@ -19,8 +19,6 @@ static u_char *nxt_http_lookup_field_end(u_char *p, const u_char *end); static nxt_int_t nxt_http_parse_field_end(nxt_http_request_parse_t *rp, u_char **pos, const u_char *end); -static nxt_int_t nxt_http_parse_complex_target(nxt_http_request_parse_t *rp); - static nxt_int_t nxt_http_field_hash_test(nxt_lvlhsh_query_t *lhq, void *data); static nxt_int_t nxt_http_field_hash_collision(nxt_lvlhsh_query_t *lhq, @@ -854,7 +852,7 @@ static const uint8_t nxt_http_normal[32] nxt_aligned(32) = { }; -static nxt_int_t +nxt_int_t nxt_http_parse_complex_target(nxt_http_request_parse_t *rp) { u_char *p, *u, c, ch, high, *args; diff --git a/src/nxt_http_parse.h b/src/nxt_http_parse.h index 88b10675..fa95e842 100644 --- a/src/nxt_http_parse.h +++ b/src/nxt_http_parse.h @@ -127,6 +127,7 @@ nxt_uint_t nxt_http_fields_hash_collisions(nxt_lvlhsh_t *hash, nxt_int_t nxt_http_fields_process(nxt_list_t *fields, nxt_lvlhsh_t *hash, void *ctx); +nxt_int_t nxt_http_parse_complex_target(nxt_http_request_parse_t *rp); nxt_buf_t *nxt_http_chunk_parse(nxt_task_t *task, nxt_http_chunk_parse_t *hcp, nxt_buf_t *in); diff --git a/src/nxt_http_request.c b/src/nxt_http_request.c index e53b1ec8..48f7dbe3 100644 --- a/src/nxt_http_request.c +++ b/src/nxt_http_request.c @@ -555,9 +555,18 @@ void nxt_http_request_action(nxt_task_t *task, nxt_http_request_t *r, nxt_http_action_t *action) { + nxt_int_t ret; + if (nxt_fast_path(action != NULL)) { do { + if (action->rewrite != NULL) { + ret = nxt_http_rewrite(task, r, action); + if (nxt_slow_path(ret != NXT_OK)) { + break; + } + } + action = action->handler(task, r, action); if (action == NULL) { diff --git a/src/nxt_http_rewrite.c b/src/nxt_http_rewrite.c new file mode 100644 index 00000000..b800a919 --- /dev/null +++ b/src/nxt_http_rewrite.c @@ -0,0 +1,104 @@ + +/* + * Copyright (C) Zhidao HONG + * Copyright (C) NGINX, Inc. + */ + +#include <nxt_router.h> +#include <nxt_http.h> + + +nxt_int_t +nxt_http_rewrite_init(nxt_router_conf_t *rtcf, nxt_http_action_t *action, + nxt_http_action_conf_t *acf) + { + nxt_str_t str; + + nxt_conf_get_string(acf->rewrite, &str); + + action->rewrite = nxt_tstr_compile(rtcf->tstr_state, &str, 0); + if (nxt_slow_path(action->rewrite == NULL)) { + return NXT_ERROR; + } + + return NXT_OK; +} + + +nxt_int_t +nxt_http_rewrite(nxt_task_t *task, nxt_http_request_t *r, + nxt_http_action_t *action) +{ + u_char *p; + nxt_int_t ret; + nxt_str_t str, encoded_path, target; + nxt_router_conf_t *rtcf; + nxt_http_request_parse_t rp; + + if (nxt_tstr_is_const(action->rewrite)) { + nxt_tstr_str(action->rewrite, &str); + + } else { + rtcf = r->conf->socket_conf->router_conf; + + ret = nxt_tstr_query_init(&r->tstr_query, rtcf->tstr_state, + &r->tstr_cache, r, r->mem_pool); + if (nxt_slow_path(ret != NXT_OK)) { + return NXT_ERROR; + } + + nxt_tstr_query(task, r->tstr_query, action->rewrite, &str); + + if (nxt_slow_path(nxt_tstr_query_failed(r->tstr_query))) { + return NXT_ERROR; + } + } + + nxt_memzero(&rp, sizeof(nxt_http_request_parse_t)); + + rp.mem_pool = r->mem_pool; + + rp.target_start = str.start; + rp.target_end = str.start + str.length; + + ret = nxt_http_parse_complex_target(&rp); + if (nxt_slow_path(ret != NXT_OK)) { + return NXT_ERROR; + } + + p = (rp.args.length > 0) ? rp.args.start - 1 : rp.target_end; + + encoded_path.start = rp.target_start; + encoded_path.length = p - encoded_path.start; + + if (r->args->length == 0) { + r->target = encoded_path; + + } else { + target.length = encoded_path.length + 1 + r->args->length; + + target.start = nxt_mp_alloc(r->mem_pool, target.length); + if (target.start == NULL) { + return NXT_ERROR; + } + + p = nxt_cpymem(target.start, encoded_path.start, encoded_path.length); + *p++ = '?'; + nxt_memcpy(p, r->args->start, r->args->length); + + r->target = target; + } + + r->path = nxt_mp_alloc(r->mem_pool, sizeof(nxt_str_t)); + if (nxt_slow_path(r->path == NULL)) { + return NXT_ERROR; + } + + *r->path = rp.path; + + if (nxt_slow_path(r->log_route)) { + nxt_log(task, NXT_LOG_NOTICE, "URI rewritten to \"%V\"", &r->target); + } + + return NXT_OK; +} diff --git a/src/nxt_http_route.c b/src/nxt_http_route.c index f439c957..0935dd4a 100644 --- a/src/nxt_http_route.c +++ b/src/nxt_http_route.c @@ -579,6 +579,11 @@ nxt_http_route_match_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, static nxt_conf_map_t nxt_http_route_action_conf[] = { { + nxt_string("rewrite"), + NXT_CONF_MAP_PTR, + offsetof(nxt_http_action_conf_t, rewrite) + }, + { nxt_string("pass"), NXT_CONF_MAP_PTR, offsetof(nxt_http_action_conf_t, pass) @@ -659,6 +664,13 @@ nxt_http_action_init(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, rtcf = tmcf->router_conf; mp = rtcf->mem_pool; + if (acf.rewrite != NULL) { + ret = nxt_http_rewrite_init(rtcf, action, &acf); + if (nxt_slow_path(ret != NXT_OK)) { + return ret; + } + } + if (acf.ret != NULL) { return nxt_http_return_init(rtcf, action, &acf); } @@ -1312,8 +1324,8 @@ nxt_http_pass_var(nxt_task_t *task, nxt_http_request_t *r, goto fail; } - action = nxt_mp_get(r->mem_pool, - sizeof(nxt_http_action_t) + sizeof(nxt_str_t)); + action = nxt_mp_zget(r->mem_pool, + sizeof(nxt_http_action_t) + sizeof(nxt_str_t)); if (nxt_slow_path(action == NULL)) { goto fail; } @@ -1496,7 +1508,7 @@ nxt_http_action_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, rtcf = tmcf->router_conf; mp = rtcf->mem_pool; - action = nxt_mp_alloc(mp, sizeof(nxt_http_action_t)); + action = nxt_mp_zalloc(mp, sizeof(nxt_http_action_t)); if (nxt_slow_path(action == NULL)) { return NULL; } @@ -1525,7 +1537,7 @@ nxt_http_pass_application(nxt_task_t *task, nxt_router_conf_t *rtcf, { nxt_http_action_t *action; - action = nxt_mp_alloc(rtcf->mem_pool, sizeof(nxt_http_action_t)); + action = nxt_mp_zalloc(rtcf->mem_pool, sizeof(nxt_http_action_t)); if (nxt_slow_path(action == NULL)) { return NULL; } diff --git a/src/nxt_tstr.c b/src/nxt_tstr.c index fda585b8..c439696e 100644 --- a/src/nxt_tstr.c +++ b/src/nxt_tstr.c @@ -296,6 +296,13 @@ nxt_tstr_query(nxt_task_t *task, nxt_tstr_query_t *query, nxt_tstr_t *tstr, } +nxt_bool_t +nxt_tstr_query_failed(nxt_tstr_query_t *query) +{ + return query->failed; +} + + void nxt_tstr_query_resolve(nxt_task_t *task, nxt_tstr_query_t *query, void *data, nxt_work_handler_t ready, nxt_work_handler_t error) diff --git a/src/nxt_tstr.h b/src/nxt_tstr.h index ce8e6f3a..afa7f56d 100644 --- a/src/nxt_tstr.h +++ b/src/nxt_tstr.h @@ -52,6 +52,7 @@ nxt_int_t nxt_tstr_query_init(nxt_tstr_query_t **query_p, nxt_mp_t *mp); void nxt_tstr_query(nxt_task_t *task, nxt_tstr_query_t *query, nxt_tstr_t *tstr, nxt_str_t *val); +nxt_bool_t nxt_tstr_query_failed(nxt_tstr_query_t *query); void nxt_tstr_query_resolve(nxt_task_t *task, nxt_tstr_query_t *query, void *data, nxt_work_handler_t ready, nxt_work_handler_t error); void nxt_tstr_query_handle(nxt_task_t *task, nxt_tstr_query_t *query, |