1964Sigor@sysoev.ru
2964Sigor@sysoev.ru /*
3964Sigor@sysoev.ru * Copyright (C) Igor Sysoev
4964Sigor@sysoev.ru * Copyright (C) NGINX, Inc.
5964Sigor@sysoev.ru */
6964Sigor@sysoev.ru
7964Sigor@sysoev.ru #include <nxt_router.h>
8964Sigor@sysoev.ru #include <nxt_http.h>
91324Saxel.duch@nginx.com #include <nxt_sockaddr.h>
101324Saxel.duch@nginx.com #include <nxt_http_route_addr.h>
111721Saxel.duch@nginx.com #include <nxt_regex.h>
12964Sigor@sysoev.ru
13964Sigor@sysoev.ru
14964Sigor@sysoev.ru typedef enum {
151059Sigor@sysoev.ru NXT_HTTP_ROUTE_TABLE = 0,
161059Sigor@sysoev.ru NXT_HTTP_ROUTE_STRING,
17964Sigor@sysoev.ru NXT_HTTP_ROUTE_STRING_PTR,
18964Sigor@sysoev.ru NXT_HTTP_ROUTE_HEADER,
19964Sigor@sysoev.ru NXT_HTTP_ROUTE_ARGUMENT,
20964Sigor@sysoev.ru NXT_HTTP_ROUTE_COOKIE,
211110Saxel.duch@nginx.com NXT_HTTP_ROUTE_SCHEME,
221991Sz.hong@f5.com NXT_HTTP_ROUTE_QUERY,
231324Saxel.duch@nginx.com NXT_HTTP_ROUTE_SOURCE,
241326Saxel.duch@nginx.com NXT_HTTP_ROUTE_DESTINATION,
25964Sigor@sysoev.ru } nxt_http_route_object_t;
26964Sigor@sysoev.ru
27964Sigor@sysoev.ru
28964Sigor@sysoev.ru typedef enum {
29964Sigor@sysoev.ru NXT_HTTP_ROUTE_PATTERN_EXACT = 0,
30964Sigor@sysoev.ru NXT_HTTP_ROUTE_PATTERN_BEGIN,
31964Sigor@sysoev.ru NXT_HTTP_ROUTE_PATTERN_END,
32964Sigor@sysoev.ru NXT_HTTP_ROUTE_PATTERN_SUBSTRING,
33964Sigor@sysoev.ru } nxt_http_route_pattern_type_t;
34964Sigor@sysoev.ru
35964Sigor@sysoev.ru
36964Sigor@sysoev.ru typedef enum {
37964Sigor@sysoev.ru NXT_HTTP_ROUTE_PATTERN_NOCASE = 0,
38964Sigor@sysoev.ru NXT_HTTP_ROUTE_PATTERN_LOWCASE,
39964Sigor@sysoev.ru NXT_HTTP_ROUTE_PATTERN_UPCASE,
40964Sigor@sysoev.ru } nxt_http_route_pattern_case_t;
41964Sigor@sysoev.ru
42964Sigor@sysoev.ru
43964Sigor@sysoev.ru typedef struct {
44964Sigor@sysoev.ru nxt_conf_value_t *host;
45964Sigor@sysoev.ru nxt_conf_value_t *uri;
46964Sigor@sysoev.ru nxt_conf_value_t *method;
471059Sigor@sysoev.ru nxt_conf_value_t *headers;
481061Sigor@sysoev.ru nxt_conf_value_t *arguments;
491062Sigor@sysoev.ru nxt_conf_value_t *cookies;
501110Saxel.duch@nginx.com nxt_conf_value_t *scheme;
511991Sz.hong@f5.com nxt_conf_value_t *query;
521324Saxel.duch@nginx.com nxt_conf_value_t *source;
531326Saxel.duch@nginx.com nxt_conf_value_t *destination;
54964Sigor@sysoev.ru } nxt_http_route_match_conf_t;
55964Sigor@sysoev.ru
56964Sigor@sysoev.ru
57964Sigor@sysoev.ru typedef struct {
581508Saxel.duch@nginx.com u_char *start;
591508Saxel.duch@nginx.com uint32_t length;
601508Saxel.duch@nginx.com nxt_http_route_pattern_type_t type:8;
611508Saxel.duch@nginx.com } nxt_http_route_pattern_slice_t;
621508Saxel.duch@nginx.com
631508Saxel.duch@nginx.com
641508Saxel.duch@nginx.com typedef struct {
651721Saxel.duch@nginx.com union {
661721Saxel.duch@nginx.com nxt_array_t *pattern_slices;
671721Saxel.duch@nginx.com #if (NXT_HAVE_REGEX)
681721Saxel.duch@nginx.com nxt_regex_t *regex;
691721Saxel.duch@nginx.com #endif
701721Saxel.duch@nginx.com } u;
71964Sigor@sysoev.ru uint32_t min_length;
721508Saxel.duch@nginx.com
73964Sigor@sysoev.ru uint8_t case_sensitive; /* 1 bit */
74964Sigor@sysoev.ru uint8_t negative; /* 1 bit */
75964Sigor@sysoev.ru uint8_t any; /* 1 bit */
761721Saxel.duch@nginx.com #if (NXT_HAVE_REGEX)
771721Saxel.duch@nginx.com uint8_t regex; /* 1 bit */
781721Saxel.duch@nginx.com #endif
79964Sigor@sysoev.ru } nxt_http_route_pattern_t;
80964Sigor@sysoev.ru
81964Sigor@sysoev.ru
82964Sigor@sysoev.ru typedef struct {
831061Sigor@sysoev.ru uint16_t hash;
841061Sigor@sysoev.ru uint16_t name_length;
851061Sigor@sysoev.ru uint32_t value_length;
861061Sigor@sysoev.ru u_char *name;
871061Sigor@sysoev.ru u_char *value;
881062Sigor@sysoev.ru } nxt_http_cookie_t;
891062Sigor@sysoev.ru
901062Sigor@sysoev.ru
911859So.canty@f5.com struct nxt_http_route_rule_s {
921059Sigor@sysoev.ru /* The object must be the first field. */
931059Sigor@sysoev.ru nxt_http_route_object_t object:8;
94964Sigor@sysoev.ru uint32_t items;
951059Sigor@sysoev.ru
961059Sigor@sysoev.ru union {
971059Sigor@sysoev.ru uintptr_t offset;
981059Sigor@sysoev.ru
991059Sigor@sysoev.ru struct {
1001059Sigor@sysoev.ru u_char *start;
1011059Sigor@sysoev.ru uint16_t hash;
1021059Sigor@sysoev.ru uint16_t length;
1031059Sigor@sysoev.ru } name;
1041059Sigor@sysoev.ru } u;
1051059Sigor@sysoev.ru
106964Sigor@sysoev.ru nxt_http_route_pattern_t pattern[0];
1071859So.canty@f5.com };
108964Sigor@sysoev.ru
109964Sigor@sysoev.ru
110964Sigor@sysoev.ru typedef struct {
111964Sigor@sysoev.ru uint32_t items;
1121059Sigor@sysoev.ru nxt_http_route_rule_t *rule[0];
1131059Sigor@sysoev.ru } nxt_http_route_ruleset_t;
1141059Sigor@sysoev.ru
1151059Sigor@sysoev.ru
1161059Sigor@sysoev.ru typedef struct {
1171059Sigor@sysoev.ru /* The object must be the first field. */
1181059Sigor@sysoev.ru nxt_http_route_object_t object:8;
1191059Sigor@sysoev.ru uint32_t items;
1201059Sigor@sysoev.ru nxt_http_route_ruleset_t *ruleset[0];
1211059Sigor@sysoev.ru } nxt_http_route_table_t;
1221059Sigor@sysoev.ru
1231059Sigor@sysoev.ru
1241936So.canty@f5.com struct nxt_http_route_addr_rule_s {
1251324Saxel.duch@nginx.com /* The object must be the first field. */
1261324Saxel.duch@nginx.com nxt_http_route_object_t object:8;
1271324Saxel.duch@nginx.com uint32_t items;
1281324Saxel.duch@nginx.com nxt_http_route_addr_pattern_t addr_pattern[0];
1291936So.canty@f5.com };
1301324Saxel.duch@nginx.com
1311324Saxel.duch@nginx.com
1321059Sigor@sysoev.ru typedef union {
1331059Sigor@sysoev.ru nxt_http_route_rule_t *rule;
1341059Sigor@sysoev.ru nxt_http_route_table_t *table;
1351324Saxel.duch@nginx.com nxt_http_route_addr_rule_t *addr_rule;
1361059Sigor@sysoev.ru } nxt_http_route_test_t;
1371059Sigor@sysoev.ru
1381059Sigor@sysoev.ru
1391059Sigor@sysoev.ru typedef struct {
1401059Sigor@sysoev.ru uint32_t items;
1411264Sigor@sysoev.ru nxt_http_action_t action;
1421059Sigor@sysoev.ru nxt_http_route_test_t test[0];
143964Sigor@sysoev.ru } nxt_http_route_match_t;
144964Sigor@sysoev.ru
145964Sigor@sysoev.ru
146964Sigor@sysoev.ru struct nxt_http_route_s {
147964Sigor@sysoev.ru nxt_str_t name;
148964Sigor@sysoev.ru uint32_t items;
149964Sigor@sysoev.ru nxt_http_route_match_t *match[0];
150964Sigor@sysoev.ru };
151964Sigor@sysoev.ru
152964Sigor@sysoev.ru
153964Sigor@sysoev.ru struct nxt_http_routes_s {
154964Sigor@sysoev.ru uint32_t items;
155964Sigor@sysoev.ru nxt_http_route_t *route[0];
156964Sigor@sysoev.ru };
157964Sigor@sysoev.ru
158964Sigor@sysoev.ru
159964Sigor@sysoev.ru static nxt_http_route_t *nxt_http_route_create(nxt_task_t *task,
160964Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf, nxt_conf_value_t *cv);
161964Sigor@sysoev.ru static nxt_http_route_match_t *nxt_http_route_match_create(nxt_task_t *task,
162964Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf, nxt_conf_value_t *cv);
1631059Sigor@sysoev.ru static nxt_http_route_table_t *nxt_http_route_table_create(nxt_task_t *task,
1641061Sigor@sysoev.ru nxt_mp_t *mp, nxt_conf_value_t *table_cv, nxt_http_route_object_t object,
1652123Sz.hong@f5.com nxt_bool_t case_sensitive, nxt_http_uri_encoding_t encoding);
1661059Sigor@sysoev.ru static nxt_http_route_ruleset_t *nxt_http_route_ruleset_create(nxt_task_t *task,
1671061Sigor@sysoev.ru nxt_mp_t *mp, nxt_conf_value_t *ruleset_cv, nxt_http_route_object_t object,
1682123Sz.hong@f5.com nxt_bool_t case_sensitive, nxt_http_uri_encoding_t encoding);
1691061Sigor@sysoev.ru static nxt_http_route_rule_t *nxt_http_route_rule_name_create(nxt_task_t *task,
1701061Sigor@sysoev.ru nxt_mp_t *mp, nxt_conf_value_t *rule_cv, nxt_str_t *name,
1712123Sz.hong@f5.com nxt_bool_t case_sensitive, nxt_http_uri_encoding_t encoding);
172964Sigor@sysoev.ru static nxt_http_route_rule_t *nxt_http_route_rule_create(nxt_task_t *task,
1731059Sigor@sysoev.ru nxt_mp_t *mp, nxt_conf_value_t *cv, nxt_bool_t case_sensitive,
1741474Saxel.duch@nginx.com nxt_http_route_pattern_case_t pattern_case,
1752123Sz.hong@f5.com nxt_http_uri_encoding_t encoding);
176964Sigor@sysoev.ru static int nxt_http_pattern_compare(const void *one, const void *two);
1771390Saxel.duch@nginx.com static int nxt_http_addr_pattern_compare(const void *one, const void *two);
178964Sigor@sysoev.ru static nxt_int_t nxt_http_route_pattern_create(nxt_task_t *task, nxt_mp_t *mp,
179964Sigor@sysoev.ru nxt_conf_value_t *cv, nxt_http_route_pattern_t *pattern,
1801474Saxel.duch@nginx.com nxt_http_route_pattern_case_t pattern_case,
1812123Sz.hong@f5.com nxt_http_uri_encoding_t encoding);
1821474Saxel.duch@nginx.com static nxt_int_t nxt_http_route_decode_str(nxt_str_t *str,
1832123Sz.hong@f5.com nxt_http_uri_encoding_t encoding);
1841508Saxel.duch@nginx.com static nxt_int_t nxt_http_route_pattern_slice(nxt_array_t *slices,
1851508Saxel.duch@nginx.com nxt_str_t *test,
1861508Saxel.duch@nginx.com nxt_http_route_pattern_type_t type,
1872123Sz.hong@f5.com nxt_http_uri_encoding_t encoding,
1881032Sigor@sysoev.ru nxt_http_route_pattern_case_t pattern_case);
189964Sigor@sysoev.ru
1901472Svbart@nginx.com static nxt_int_t nxt_http_route_resolve(nxt_task_t *task,
191964Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf, nxt_http_route_t *route);
1921472Svbart@nginx.com static nxt_int_t nxt_http_action_resolve(nxt_task_t *task,
1931264Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf, nxt_http_action_t *action);
1941954Sz.hong@f5.com static nxt_http_action_t *nxt_http_pass_var(nxt_task_t *task,
1951563Svbart@nginx.com nxt_http_request_t *r, nxt_http_action_t *action);
1961954Sz.hong@f5.com static void nxt_http_pass_var_ready(nxt_task_t *task, void *obj, void *data);
1971954Sz.hong@f5.com static void nxt_http_pass_var_error(nxt_task_t *task, void *obj, void *data);
1981954Sz.hong@f5.com static nxt_int_t nxt_http_pass_find(nxt_mp_t *mp, nxt_router_conf_t *rtcf,
1991954Sz.hong@f5.com nxt_str_t *pass, nxt_http_action_t *action);
2001563Svbart@nginx.com static nxt_int_t nxt_http_route_find(nxt_http_routes_t *routes, nxt_str_t *name,
2011392Sigor@sysoev.ru nxt_http_action_t *action);
202964Sigor@sysoev.ru
2031264Sigor@sysoev.ru static nxt_http_action_t *nxt_http_route_handler(nxt_task_t *task,
2041264Sigor@sysoev.ru nxt_http_request_t *r, nxt_http_action_t *start);
2051326Saxel.duch@nginx.com static nxt_http_action_t *nxt_http_route_match(nxt_task_t *task,
2061326Saxel.duch@nginx.com nxt_http_request_t *r, nxt_http_route_match_t *match);
2071060Sigor@sysoev.ru static nxt_int_t nxt_http_route_table(nxt_http_request_t *r,
2081059Sigor@sysoev.ru nxt_http_route_table_t *table);
2091060Sigor@sysoev.ru static nxt_int_t nxt_http_route_ruleset(nxt_http_request_t *r,
2101059Sigor@sysoev.ru nxt_http_route_ruleset_t *ruleset);
2111060Sigor@sysoev.ru static nxt_int_t nxt_http_route_rule(nxt_http_request_t *r,
212964Sigor@sysoev.ru nxt_http_route_rule_t *rule);
2131060Sigor@sysoev.ru static nxt_int_t nxt_http_route_header(nxt_http_request_t *r,
2141059Sigor@sysoev.ru nxt_http_route_rule_t *rule);
2151061Sigor@sysoev.ru static nxt_int_t nxt_http_route_arguments(nxt_http_request_t *r,
2161061Sigor@sysoev.ru nxt_http_route_rule_t *rule);
2171061Sigor@sysoev.ru static nxt_int_t nxt_http_route_test_argument(nxt_http_request_t *r,
2181061Sigor@sysoev.ru nxt_http_route_rule_t *rule, nxt_array_t *array);
2191110Saxel.duch@nginx.com static nxt_int_t nxt_http_route_scheme(nxt_http_request_t *r,
2201110Saxel.duch@nginx.com nxt_http_route_rule_t *rule);
2211991Sz.hong@f5.com static nxt_int_t nxt_http_route_query(nxt_http_request_t *r,
2221991Sz.hong@f5.com nxt_http_route_rule_t *rule);
2231062Sigor@sysoev.ru static nxt_int_t nxt_http_route_cookies(nxt_http_request_t *r,
2241062Sigor@sysoev.ru nxt_http_route_rule_t *rule);
2251062Sigor@sysoev.ru static nxt_int_t nxt_http_route_test_cookie(nxt_http_request_t *r,
2261062Sigor@sysoev.ru nxt_http_route_rule_t *rule, nxt_array_t *array);
2271060Sigor@sysoev.ru static nxt_int_t nxt_http_route_pattern(nxt_http_request_t *r,
228964Sigor@sysoev.ru nxt_http_route_pattern_t *pattern, u_char *start, size_t length);
2291060Sigor@sysoev.ru static nxt_int_t nxt_http_route_memcmp(u_char *start, u_char *test,
2301032Sigor@sysoev.ru size_t length, nxt_bool_t case_sensitive);
231964Sigor@sysoev.ru
232964Sigor@sysoev.ru
233964Sigor@sysoev.ru nxt_http_routes_t *
nxt_http_routes_create(nxt_task_t * task,nxt_router_temp_conf_t * tmcf,nxt_conf_value_t * routes_conf)234964Sigor@sysoev.ru nxt_http_routes_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
235964Sigor@sysoev.ru nxt_conf_value_t *routes_conf)
236964Sigor@sysoev.ru {
237964Sigor@sysoev.ru size_t size;
238964Sigor@sysoev.ru uint32_t i, n, next;
239964Sigor@sysoev.ru nxt_mp_t *mp;
240964Sigor@sysoev.ru nxt_str_t name, *string;
241964Sigor@sysoev.ru nxt_bool_t object;
242964Sigor@sysoev.ru nxt_conf_value_t *route_conf;
243964Sigor@sysoev.ru nxt_http_route_t *route;
244964Sigor@sysoev.ru nxt_http_routes_t *routes;
245964Sigor@sysoev.ru
246964Sigor@sysoev.ru object = (nxt_conf_type(routes_conf) == NXT_CONF_OBJECT);
247964Sigor@sysoev.ru n = object ? nxt_conf_object_members_count(routes_conf) : 1;
248964Sigor@sysoev.ru size = sizeof(nxt_http_routes_t) + n * sizeof(nxt_http_route_t *);
249964Sigor@sysoev.ru
250964Sigor@sysoev.ru mp = tmcf->router_conf->mem_pool;
251964Sigor@sysoev.ru
252964Sigor@sysoev.ru routes = nxt_mp_alloc(mp, size);
253964Sigor@sysoev.ru if (nxt_slow_path(routes == NULL)) {
254964Sigor@sysoev.ru return NULL;
255964Sigor@sysoev.ru }
256964Sigor@sysoev.ru
257964Sigor@sysoev.ru routes->items = n;
258964Sigor@sysoev.ru
259964Sigor@sysoev.ru if (object) {
260964Sigor@sysoev.ru next = 0;
261964Sigor@sysoev.ru
262964Sigor@sysoev.ru for (i = 0; i < n; i++) {
263964Sigor@sysoev.ru route_conf = nxt_conf_next_object_member(routes_conf, &name, &next);
264964Sigor@sysoev.ru
265964Sigor@sysoev.ru route = nxt_http_route_create(task, tmcf, route_conf);
266964Sigor@sysoev.ru if (nxt_slow_path(route == NULL)) {
267964Sigor@sysoev.ru return NULL;
268964Sigor@sysoev.ru }
269964Sigor@sysoev.ru
270964Sigor@sysoev.ru routes->route[i] = route;
271964Sigor@sysoev.ru
272964Sigor@sysoev.ru string = nxt_str_dup(mp, &route->name, &name);
273964Sigor@sysoev.ru if (nxt_slow_path(string == NULL)) {
274964Sigor@sysoev.ru return NULL;
275964Sigor@sysoev.ru }
276964Sigor@sysoev.ru }
277964Sigor@sysoev.ru
278964Sigor@sysoev.ru } else {
279964Sigor@sysoev.ru route = nxt_http_route_create(task, tmcf, routes_conf);
280964Sigor@sysoev.ru if (nxt_slow_path(route == NULL)) {
281964Sigor@sysoev.ru return NULL;
282964Sigor@sysoev.ru }
283964Sigor@sysoev.ru
284964Sigor@sysoev.ru routes->route[0] = route;
285964Sigor@sysoev.ru
286964Sigor@sysoev.ru route->name.length = 0;
287964Sigor@sysoev.ru route->name.start = NULL;
288964Sigor@sysoev.ru }
289964Sigor@sysoev.ru
290964Sigor@sysoev.ru return routes;
291964Sigor@sysoev.ru }
292964Sigor@sysoev.ru
293964Sigor@sysoev.ru
294964Sigor@sysoev.ru static nxt_conf_map_t nxt_http_route_match_conf[] = {
295964Sigor@sysoev.ru {
2961110Saxel.duch@nginx.com nxt_string("scheme"),
2971110Saxel.duch@nginx.com NXT_CONF_MAP_PTR,
2981110Saxel.duch@nginx.com offsetof(nxt_http_route_match_conf_t, scheme)
2991110Saxel.duch@nginx.com },
3001110Saxel.duch@nginx.com {
301964Sigor@sysoev.ru nxt_string("host"),
302964Sigor@sysoev.ru NXT_CONF_MAP_PTR,
303964Sigor@sysoev.ru offsetof(nxt_http_route_match_conf_t, host),
304964Sigor@sysoev.ru },
305964Sigor@sysoev.ru
306964Sigor@sysoev.ru {
307964Sigor@sysoev.ru nxt_string("uri"),
308964Sigor@sysoev.ru NXT_CONF_MAP_PTR,
309964Sigor@sysoev.ru offsetof(nxt_http_route_match_conf_t, uri),
310964Sigor@sysoev.ru },
311964Sigor@sysoev.ru
312964Sigor@sysoev.ru {
313964Sigor@sysoev.ru nxt_string("method"),
314964Sigor@sysoev.ru NXT_CONF_MAP_PTR,
315964Sigor@sysoev.ru offsetof(nxt_http_route_match_conf_t, method),
316964Sigor@sysoev.ru },
3171059Sigor@sysoev.ru
3181059Sigor@sysoev.ru {
3191059Sigor@sysoev.ru nxt_string("headers"),
3201059Sigor@sysoev.ru NXT_CONF_MAP_PTR,
3211059Sigor@sysoev.ru offsetof(nxt_http_route_match_conf_t, headers),
3221059Sigor@sysoev.ru },
3231061Sigor@sysoev.ru
3241061Sigor@sysoev.ru {
3251061Sigor@sysoev.ru nxt_string("arguments"),
3261061Sigor@sysoev.ru NXT_CONF_MAP_PTR,
3271061Sigor@sysoev.ru offsetof(nxt_http_route_match_conf_t, arguments),
3281061Sigor@sysoev.ru },
3291062Sigor@sysoev.ru
3301062Sigor@sysoev.ru {
3311062Sigor@sysoev.ru nxt_string("cookies"),
3321062Sigor@sysoev.ru NXT_CONF_MAP_PTR,
3331062Sigor@sysoev.ru offsetof(nxt_http_route_match_conf_t, cookies),
3341062Sigor@sysoev.ru },
3351324Saxel.duch@nginx.com
3361324Saxel.duch@nginx.com {
3371991Sz.hong@f5.com nxt_string("query"),
3381991Sz.hong@f5.com NXT_CONF_MAP_PTR,
3391991Sz.hong@f5.com offsetof(nxt_http_route_match_conf_t, query),
3401991Sz.hong@f5.com },
3411991Sz.hong@f5.com
3421991Sz.hong@f5.com {
3431324Saxel.duch@nginx.com nxt_string("source"),
3441324Saxel.duch@nginx.com NXT_CONF_MAP_PTR,
3451324Saxel.duch@nginx.com offsetof(nxt_http_route_match_conf_t, source),
3461324Saxel.duch@nginx.com },
3471326Saxel.duch@nginx.com
3481326Saxel.duch@nginx.com {
3491326Saxel.duch@nginx.com nxt_string("destination"),
3501326Saxel.duch@nginx.com NXT_CONF_MAP_PTR,
3511326Saxel.duch@nginx.com offsetof(nxt_http_route_match_conf_t, destination),
3521326Saxel.duch@nginx.com },
353964Sigor@sysoev.ru };
354964Sigor@sysoev.ru
355964Sigor@sysoev.ru
356964Sigor@sysoev.ru static nxt_http_route_t *
nxt_http_route_create(nxt_task_t * task,nxt_router_temp_conf_t * tmcf,nxt_conf_value_t * cv)357964Sigor@sysoev.ru nxt_http_route_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
358964Sigor@sysoev.ru nxt_conf_value_t *cv)
359964Sigor@sysoev.ru {
360964Sigor@sysoev.ru size_t size;
361964Sigor@sysoev.ru uint32_t i, n;
362964Sigor@sysoev.ru nxt_conf_value_t *value;
363964Sigor@sysoev.ru nxt_http_route_t *route;
364964Sigor@sysoev.ru nxt_http_route_match_t *match, **m;
365964Sigor@sysoev.ru
366964Sigor@sysoev.ru n = nxt_conf_array_elements_count(cv);
367964Sigor@sysoev.ru size = sizeof(nxt_http_route_t) + n * sizeof(nxt_http_route_match_t *);
368964Sigor@sysoev.ru
369964Sigor@sysoev.ru route = nxt_mp_alloc(tmcf->router_conf->mem_pool, size);
370964Sigor@sysoev.ru if (nxt_slow_path(route == NULL)) {
371964Sigor@sysoev.ru return NULL;
372964Sigor@sysoev.ru }
373964Sigor@sysoev.ru
374964Sigor@sysoev.ru route->items = n;
375964Sigor@sysoev.ru m = &route->match[0];
376964Sigor@sysoev.ru
377964Sigor@sysoev.ru for (i = 0; i < n; i++) {
378964Sigor@sysoev.ru value = nxt_conf_get_array_element(cv, i);
379964Sigor@sysoev.ru
380964Sigor@sysoev.ru match = nxt_http_route_match_create(task, tmcf, value);
381964Sigor@sysoev.ru if (match == NULL) {
382964Sigor@sysoev.ru return NULL;
383964Sigor@sysoev.ru }
384964Sigor@sysoev.ru
385964Sigor@sysoev.ru *m++ = match;
386964Sigor@sysoev.ru }
387964Sigor@sysoev.ru
388964Sigor@sysoev.ru return route;
389964Sigor@sysoev.ru }
390964Sigor@sysoev.ru
391964Sigor@sysoev.ru
392964Sigor@sysoev.ru static nxt_http_route_match_t *
nxt_http_route_match_create(nxt_task_t * task,nxt_router_temp_conf_t * tmcf,nxt_conf_value_t * cv)393964Sigor@sysoev.ru nxt_http_route_match_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
394964Sigor@sysoev.ru nxt_conf_value_t *cv)
395964Sigor@sysoev.ru {
396964Sigor@sysoev.ru size_t size;
397964Sigor@sysoev.ru uint32_t n;
3981059Sigor@sysoev.ru nxt_mp_t *mp;
399964Sigor@sysoev.ru nxt_int_t ret;
4001378Svbart@nginx.com nxt_conf_value_t *match_conf, *action_conf;
4011059Sigor@sysoev.ru nxt_http_route_test_t *test;
4021059Sigor@sysoev.ru nxt_http_route_rule_t *rule;
4031059Sigor@sysoev.ru nxt_http_route_table_t *table;
404964Sigor@sysoev.ru nxt_http_route_match_t *match;
4051324Saxel.duch@nginx.com nxt_http_route_addr_rule_t *addr_rule;
406964Sigor@sysoev.ru nxt_http_route_match_conf_t mtcf;
407964Sigor@sysoev.ru
408964Sigor@sysoev.ru static nxt_str_t match_path = nxt_string("/match");
4091378Svbart@nginx.com static nxt_str_t action_path = nxt_string("/action");
410964Sigor@sysoev.ru
411964Sigor@sysoev.ru match_conf = nxt_conf_get_path(cv, &match_path);
412964Sigor@sysoev.ru
413964Sigor@sysoev.ru n = (match_conf != NULL) ? nxt_conf_object_members_count(match_conf) : 0;
4141859So.canty@f5.com size = sizeof(nxt_http_route_match_t) + n * sizeof(nxt_http_route_test_t *);
415964Sigor@sysoev.ru
4161059Sigor@sysoev.ru mp = tmcf->router_conf->mem_pool;
4171059Sigor@sysoev.ru
4181059Sigor@sysoev.ru match = nxt_mp_alloc(mp, size);
419964Sigor@sysoev.ru if (nxt_slow_path(match == NULL)) {
420964Sigor@sysoev.ru return NULL;
421964Sigor@sysoev.ru }
422964Sigor@sysoev.ru
423964Sigor@sysoev.ru match->items = n;
424964Sigor@sysoev.ru
4251378Svbart@nginx.com action_conf = nxt_conf_get_path(cv, &action_path);
4261378Svbart@nginx.com if (nxt_slow_path(action_conf == NULL)) {
4271378Svbart@nginx.com return NULL;
4281378Svbart@nginx.com }
4291378Svbart@nginx.com
4301903Sz.hong@f5.com ret = nxt_http_action_init(task, tmcf, action_conf, &match->action);
4311264Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) {
432964Sigor@sysoev.ru return NULL;
433964Sigor@sysoev.ru }
434964Sigor@sysoev.ru
435964Sigor@sysoev.ru if (n == 0) {
436964Sigor@sysoev.ru return match;
437964Sigor@sysoev.ru }
438964Sigor@sysoev.ru
439964Sigor@sysoev.ru nxt_memzero(&mtcf, sizeof(mtcf));
440964Sigor@sysoev.ru
441964Sigor@sysoev.ru ret = nxt_conf_map_object(tmcf->mem_pool,
442964Sigor@sysoev.ru match_conf, nxt_http_route_match_conf,
443964Sigor@sysoev.ru nxt_nitems(nxt_http_route_match_conf), &mtcf);
444964Sigor@sysoev.ru if (ret != NXT_OK) {
445964Sigor@sysoev.ru return NULL;
446964Sigor@sysoev.ru }
447964Sigor@sysoev.ru
4481059Sigor@sysoev.ru test = &match->test[0];
449964Sigor@sysoev.ru
4501110Saxel.duch@nginx.com if (mtcf.scheme != NULL) {
4511110Saxel.duch@nginx.com rule = nxt_http_route_rule_create(task, mp, mtcf.scheme, 1,
4521474Saxel.duch@nginx.com NXT_HTTP_ROUTE_PATTERN_NOCASE,
4532123Sz.hong@f5.com NXT_HTTP_URI_ENCODING_NONE);
4541110Saxel.duch@nginx.com if (rule == NULL) {
4551110Saxel.duch@nginx.com return NULL;
4561110Saxel.duch@nginx.com }
4571110Saxel.duch@nginx.com
4581110Saxel.duch@nginx.com rule->object = NXT_HTTP_ROUTE_SCHEME;
4591110Saxel.duch@nginx.com test->rule = rule;
4601110Saxel.duch@nginx.com test++;
4611110Saxel.duch@nginx.com }
4621110Saxel.duch@nginx.com
463964Sigor@sysoev.ru if (mtcf.host != NULL) {
4641059Sigor@sysoev.ru rule = nxt_http_route_rule_create(task, mp, mtcf.host, 1,
4651474Saxel.duch@nginx.com NXT_HTTP_ROUTE_PATTERN_LOWCASE,
4662123Sz.hong@f5.com NXT_HTTP_URI_ENCODING_NONE);
467964Sigor@sysoev.ru if (rule == NULL) {
468964Sigor@sysoev.ru return NULL;
469964Sigor@sysoev.ru }
470964Sigor@sysoev.ru
4711059Sigor@sysoev.ru rule->u.offset = offsetof(nxt_http_request_t, host);
472964Sigor@sysoev.ru rule->object = NXT_HTTP_ROUTE_STRING;
4731059Sigor@sysoev.ru test->rule = rule;
4741059Sigor@sysoev.ru test++;
475964Sigor@sysoev.ru }
476964Sigor@sysoev.ru
477964Sigor@sysoev.ru if (mtcf.uri != NULL) {
4781059Sigor@sysoev.ru rule = nxt_http_route_rule_create(task, mp, mtcf.uri, 1,
4791474Saxel.duch@nginx.com NXT_HTTP_ROUTE_PATTERN_NOCASE,
4802123Sz.hong@f5.com NXT_HTTP_URI_ENCODING);
481964Sigor@sysoev.ru if (rule == NULL) {
482964Sigor@sysoev.ru return NULL;
483964Sigor@sysoev.ru }
484964Sigor@sysoev.ru
4851059Sigor@sysoev.ru rule->u.offset = offsetof(nxt_http_request_t, path);
486964Sigor@sysoev.ru rule->object = NXT_HTTP_ROUTE_STRING_PTR;
4871059Sigor@sysoev.ru test->rule = rule;
4881059Sigor@sysoev.ru test++;
489964Sigor@sysoev.ru }
490964Sigor@sysoev.ru
491964Sigor@sysoev.ru if (mtcf.method != NULL) {
4921059Sigor@sysoev.ru rule = nxt_http_route_rule_create(task, mp, mtcf.method, 1,
4931474Saxel.duch@nginx.com NXT_HTTP_ROUTE_PATTERN_UPCASE,
4942123Sz.hong@f5.com NXT_HTTP_URI_ENCODING_NONE);
495964Sigor@sysoev.ru if (rule == NULL) {
496964Sigor@sysoev.ru return NULL;
497964Sigor@sysoev.ru }
498964Sigor@sysoev.ru
4991059Sigor@sysoev.ru rule->u.offset = offsetof(nxt_http_request_t, method);
500964Sigor@sysoev.ru rule->object = NXT_HTTP_ROUTE_STRING_PTR;
5011059Sigor@sysoev.ru test->rule = rule;
5021059Sigor@sysoev.ru test++;
5031059Sigor@sysoev.ru }
5041059Sigor@sysoev.ru
5051059Sigor@sysoev.ru if (mtcf.headers != NULL) {
5061061Sigor@sysoev.ru table = nxt_http_route_table_create(task, mp, mtcf.headers,
5071474Saxel.duch@nginx.com NXT_HTTP_ROUTE_HEADER, 0,
5082123Sz.hong@f5.com NXT_HTTP_URI_ENCODING_NONE);
5091061Sigor@sysoev.ru if (table == NULL) {
5101061Sigor@sysoev.ru return NULL;
5111061Sigor@sysoev.ru }
5121061Sigor@sysoev.ru
5131061Sigor@sysoev.ru test->table = table;
5141061Sigor@sysoev.ru test++;
5151061Sigor@sysoev.ru }
5161061Sigor@sysoev.ru
5171061Sigor@sysoev.ru if (mtcf.arguments != NULL) {
5181061Sigor@sysoev.ru table = nxt_http_route_table_create(task, mp, mtcf.arguments,
5191474Saxel.duch@nginx.com NXT_HTTP_ROUTE_ARGUMENT, 1,
5202123Sz.hong@f5.com NXT_HTTP_URI_ENCODING_PLUS);
5211059Sigor@sysoev.ru if (table == NULL) {
5221059Sigor@sysoev.ru return NULL;
5231059Sigor@sysoev.ru }
5241059Sigor@sysoev.ru
5251059Sigor@sysoev.ru test->table = table;
5261059Sigor@sysoev.ru test++;
527964Sigor@sysoev.ru }
528964Sigor@sysoev.ru
5291062Sigor@sysoev.ru if (mtcf.cookies != NULL) {
5301062Sigor@sysoev.ru table = nxt_http_route_table_create(task, mp, mtcf.cookies,
5311474Saxel.duch@nginx.com NXT_HTTP_ROUTE_COOKIE, 1,
5322123Sz.hong@f5.com NXT_HTTP_URI_ENCODING_NONE);
5331062Sigor@sysoev.ru if (table == NULL) {
5341062Sigor@sysoev.ru return NULL;
5351062Sigor@sysoev.ru }
5361062Sigor@sysoev.ru
5371062Sigor@sysoev.ru test->table = table;
5381062Sigor@sysoev.ru test++;
5391062Sigor@sysoev.ru }
5401062Sigor@sysoev.ru
5411991Sz.hong@f5.com if (mtcf.query != NULL) {
5421991Sz.hong@f5.com rule = nxt_http_route_rule_create(task, mp, mtcf.query, 1,
5431991Sz.hong@f5.com NXT_HTTP_ROUTE_PATTERN_NOCASE,
5442123Sz.hong@f5.com NXT_HTTP_URI_ENCODING_PLUS);
5451991Sz.hong@f5.com if (rule == NULL) {
5461991Sz.hong@f5.com return NULL;
5471991Sz.hong@f5.com }
5481991Sz.hong@f5.com
5491991Sz.hong@f5.com rule->object = NXT_HTTP_ROUTE_QUERY;
5501991Sz.hong@f5.com test->rule = rule;
5511991Sz.hong@f5.com test++;
5521991Sz.hong@f5.com }
5531991Sz.hong@f5.com
5541324Saxel.duch@nginx.com if (mtcf.source != NULL) {
5551324Saxel.duch@nginx.com addr_rule = nxt_http_route_addr_rule_create(task, mp, mtcf.source);
5561324Saxel.duch@nginx.com if (addr_rule == NULL) {
5571324Saxel.duch@nginx.com return NULL;
5581324Saxel.duch@nginx.com }
5591324Saxel.duch@nginx.com
5601324Saxel.duch@nginx.com addr_rule->object = NXT_HTTP_ROUTE_SOURCE;
5611324Saxel.duch@nginx.com test->addr_rule = addr_rule;
5621324Saxel.duch@nginx.com test++;
5631324Saxel.duch@nginx.com }
5641324Saxel.duch@nginx.com
5651326Saxel.duch@nginx.com if (mtcf.destination != NULL) {
5661326Saxel.duch@nginx.com addr_rule = nxt_http_route_addr_rule_create(task, mp, mtcf.destination);
5671326Saxel.duch@nginx.com if (addr_rule == NULL) {
5681326Saxel.duch@nginx.com return NULL;
5691326Saxel.duch@nginx.com }
5701326Saxel.duch@nginx.com
5711326Saxel.duch@nginx.com addr_rule->object = NXT_HTTP_ROUTE_DESTINATION;
5721326Saxel.duch@nginx.com test->addr_rule = addr_rule;
5731326Saxel.duch@nginx.com test++;
5741326Saxel.duch@nginx.com }
5751326Saxel.duch@nginx.com
576964Sigor@sysoev.ru return match;
577964Sigor@sysoev.ru }
578964Sigor@sysoev.ru
579964Sigor@sysoev.ru
5801264Sigor@sysoev.ru static nxt_conf_map_t nxt_http_route_action_conf[] = {
5811264Sigor@sysoev.ru {
5821264Sigor@sysoev.ru nxt_string("pass"),
5831264Sigor@sysoev.ru NXT_CONF_MAP_PTR,
5841903Sz.hong@f5.com offsetof(nxt_http_action_conf_t, pass)
5851264Sigor@sysoev.ru },
5861264Sigor@sysoev.ru {
5871429Svbart@nginx.com nxt_string("return"),
5881429Svbart@nginx.com NXT_CONF_MAP_PTR,
5891903Sz.hong@f5.com offsetof(nxt_http_action_conf_t, ret)
5901429Svbart@nginx.com },
5911429Svbart@nginx.com {
5921432Svbart@nginx.com nxt_string("location"),
5932098Salx.manpages@gmail.com NXT_CONF_MAP_PTR,
5941903Sz.hong@f5.com offsetof(nxt_http_action_conf_t, location)
5951432Svbart@nginx.com },
5961432Svbart@nginx.com {
5971854Sz.hong@f5.com nxt_string("proxy"),
5981854Sz.hong@f5.com NXT_CONF_MAP_PTR,
5991903Sz.hong@f5.com offsetof(nxt_http_action_conf_t, proxy)
6001854Sz.hong@f5.com },
6011854Sz.hong@f5.com {
6021264Sigor@sysoev.ru nxt_string("share"),
6031264Sigor@sysoev.ru NXT_CONF_MAP_PTR,
6041903Sz.hong@f5.com offsetof(nxt_http_action_conf_t, share)
6051264Sigor@sysoev.ru },
6061270Sigor@sysoev.ru {
6072108Salx.manpages@gmail.com nxt_string("index"),
6082108Salx.manpages@gmail.com NXT_CONF_MAP_PTR,
6092108Salx.manpages@gmail.com offsetof(nxt_http_action_conf_t, index)
6102108Salx.manpages@gmail.com },
6112108Salx.manpages@gmail.com {
6121855Sz.hong@f5.com nxt_string("chroot"),
6131855Sz.hong@f5.com NXT_CONF_MAP_STR,
6141903Sz.hong@f5.com offsetof(nxt_http_action_conf_t, chroot)
6151855Sz.hong@f5.com },
6161855Sz.hong@f5.com {
6171855Sz.hong@f5.com nxt_string("follow_symlinks"),
6181855Sz.hong@f5.com NXT_CONF_MAP_PTR,
6191903Sz.hong@f5.com offsetof(nxt_http_action_conf_t, follow_symlinks)
6201855Sz.hong@f5.com },
6211855Sz.hong@f5.com {
6221855Sz.hong@f5.com nxt_string("traverse_mounts"),
6231855Sz.hong@f5.com NXT_CONF_MAP_PTR,
6241903Sz.hong@f5.com offsetof(nxt_http_action_conf_t, traverse_mounts)
6251855Sz.hong@f5.com },
6261855Sz.hong@f5.com {
6271859So.canty@f5.com nxt_string("types"),
6281859So.canty@f5.com NXT_CONF_MAP_PTR,
6291903Sz.hong@f5.com offsetof(nxt_http_action_conf_t, types)
6301859So.canty@f5.com },
6311859So.canty@f5.com {
6321378Svbart@nginx.com nxt_string("fallback"),
6331378Svbart@nginx.com NXT_CONF_MAP_PTR,
6341903Sz.hong@f5.com offsetof(nxt_http_action_conf_t, fallback)
6351378Svbart@nginx.com },
6361264Sigor@sysoev.ru };
6371264Sigor@sysoev.ru
6381264Sigor@sysoev.ru
6391923Sz.hong@f5.com nxt_int_t
nxt_http_action_init(nxt_task_t * task,nxt_router_temp_conf_t * tmcf,nxt_conf_value_t * cv,nxt_http_action_t * action)6401903Sz.hong@f5.com nxt_http_action_init(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
6411859So.canty@f5.com nxt_conf_value_t *cv, nxt_http_action_t *action)
6421264Sigor@sysoev.ru {
6431903Sz.hong@f5.com nxt_mp_t *mp;
6441903Sz.hong@f5.com nxt_int_t ret;
6451954Sz.hong@f5.com nxt_str_t pass;
6461903Sz.hong@f5.com nxt_http_action_conf_t acf;
6471903Sz.hong@f5.com
6481903Sz.hong@f5.com nxt_memzero(&acf, sizeof(acf));
6491264Sigor@sysoev.ru
6501378Svbart@nginx.com ret = nxt_conf_map_object(tmcf->mem_pool, cv, nxt_http_route_action_conf,
6511903Sz.hong@f5.com nxt_nitems(nxt_http_route_action_conf), &acf);
6521264Sigor@sysoev.ru if (ret != NXT_OK) {
6531264Sigor@sysoev.ru return ret;
6541264Sigor@sysoev.ru }
6551264Sigor@sysoev.ru
6561428Svbart@nginx.com nxt_memzero(action, sizeof(nxt_http_action_t));
6571428Svbart@nginx.com
6581432Svbart@nginx.com mp = tmcf->router_conf->mem_pool;
6591432Svbart@nginx.com
6601903Sz.hong@f5.com if (acf.ret != NULL) {
6611903Sz.hong@f5.com return nxt_http_return_init(mp, action, &acf);
6621429Svbart@nginx.com }
6631429Svbart@nginx.com
6641903Sz.hong@f5.com if (acf.share != NULL) {
6651923Sz.hong@f5.com return nxt_http_static_init(task, tmcf, action, &acf);
6661923Sz.hong@f5.com }
6671923Sz.hong@f5.com
6681923Sz.hong@f5.com if (acf.proxy != NULL) {
6691924Sz.hong@f5.com return nxt_http_proxy_init(mp, action, &acf);
6701264Sigor@sysoev.ru }
6711264Sigor@sysoev.ru
6721954Sz.hong@f5.com nxt_conf_get_string(acf.pass, &pass);
6731954Sz.hong@f5.com
6741959Sz.hong@f5.com action->u.var = nxt_var_compile(&pass, mp, 0);
6751954Sz.hong@f5.com if (nxt_slow_path(action->u.var == NULL)) {
6761264Sigor@sysoev.ru return NXT_ERROR;
6771264Sigor@sysoev.ru }
6781264Sigor@sysoev.ru
6791264Sigor@sysoev.ru return NXT_OK;
6801264Sigor@sysoev.ru }
6811264Sigor@sysoev.ru
6821264Sigor@sysoev.ru
6831059Sigor@sysoev.ru static nxt_http_route_table_t *
nxt_http_route_table_create(nxt_task_t * task,nxt_mp_t * mp,nxt_conf_value_t * table_cv,nxt_http_route_object_t object,nxt_bool_t case_sensitive,nxt_http_uri_encoding_t encoding)6841059Sigor@sysoev.ru nxt_http_route_table_create(nxt_task_t *task, nxt_mp_t *mp,
6851061Sigor@sysoev.ru nxt_conf_value_t *table_cv, nxt_http_route_object_t object,
6862123Sz.hong@f5.com nxt_bool_t case_sensitive, nxt_http_uri_encoding_t encoding)
6871059Sigor@sysoev.ru {
6881059Sigor@sysoev.ru size_t size;
6891059Sigor@sysoev.ru uint32_t i, n;
6901059Sigor@sysoev.ru nxt_conf_value_t *ruleset_cv;
6911059Sigor@sysoev.ru nxt_http_route_table_t *table;
6921059Sigor@sysoev.ru nxt_http_route_ruleset_t *ruleset;
6931059Sigor@sysoev.ru
6942077Salx.manpages@gmail.com n = nxt_conf_array_elements_count_or_1(table_cv);
6951059Sigor@sysoev.ru size = sizeof(nxt_http_route_table_t)
6961059Sigor@sysoev.ru + n * sizeof(nxt_http_route_ruleset_t *);
6971059Sigor@sysoev.ru
6981059Sigor@sysoev.ru table = nxt_mp_alloc(mp, size);
6991059Sigor@sysoev.ru if (nxt_slow_path(table == NULL)) {
7001059Sigor@sysoev.ru return NULL;
7011059Sigor@sysoev.ru }
7021059Sigor@sysoev.ru
7031059Sigor@sysoev.ru table->items = n;
7041059Sigor@sysoev.ru table->object = NXT_HTTP_ROUTE_TABLE;
7051059Sigor@sysoev.ru
7061059Sigor@sysoev.ru for (i = 0; i < n; i++) {
7072077Salx.manpages@gmail.com ruleset_cv = nxt_conf_get_array_element_or_itself(table_cv, i);
7081059Sigor@sysoev.ru
7091474Saxel.duch@nginx.com ruleset = nxt_http_route_ruleset_create(task, mp, ruleset_cv, object,
7101474Saxel.duch@nginx.com case_sensitive, encoding);
7111059Sigor@sysoev.ru if (nxt_slow_path(ruleset == NULL)) {
7121059Sigor@sysoev.ru return NULL;
7131059Sigor@sysoev.ru }
7141059Sigor@sysoev.ru
7151059Sigor@sysoev.ru table->ruleset[i] = ruleset;
7161059Sigor@sysoev.ru }
7171059Sigor@sysoev.ru
7181059Sigor@sysoev.ru return table;
7191059Sigor@sysoev.ru }
7201059Sigor@sysoev.ru
7211059Sigor@sysoev.ru
7221059Sigor@sysoev.ru static nxt_http_route_ruleset_t *
nxt_http_route_ruleset_create(nxt_task_t * task,nxt_mp_t * mp,nxt_conf_value_t * ruleset_cv,nxt_http_route_object_t object,nxt_bool_t case_sensitive,nxt_http_uri_encoding_t encoding)7231059Sigor@sysoev.ru nxt_http_route_ruleset_create(nxt_task_t *task, nxt_mp_t *mp,
7241061Sigor@sysoev.ru nxt_conf_value_t *ruleset_cv, nxt_http_route_object_t object,
7252123Sz.hong@f5.com nxt_bool_t case_sensitive, nxt_http_uri_encoding_t encoding)
7261059Sigor@sysoev.ru {
7271059Sigor@sysoev.ru size_t size;
7281059Sigor@sysoev.ru uint32_t i, n, next;
7291059Sigor@sysoev.ru nxt_str_t name;
7301059Sigor@sysoev.ru nxt_conf_value_t *rule_cv;
7311059Sigor@sysoev.ru nxt_http_route_rule_t *rule;
7321059Sigor@sysoev.ru nxt_http_route_ruleset_t *ruleset;
7331059Sigor@sysoev.ru
7341059Sigor@sysoev.ru n = nxt_conf_object_members_count(ruleset_cv);
7351059Sigor@sysoev.ru size = sizeof(nxt_http_route_ruleset_t)
7361059Sigor@sysoev.ru + n * sizeof(nxt_http_route_rule_t *);
7371059Sigor@sysoev.ru
7381059Sigor@sysoev.ru ruleset = nxt_mp_alloc(mp, size);
7391059Sigor@sysoev.ru if (nxt_slow_path(ruleset == NULL)) {
7401059Sigor@sysoev.ru return NULL;
7411059Sigor@sysoev.ru }
7421059Sigor@sysoev.ru
7431059Sigor@sysoev.ru ruleset->items = n;
7441059Sigor@sysoev.ru
7451059Sigor@sysoev.ru next = 0;
7461059Sigor@sysoev.ru
7471785Svbart@nginx.com /*
7481785Svbart@nginx.com * A workaround for GCC 10 with -flto -O2 flags that warns about "name"
7491785Svbart@nginx.com * may be uninitialized in nxt_http_route_rule_name_create().
7501785Svbart@nginx.com */
7511785Svbart@nginx.com nxt_str_null(&name);
7521785Svbart@nginx.com
7531059Sigor@sysoev.ru for (i = 0; i < n; i++) {
7541059Sigor@sysoev.ru rule_cv = nxt_conf_next_object_member(ruleset_cv, &name, &next);
7551059Sigor@sysoev.ru
7561061Sigor@sysoev.ru rule = nxt_http_route_rule_name_create(task, mp, rule_cv, &name,
7571474Saxel.duch@nginx.com case_sensitive, encoding);
7581059Sigor@sysoev.ru if (nxt_slow_path(rule == NULL)) {
7591059Sigor@sysoev.ru return NULL;
7601059Sigor@sysoev.ru }
7611059Sigor@sysoev.ru
7621061Sigor@sysoev.ru rule->object = object;
7631059Sigor@sysoev.ru ruleset->rule[i] = rule;
7641059Sigor@sysoev.ru }
7651059Sigor@sysoev.ru
7661059Sigor@sysoev.ru return ruleset;
7671059Sigor@sysoev.ru }
7681059Sigor@sysoev.ru
7691059Sigor@sysoev.ru
770964Sigor@sysoev.ru static nxt_http_route_rule_t *
nxt_http_route_rule_name_create(nxt_task_t * task,nxt_mp_t * mp,nxt_conf_value_t * rule_cv,nxt_str_t * name,nxt_bool_t case_sensitive,nxt_http_uri_encoding_t encoding)7711061Sigor@sysoev.ru nxt_http_route_rule_name_create(nxt_task_t *task, nxt_mp_t *mp,
7721474Saxel.duch@nginx.com nxt_conf_value_t *rule_cv, nxt_str_t *name, nxt_bool_t case_sensitive,
7732123Sz.hong@f5.com nxt_http_uri_encoding_t encoding)
7741059Sigor@sysoev.ru {
7752123Sz.hong@f5.com int64_t hash;
7761059Sigor@sysoev.ru nxt_http_route_rule_t *rule;
7771059Sigor@sysoev.ru
7781061Sigor@sysoev.ru rule = nxt_http_route_rule_create(task, mp, rule_cv, case_sensitive,
7791474Saxel.duch@nginx.com NXT_HTTP_ROUTE_PATTERN_NOCASE,
7801474Saxel.duch@nginx.com encoding);
7811059Sigor@sysoev.ru if (nxt_slow_path(rule == NULL)) {
7821059Sigor@sysoev.ru return NULL;
7831059Sigor@sysoev.ru }
7841059Sigor@sysoev.ru
7852123Sz.hong@f5.com hash = nxt_http_field_hash(mp, name, case_sensitive, encoding);
7862123Sz.hong@f5.com if (nxt_slow_path(hash == -1)) {
7871059Sigor@sysoev.ru return NULL;
7881059Sigor@sysoev.ru }
7891059Sigor@sysoev.ru
7902123Sz.hong@f5.com rule->u.name.hash = hash;
7912123Sz.hong@f5.com rule->u.name.start = name->start;
7922123Sz.hong@f5.com rule->u.name.length = name->length;
7931059Sigor@sysoev.ru
7941059Sigor@sysoev.ru return rule;
7951059Sigor@sysoev.ru }
7961059Sigor@sysoev.ru
7971059Sigor@sysoev.ru
7981059Sigor@sysoev.ru static nxt_http_route_rule_t *
nxt_http_route_rule_create(nxt_task_t * task,nxt_mp_t * mp,nxt_conf_value_t * cv,nxt_bool_t case_sensitive,nxt_http_route_pattern_case_t pattern_case,nxt_http_uri_encoding_t encoding)7991059Sigor@sysoev.ru nxt_http_route_rule_create(nxt_task_t *task, nxt_mp_t *mp,
800964Sigor@sysoev.ru nxt_conf_value_t *cv, nxt_bool_t case_sensitive,
8011474Saxel.duch@nginx.com nxt_http_route_pattern_case_t pattern_case,
8022123Sz.hong@f5.com nxt_http_uri_encoding_t encoding)
803964Sigor@sysoev.ru {
804964Sigor@sysoev.ru size_t size;
805964Sigor@sysoev.ru uint32_t i, n;
806964Sigor@sysoev.ru nxt_int_t ret;
807964Sigor@sysoev.ru nxt_conf_value_t *value;
808964Sigor@sysoev.ru nxt_http_route_rule_t *rule;
809964Sigor@sysoev.ru nxt_http_route_pattern_t *pattern;
810964Sigor@sysoev.ru
8112077Salx.manpages@gmail.com n = nxt_conf_array_elements_count_or_1(cv);
812964Sigor@sysoev.ru size = sizeof(nxt_http_route_rule_t) + n * sizeof(nxt_http_route_pattern_t);
813964Sigor@sysoev.ru
814964Sigor@sysoev.ru rule = nxt_mp_alloc(mp, size);
815964Sigor@sysoev.ru if (nxt_slow_path(rule == NULL)) {
816964Sigor@sysoev.ru return NULL;
817964Sigor@sysoev.ru }
818964Sigor@sysoev.ru
819964Sigor@sysoev.ru rule->items = n;
820964Sigor@sysoev.ru
821964Sigor@sysoev.ru pattern = &rule->pattern[0];
822964Sigor@sysoev.ru
823964Sigor@sysoev.ru nxt_conf_array_qsort(cv, nxt_http_pattern_compare);
824964Sigor@sysoev.ru
825964Sigor@sysoev.ru for (i = 0; i < n; i++) {
826964Sigor@sysoev.ru pattern[i].case_sensitive = case_sensitive;
8272077Salx.manpages@gmail.com value = nxt_conf_get_array_element_or_itself(cv, i);
828964Sigor@sysoev.ru
829964Sigor@sysoev.ru ret = nxt_http_route_pattern_create(task, mp, value, &pattern[i],
8301474Saxel.duch@nginx.com pattern_case, encoding);
831964Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) {
832964Sigor@sysoev.ru return NULL;
833964Sigor@sysoev.ru }
834964Sigor@sysoev.ru }
835964Sigor@sysoev.ru
836964Sigor@sysoev.ru return rule;
837964Sigor@sysoev.ru }
838964Sigor@sysoev.ru
839964Sigor@sysoev.ru
8401936So.canty@f5.com nxt_http_route_addr_rule_t *
nxt_http_route_addr_rule_create(nxt_task_t * task,nxt_mp_t * mp,nxt_conf_value_t * cv)8411324Saxel.duch@nginx.com nxt_http_route_addr_rule_create(nxt_task_t *task, nxt_mp_t *mp,
8422078Salx.manpages@gmail.com nxt_conf_value_t *cv)
8431324Saxel.duch@nginx.com {
8441324Saxel.duch@nginx.com size_t size;
8451324Saxel.duch@nginx.com uint32_t i, n;
8461324Saxel.duch@nginx.com nxt_conf_value_t *value;
8471324Saxel.duch@nginx.com nxt_http_route_addr_rule_t *addr_rule;
8481324Saxel.duch@nginx.com nxt_http_route_addr_pattern_t *pattern;
8491324Saxel.duch@nginx.com
8502077Salx.manpages@gmail.com n = nxt_conf_array_elements_count_or_1(cv);
8511324Saxel.duch@nginx.com
8521324Saxel.duch@nginx.com size = sizeof(nxt_http_route_addr_rule_t)
8531324Saxel.duch@nginx.com + n * sizeof(nxt_http_route_addr_pattern_t);
8541324Saxel.duch@nginx.com
8551324Saxel.duch@nginx.com addr_rule = nxt_mp_alloc(mp, size);
8561324Saxel.duch@nginx.com if (nxt_slow_path(addr_rule == NULL)) {
8571324Saxel.duch@nginx.com return NULL;
8581324Saxel.duch@nginx.com }
8591324Saxel.duch@nginx.com
8601324Saxel.duch@nginx.com addr_rule->items = n;
8611324Saxel.duch@nginx.com
8621324Saxel.duch@nginx.com for (i = 0; i < n; i++) {
8631324Saxel.duch@nginx.com pattern = &addr_rule->addr_pattern[i];
8642077Salx.manpages@gmail.com value = nxt_conf_get_array_element_or_itself(cv, i);
8651324Saxel.duch@nginx.com
8661324Saxel.duch@nginx.com if (nxt_http_route_addr_pattern_parse(mp, pattern, value) != NXT_OK) {
8671324Saxel.duch@nginx.com return NULL;
8681324Saxel.duch@nginx.com }
8691324Saxel.duch@nginx.com }
8701324Saxel.duch@nginx.com
8711390Saxel.duch@nginx.com if (n > 1) {
8721390Saxel.duch@nginx.com nxt_qsort(addr_rule->addr_pattern, addr_rule->items,
8731390Saxel.duch@nginx.com sizeof(nxt_http_route_addr_pattern_t),
8741390Saxel.duch@nginx.com nxt_http_addr_pattern_compare);
8751390Saxel.duch@nginx.com }
8761390Saxel.duch@nginx.com
8771324Saxel.duch@nginx.com return addr_rule;
8781324Saxel.duch@nginx.com }
8791324Saxel.duch@nginx.com
8801324Saxel.duch@nginx.com
8811923Sz.hong@f5.com nxt_http_route_rule_t *
nxt_http_route_types_rule_create(nxt_task_t * task,nxt_mp_t * mp,nxt_conf_value_t * types)8821923Sz.hong@f5.com nxt_http_route_types_rule_create(nxt_task_t *task, nxt_mp_t *mp,
8831923Sz.hong@f5.com nxt_conf_value_t *types)
8841923Sz.hong@f5.com {
8851923Sz.hong@f5.com return nxt_http_route_rule_create(task, mp, types, 0,
8861923Sz.hong@f5.com NXT_HTTP_ROUTE_PATTERN_LOWCASE,
8872123Sz.hong@f5.com NXT_HTTP_URI_ENCODING_NONE);
8881923Sz.hong@f5.com }
8891923Sz.hong@f5.com
8901923Sz.hong@f5.com
891964Sigor@sysoev.ru static int
nxt_http_pattern_compare(const void * one,const void * two)892964Sigor@sysoev.ru nxt_http_pattern_compare(const void *one, const void *two)
893964Sigor@sysoev.ru {
894964Sigor@sysoev.ru nxt_str_t test;
895964Sigor@sysoev.ru nxt_bool_t negative1, negative2;
896964Sigor@sysoev.ru nxt_conf_value_t *value;
897964Sigor@sysoev.ru
898964Sigor@sysoev.ru value = (nxt_conf_value_t *) one;
899964Sigor@sysoev.ru nxt_conf_get_string(value, &test);
900964Sigor@sysoev.ru negative1 = (test.length != 0 && test.start[0] == '!');
901964Sigor@sysoev.ru
902964Sigor@sysoev.ru value = (nxt_conf_value_t *) two;
903964Sigor@sysoev.ru nxt_conf_get_string(value, &test);
904964Sigor@sysoev.ru negative2 = (test.length != 0 && test.start[0] == '!');
905964Sigor@sysoev.ru
906964Sigor@sysoev.ru return (negative2 - negative1);
907964Sigor@sysoev.ru }
908964Sigor@sysoev.ru
909964Sigor@sysoev.ru
9101390Saxel.duch@nginx.com static int
nxt_http_addr_pattern_compare(const void * one,const void * two)9111390Saxel.duch@nginx.com nxt_http_addr_pattern_compare(const void *one, const void *two)
9121390Saxel.duch@nginx.com {
9131390Saxel.duch@nginx.com const nxt_http_route_addr_pattern_t *p1, *p2;
9141390Saxel.duch@nginx.com
9151390Saxel.duch@nginx.com p1 = one;
9161390Saxel.duch@nginx.com p2 = two;
9171390Saxel.duch@nginx.com
9181390Saxel.duch@nginx.com return (p2->base.negative - p1->base.negative);
9191390Saxel.duch@nginx.com }
9201390Saxel.duch@nginx.com
9211390Saxel.duch@nginx.com
922964Sigor@sysoev.ru static nxt_int_t
nxt_http_route_pattern_create(nxt_task_t * task,nxt_mp_t * mp,nxt_conf_value_t * cv,nxt_http_route_pattern_t * pattern,nxt_http_route_pattern_case_t pattern_case,nxt_http_uri_encoding_t encoding)923964Sigor@sysoev.ru nxt_http_route_pattern_create(nxt_task_t *task, nxt_mp_t *mp,
924964Sigor@sysoev.ru nxt_conf_value_t *cv, nxt_http_route_pattern_t *pattern,
9251474Saxel.duch@nginx.com nxt_http_route_pattern_case_t pattern_case,
9262123Sz.hong@f5.com nxt_http_uri_encoding_t encoding)
927964Sigor@sysoev.ru {
9281508Saxel.duch@nginx.com u_char c, *p, *end;
9291508Saxel.duch@nginx.com nxt_str_t test, tmp;
9301508Saxel.duch@nginx.com nxt_int_t ret;
9311508Saxel.duch@nginx.com nxt_array_t *slices;
9321721Saxel.duch@nginx.com #if (NXT_HAVE_REGEX)
9331721Saxel.duch@nginx.com nxt_regex_t *re;
9341721Saxel.duch@nginx.com nxt_regex_err_t err;
9351721Saxel.duch@nginx.com #endif
9361508Saxel.duch@nginx.com nxt_http_route_pattern_type_t type;
9371508Saxel.duch@nginx.com nxt_http_route_pattern_slice_t *slice;
938964Sigor@sysoev.ru
939964Sigor@sysoev.ru type = NXT_HTTP_ROUTE_PATTERN_EXACT;
940964Sigor@sysoev.ru
941964Sigor@sysoev.ru nxt_conf_get_string(cv, &test);
942964Sigor@sysoev.ru
9431721Saxel.duch@nginx.com pattern->u.pattern_slices = NULL;
944964Sigor@sysoev.ru pattern->negative = 0;
945964Sigor@sysoev.ru pattern->any = 1;
9461474Saxel.duch@nginx.com pattern->min_length = 0;
9471721Saxel.duch@nginx.com #if (NXT_HAVE_REGEX)
9481721Saxel.duch@nginx.com pattern->regex = 0;
9491721Saxel.duch@nginx.com #endif
950964Sigor@sysoev.ru
9511508Saxel.duch@nginx.com if (test.length != 0 && test.start[0] == '!') {
9521508Saxel.duch@nginx.com test.start++;
9531508Saxel.duch@nginx.com test.length--;
9541508Saxel.duch@nginx.com
9551508Saxel.duch@nginx.com pattern->negative = 1;
9561508Saxel.duch@nginx.com pattern->any = 0;
9571508Saxel.duch@nginx.com }
9581508Saxel.duch@nginx.com
9591721Saxel.duch@nginx.com if (test.length > 0 && test.start[0] == '~') {
9601721Saxel.duch@nginx.com #if (NXT_HAVE_REGEX)
9611721Saxel.duch@nginx.com test.start++;
9621721Saxel.duch@nginx.com test.length--;
9631721Saxel.duch@nginx.com
9641721Saxel.duch@nginx.com re = nxt_regex_compile(mp, &test, &err);
9651721Saxel.duch@nginx.com if (nxt_slow_path(re == NULL)) {
9661721Saxel.duch@nginx.com if (err.offset < test.length) {
9671721Saxel.duch@nginx.com nxt_alert(task, "nxt_regex_compile(%V) failed: %s at offset %d",
9681721Saxel.duch@nginx.com &test, err.msg, (int) err.offset);
9691721Saxel.duch@nginx.com return NXT_ERROR;
9701721Saxel.duch@nginx.com }
9711721Saxel.duch@nginx.com
9721721Saxel.duch@nginx.com nxt_alert(task, "nxt_regex_compile(%V) failed %s", &test, err.msg);
9731721Saxel.duch@nginx.com
9741721Saxel.duch@nginx.com return NXT_ERROR;
9751721Saxel.duch@nginx.com }
9761721Saxel.duch@nginx.com
9771721Saxel.duch@nginx.com pattern->u.regex = re;
9781721Saxel.duch@nginx.com pattern->regex = 1;
9791721Saxel.duch@nginx.com
9801721Saxel.duch@nginx.com return NXT_OK;
9811721Saxel.duch@nginx.com
9821721Saxel.duch@nginx.com #else
9831721Saxel.duch@nginx.com return NXT_ERROR;
9841721Saxel.duch@nginx.com #endif
9851721Saxel.duch@nginx.com }
9861721Saxel.duch@nginx.com
9871721Saxel.duch@nginx.com slices = nxt_array_create(mp, 1, sizeof(nxt_http_route_pattern_slice_t));
9881721Saxel.duch@nginx.com if (nxt_slow_path(slices == NULL)) {
9891721Saxel.duch@nginx.com return NXT_ERROR;
9901721Saxel.duch@nginx.com }
9911721Saxel.duch@nginx.com
9921721Saxel.duch@nginx.com pattern->u.pattern_slices = slices;
9931721Saxel.duch@nginx.com
9941508Saxel.duch@nginx.com if (test.length == 0) {
9951508Saxel.duch@nginx.com slice = nxt_array_add(slices);
9961508Saxel.duch@nginx.com if (nxt_slow_path(slice == NULL)) {
9971508Saxel.duch@nginx.com return NXT_ERROR;
998964Sigor@sysoev.ru }
999964Sigor@sysoev.ru
10001508Saxel.duch@nginx.com slice->type = NXT_HTTP_ROUTE_PATTERN_EXACT;
10011508Saxel.duch@nginx.com slice->start = NULL;
10021508Saxel.duch@nginx.com slice->length = 0;
10031508Saxel.duch@nginx.com
10041508Saxel.duch@nginx.com return NXT_OK;
10051508Saxel.duch@nginx.com }
10061508Saxel.duch@nginx.com
10071508Saxel.duch@nginx.com if (test.start[0] == '*') {
10081508Saxel.duch@nginx.com /* 'type' is no longer 'EXACT', assume 'END'. */
10091508Saxel.duch@nginx.com type = NXT_HTTP_ROUTE_PATTERN_END;
10101508