Skip to content

Commit 14d6d97

Browse files
committed
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 <[email protected]>
1 parent 8843e30 commit 14d6d97

File tree

11 files changed

+167
-11
lines changed

11 files changed

+167
-11
lines changed

auto/sources

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ NXT_LIB_SRCS=" \
9292
src/nxt_http_error.c \
9393
src/nxt_http_route.c \
9494
src/nxt_http_route_addr.c \
95+
src/nxt_http_rewrite.c \
9596
src/nxt_http_return.c \
9697
src/nxt_http_static.c \
9798
src/nxt_http_proxy.c \

docs/changes.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,12 @@ NGINX Unit updated to 1.30.0.
3232
date="" time=""
3333
packager="Nginx Packaging &lt;[email protected]&gt;">
3434

35+
<change type="feature">
36+
<para>
37+
basic URI rewrite support.
38+
</para>
39+
</change>
40+
3541
<change type="feature">
3642
<para>
3743
added conditional logging of route selection for HTTP requests.

src/nxt_conf_validation.c

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -669,6 +669,16 @@ static nxt_conf_vldt_object_t nxt_conf_vldt_match_members[] = {
669669
};
670670

671671

672+
static nxt_conf_vldt_object_t nxt_conf_vldt_action_common_members[] = {
673+
{
674+
.name = nxt_string("rewrite"),
675+
.type = NXT_CONF_VLDT_STRING,
676+
},
677+
678+
NXT_CONF_VLDT_END
679+
};
680+
681+
672682
static nxt_conf_vldt_object_t nxt_conf_vldt_pass_action_members[] = {
673683
{
674684
.name = nxt_string("pass"),
@@ -677,7 +687,7 @@ static nxt_conf_vldt_object_t nxt_conf_vldt_pass_action_members[] = {
677687
.flags = NXT_CONF_VLDT_TSTR,
678688
},
679689

680-
NXT_CONF_VLDT_END
690+
NXT_CONF_VLDT_NEXT(nxt_conf_vldt_action_common_members)
681691
};
682692

683693

@@ -692,7 +702,7 @@ static nxt_conf_vldt_object_t nxt_conf_vldt_return_action_members[] = {
692702
.flags = NXT_CONF_VLDT_TSTR,
693703
},
694704

695-
NXT_CONF_VLDT_END
705+
NXT_CONF_VLDT_NEXT(nxt_conf_vldt_action_common_members)
696706
};
697707

698708

@@ -736,7 +746,7 @@ static nxt_conf_vldt_object_t nxt_conf_vldt_share_action_members[] = {
736746
#endif
737747
},
738748

739-
NXT_CONF_VLDT_END
749+
NXT_CONF_VLDT_NEXT(nxt_conf_vldt_action_common_members)
740750
};
741751

742752

@@ -747,7 +757,7 @@ static nxt_conf_vldt_object_t nxt_conf_vldt_proxy_action_members[] = {
747757
.validator = nxt_conf_vldt_proxy,
748758
},
749759

750-
NXT_CONF_VLDT_END
760+
NXT_CONF_VLDT_NEXT(nxt_conf_vldt_action_common_members)
751761
};
752762

753763

src/nxt_http.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,7 @@ typedef struct nxt_http_route_addr_rule_s nxt_http_route_addr_rule_t;
226226

227227

228228
typedef struct {
229+
nxt_conf_value_t *rewrite;
229230
nxt_conf_value_t *pass;
230231
nxt_conf_value_t *ret;
231232
nxt_conf_value_t *location;
@@ -253,6 +254,7 @@ struct nxt_http_action_s {
253254
nxt_str_t *pass;
254255
} u;
255256

257+
nxt_tstr_t *rewrite;
256258
nxt_http_action_t *fallback;
257259
};
258260

@@ -378,6 +380,11 @@ nxt_int_t nxt_upstreams_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
378380
nxt_int_t nxt_upstreams_joint_create(nxt_router_temp_conf_t *tmcf,
379381
nxt_upstream_t ***upstream_joint);
380382

383+
nxt_int_t nxt_http_rewrite_init(nxt_router_conf_t *rtcf,
384+
nxt_http_action_t *action, nxt_http_action_conf_t *acf);
385+
nxt_int_t nxt_http_rewrite(nxt_task_t *task, nxt_http_request_t *r,
386+
nxt_http_action_t *action);
387+
381388
nxt_int_t nxt_http_return_init(nxt_router_conf_t *rtcf,
382389
nxt_http_action_t *action, nxt_http_action_conf_t *acf);
383390

