summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--auto/sources1
-rw-r--r--docs/changes.xml6
-rw-r--r--src/nxt_conf_validation.c18
-rw-r--r--src/nxt_http.h7
-rw-r--r--src/nxt_http_parse.c4
-rw-r--r--src/nxt_http_parse.h1
-rw-r--r--src/nxt_http_request.c9
-rw-r--r--src/nxt_http_rewrite.c104
-rw-r--r--src/nxt_http_route.c20
-rw-r--r--src/nxt_tstr.c7
-rw-r--r--src/nxt_tstr.h1
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,