summaryrefslogtreecommitdiffhomepage
path: root/src/nxt_http_route.c
diff options
context:
space:
mode:
authorZhidao HONG <z.hong@f5.com>2024-08-16 00:29:16 +0800
committerZhidao HONG <z.hong@f5.com>2024-08-20 09:17:24 +0800
commitdebd61c3a4f7e5817bf842c2166217929ef80c88 (patch)
tree037909415bcd46a43a73ab89ca698ab74687243d /src/nxt_http_route.c
parent57f939569d3c3db11d8bbc7dd0b45693cbe3344e (diff)
downloadunit-debd61c3a4f7e5817bf842c2166217929ef80c88.tar.gz
unit-debd61c3a4f7e5817bf842c2166217929ef80c88.tar.bz2
http: Add "if" option to the "match" object
This feature allows users to specify conditions to check if one route is matched. It is used the same way as the "if" option in the access log. Example: { "match": { "if": "`${headers['User-Agent'].split('/')[0] == 'curl'}`" }, "action": { "return": 204 } }
Diffstat (limited to '')
-rw-r--r--src/nxt_http_route.c46
1 files changed, 42 insertions, 4 deletions
diff --git a/src/nxt_http_route.c b/src/nxt_http_route.c
index a82518a4..bd0646f3 100644
--- a/src/nxt_http_route.c
+++ b/src/nxt_http_route.c
@@ -51,6 +51,7 @@ typedef struct {
nxt_conf_value_t *query;
nxt_conf_value_t *source;
nxt_conf_value_t *destination;
+ nxt_conf_value_t *condition;
} nxt_http_route_match_conf_t;
@@ -138,6 +139,7 @@ typedef union {
typedef struct {
uint32_t items;
+ nxt_tstr_cond_t condition;
nxt_http_action_t action;
nxt_http_route_test_t test[];
} nxt_http_route_match_t;
@@ -350,6 +352,12 @@ static nxt_conf_map_t nxt_http_route_match_conf[] = {
NXT_CONF_MAP_PTR,
offsetof(nxt_http_route_match_conf_t, destination),
},
+
+ {
+ nxt_string("if"),
+ NXT_CONF_MAP_PTR,
+ offsetof(nxt_http_route_match_conf_t, condition),
+ },
};
@@ -397,7 +405,9 @@ nxt_http_route_match_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
uint32_t n;
nxt_mp_t *mp;
nxt_int_t ret;
- nxt_conf_value_t *match_conf, *action_conf;
+ nxt_str_t str;
+ nxt_conf_value_t *match_conf, *action_conf, *condition;
+ nxt_router_conf_t *rtcf;
nxt_http_route_test_t *test;
nxt_http_route_rule_t *rule;
nxt_http_route_table_t *table;
@@ -405,6 +415,7 @@ nxt_http_route_match_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
nxt_http_route_addr_rule_t *addr_rule;
nxt_http_route_match_conf_t mtcf;
+ static const nxt_str_t if_path = nxt_string("/if");
static const nxt_str_t match_path = nxt_string("/match");
static const nxt_str_t action_path = nxt_string("/action");
@@ -413,9 +424,21 @@ nxt_http_route_match_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
n = (match_conf != NULL) ? nxt_conf_object_members_count(match_conf) : 0;
size = sizeof(nxt_http_route_match_t) + n * sizeof(nxt_http_route_test_t *);
- mp = tmcf->router_conf->mem_pool;
+ rtcf = tmcf->router_conf;
+ mp = rtcf->mem_pool;
+
+ condition = NULL;
+
+ if (match_conf != NULL) {
+ condition = nxt_conf_get_path(match_conf, &if_path);
+
+ if (condition != NULL) {
+ n--;
+ size -= sizeof(nxt_http_route_test_t *);
+ }
+ }
- match = nxt_mp_alloc(mp, size);
+ match = nxt_mp_zalloc(mp, size);
if (nxt_slow_path(match == NULL)) {
return NULL;
}
@@ -432,7 +455,7 @@ nxt_http_route_match_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
return NULL;
}
- if (n == 0) {
+ if (n == 0 && condition == NULL) {
return match;
}
@@ -445,6 +468,15 @@ nxt_http_route_match_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
return NULL;
}
+ if (condition != NULL) {
+ nxt_conf_get_string(condition, &str);
+
+ ret = nxt_tstr_cond_compile(rtcf->tstr_state, &str, &match->condition);
+ if (nxt_slow_path(ret != NXT_OK)) {
+ return NULL;
+ }
+ }
+
test = &match->test[0];
if (mtcf.scheme != NULL) {
@@ -1596,6 +1628,12 @@ nxt_http_route_match(nxt_task_t *task, nxt_http_request_t *r,
nxt_int_t ret;
nxt_http_route_test_t *test, *end;
+ ret = nxt_http_cond_value(task, r, &match->condition);
+ if (ret <= 0) {
+ /* 0 => NULL, -1 => NXT_HTTP_ACTION_ERROR. */
+ return (nxt_http_action_t *) (intptr_t) ret;
+ }
+
test = &match->test[0];
end = test + match->items;