src/nxt_http_parse.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,6 @@ static u_char *nxt_http_lookup_field_end(u_char *p, const u_char *end);
1919
static nxt_int_t nxt_http_parse_field_end(nxt_http_request_parse_t *rp,
2020
u_char **pos, const u_char *end);
2121

22-
static nxt_int_t nxt_http_parse_complex_target(nxt_http_request_parse_t *rp);
23-
2422
static nxt_int_t nxt_http_field_hash_test(nxt_lvlhsh_query_t *lhq, void *data);
2523

2624
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) = {
854852
};
855853

856854

857-
static nxt_int_t
855+
nxt_int_t
858856
nxt_http_parse_complex_target(nxt_http_request_parse_t *rp)
859857
{
860858
u_char *p, *u, c, ch, high, *args;

src/nxt_http_parse.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ nxt_uint_t nxt_http_fields_hash_collisions(nxt_lvlhsh_t *hash,
127127
nxt_int_t nxt_http_fields_process(nxt_list_t *fields, nxt_lvlhsh_t *hash,
128128
void *ctx);
129129

130+
nxt_int_t nxt_http_parse_complex_target(nxt_http_request_parse_t *rp);
130131
nxt_buf_t *nxt_http_chunk_parse(nxt_task_t *task, nxt_http_chunk_parse_t *hcp,
131132
nxt_buf_t *in);
132133

src/nxt_http_request.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -555,9 +555,18 @@ void
555555
nxt_http_request_action(nxt_task_t *task, nxt_http_request_t *r,
556556
nxt_http_action_t *action)
557557
{
558+
nxt_int_t ret;
559+
558560
if (nxt_fast_path(action != NULL)) {
559561

560562
do {
563+
if (action->rewrite != NULL) {
564+
ret = nxt_http_rewrite(task, r, action);
565+
if (nxt_slow_path(ret != NXT_OK)) {
566+
break;
567+
}
568+
}
569+
561570
action = action->handler(task, r, action);
562571

563572
if (action == NULL) {

src/nxt_http_rewrite.c

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
2+
/*
3+
* Copyright (C) Zhidao HONG
4+
* Copyright (C) NGINX, Inc.
5+
*/
6+
7+
#include <nxt_router.h>
8+
#include <nxt_http.h>
9+
10+
11+
nxt_int_t
12+
nxt_http_rewrite_init(nxt_router_conf_t *rtcf, nxt_http_action_t *action,
13+
nxt_http_action_conf_t *acf)
14+
{
15+
nxt_str_t str;
16+
17+
nxt_conf_get_string(acf->rewrite, &str);
18+
19+
action->rewrite = nxt_tstr_compile(rtcf->tstr_state, &str, 0);
20+
if (nxt_slow_path(action->rewrite == NULL)) {
21+
return NXT_ERROR;
22+
}
23+
24+
return NXT_OK;
25+
}
26+
27+
28+
nxt_int_t
29+
nxt_http_rewrite(nxt_task_t *task, nxt_http_request_t *r,
30+
nxt_http_action_t *action)
31+
{
32+
u_char *p;
33+
nxt_int_t ret;
34+
nxt_str_t str, encoded_path, target;
35+
nxt_router_conf_t *rtcf;
36+
nxt_http_request_parse_t rp;
37+
38+
if (nxt_tstr_is_const(action->rewrite)) {
39+
nxt_tstr_str(action->rewrite, &str);
40+
41+
} else {
42+
rtcf = r->conf->socket_conf->router_conf;
43+
44+
ret = nxt_tstr_query_init(&r->tstr_query, rtcf->tstr_state,
45+
&r->tstr_cache, r, r->mem_pool);
46+
if (nxt_slow_path(ret != NXT_OK)) {
47+
return NXT_ERROR;
48+
}
49+
50+
nxt_tstr_query(task, r->tstr_query, action->rewrite, &str);
51+
52+
if (nxt_slow_path(nxt_tstr_query_failed(r->tstr_query))) {
53+
return NXT_ERROR;
54+
}
55+
}
56+
57+
nxt_memzero(&rp, sizeof(nxt_http_request_parse_t));
58+
59+
rp.mem_pool = r->mem_pool;
60+
61+
rp.target_start = str.start;
62+
rp.target_end = str.start + str.length;
63+
64+
ret = nxt_http_parse_complex_target(&rp);
65+
if (nxt_slow_path(ret != NXT_OK)) {
66+
return NXT_ERROR;
67+
}
68+
69+
p = (rp.args.length > 0) ? rp.args.start - 1 : rp.target_end;
70+
71+
encoded_path.start = rp.target_start;
72+
encoded_path.length = p - encoded_path.start;
73+
74+
if (r->args->length == 0) {
75+
r->target = encoded_path;
76+
77+
} else {
78+
target.length = encoded_path.length + 1 + r->args->length;
79+
80+
target.start = nxt_mp_alloc(r->mem_pool, target.length);
81+
if (target.start == NULL) {
82+
return NXT_ERROR;
83+
}
84+
85+
p = nxt_cpymem(target.start, encoded_path.start, encoded_path.length);
86+
*p++ = '?';
87+
nxt_memcpy(p, r->args->start, r->args->length);
88+
89+
r->target = target;
90+
}
91+
92+
r->path = nxt_mp_alloc(r->mem_pool, sizeof(nxt_str_t));
93+
if (nxt_slow_path(r->path == NULL)) {
94+
return NXT_ERROR;
95+
}
96+
97+
*r->path = rp.path;
98+
99+
if (nxt_slow_path(r->log_route)) {
100+
nxt_log(task, NXT_LOG_NOTICE, "URI rewritten to \"%V\"", &r->target);
101+
}
102+
103+
return NXT_OK;
104+
}

src/nxt_http_route.c

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -578,6 +578,11 @@ nxt_http_route_match_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
578578

579579

580580
static nxt_conf_map_t nxt_http_route_action_conf[] = {
581+
{
582+
nxt_string("rewrite"),
583+
NXT_CONF_MAP_PTR,
584+
offsetof(nxt_http_action_conf_t, rewrite)
585+
},
581586
{
582587
nxt_string("pass"),
583588
NXT_CONF_MAP_PTR,
@@ -659,6 +664,13 @@ nxt_http_action_init(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
659664
rtcf = tmcf->router_conf;
660665
mp = rtcf->mem_pool;
661666

667+
if (acf.rewrite != NULL) {
668+
ret = nxt_http_rewrite_init(rtcf, action, &acf);
669+
if (nxt_slow_path(ret != NXT_OK)) {
670+
return ret;
671+
}
672+
}
673+
662674
if (acf.ret != NULL) {
663675
return nxt_http_return_init(rtcf, action, &acf);
664676
}
@@ -1312,8 +1324,8 @@ nxt_http_pass_var(nxt_task_t *task, nxt_http_request_t *r,
13121324
goto fail;
13131325
}
13141326

1315-
action = nxt_mp_get(r->mem_pool,
1316-
sizeof(nxt_http_action_t) + sizeof(nxt_str_t));
1327+
action = nxt_mp_zget(r->mem_pool,
1328+
sizeof(nxt_http_action_t) + sizeof(nxt_str_t));
13171329
if (nxt_slow_path(action == NULL)) {
13181330
goto fail;
13191331
}
@@ -1496,7 +1508,7 @@ nxt_http_action_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
14961508
rtcf = tmcf->router_conf;
14971509
mp = rtcf->mem_pool;
14981510

1499-
action = nxt_mp_alloc(mp, sizeof(nxt_http_action_t));
1511+
action = nxt_mp_zalloc(mp, sizeof(nxt_http_action_t));
15001512
if (nxt_slow_path(action == NULL)) {
15011513
return NULL;
15021514
}
@@ -1525,7 +1537,7 @@ nxt_http_pass_application(nxt_task_t *task, nxt_router_conf_t *rtcf,
15251537
{
15261538
nxt_http_action_t *action;
15271539

1528-
action = nxt_mp_alloc(rtcf->mem_pool, sizeof(nxt_http_action_t));
1540+
action = nxt_mp_zalloc(rtcf->mem_pool, sizeof(nxt_http_action_t));
15291541
if (nxt_slow_path(action == NULL)) {
15301542
return NULL;
15311543
}

src/nxt_tstr.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,13 @@ nxt_tstr_query(nxt_task_t *task, nxt_tstr_query_t *query, nxt_tstr_t *tstr,
296296
}
297297

298298

299+
nxt_bool_t
300+
nxt_tstr_query_failed(nxt_tstr_query_t *query)
301+
{
302+
return query->failed;
303+
}
304+
305+
299306
void
300307
nxt_tstr_query_resolve(nxt_task_t *task, nxt_tstr_query_t *query, void *data,
301308
nxt_work_handler_t ready, nxt_work_handler_t error)

0 commit comments

Comments
 (0)