HTTP: added basic URI rewrite.
This commit introduced the basic URI rewrite. It allows users to change request URI. Note the "rewrite" option ignores the contained query if any and the query from the request is preserverd. An example: "routes": [ { "match": { "uri": "/v1/test" }, "action": { "return": 200 } }, { "action": { "rewrite": "/v1$uri", "pass": "routes" } } ] Reviewed-by: Alejandro Colomar <alx@nginx.com>
This commit is contained in:
parent
8843e30e82
commit
14d6d97bac
11 changed files with 167 additions and 11 deletions
|
@ -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 \
|
||||
|
|
|
@ -32,6 +32,12 @@ NGINX Unit updated to 1.30.0.
|
|||
date="" time=""
|
||||
packager="Nginx Packaging <nginx-packaging@f5.com>">
|
||||
|
||||
<change type="feature">
|
||||
<para>
|
||||
basic URI rewrite support.
|
||||
</para>
|
||||
</change>
|
||||
|
||||
<change type="feature">
|
||||
<para>
|
||||
added conditional logging of route selection for HTTP requests.
|
||||
|
|
|
@ -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)
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
104
src/nxt_http_rewrite.c
Normal file
104
src/nxt_http_rewrite.c
Normal file
|
@ -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;
|
||||
}
|
|
@ -578,6 +578,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,
|
||||
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in a new issue