xref: /unit/src/nxt_http_route.c (revision 2743:3aeba568771b)
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);
1962246Sz.hong@f5.com static void nxt_http_pass_query_ready(nxt_task_t *task, void *obj, void *data);
1972246Sz.hong@f5.com static void nxt_http_pass_query_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     {
5822448Sz.hong@f5.com         nxt_string("rewrite"),
5832448Sz.hong@f5.com         NXT_CONF_MAP_PTR,
5842448Sz.hong@f5.com         offsetof(nxt_http_action_conf_t, rewrite)
5852448Sz.hong@f5.com     },
5862448Sz.hong@f5.com     {
5872512Sz.hong@f5.com         nxt_string("response_headers"),
5882512Sz.hong@f5.com         NXT_CONF_MAP_PTR,
5892512Sz.hong@f5.com         offsetof(nxt_http_action_conf_t, set_headers)
5902512Sz.hong@f5.com     },
5912512Sz.hong@f5.com     {
5921264Sigor@sysoev.ru         nxt_string("pass"),
5931264Sigor@sysoev.ru         NXT_CONF_MAP_PTR,
5941903Sz.hong@f5.com         offsetof(nxt_http_action_conf_t, pass)
5951264Sigor@sysoev.ru     },
5961264Sigor@sysoev.ru     {
5971429Svbart@nginx.com         nxt_string("return"),
5981429Svbart@nginx.com         NXT_CONF_MAP_PTR,
5991903Sz.hong@f5.com         offsetof(nxt_http_action_conf_t, ret)
6001429Svbart@nginx.com     },
6011429Svbart@nginx.com     {
6021432Svbart@nginx.com         nxt_string("location"),
6032098Salx.manpages@gmail.com         NXT_CONF_MAP_PTR,
6041903Sz.hong@f5.com         offsetof(nxt_http_action_conf_t, location)
6051432Svbart@nginx.com     },
6061432Svbart@nginx.com     {
6071854Sz.hong@f5.com         nxt_string("proxy"),
6081854Sz.hong@f5.com         NXT_CONF_MAP_PTR,
6091903Sz.hong@f5.com         offsetof(nxt_http_action_conf_t, proxy)
6101854Sz.hong@f5.com     },
6111854Sz.hong@f5.com     {
6121264Sigor@sysoev.ru         nxt_string("share"),
6131264Sigor@sysoev.ru         NXT_CONF_MAP_PTR,
6141903Sz.hong@f5.com         offsetof(nxt_http_action_conf_t, share)
6151264Sigor@sysoev.ru     },
6161270Sigor@sysoev.ru     {
6172108Salx.manpages@gmail.com         nxt_string("index"),
6182108Salx.manpages@gmail.com         NXT_CONF_MAP_PTR,
6192108Salx.manpages@gmail.com         offsetof(nxt_http_action_conf_t, index)
6202108Salx.manpages@gmail.com     },
6212108Salx.manpages@gmail.com     {
6221855Sz.hong@f5.com         nxt_string("chroot"),
6231855Sz.hong@f5.com         NXT_CONF_MAP_STR,
6241903Sz.hong@f5.com         offsetof(nxt_http_action_conf_t, chroot)
6251855Sz.hong@f5.com     },
6261855Sz.hong@f5.com     {
6271855Sz.hong@f5.com         nxt_string("follow_symlinks"),
6281855Sz.hong@f5.com         NXT_CONF_MAP_PTR,
6291903Sz.hong@f5.com         offsetof(nxt_http_action_conf_t, follow_symlinks)
6301855Sz.hong@f5.com     },
6311855Sz.hong@f5.com     {
6321855Sz.hong@f5.com         nxt_string("traverse_mounts"),
6331855Sz.hong@f5.com         NXT_CONF_MAP_PTR,
6341903Sz.hong@f5.com         offsetof(nxt_http_action_conf_t, traverse_mounts)
6351855Sz.hong@f5.com     },
6361855Sz.hong@f5.com     {
6371859So.canty@f5.com         nxt_string("types"),
6381859So.canty@f5.com         NXT_CONF_MAP_PTR,
6391903Sz.hong@f5.com         offsetof(nxt_http_action_conf_t, types)
6401859So.canty@f5.com     },
6411859So.canty@f5.com     {
6421378Svbart@nginx.com         nxt_string("fallback"),
6431378Svbart@nginx.com         NXT_CONF_MAP_PTR,
6441903Sz.hong@f5.com         offsetof(nxt_http_action_conf_t, fallback)
6451378Svbart@nginx.com     },
6461264Sigor@sysoev.ru };
6471264Sigor@sysoev.ru 
6481264Sigor@sysoev.ru 
6491923Sz.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)6501903Sz.hong@f5.com nxt_http_action_init(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
6511859So.canty@f5.com     nxt_conf_value_t *cv, nxt_http_action_t *action)
6521264Sigor@sysoev.ru {
6531903Sz.hong@f5.com     nxt_mp_t                *mp;
6541903Sz.hong@f5.com     nxt_int_t               ret;
6551954Sz.hong@f5.com     nxt_str_t               pass;
6562147Sz.hong@f5.com     nxt_router_conf_t       *rtcf;
6571903Sz.hong@f5.com     nxt_http_action_conf_t  acf;
6581903Sz.hong@f5.com 
6591903Sz.hong@f5.com     nxt_memzero(&acf, sizeof(acf));
6601264Sigor@sysoev.ru 
6611378Svbart@nginx.com     ret = nxt_conf_map_object(tmcf->mem_pool, cv, nxt_http_route_action_conf,
6621903Sz.hong@f5.com                               nxt_nitems(nxt_http_route_action_conf), &acf);
6631264Sigor@sysoev.ru     if (ret != NXT_OK) {
6641264Sigor@sysoev.ru         return ret;
6651264Sigor@sysoev.ru     }
6661264Sigor@sysoev.ru 
6671428Svbart@nginx.com     nxt_memzero(action, sizeof(nxt_http_action_t));
6681428Svbart@nginx.com 
6692147Sz.hong@f5.com     rtcf = tmcf->router_conf;
6702147Sz.hong@f5.com     mp = rtcf->mem_pool;
6711432Svbart@nginx.com 
6722448Sz.hong@f5.com     if (acf.rewrite != NULL) {
6732448Sz.hong@f5.com         ret = nxt_http_rewrite_init(rtcf, action, &acf);
6742448Sz.hong@f5.com         if (nxt_slow_path(ret != NXT_OK)) {
6752448Sz.hong@f5.com             return ret;
6762448Sz.hong@f5.com         }
6772448Sz.hong@f5.com     }
6782448Sz.hong@f5.com 
6792512Sz.hong@f5.com     if (acf.set_headers != NULL) {
6802512Sz.hong@f5.com         ret = nxt_http_set_headers_init(rtcf, action, &acf);
6812512Sz.hong@f5.com         if (nxt_slow_path(ret != NXT_OK)) {
6822512Sz.hong@f5.com             return ret;
6832512Sz.hong@f5.com         }
6842512Sz.hong@f5.com     }
6852512Sz.hong@f5.com 
6861903Sz.hong@f5.com     if (acf.ret != NULL) {
6872147Sz.hong@f5.com         return nxt_http_return_init(rtcf, action, &acf);
6881429Svbart@nginx.com     }
6891429Svbart@nginx.com 
6901903Sz.hong@f5.com     if (acf.share != NULL) {
6911923Sz.hong@f5.com         return nxt_http_static_init(task, tmcf, action, &acf);
6921923Sz.hong@f5.com     }
6931923Sz.hong@f5.com 
6941923Sz.hong@f5.com     if (acf.proxy != NULL) {
6951924Sz.hong@f5.com         return nxt_http_proxy_init(mp, action, &acf);
6961264Sigor@sysoev.ru     }
6971264Sigor@sysoev.ru 
6981954Sz.hong@f5.com     nxt_conf_get_string(acf.pass, &pass);
6991954Sz.hong@f5.com 
7002246Sz.hong@f5.com     action->u.tstr = nxt_tstr_compile(rtcf->tstr_state, &pass, 0);
7012246Sz.hong@f5.com     if (nxt_slow_path(action->u.tstr == NULL)) {
7021264Sigor@sysoev.ru         return NXT_ERROR;
7031264Sigor@sysoev.ru     }
7041264Sigor@sysoev.ru 
7051264Sigor@sysoev.ru     return NXT_OK;
7061264Sigor@sysoev.ru }
7071264Sigor@sysoev.ru 
7081264Sigor@sysoev.ru 
7091059Sigor@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)7101059Sigor@sysoev.ru nxt_http_route_table_create(nxt_task_t *task, nxt_mp_t *mp,
7111061Sigor@sysoev.ru     nxt_conf_value_t *table_cv, nxt_http_route_object_t object,
7122123Sz.hong@f5.com     nxt_bool_t case_sensitive, nxt_http_uri_encoding_t encoding)
7131059Sigor@sysoev.ru {
7141059Sigor@sysoev.ru     size_t                    size;
7151059Sigor@sysoev.ru     uint32_t                  i, n;
7161059Sigor@sysoev.ru     nxt_conf_value_t          *ruleset_cv;
7171059Sigor@sysoev.ru     nxt_http_route_table_t    *table;
7181059Sigor@sysoev.ru     nxt_http_route_ruleset_t  *ruleset;
7191059Sigor@sysoev.ru 
7202077Salx.manpages@gmail.com     n = nxt_conf_array_elements_count_or_1(table_cv);
7211059Sigor@sysoev.ru     size = sizeof(nxt_http_route_table_t)
7221059Sigor@sysoev.ru            + n * sizeof(nxt_http_route_ruleset_t *);
7231059Sigor@sysoev.ru 
7241059Sigor@sysoev.ru     table = nxt_mp_alloc(mp, size);
7251059Sigor@sysoev.ru     if (nxt_slow_path(table == NULL)) {
7261059Sigor@sysoev.ru         return NULL;
7271059Sigor@sysoev.ru     }
7281059Sigor@sysoev.ru 
7291059Sigor@sysoev.ru     table->items = n;
7301059Sigor@sysoev.ru     table->object = NXT_HTTP_ROUTE_TABLE;
7311059Sigor@sysoev.ru 
7321059Sigor@sysoev.ru     for (i = 0; i < n; i++) {
7332077Salx.manpages@gmail.com         ruleset_cv = nxt_conf_get_array_element_or_itself(table_cv, i);
7341059Sigor@sysoev.ru 
7351474Saxel.duch@nginx.com         ruleset = nxt_http_route_ruleset_create(task, mp, ruleset_cv, object,
7361474Saxel.duch@nginx.com                                                 case_sensitive, encoding);
7371059Sigor@sysoev.ru         if (nxt_slow_path(ruleset == NULL)) {
7381059Sigor@sysoev.ru             return NULL;
7391059Sigor@sysoev.ru         }
7401059Sigor@sysoev.ru 
7411059Sigor@sysoev.ru         table->ruleset[i] = ruleset;
7421059Sigor@sysoev.ru     }
7431059Sigor@sysoev.ru 
7441059Sigor@sysoev.ru     return table;
7451059Sigor@sysoev.ru }
7461059Sigor@sysoev.ru 
7471059Sigor@sysoev.ru 
7481059Sigor@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)7491059Sigor@sysoev.ru nxt_http_route_ruleset_create(nxt_task_t *task, nxt_mp_t *mp,
7501061Sigor@sysoev.ru     nxt_conf_value_t *ruleset_cv, nxt_http_route_object_t object,
7512123Sz.hong@f5.com     nxt_bool_t case_sensitive, nxt_http_uri_encoding_t encoding)
7521059Sigor@sysoev.ru {
7531059Sigor@sysoev.ru     size_t                    size;
7541059Sigor@sysoev.ru     uint32_t                  i, n, next;
7551059Sigor@sysoev.ru     nxt_str_t                 name;
7561059Sigor@sysoev.ru     nxt_conf_value_t          *rule_cv;
7571059Sigor@sysoev.ru     nxt_http_route_rule_t     *rule;
7581059Sigor@sysoev.ru     nxt_http_route_ruleset_t  *ruleset;
7591059Sigor@sysoev.ru 
7601059Sigor@sysoev.ru     n = nxt_conf_object_members_count(ruleset_cv);
7611059Sigor@sysoev.ru     size = sizeof(nxt_http_route_ruleset_t)
7621059Sigor@sysoev.ru            + n * sizeof(nxt_http_route_rule_t *);
7631059Sigor@sysoev.ru 
7641059Sigor@sysoev.ru     ruleset = nxt_mp_alloc(mp, size);
7651059Sigor@sysoev.ru     if (nxt_slow_path(ruleset == NULL)) {
7661059Sigor@sysoev.ru         return NULL;
7671059Sigor@sysoev.ru     }
7681059Sigor@sysoev.ru 
7691059Sigor@sysoev.ru     ruleset->items = n;
7701059Sigor@sysoev.ru 
7711059Sigor@sysoev.ru     next = 0;
7721059Sigor@sysoev.ru 
7731785Svbart@nginx.com     /*
7741785Svbart@nginx.com      * A workaround for GCC 10 with -flto -O2 flags that warns about "name"
7751785Svbart@nginx.com      * may be uninitialized in nxt_http_route_rule_name_create().
7761785Svbart@nginx.com      */
7771785Svbart@nginx.com     nxt_str_null(&name);
7781785Svbart@nginx.com 
7791059Sigor@sysoev.ru     for (i = 0; i < n; i++) {
7801059Sigor@sysoev.ru         rule_cv = nxt_conf_next_object_member(ruleset_cv, &name, &next);
7811059Sigor@sysoev.ru 
7821061Sigor@sysoev.ru         rule = nxt_http_route_rule_name_create(task, mp, rule_cv, &name,
7831474Saxel.duch@nginx.com                                                case_sensitive, encoding);
7841059Sigor@sysoev.ru         if (nxt_slow_path(rule == NULL)) {
7851059Sigor@sysoev.ru             return NULL;
7861059Sigor@sysoev.ru         }
7871059Sigor@sysoev.ru 
7881061Sigor@sysoev.ru         rule->object = object;
7891059Sigor@sysoev.ru         ruleset->rule[i] = rule;
7901059Sigor@sysoev.ru     }
7911059Sigor@sysoev.ru 
7921059Sigor@sysoev.ru     return ruleset;
7931059Sigor@sysoev.ru }
7941059Sigor@sysoev.ru 
7951059Sigor@sysoev.ru 
796964Sigor@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)7971061Sigor@sysoev.ru nxt_http_route_rule_name_create(nxt_task_t *task, nxt_mp_t *mp,
7981474Saxel.duch@nginx.com     nxt_conf_value_t *rule_cv, nxt_str_t *name, nxt_bool_t case_sensitive,
7992123Sz.hong@f5.com     nxt_http_uri_encoding_t encoding)
8001059Sigor@sysoev.ru {
8012123Sz.hong@f5.com     int64_t                hash;
8021059Sigor@sysoev.ru     nxt_http_route_rule_t  *rule;
8031059Sigor@sysoev.ru 
8041061Sigor@sysoev.ru     rule = nxt_http_route_rule_create(task, mp, rule_cv, case_sensitive,
8051474Saxel.duch@nginx.com                                       NXT_HTTP_ROUTE_PATTERN_NOCASE,
8061474Saxel.duch@nginx.com                                       encoding);
8071059Sigor@sysoev.ru     if (nxt_slow_path(rule == NULL)) {
8081059Sigor@sysoev.ru         return NULL;
8091059Sigor@sysoev.ru     }
8101059Sigor@sysoev.ru 
8112123Sz.hong@f5.com     hash = nxt_http_field_hash(mp, name, case_sensitive, encoding);
8122123Sz.hong@f5.com     if (nxt_slow_path(hash == -1)) {
8131059Sigor@sysoev.ru         return NULL;
8141059Sigor@sysoev.ru     }
8151059Sigor@sysoev.ru 
8162123Sz.hong@f5.com     rule->u.name.hash = hash;
8172123Sz.hong@f5.com     rule->u.name.start = name->start;
8182123Sz.hong@f5.com     rule->u.name.length = name->length;
8191059Sigor@sysoev.ru 
8201059Sigor@sysoev.ru     return rule;
8211059Sigor@sysoev.ru }
8221059Sigor@sysoev.ru 
8231059Sigor@sysoev.ru 
8241059Sigor@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)8251059Sigor@sysoev.ru nxt_http_route_rule_create(nxt_task_t *task, nxt_mp_t *mp,
826964Sigor@sysoev.ru     nxt_conf_value_t *cv, nxt_bool_t case_sensitive,
8271474Saxel.duch@nginx.com     nxt_http_route_pattern_case_t pattern_case,
8282123Sz.hong@f5.com     nxt_http_uri_encoding_t encoding)
829964Sigor@sysoev.ru {
830964Sigor@sysoev.ru     size_t                    size;
831964Sigor@sysoev.ru     uint32_t                  i, n;
832964Sigor@sysoev.ru     nxt_int_t                 ret;
833964Sigor@sysoev.ru     nxt_conf_value_t          *value;
834964Sigor@sysoev.ru     nxt_http_route_rule_t     *rule;
835964Sigor@sysoev.ru     nxt_http_route_pattern_t  *pattern;
836964Sigor@sysoev.ru 
8372077Salx.manpages@gmail.com     n = nxt_conf_array_elements_count_or_1(cv);
838964Sigor@sysoev.ru     size = sizeof(nxt_http_route_rule_t) + n * sizeof(nxt_http_route_pattern_t);
839964Sigor@sysoev.ru 
840964Sigor@sysoev.ru     rule = nxt_mp_alloc(mp, size);
841964Sigor@sysoev.ru     if (nxt_slow_path(rule == NULL)) {
842964Sigor@sysoev.ru         return NULL;
843964Sigor@sysoev.ru     }
844964Sigor@sysoev.ru 
845964Sigor@sysoev.ru     rule->items = n;
846964Sigor@sysoev.ru 
847964Sigor@sysoev.ru     pattern = &rule->pattern[0];
848964Sigor@sysoev.ru 
849964Sigor@sysoev.ru     nxt_conf_array_qsort(cv, nxt_http_pattern_compare);
850964Sigor@sysoev.ru 
851964Sigor@sysoev.ru     for (i = 0; i < n; i++) {
852964Sigor@sysoev.ru         pattern[i].case_sensitive = case_sensitive;
8532077Salx.manpages@gmail.com         value = nxt_conf_get_array_element_or_itself(cv, i);
854964Sigor@sysoev.ru 
855964Sigor@sysoev.ru         ret = nxt_http_route_pattern_create(task, mp, value, &pattern[i],
8561474Saxel.duch@nginx.com                                             pattern_case, encoding);
857964Sigor@sysoev.ru         if (nxt_slow_path(ret != NXT_OK)) {
858964Sigor@sysoev.ru             return NULL;
859964Sigor@sysoev.ru         }
860964Sigor@sysoev.ru     }
861964Sigor@sysoev.ru 
862964Sigor@sysoev.ru     return rule;
863964Sigor@sysoev.ru }
864964Sigor@sysoev.ru 
865964Sigor@sysoev.ru 
8661936So.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)8671324Saxel.duch@nginx.com nxt_http_route_addr_rule_create(nxt_task_t *task, nxt_mp_t *mp,
8682078Salx.manpages@gmail.com     nxt_conf_value_t *cv)
8691324Saxel.duch@nginx.com {
8701324Saxel.duch@nginx.com     size_t                         size;
8711324Saxel.duch@nginx.com     uint32_t                       i, n;
8721324Saxel.duch@nginx.com     nxt_conf_value_t               *value;
8731324Saxel.duch@nginx.com     nxt_http_route_addr_rule_t     *addr_rule;
8741324Saxel.duch@nginx.com     nxt_http_route_addr_pattern_t  *pattern;
8751324Saxel.duch@nginx.com 
8762077Salx.manpages@gmail.com     n = nxt_conf_array_elements_count_or_1(cv);
8771324Saxel.duch@nginx.com 
8781324Saxel.duch@nginx.com     size = sizeof(nxt_http_route_addr_rule_t)
8791324Saxel.duch@nginx.com            + n * sizeof(nxt_http_route_addr_pattern_t);
8801324Saxel.duch@nginx.com 
8811324Saxel.duch@nginx.com     addr_rule = nxt_mp_alloc(mp, size);
8821324Saxel.duch@nginx.com     if (nxt_slow_path(addr_rule == NULL)) {
8831324Saxel.duch@nginx.com         return NULL;
8841324Saxel.duch@nginx.com     }
8851324Saxel.duch@nginx.com 
8861324Saxel.duch@nginx.com     addr_rule->items = n;
8871324Saxel.duch@nginx.com 
8881324Saxel.duch@nginx.com     for (i = 0; i < n; i++) {
8891324Saxel.duch@nginx.com         pattern = &addr_rule->addr_pattern[i];
8902077Salx.manpages@gmail.com         value = nxt_conf_get_array_element_or_itself(cv, i);
8911324Saxel.duch@nginx.com 
8921324Saxel.duch@nginx.com         if (nxt_http_route_addr_pattern_parse(mp, pattern, value) != NXT_OK) {
8931324Saxel.duch@nginx.com             return NULL;
8941324Saxel.duch@nginx.com         }
8951324Saxel.duch@nginx.com     }
8961324Saxel.duch@nginx.com 
8971390Saxel.duch@nginx.com     if (n > 1) {
8981390Saxel.duch@nginx.com         nxt_qsort(addr_rule->addr_pattern, addr_rule->items,
8991390Saxel.duch@nginx.com             sizeof(nxt_http_route_addr_pattern_t),
9001390Saxel.duch@nginx.com             nxt_http_addr_pattern_compare);
9011390Saxel.duch@nginx.com     }
9021390Saxel.duch@nginx.com 
9031324Saxel.duch@nginx.com     return addr_rule;
9041324Saxel.duch@nginx.com }
9051324Saxel.duch@nginx.com 
9061324Saxel.duch@nginx.com 
9071923Sz.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)9081923Sz.hong@f5.com nxt_http_route_types_rule_create(nxt_task_t *task, nxt_mp_t *mp,
9091923Sz.hong@f5.com     nxt_conf_value_t *types)
9101923Sz.hong@f5.com {
9111923Sz.hong@f5.com     return nxt_http_route_rule_create(task, mp, types, 0,
9121923Sz.hong@f5.com                                       NXT_HTTP_ROUTE_PATTERN_LOWCASE,
9132123Sz.hong@f5.com                                       NXT_HTTP_URI_ENCODING_NONE);
9141923Sz.hong@f5.com }
9151923Sz.hong@f5.com 
9161923Sz.hong@f5.com 
917964Sigor@sysoev.ru static int
nxt_http_pattern_compare(const void * one,const void * two)918964Sigor@sysoev.ru nxt_http_pattern_compare(const void *one, const void *two)
919964Sigor@sysoev.ru {
920964Sigor@sysoev.ru     nxt_str_t         test;
921964Sigor@sysoev.ru     nxt_bool_t        negative1, negative2;
922964Sigor@sysoev.ru     nxt_conf_value_t  *value;
923964Sigor@sysoev.ru 
924964Sigor@sysoev.ru     value = (nxt_conf_value_t *) one;
925964Sigor@sysoev.ru     nxt_conf_get_string(value, &test);
926964Sigor@sysoev.ru     negative1 = (test.length != 0 && test.start[0] == '!');
927964Sigor@sysoev.ru 
928964Sigor@sysoev.ru     value = (nxt_conf_value_t *) two;
929964Sigor@sysoev.ru     nxt_conf_get_string(value, &test);
930964Sigor@sysoev.ru     negative2 = (test.length != 0 && test.start[0] == '!');
931964Sigor@sysoev.ru 
932964Sigor@sysoev.ru     return (negative2 - negative1);
933964Sigor@sysoev.ru }
934964Sigor@sysoev.ru 
935964Sigor@sysoev.ru 
9361390Saxel.duch@nginx.com static int
nxt_http_addr_pattern_compare(const void * one,const void * two)9371390Saxel.duch@nginx.com nxt_http_addr_pattern_compare(const void *one, const void *two)
9381390Saxel.duch@nginx.com {
9391390Saxel.duch@nginx.com     const nxt_http_route_addr_pattern_t  *p1, *p2;
9401390Saxel.duch@nginx.com 
9411390Saxel.duch@nginx.com     p1 = one;
9421390Saxel.duch@nginx.com     p2 = two;
9431390Saxel.duch@nginx.com 
9441390Saxel.duch@nginx.com     return (p2->base.negative - p1->base.negative);
9451390Saxel.duch@nginx.com }
9461390Saxel.duch@nginx.com 
9471390Saxel.duch@nginx.com 
948964Sigor@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)949964Sigor@sysoev.ru nxt_http_route_pattern_create(nxt_task_t *task, nxt_mp_t *mp,
950964Sigor@sysoev.ru     nxt_conf_value_t *cv, nxt_http_route_pattern_t *pattern,
9511474Saxel.duch@nginx.com     nxt_http_route_pattern_case_t pattern_case,
9522123Sz.hong@f5.com     nxt_http_uri_encoding_t encoding)
953964Sigor@sysoev.ru {
9541508Saxel.duch@nginx.com     u_char                          c, *p, *end;
9551508Saxel.duch@nginx.com     nxt_str_t                       test, tmp;
9561508Saxel.duch@nginx.com     nxt_int_t                       ret;
9571508Saxel.duch@nginx.com     nxt_array_t                     *slices;
9581721Saxel.duch@nginx.com #if (NXT_HAVE_REGEX)
9591721Saxel.duch@nginx.com     nxt_regex_t                     *re;
9601721Saxel.duch@nginx.com     nxt_regex_err_t                 err;
9611721Saxel.duch@nginx.com #endif
9621508Saxel.duch@nginx.com     nxt_http_route_pattern_type_t   type;
9631508Saxel.duch@nginx.com     nxt_http_route_pattern_slice_t  *slice;
964964Sigor@sysoev.ru 
965964Sigor@sysoev.ru     type = NXT_HTTP_ROUTE_PATTERN_EXACT;
966964Sigor@sysoev.ru 
967964Sigor@sysoev.ru     nxt_conf_get_string(cv, &test);
968964Sigor@sysoev.ru 
9691721Saxel.duch@nginx.com     pattern->u.pattern_slices = NULL;
970964Sigor@sysoev.ru     pattern->negative = 0;
971964Sigor@sysoev.ru     pattern->any = 1;
9721474Saxel.duch@nginx.com     pattern->min_length = 0;
9731721Saxel.duch@nginx.com #if (NXT_HAVE_REGEX)
9741721Saxel.duch@nginx.com     pattern->regex = 0;
9751721Saxel.duch@nginx.com #endif
976964Sigor@sysoev.ru 
9771508Saxel.duch@nginx.com     if (test.length != 0 && test.start[0] == '!') {
9781508Saxel.duch@nginx.com         test.start++;
9791508Saxel.duch@nginx.com         test.length--;
9801508Saxel.duch@nginx.com 
9811508Saxel.duch@nginx.com         pattern->negative = 1;
9821508Saxel.duch@nginx.com         pattern->any = 0;
9831508Saxel.duch@nginx.com     }
9841508Saxel.duch@nginx.com 
9851721Saxel.duch@nginx.com     if (test.length > 0 && test.start[0] == '~') {
9861721Saxel.duch@nginx.com #if (NXT_HAVE_REGEX)
9871721Saxel.duch@nginx.com         test.start++;
9881721Saxel.duch@nginx.com         test.length--;
9891721Saxel.duch@nginx.com 
9901721Saxel.duch@nginx.com         re = nxt_regex_compile(mp, &test, &err);
9911721Saxel.duch@nginx.com         if (nxt_slow_path(re == NULL)) {
9921721Saxel.duch@nginx.com             if (err.offset < test.length) {
9931721Saxel.duch@nginx.com                 nxt_alert(task, "nxt_regex_compile(%V) failed: %s at offset %d",
9941721Saxel.duch@nginx.com                           &test, err.msg, (int) err.offset);
9951721Saxel.duch@nginx.com                 return NXT_ERROR;
9961721Saxel.duch@nginx.com             }
9971721Saxel.duch@nginx.com 
9981721Saxel.duch@nginx.com             nxt_alert(task, "nxt_regex_compile(%V) failed %s", &test, err.msg);
9991721Saxel.duch@nginx.com 
10001721Saxel.duch@nginx.com             return NXT_ERROR;
10011721Saxel.duch@nginx.com         }
10021721Saxel.duch@nginx.com 
10031721Saxel.duch@nginx.com         pattern->u.regex = re;
10041721Saxel.duch@nginx.com         pattern->regex = 1;
10051721Saxel.duch@nginx.com 
10061721Saxel.duch@nginx.com         return NXT_OK;
10071721Saxel.duch@nginx.com 
10081721Saxel.duch@nginx.com #else
10091721Saxel.duch@nginx.com         return NXT_ERROR;
10101721Saxel.duch@nginx.com #endif
10111721Saxel.duch@nginx.com     }
10121721Saxel.duch@nginx.com 
10131721Saxel.duch@nginx.com     slices = nxt_array_create(mp, 1, sizeof(nxt_http_route_pattern_slice_t));
10141721Saxel.duch@nginx.com     if (nxt_slow_path(slices == NULL)) {
10151721Saxel.duch@nginx.com         return NXT_ERROR;
10161721Saxel.duch@nginx.com     }
10171721Saxel.duch@nginx.com 
10181721Saxel.duch@nginx.com     pattern->u.pattern_slices = slices;
10191721Saxel.duch@nginx.com 
10201508Saxel.duch@nginx.com     if (test.length == 0) {
10211508Saxel.duch@nginx.com         slice = nxt_array_add(slices);
10221508Saxel.duch@nginx.com         if (nxt_slow_path(slice == NULL)) {
10231508Saxel.duch@nginx.com             return NXT_ERROR;
1024964Sigor@sysoev.ru         }
1025964Sigor@sysoev.ru 
10261508Saxel.duch@nginx.com         slice->type = NXT_HTTP_ROUTE_PATTERN_EXACT;
10271508Saxel.duch@nginx.com         slice->start = NULL;
10281508Saxel.duch@nginx.com         slice->length = 0;
10291508Saxel.duch@nginx.com 
10301508Saxel.duch@nginx.com         return NXT_OK;
10311508Saxel.duch@nginx.com     }
10321508Saxel.duch@nginx.com 
10331508Saxel.duch@nginx.com     if (test.start[0] == '*') {
10341508Saxel.duch@nginx.com         /* 'type' is no longer 'EXACT', assume 'END'. */
10351508Saxel.duch@nginx.com         type = NXT_HTTP_ROUTE_PATTERN_END;
10361508Saxel.duch@nginx.com         test.start++;
10371508Saxel.duch@nginx.com         test.length--;
10381508Saxel.duch@nginx.com     }
10391508Saxel.duch@nginx.com 
10401522Saxel.duch@nginx.com     if (type == NXT_HTTP_ROUTE_PATTERN_EXACT) {
10411508Saxel.duch@nginx.com         tmp.start = test.start;
10421508Saxel.duch@nginx.com 
10432232Salx@nginx.com         p = memchr(test.start, '*', test.length);
10441508Saxel.duch@nginx.com 
10451508Saxel.duch@nginx.com         if (p == NULL) {
10461508Saxel.duch@nginx.com             /* No '*' found - EXACT pattern. */
10471508Saxel.duch@nginx.com             tmp.length = test.length;
10481508Saxel.duch@nginx.com             type = NXT_HTTP_ROUTE_PATTERN_EXACT;
10491508Saxel.duch@nginx.com 
10501508Saxel.duch@nginx.com             test.start += test.length;
10511508Saxel.duch@nginx.com             test.length = 0;
10521508Saxel.duch@nginx.com 
10531508Saxel.duch@nginx.com         } else {
10541508Saxel.duch@nginx.com             /* '*' found - BEGIN pattern. */
10551508Saxel.duch@nginx.com             tmp.length = p - test.start;
10561508Saxel.duch@nginx.com             type = NXT_HTTP_ROUTE_PATTERN_BEGIN;
10571508Saxel.duch@nginx.com 
10581508Saxel.duch@nginx.com             test.start = p + 1;
10591508Saxel.duch@nginx.com             test.length -= tmp.length + 1;
10601508Saxel.duch@nginx.com         }
10611508Saxel.duch@nginx.com 
10621508Saxel.duch@nginx.com         ret = nxt_http_route_pattern_slice(slices, &tmp, type, encoding,
10631508Saxel.duch@nginx.com                                            pattern_case);
10641508Saxel.duch@nginx.com         if (nxt_slow_path(ret != NXT_OK)) {
10651508Saxel.duch@nginx.com             return ret;
10661508Saxel.duch@nginx.com         }
10671508Saxel.duch@nginx.com 
10681508Saxel.duch@nginx.com         pattern->min_length += tmp.length;
10691508Saxel.duch@nginx.com     }
10701508Saxel.duch@nginx.com 
10711508Saxel.duch@nginx.com     end = test.start + test.length;
10721508Saxel.duch@nginx.com 
10731508Saxel.duch@nginx.com     if (test.length != 0 && end[-1] != '*') {
10741508Saxel.duch@nginx.com         p = end - 1;
10751508Saxel.duch@nginx.com 
10761508Saxel.duch@nginx.com         while (p != test.start) {
10771508Saxel.duch@nginx.com             c = *p--;
10781508Saxel.duch@nginx.com 
10791508Saxel.duch@nginx.com             if (c == '*') {
10801508Saxel.duch@nginx.com                 p += 2;
10811508Saxel.duch@nginx.com                 break;
10821474Saxel.duch@nginx.com             }
1083964Sigor@sysoev.ru         }
10841508Saxel.duch@nginx.com 
10851508Saxel.duch@nginx.com         tmp.start = p;
10861508Saxel.duch@nginx.com         tmp.length = end - p;
10871508Saxel.duch@nginx.com 
10881508Saxel.duch@nginx.com         test.length -= tmp.length;
10891508Saxel.duch@nginx.com         end = p;
10901508Saxel.duch@nginx.com 
10911508Saxel.duch@nginx.com         ret = nxt_http_route_pattern_slice(slices, &tmp,
10921508Saxel.duch@nginx.com                                            NXT_HTTP_ROUTE_PATTERN_END,
10931508Saxel.duch@nginx.com                                            encoding, pattern_case);
10941508Saxel.duch@nginx.com         if (nxt_slow_path(ret != NXT_OK)) {
10951508Saxel.duch@nginx.com             return ret;
10961508Saxel.duch@nginx.com         }
10971508Saxel.duch@nginx.com 
10981508Saxel.duch@nginx.com         pattern->min_length += tmp.length;
1099964Sigor@sysoev.ru     }
1100964Sigor@sysoev.ru 
11011508Saxel.duch@nginx.com     tmp.start = test.start;
11021508Saxel.duch@nginx.com     tmp.length = 0;
11031508Saxel.duch@nginx.com 
11041508Saxel.duch@nginx.com     p = tmp.start;
11051508Saxel.duch@nginx.com 
11061508Saxel.duch@nginx.com     while (p != end) {
11071508Saxel.duch@nginx.com         c = *p++;
11081508Saxel.duch@nginx.com 
11091508Saxel.duch@nginx.com         if (c != '*') {
11101508Saxel.duch@nginx.com             tmp.length++;
11111508Saxel.duch@nginx.com             continue;
11121508Saxel.duch@nginx.com         }
11131508Saxel.duch@nginx.com 
11141508Saxel.duch@nginx.com         if (tmp.length == 0) {
11151508Saxel.duch@nginx.com             tmp.start = p;
11161508Saxel.duch@nginx.com             continue;
11171508Saxel.duch@nginx.com         }
11181508Saxel.duch@nginx.com 
11191508Saxel.duch@nginx.com         ret = nxt_http_route_pattern_slice(slices, &tmp,
11201508Saxel.duch@nginx.com                                            NXT_HTTP_ROUTE_PATTERN_SUBSTRING,
11211508Saxel.duch@nginx.com                                            encoding, pattern_case);
11221508Saxel.duch@nginx.com         if (nxt_slow_path(ret != NXT_OK)) {
11231508Saxel.duch@nginx.com             return ret;
11241508Saxel.duch@nginx.com         }
11251508Saxel.duch@nginx.com 
11261508Saxel.duch@nginx.com         pattern->min_length += tmp.length;
11271508Saxel.duch@nginx.com 
11281508Saxel.duch@nginx.com         tmp.start = p;
11291508Saxel.duch@nginx.com         tmp.length = 0;
1130964Sigor@sysoev.ru     }
1131964Sigor@sysoev.ru 
11321508Saxel.duch@nginx.com     if (tmp.length != 0) {
11331508Saxel.duch@nginx.com         ret = nxt_http_route_pattern_slice(slices, &tmp,
11341508Saxel.duch@nginx.com                                            NXT_HTTP_ROUTE_PATTERN_SUBSTRING,
11351508Saxel.duch@nginx.com                                            encoding, pattern_case);
11361508Saxel.duch@nginx.com         if (nxt_slow_path(ret != NXT_OK)) {
11371508Saxel.duch@nginx.com             return ret;
11381508Saxel.duch@nginx.com         }
11391508Saxel.duch@nginx.com 
11401508Saxel.duch@nginx.com         pattern->min_length += tmp.length;
11411508Saxel.duch@nginx.com     }
11421032Sigor@sysoev.ru 
11431474Saxel.duch@nginx.com     return NXT_OK;
11441474Saxel.duch@nginx.com }
11451474Saxel.duch@nginx.com 
11461474Saxel.duch@nginx.com 
11471474Saxel.duch@nginx.com static nxt_int_t
nxt_http_route_decode_str(nxt_str_t * str,nxt_http_uri_encoding_t encoding)11482123Sz.hong@f5.com nxt_http_route_decode_str(nxt_str_t *str, nxt_http_uri_encoding_t encoding)
11491474Saxel.duch@nginx.com {
11501474Saxel.duch@nginx.com     u_char  *start, *end;
11511474Saxel.duch@nginx.com 
11521474Saxel.duch@nginx.com     switch (encoding) {
11532123Sz.hong@f5.com     case NXT_HTTP_URI_ENCODING_NONE:
11541474Saxel.duch@nginx.com         break;
11551474Saxel.duch@nginx.com 
11562123Sz.hong@f5.com     case NXT_HTTP_URI_ENCODING:
11571474Saxel.duch@nginx.com         start = str->start;
11581474Saxel.duch@nginx.com 
11591474Saxel.duch@nginx.com         end = nxt_decode_uri(start, start, str->length);
11601474Saxel.duch@nginx.com         if (nxt_slow_path(end == NULL)) {
11611032Sigor@sysoev.ru             return NXT_ERROR;
11621032Sigor@sysoev.ru         }
11631032Sigor@sysoev.ru 
11641474Saxel.duch@nginx.com         str->length = end - start;
11651474Saxel.duch@nginx.com         break;
11661474Saxel.duch@nginx.com 
11672123Sz.hong@f5.com     case NXT_HTTP_URI_ENCODING_PLUS:
11681474Saxel.duch@nginx.com         start = str->start;
11691474Saxel.duch@nginx.com 
11701474Saxel.duch@nginx.com         end = nxt_decode_uri_plus(start, start, str->length);
11711474Saxel.duch@nginx.com         if (nxt_slow_path(end == NULL)) {
11721474Saxel.duch@nginx.com             return NXT_ERROR;
11731474Saxel.duch@nginx.com         }
11741474Saxel.duch@nginx.com 
11751474Saxel.duch@nginx.com         str->length = end - start;
11761474Saxel.duch@nginx.com         break;
11771474Saxel.duch@nginx.com 
11781474Saxel.duch@nginx.com     default:
11791474Saxel.duch@nginx.com         nxt_unreachable();
11801032Sigor@sysoev.ru     }
11811032Sigor@sysoev.ru 
11821032Sigor@sysoev.ru     return NXT_OK;
11831032Sigor@sysoev.ru }
11841032Sigor@sysoev.ru 
11851032Sigor@sysoev.ru 
11861508Saxel.duch@nginx.com static nxt_int_t
nxt_http_route_pattern_slice(nxt_array_t * slices,nxt_str_t * test,nxt_http_route_pattern_type_t type,nxt_http_uri_encoding_t encoding,nxt_http_route_pattern_case_t pattern_case)11871508Saxel.duch@nginx.com nxt_http_route_pattern_slice(nxt_array_t *slices,
11882123Sz.hong@f5.com     nxt_str_t *test, nxt_http_route_pattern_type_t type,
11892123Sz.hong@f5.com     nxt_http_uri_encoding_t encoding,
11901032Sigor@sysoev.ru     nxt_http_route_pattern_case_t pattern_case)
11911032Sigor@sysoev.ru {
11921508Saxel.duch@nginx.com     u_char                          *start;
11931508Saxel.duch@nginx.com     nxt_int_t                       ret;
11941508Saxel.duch@nginx.com     nxt_http_route_pattern_slice_t  *slice;
11951508Saxel.duch@nginx.com 
11961508Saxel.duch@nginx.com     ret = nxt_http_route_decode_str(test, encoding);
11971508Saxel.duch@nginx.com     if (nxt_slow_path(ret != NXT_OK)) {
11981508Saxel.duch@nginx.com         return ret;
11991508Saxel.duch@nginx.com     }
12001508Saxel.duch@nginx.com 
12011508Saxel.duch@nginx.com     start = nxt_mp_nget(slices->mem_pool, test->length);
12021032Sigor@sysoev.ru     if (nxt_slow_path(start == NULL)) {
12031508Saxel.duch@nginx.com         return NXT_ERROR;
12041032Sigor@sysoev.ru     }
1205964Sigor@sysoev.ru 
1206964Sigor@sysoev.ru     switch (pattern_case) {
1207964Sigor@sysoev.ru 
1208964Sigor@sysoev.ru     case NXT_HTTP_ROUTE_PATTERN_UPCASE:
12091032Sigor@sysoev.ru         nxt_memcpy_upcase(start, test->start, test->length);
1210964Sigor@sysoev.ru         break;
1211964Sigor@sysoev.ru 
1212964Sigor@sysoev.ru     case NXT_HTTP_ROUTE_PATTERN_LOWCASE:
12131032Sigor@sysoev.ru         nxt_memcpy_lowcase(start, test->start, test->length);
1214964Sigor@sysoev.ru         break;
1215964Sigor@sysoev.ru 
1216964Sigor@sysoev.ru     case NXT_HTTP_ROUTE_PATTERN_NOCASE:
12171032Sigor@sysoev.ru         nxt_memcpy(start, test->start, test->length);
1218964Sigor@sysoev.ru         break;
1219964Sigor@sysoev.ru     }
1220964Sigor@sysoev.ru 
12211508Saxel.duch@nginx.com     slice = nxt_array_add(slices);
12221564Svbart@nginx.com     if (nxt_slow_path(slice == NULL)) {
12231508Saxel.duch@nginx.com         return NXT_ERROR;
12241508Saxel.duch@nginx.com     }
12251508Saxel.duch@nginx.com 
12261508Saxel.duch@nginx.com     slice->type = type;
12271508Saxel.duch@nginx.com     slice->start = start;
12281508Saxel.duch@nginx.com     slice->length = test->length;
12291508Saxel.duch@nginx.com 
12301508Saxel.duch@nginx.com     return NXT_OK;
1231964Sigor@sysoev.ru }
1232964Sigor@sysoev.ru 
1233964Sigor@sysoev.ru 
12341472Svbart@nginx.com nxt_int_t
nxt_http_routes_resolve(nxt_task_t * task,nxt_router_temp_conf_t * tmcf)1235964Sigor@sysoev.ru nxt_http_routes_resolve(nxt_task_t *task, nxt_router_temp_conf_t *tmcf)
1236964Sigor@sysoev.ru {
12371472Svbart@nginx.com     nxt_int_t          ret;
12381033Svbart@nginx.com     nxt_http_route_t   **route, **end;
1239964Sigor@sysoev.ru     nxt_http_routes_t  *routes;
1240964Sigor@sysoev.ru 
1241964Sigor@sysoev.ru     routes = tmcf->router_conf->routes;
12421059Sigor@sysoev.ru 
1243964Sigor@sysoev.ru     if (routes != NULL) {
1244964Sigor@sysoev.ru         route = &routes->route[0];
12451033Svbart@nginx.com         end = route + routes->items;
1246964Sigor@sysoev.ru 
12471033Svbart@nginx.com         while (route < end) {
12481472Svbart@nginx.com             ret = nxt_http_route_resolve(task, tmcf, *route);
12491472Svbart@nginx.com             if (nxt_slow_path(ret != NXT_OK)) {
12501472Svbart@nginx.com                 return NXT_ERROR;
12511472Svbart@nginx.com             }
1252964Sigor@sysoev.ru 
1253964Sigor@sysoev.ru             route++;
1254964Sigor@sysoev.ru         }
1255964Sigor@sysoev.ru     }
12561472Svbart@nginx.com 
12571472Svbart@nginx.com     return NXT_OK;
1258964Sigor@sysoev.ru }
1259964Sigor@sysoev.ru 
1260964Sigor@sysoev.ru 
12611472Svbart@nginx.com static nxt_int_t
nxt_http_route_resolve(nxt_task_t * task,nxt_router_temp_conf_t * tmcf,nxt_http_route_t * route)1262964Sigor@sysoev.ru nxt_http_route_resolve(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
1263964Sigor@sysoev.ru     nxt_http_route_t *route)
1264964Sigor@sysoev.ru {
12651472Svbart@nginx.com     nxt_int_t               ret;
12661033Svbart@nginx.com     nxt_http_route_match_t  **match, **end;
1267964Sigor@sysoev.ru 
1268964Sigor@sysoev.ru     match = &route->match[0];
12691033Svbart@nginx.com     end = match + route->items;
1270964Sigor@sysoev.ru 
12711033Svbart@nginx.com     while (match < end) {
12721472Svbart@nginx.com         ret = nxt_http_action_resolve(task, tmcf, &(*match)->action);
12731472Svbart@nginx.com         if (nxt_slow_path(ret != NXT_OK)) {
12741472Svbart@nginx.com             return NXT_ERROR;
12751472Svbart@nginx.com         }
1276964Sigor@sysoev.ru 
1277964Sigor@sysoev.ru         match++;
1278964Sigor@sysoev.ru     }
12791472Svbart@nginx.com 
12801472Svbart@nginx.com     return NXT_OK;
1281964Sigor@sysoev.ru }
1282964Sigor@sysoev.ru 
1283964Sigor@sysoev.ru 
12841472Svbart@nginx.com static nxt_int_t
nxt_http_action_resolve(nxt_task_t * task,nxt_router_temp_conf_t * tmcf,nxt_http_action_t * action)12851264Sigor@sysoev.ru nxt_http_action_resolve(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
12861264Sigor@sysoev.ru     nxt_http_action_t *action)
1287964Sigor@sysoev.ru {
12881923Sz.hong@f5.com     nxt_int_t  ret;
12891954Sz.hong@f5.com     nxt_str_t  pass;
1290964Sigor@sysoev.ru 
12911378Svbart@nginx.com     if (action->handler != NULL) {
12921923Sz.hong@f5.com         if (action->fallback != NULL) {
12931923Sz.hong@f5.com             return nxt_http_action_resolve(task, tmcf, action->fallback);
12941378Svbart@nginx.com         }
12951378Svbart@nginx.com 
12961472Svbart@nginx.com         return NXT_OK;
12971378Svbart@nginx.com     }
12981378Svbart@nginx.com 
12992246Sz.hong@f5.com     if (nxt_tstr_is_const(action->u.tstr)) {
13002246Sz.hong@f5.com         nxt_tstr_str(action->u.tstr, &pass);
13011954Sz.hong@f5.com 
13021954Sz.hong@f5.com         ret = nxt_http_pass_find(tmcf->mem_pool, tmcf->router_conf, &pass,
13031954Sz.hong@f5.com                                  action);
13041954Sz.hong@f5.com         if (nxt_slow_path(ret != NXT_OK)) {
13051563Svbart@nginx.com             return NXT_ERROR;
13061563Svbart@nginx.com         }
13071563Svbart@nginx.com 
13081954Sz.hong@f5.com     } else {
13091954Sz.hong@f5.com         action->handler = nxt_http_pass_var;
13101472Svbart@nginx.com     }
13111472Svbart@nginx.com 
13121563Svbart@nginx.com     return NXT_OK;
13131563Svbart@nginx.com }
13141563Svbart@nginx.com 
13151563Svbart@nginx.com 
13161563Svbart@nginx.com static nxt_http_action_t *
nxt_http_pass_var(nxt_task_t * task,nxt_http_request_t * r,nxt_http_action_t * action)13171954Sz.hong@f5.com nxt_http_pass_var(nxt_task_t *task, nxt_http_request_t *r,
13181563Svbart@nginx.com     nxt_http_action_t *action)
13191563Svbart@nginx.com {
13202246Sz.hong@f5.com     nxt_int_t          ret;
13212246Sz.hong@f5.com     nxt_str_t          str;
13222246Sz.hong@f5.com     nxt_tstr_t         *tstr;
13232246Sz.hong@f5.com     nxt_router_conf_t  *rtcf;
13242246Sz.hong@f5.com 
13252246Sz.hong@f5.com     tstr = action->u.tstr;
13262246Sz.hong@f5.com 
13272246Sz.hong@f5.com     nxt_tstr_str(tstr, &str);
13281954Sz.hong@f5.com 
13291954Sz.hong@f5.com     nxt_debug(task, "http pass: \"%V\"", &str);
13301563Svbart@nginx.com 
13312246Sz.hong@f5.com     rtcf = r->conf->socket_conf->router_conf;
13322246Sz.hong@f5.com 
13332247Sz.hong@f5.com     ret = nxt_tstr_query_init(&r->tstr_query, rtcf->tstr_state, &r->tstr_cache,
13342246Sz.hong@f5.com                               r, r->mem_pool);
13351563Svbart@nginx.com     if (nxt_slow_path(ret != NXT_OK)) {
13361563Svbart@nginx.com         goto fail;
13371563Svbart@nginx.com     }
13381563Svbart@nginx.com 
13392448Sz.hong@f5.com     action = nxt_mp_zget(r->mem_pool,
13402448Sz.hong@f5.com                          sizeof(nxt_http_action_t) + sizeof(nxt_str_t));
13411563Svbart@nginx.com     if (nxt_slow_path(action == NULL)) {
13421563Svbart@nginx.com         goto fail;
13431563Svbart@nginx.com     }
13441563Svbart@nginx.com 
13451954Sz.hong@f5.com     action->u.pass = nxt_pointer_to(action, sizeof(nxt_http_action_t));
13461954Sz.hong@f5.com 
13472246Sz.hong@f5.com     nxt_tstr_query(task, r->tstr_query, tstr, action->u.pass);
13482246Sz.hong@f5.com     nxt_tstr_query_resolve(task, r->tstr_query, action,
13492246Sz.hong@f5.com                            nxt_http_pass_query_ready,
13502246Sz.hong@f5.com                            nxt_http_pass_query_error);
13511563Svbart@nginx.com     return NULL;
13521563Svbart@nginx.com 
13531563Svbart@nginx.com fail:
13541563Svbart@nginx.com 
13551563Svbart@nginx.com     nxt_http_request_error(task, r, NXT_HTTP_INTERNAL_SERVER_ERROR);
13561563Svbart@nginx.com     return NULL;
13571563Svbart@nginx.com }
13581563Svbart@nginx.com 
13591563Svbart@nginx.com 
13601563Svbart@nginx.com static void
nxt_http_pass_query_ready(nxt_task_t * task,void * obj,void * data)13612246Sz.hong@f5.com nxt_http_pass_query_ready(nxt_task_t *task, void *obj, void *data)
13621563Svbart@nginx.com {
13631563Svbart@nginx.com     nxt_int_t           ret;
13641563Svbart@nginx.com     nxt_router_conf_t   *rtcf;
13651563Svbart@nginx.com     nxt_http_action_t   *action;
13661563Svbart@nginx.com     nxt_http_status_t   status;
13671563Svbart@nginx.com     nxt_http_request_t  *r;
13681563Svbart@nginx.com 
13691563Svbart@nginx.com     r = obj;
13701563Svbart@nginx.com     action = data;
13711563Svbart@nginx.com     rtcf = r->conf->socket_conf->router_conf;
13721563Svbart@nginx.com 
13731954Sz.hong@f5.com     nxt_debug(task, "http pass lookup: %V", action->u.pass);
13741954Sz.hong@f5.com 
13751954Sz.hong@f5.com     ret = nxt_http_pass_find(r->mem_pool, rtcf, action->u.pass, action);
13761563Svbart@nginx.com 
13771563Svbart@nginx.com     if (ret != NXT_OK) {
13781563Svbart@nginx.com         status = (ret == NXT_DECLINED) ? NXT_HTTP_NOT_FOUND
13791563Svbart@nginx.com                                        : NXT_HTTP_INTERNAL_SERVER_ERROR;
13801563Svbart@nginx.com 
13811563Svbart@nginx.com         nxt_http_request_error(task, r, status);
13821563Svbart@nginx.com         return;
13831563Svbart@nginx.com     }
13841563Svbart@nginx.com 
13851563Svbart@nginx.com     nxt_http_request_action(task, r, action);
13861563Svbart@nginx.com }
13871563Svbart@nginx.com 
13881563Svbart@nginx.com 
13891563Svbart@nginx.com static void
nxt_http_pass_query_error(nxt_task_t * task,void * obj,void * data)13902246Sz.hong@f5.com nxt_http_pass_query_error(nxt_task_t *task, void *obj, void *data)
13911563Svbart@nginx.com {
13921563Svbart@nginx.com     nxt_http_request_t  *r;
13931563Svbart@nginx.com 
13941563Svbart@nginx.com     r = obj;
13951563Svbart@nginx.com 
13961563Svbart@nginx.com     nxt_http_request_error(task, r, NXT_HTTP_INTERNAL_SERVER_ERROR);
13971563Svbart@nginx.com }
13981563Svbart@nginx.com 
13991563Svbart@nginx.com 
14001563Svbart@nginx.com static nxt_int_t
nxt_http_pass_find(nxt_mp_t * mp,nxt_router_conf_t * rtcf,nxt_str_t * pass,nxt_http_action_t * action)14011954Sz.hong@f5.com nxt_http_pass_find(nxt_mp_t *mp, nxt_router_conf_t *rtcf, nxt_str_t *pass,
14021563Svbart@nginx.com     nxt_http_action_t *action)
14031563Svbart@nginx.com {
14041954Sz.hong@f5.com     nxt_int_t  ret;
14051954Sz.hong@f5.com     nxt_str_t  segments[3];
14061954Sz.hong@f5.com 
14071954Sz.hong@f5.com     ret = nxt_http_pass_segments(mp, pass, segments, 3);
14081563Svbart@nginx.com     if (nxt_slow_path(ret != NXT_OK)) {
14091563Svbart@nginx.com         return ret;
14101563Svbart@nginx.com     }
14111563Svbart@nginx.com 
14121472Svbart@nginx.com     if (nxt_str_eq(&segments[0], "applications", 12)) {
14131925Sz.hong@f5.com         return nxt_router_application_init(rtcf, &segments[1], &segments[2],
14141925Sz.hong@f5.com                                            action);
14151472Svbart@nginx.com     }
14161472Svbart@nginx.com 
14171563Svbart@nginx.com     if (segments[2].length == 0) {
14181563Svbart@nginx.com         if (nxt_str_eq(&segments[0], "upstreams", 9)) {
14191563Svbart@nginx.com             return nxt_upstream_find(rtcf->upstreams, &segments[1], action);
14201563Svbart@nginx.com         }
14211563Svbart@nginx.com 
14221563Svbart@nginx.com         if (nxt_str_eq(&segments[0], "routes", 6)) {
14231563Svbart@nginx.com             return nxt_http_route_find(rtcf->routes, &segments[1], action);
14241563Svbart@nginx.com         }
14251563Svbart@nginx.com     }
14261563Svbart@nginx.com 
14271563Svbart@nginx.com     return NXT_DECLINED;
14281472Svbart@nginx.com }
14291472Svbart@nginx.com 
14301472Svbart@nginx.com 
14311472Svbart@nginx.com nxt_int_t
nxt_http_pass_segments(nxt_mp_t * mp,nxt_str_t * pass,nxt_str_t * segments,nxt_uint_t n)14321472Svbart@nginx.com nxt_http_pass_segments(nxt_mp_t *mp, nxt_str_t *pass, nxt_str_t *segments,
14331472Svbart@nginx.com     nxt_uint_t n)
14341472Svbart@nginx.com {
14351472Svbart@nginx.com     u_char     *p;
14361472Svbart@nginx.com     nxt_str_t  rest;
14371472Svbart@nginx.com 
14381472Svbart@nginx.com     if (nxt_slow_path(nxt_str_dup(mp, &rest, pass) == NULL)) {
14391472Svbart@nginx.com         return NXT_ERROR;
14401472Svbart@nginx.com     }
14411472Svbart@nginx.com 
14421472Svbart@nginx.com     nxt_memzero(segments, n * sizeof(nxt_str_t));
14431472Svbart@nginx.com 
14441472Svbart@nginx.com     do {
14452232Salx@nginx.com         p = memchr(rest.start, '/', rest.length);
14461472Svbart@nginx.com 
14471472Svbart@nginx.com         if (p != NULL) {
14481472Svbart@nginx.com             n--;
14491472Svbart@nginx.com 
14501472Svbart@nginx.com             if (n == 0) {
14511472Svbart@nginx.com                 return NXT_DECLINED;
14521472Svbart@nginx.com             }
14531472Svbart@nginx.com 
14541472Svbart@nginx.com             segments->length = p - rest.start;
14551472Svbart@nginx.com             segments->start = rest.start;
14561472Svbart@nginx.com 
14571472Svbart@nginx.com             rest.length -= segments->length + 1;
14581472Svbart@nginx.com             rest.start = p + 1;
14591472Svbart@nginx.com 
14601472Svbart@nginx.com         } else {
14611472Svbart@nginx.com             n = 0;
14621472Svbart@nginx.com             *segments = rest;
1463964Sigor@sysoev.ru         }
1464964Sigor@sysoev.ru 
14651472Svbart@nginx.com         if (segments->length == 0) {
14661472Svbart@nginx.com             return NXT_DECLINED;
14671472Svbart@nginx.com         }
14681472Svbart@nginx.com 
14691472Svbart@nginx.com         p = nxt_decode_uri(segments->start, segments->start, segments->length);
14701472Svbart@nginx.com         if (p == NULL) {
14711472Svbart@nginx.com             return NXT_DECLINED;
14721472Svbart@nginx.com         }
14731472Svbart@nginx.com 
14741472Svbart@nginx.com         segments->length = p - segments->start;
14751472Svbart@nginx.com         segments++;
14761472Svbart@nginx.com 
14771472Svbart@nginx.com     } while (n);
14781472Svbart@nginx.com 
14791472Svbart@nginx.com     return NXT_OK;
1480964Sigor@sysoev.ru }
1481964Sigor@sysoev.ru 
1482964Sigor@sysoev.ru 
14831563Svbart@nginx.com static nxt_int_t
nxt_http_route_find(nxt_http_routes_t * routes,nxt_str_t * name,nxt_http_action_t * action)14841392Sigor@sysoev.ru nxt_http_route_find(nxt_http_routes_t *routes, nxt_str_t *name,
14851392Sigor@sysoev.ru     nxt_http_action_t *action)
1486964Sigor@sysoev.ru {
14871033Svbart@nginx.com     nxt_http_route_t  **route, **end;
1488964Sigor@sysoev.ru 
14891928Sz.hong@f5.com     if (routes == NULL) {
14901928Sz.hong@f5.com         return NXT_DECLINED;
14911928Sz.hong@f5.com     }
14921928Sz.hong@f5.com 
1493964Sigor@sysoev.ru     route = &routes->route[0];
14941033Svbart@nginx.com     end = route + routes->items;
1495964Sigor@sysoev.ru 
14961058Sigor@sysoev.ru     while (route < end) {
1497964Sigor@sysoev.ru         if (nxt_strstr_eq(&(*route)->name, name)) {
14981392Sigor@sysoev.ru             action->u.route = *route;
14991392Sigor@sysoev.ru             action->handler = nxt_http_route_handler;
15001392Sigor@sysoev.ru 
15011563Svbart@nginx.com             return NXT_OK;
1502964Sigor@sysoev.ru         }
1503964Sigor@sysoev.ru 
1504964Sigor@sysoev.ru         route++;
15051058Sigor@sysoev.ru     }
15061563Svbart@nginx.com 
15071563Svbart@nginx.com     return NXT_DECLINED;
1508964Sigor@sysoev.ru }
1509964Sigor@sysoev.ru 
1510964Sigor@sysoev.ru 
15111264Sigor@sysoev.ru nxt_http_action_t *
nxt_http_action_create(nxt_task_t * task,nxt_router_temp_conf_t * tmcf,nxt_str_t * pass)15121264Sigor@sysoev.ru nxt_http_action_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
15131954Sz.hong@f5.com     nxt_str_t *pass)
1514964Sigor@sysoev.ru {
15151954Sz.hong@f5.com     nxt_mp_t           *mp;
15161597Shongzhidao@gmail.com     nxt_int_t          ret;
15172147Sz.hong@f5.com     nxt_router_conf_t  *rtcf;
15181264Sigor@sysoev.ru     nxt_http_action_t  *action;
1519964Sigor@sysoev.ru 
15202147Sz.hong@f5.com     rtcf = tmcf->router_conf;
15212147Sz.hong@f5.com     mp = rtcf->mem_pool;
15221954Sz.hong@f5.com 
15232448Sz.hong@f5.com     action = nxt_mp_zalloc(mp, sizeof(nxt_http_action_t));
15241264Sigor@sysoev.ru     if (nxt_slow_path(action == NULL)) {
1525964Sigor@sysoev.ru         return NULL;
1526964Sigor@sysoev.ru     }
1527964Sigor@sysoev.ru 
15282246Sz.hong@f5.com     action->u.tstr = nxt_tstr_compile(rtcf->tstr_state, pass, 0);
15292246Sz.hong@f5.com     if (nxt_slow_path(action->u.tstr == NULL)) {
15301954Sz.hong@f5.com         return NULL;
15311954Sz.hong@f5.com     }
15321954Sz.hong@f5.com 
15331270Sigor@sysoev.ru     action->handler = NULL;
1534964Sigor@sysoev.ru 
15351597Shongzhidao@gmail.com     ret = nxt_http_action_resolve(task, tmcf, action);
15361597Shongzhidao@gmail.com     if (nxt_slow_path(ret != NXT_OK)) {
15371597Shongzhidao@gmail.com         return NULL;
15381597Shongzhidao@gmail.com     }
1539964Sigor@sysoev.ru 
15401264Sigor@sysoev.ru     return action;
1541964Sigor@sysoev.ru }
1542964Sigor@sysoev.ru 
1543964Sigor@sysoev.ru 
1544964Sigor@sysoev.ru /* COMPATIBILITY: listener application. */
1545964Sigor@sysoev.ru 
15461264Sigor@sysoev.ru nxt_http_action_t *
nxt_http_pass_application(nxt_task_t * task,nxt_router_conf_t * rtcf,nxt_str_t * name)15471563Svbart@nginx.com nxt_http_pass_application(nxt_task_t *task, nxt_router_conf_t *rtcf,
1548964Sigor@sysoev.ru     nxt_str_t *name)
1549964Sigor@sysoev.ru {
15501264Sigor@sysoev.ru     nxt_http_action_t  *action;
1551964Sigor@sysoev.ru 
15522448Sz.hong@f5.com     action = nxt_mp_zalloc(rtcf->mem_pool, sizeof(nxt_http_action_t));
15531264Sigor@sysoev.ru     if (nxt_slow_path(action == NULL)) {
1554964Sigor@sysoev.ru         return NULL;
1555964Sigor@sysoev.ru     }
1556964Sigor@sysoev.ru 
15571925Sz.hong@f5.com     (void) nxt_router_application_init(rtcf, name, NULL, action);
15581473Svbart@nginx.com 
15591264Sigor@sysoev.ru     return action;
1560964Sigor@sysoev.ru }
1561964Sigor@sysoev.ru 
1562964Sigor@sysoev.ru 
15631264Sigor@sysoev.ru static nxt_http_action_t *
nxt_http_route_handler(nxt_task_t * task,nxt_http_request_t * r,nxt_http_action_t * start)15641264Sigor@sysoev.ru nxt_http_route_handler(nxt_task_t *task, nxt_http_request_t *r,
15651264Sigor@sysoev.ru     nxt_http_action_t *start)
1566964Sigor@sysoev.ru {
15672380Salx@nginx.com     size_t                  i;
1568964Sigor@sysoev.ru     nxt_http_route_t        *route;
15691264Sigor@sysoev.ru     nxt_http_action_t       *action;
1570964Sigor@sysoev.ru 
1571964Sigor@sysoev.ru     route = start->u.route;
15722380Salx@nginx.com 
15732380Salx@nginx.com     for (i = 0; i < route->items; i++) {
15742380Salx@nginx.com         action = nxt_http_route_match(task, r, route->match[i]);
15752381Salx@nginx.com 
15762381Salx@nginx.com         if (nxt_slow_path(r->log_route)) {
15772381Salx@nginx.com             uint32_t    lvl = (action == NULL) ? NXT_LOG_INFO : NXT_LOG_NOTICE;
15782381Salx@nginx.com             const char  *sel = (action == NULL) ? "discarded" : "selected";
15792381Salx@nginx.com 
15802381Salx@nginx.com             if (route->name.length == 0) {
15812381Salx@nginx.com                 nxt_log(task, lvl, "\"routes/%z\" %s", i, sel);
15822381Salx@nginx.com             } else {
15832381Salx@nginx.com                 nxt_log(task, lvl, "\"routes/%V/%z\" %s", &route->name, i, sel);
15842381Salx@nginx.com             }
15852381Salx@nginx.com         }
15862381Salx@nginx.com 
15871264Sigor@sysoev.ru         if (action != NULL) {
15882511Sz.hong@f5.com 
15892511Sz.hong@f5.com             if (action != NXT_HTTP_ACTION_ERROR) {
15902511Sz.hong@f5.com                 r->action = action;
15912511Sz.hong@f5.com             }
15922511Sz.hong@f5.com 
15931264Sigor@sysoev.ru             return action;
1594964Sigor@sysoev.ru         }
1595964Sigor@sysoev.ru     }
1596964Sigor@sysoev.ru 
1597964Sigor@sysoev.ru     nxt_http_request_error(task, r, NXT_HTTP_NOT_FOUND);
1598964Sigor@sysoev.ru 
1599964Sigor@sysoev.ru     return NULL;
1600964Sigor@sysoev.ru }
1601964Sigor@sysoev.ru 
1602964Sigor@sysoev.ru 
16031264Sigor@sysoev.ru static nxt_http_action_t *
nxt_http_route_match(nxt_task_t * task,nxt_http_request_t * r,nxt_http_route_match_t * match)16041326Saxel.duch@nginx.com nxt_http_route_match(nxt_task_t *task, nxt_http_request_t *r,
16051326Saxel.duch@nginx.com     nxt_http_route_match_t *match)
1606964Sigor@sysoev.ru {
16071060Sigor@sysoev.ru     nxt_int_t              ret;
16081059Sigor@sysoev.ru     nxt_http_route_test_t  *test, *end;
16091059Sigor@sysoev.ru 
16101059Sigor@sysoev.ru     test = &match->test[0];
16111059Sigor@sysoev.ru     end = test + match->items;
1612964Sigor@sysoev.ru 
16131059Sigor@sysoev.ru     while (test < end) {
16141324Saxel.duch@nginx.com         switch (test->rule->object) {
16151324Saxel.duch@nginx.com         case NXT_HTTP_ROUTE_TABLE:
16161324Saxel.duch@nginx.com             ret = nxt_http_route_table(r, test->table);
16171324Saxel.duch@nginx.com             break;
16181324Saxel.duch@nginx.com         case NXT_HTTP_ROUTE_SOURCE:
16191324Saxel.duch@nginx.com             ret = nxt_http_route_addr_rule(r, test->addr_rule, r->remote);
16201324Saxel.duch@nginx.com             break;
16211326Saxel.duch@nginx.com         case NXT_HTTP_ROUTE_DESTINATION:
16221326Saxel.duch@nginx.com             if (r->local == NULL && nxt_fast_path(r->proto.any != NULL)) {
16231326Saxel.duch@nginx.com                 nxt_http_proto[r->protocol].local_addr(task, r);
16241326Saxel.duch@nginx.com             }
16251326Saxel.duch@nginx.com 
16261326Saxel.duch@nginx.com             ret = nxt_http_route_addr_rule(r, test->addr_rule, r->local);
16271326Saxel.duch@nginx.com             break;
16281324Saxel.duch@nginx.com         default:
16291059Sigor@sysoev.ru             ret = nxt_http_route_rule(r, test->rule);
16301324Saxel.duch@nginx.com             break;
16311059Sigor@sysoev.ru         }
16321059Sigor@sysoev.ru 
16331060Sigor@sysoev.ru         if (ret <= 0) {
16341264Sigor@sysoev.ru             /* 0 => NULL, -1 => NXT_HTTP_ACTION_ERROR. */
16351264Sigor@sysoev.ru             return (nxt_http_action_t *) (intptr_t) ret;
1636964Sigor@sysoev.ru         }
1637964Sigor@sysoev.ru 
16381059Sigor@sysoev.ru         test++;
1639964Sigor@sysoev.ru     }
1640964Sigor@sysoev.ru 
16411264Sigor@sysoev.ru     return &match->action;
1642964Sigor@sysoev.ru }
1643964Sigor@sysoev.ru 
1644964Sigor@sysoev.ru 
16451060Sigor@sysoev.ru static nxt_int_t
nxt_http_route_table(nxt_http_request_t * r,nxt_http_route_table_t * table)16461059Sigor@sysoev.ru nxt_http_route_table(nxt_http_request_t *r, nxt_http_route_table_t *table)
1647964Sigor@sysoev.ru {
16481060Sigor@sysoev.ru     nxt_int_t                 ret;
16491059Sigor@sysoev.ru     nxt_http_route_ruleset_t  **ruleset, **end;
16501059Sigor@sysoev.ru 
16511059Sigor@sysoev.ru     ret = 1;
16521059Sigor@sysoev.ru     ruleset = &table->ruleset[0];
16531059Sigor@sysoev.ru     end = ruleset + table->items;
16541059Sigor@sysoev.ru 
16551059Sigor@sysoev.ru     while (ruleset < end) {
16561059Sigor@sysoev.ru         ret = nxt_http_route_ruleset(r, *ruleset);
16571059Sigor@sysoev.ru 
16581060Sigor@sysoev.ru         if (ret != 0) {
16591059Sigor@sysoev.ru             return ret;
16601059Sigor@sysoev.ru         }
1661964Sigor@sysoev.ru 
16621059Sigor@sysoev.ru         ruleset++;
16631059Sigor@sysoev.ru     }
16641059Sigor@sysoev.ru 
16651059Sigor@sysoev.ru     return ret;
16661059Sigor@sysoev.ru }
16671059Sigor@sysoev.ru 
1668964Sigor@sysoev.ru 
16691060Sigor@sysoev.ru static nxt_int_t
nxt_http_route_ruleset(nxt_http_request_t * r,nxt_http_route_ruleset_t * ruleset)16701059Sigor@sysoev.ru nxt_http_route_ruleset(nxt_http_request_t *r, nxt_http_route_ruleset_t *ruleset)
16711059Sigor@sysoev.ru {
16721060Sigor@sysoev.ru     nxt_int_t              ret;
16731059Sigor@sysoev.ru     nxt_http_route_rule_t  **rule, **end;
1674964Sigor@sysoev.ru 
16751059Sigor@sysoev.ru     rule = &ruleset->rule[0];
16761059Sigor@sysoev.ru     end = rule + ruleset->items;
1677964Sigor@sysoev.ru 
16781059Sigor@sysoev.ru     while (rule < end) {
16791060Sigor@sysoev.ru         ret = nxt_http_route_rule(r, *rule);
16801060Sigor@sysoev.ru 
16811060Sigor@sysoev.ru         if (ret <= 0) {
16821060Sigor@sysoev.ru             return ret;
1683964Sigor@sysoev.ru         }
1684964Sigor@sysoev.ru 
16851059Sigor@sysoev.ru         rule++;
16861059Sigor@sysoev.ru     }
16871059Sigor@sysoev.ru 
16881059Sigor@sysoev.ru     return 1;
16891059Sigor@sysoev.ru }
16901059Sigor@sysoev.ru 
1691964Sigor@sysoev.ru 
16921060Sigor@sysoev.ru static nxt_int_t
nxt_http_route_rule(nxt_http_request_t * r,nxt_http_route_rule_t * rule)16931059Sigor@sysoev.ru nxt_http_route_rule(nxt_http_request_t *r, nxt_http_route_rule_t *rule)
16941059Sigor@sysoev.ru {
16951059Sigor@sysoev.ru     void       *p, **pp;
16961059Sigor@sysoev.ru     u_char     *start;
16971059Sigor@sysoev.ru     size_t     length;
16981059Sigor@sysoev.ru     nxt_str_t  *s;
16991059Sigor@sysoev.ru 
17001059Sigor@sysoev.ru     switch (rule->object) {
17011059Sigor@sysoev.ru 
17021059Sigor@sysoev.ru     case NXT_HTTP_ROUTE_HEADER:
17031059Sigor@sysoev.ru         return nxt_http_route_header(r, rule);
1704964Sigor@sysoev.ru 
17051059Sigor@sysoev.ru     case NXT_HTTP_ROUTE_ARGUMENT:
17061061Sigor@sysoev.ru         return nxt_http_route_arguments(r, rule);
1707964Sigor@sysoev.ru 
17081059Sigor@sysoev.ru     case NXT_HTTP_ROUTE_COOKIE:
17091062Sigor@sysoev.ru         return nxt_http_route_cookies(r, rule);
17101059Sigor@sysoev.ru 
17111110Saxel.duch@nginx.com     case NXT_HTTP_ROUTE_SCHEME:
17121110Saxel.duch@nginx.com         return nxt_http_route_scheme(r, rule);
17131110Saxel.duch@nginx.com 
17141991Sz.hong@f5.com     case NXT_HTTP_ROUTE_QUERY:
17151991Sz.hong@f5.com         return nxt_http_route_query(r, rule);
17161991Sz.hong@f5.com 
17171059Sigor@sysoev.ru     default:
17181059Sigor@sysoev.ru         break;
17191059Sigor@sysoev.ru     }
1720964Sigor@sysoev.ru 
17211059Sigor@sysoev.ru     p = nxt_pointer_to(r, rule->u.offset);
17221059Sigor@sysoev.ru 
17231059Sigor@sysoev.ru     if (rule->object == NXT_HTTP_ROUTE_STRING) {
17241059Sigor@sysoev.ru         s = p;
1725964Sigor@sysoev.ru 
17261059Sigor@sysoev.ru     } else {
17271059Sigor@sysoev.ru         /* NXT_HTTP_ROUTE_STRING_PTR */
17281059Sigor@sysoev.ru         pp = p;
17291059Sigor@sysoev.ru         s = *pp;
1730964Sigor@sysoev.ru 
17311059Sigor@sysoev.ru         if (s == NULL) {
1732964Sigor@sysoev.ru             return 0;
1733964Sigor@sysoev.ru         }
1734964Sigor@sysoev.ru     }
1735964Sigor@sysoev.ru 
17361059Sigor@sysoev.ru     length = s->length;
17371059Sigor@sysoev.ru     start = s->start;
17381059Sigor@sysoev.ru 
17391059Sigor@sysoev.ru     return nxt_http_route_test_rule(r, rule, start, length);
17401059Sigor@sysoev.ru }
17411059Sigor@sysoev.ru 
17421059Sigor@sysoev.ru 
17431060Sigor@sysoev.ru static nxt_int_t
nxt_http_route_addr_pattern_match(nxt_http_route_addr_pattern_t * p,nxt_sockaddr_t * sa)17441324Saxel.duch@nginx.com nxt_http_route_addr_pattern_match(nxt_http_route_addr_pattern_t *p,
17451324Saxel.duch@nginx.com     nxt_sockaddr_t *sa)
17461324Saxel.duch@nginx.com {
17471324Saxel.duch@nginx.com #if (NXT_INET6)
17481324Saxel.duch@nginx.com     uint32_t                    i;
17491324Saxel.duch@nginx.com #endif
17501324Saxel.duch@nginx.com     in_port_t                   in_port;
17511324Saxel.duch@nginx.com     nxt_int_t                   match;
17521324Saxel.duch@nginx.com     struct sockaddr_in          *sin;
17531324Saxel.duch@nginx.com #if (NXT_INET6)
17541324Saxel.duch@nginx.com     struct sockaddr_in6         *sin6;
17551324Saxel.duch@nginx.com #endif
17561324Saxel.duch@nginx.com     nxt_http_route_addr_base_t  *base;
17571324Saxel.duch@nginx.com 
17581324Saxel.duch@nginx.com     base = &p->base;
17591324Saxel.duch@nginx.com 
17601324Saxel.duch@nginx.com     switch (sa->u.sockaddr.sa_family) {
17611324Saxel.duch@nginx.com 
17621324Saxel.duch@nginx.com     case AF_INET:
17631324Saxel.duch@nginx.com 
17641324Saxel.duch@nginx.com         match = (base->addr_family == AF_INET
17651324Saxel.duch@nginx.com                  || base->addr_family == AF_UNSPEC);
17661324Saxel.duch@nginx.com         if (!match) {
17671324Saxel.duch@nginx.com             break;
17681324Saxel.duch@nginx.com         }
17691324Saxel.duch@nginx.com 
17701324Saxel.duch@nginx.com         sin = &sa->u.sockaddr_in;
17711324Saxel.duch@nginx.com         in_port = ntohs(sin->sin_port);
17721324Saxel.duch@nginx.com 
17731324Saxel.duch@nginx.com         match = (in_port >= base->port.start && in_port <= base->port.end);
17741324Saxel.duch@nginx.com         if (!match) {
17751324Saxel.duch@nginx.com             break;
17761324Saxel.duch@nginx.com         }
17771324Saxel.duch@nginx.com 
17781324Saxel.duch@nginx.com         switch (base->match_type) {
17791324Saxel.duch@nginx.com 
17801324Saxel.duch@nginx.com         case NXT_HTTP_ROUTE_ADDR_ANY:
17811324Saxel.duch@nginx.com             break;
17821324Saxel.duch@nginx.com 
17831324Saxel.duch@nginx.com         case NXT_HTTP_ROUTE_ADDR_EXACT:
17842231Salx@nginx.com             match = (memcmp(&sin->sin_addr, &p->addr.v4.start,
17851324Saxel.duch@nginx.com                                 sizeof(struct in_addr))
17861324Saxel.duch@nginx.com                      == 0);
17871324Saxel.duch@nginx.com             break;
17881324Saxel.duch@nginx.com 
17891324Saxel.duch@nginx.com         case NXT_HTTP_ROUTE_ADDR_RANGE:
17902231Salx@nginx.com             match = (memcmp(&sin->sin_addr, &p->addr.v4.start,
17911324Saxel.duch@nginx.com                                 sizeof(struct in_addr)) >= 0
17922231Salx@nginx.com                      && memcmp(&sin->sin_addr, &p->addr.v4.end,
17931324Saxel.duch@nginx.com                                    sizeof(struct in_addr)) <= 0);
17941324Saxel.duch@nginx.com             break;
17951324Saxel.duch@nginx.com 
17961324Saxel.duch@nginx.com         case NXT_HTTP_ROUTE_ADDR_CIDR:
17971324Saxel.duch@nginx.com             match = ((sin->sin_addr.s_addr & p->addr.v4.end)
17981324Saxel.duch@nginx.com                      == p->addr.v4.start);
17991324Saxel.duch@nginx.com             break;
18001324Saxel.duch@nginx.com 
18011324Saxel.duch@nginx.com         default:
18021324Saxel.duch@nginx.com             nxt_unreachable();
18031324Saxel.duch@nginx.com         }
18041324Saxel.duch@nginx.com 
18051324Saxel.duch@nginx.com         break;
18061324Saxel.duch@nginx.com 
18071324Saxel.duch@nginx.com #if (NXT_INET6)
18081324Saxel.duch@nginx.com     case AF_INET6:
18091324Saxel.duch@nginx.com 
18101324Saxel.duch@nginx.com         match = (base->addr_family == AF_INET6
18111324Saxel.duch@nginx.com                  || base->addr_family == AF_UNSPEC);
18121324Saxel.duch@nginx.com         if (!match) {
18131324Saxel.duch@nginx.com             break;
18141324Saxel.duch@nginx.com         }
18151324Saxel.duch@nginx.com 
18161324Saxel.duch@nginx.com         sin6 = &sa->u.sockaddr_in6;
18171324Saxel.duch@nginx.com         in_port = ntohs(sin6->sin6_port);
18181324Saxel.duch@nginx.com 
18191324Saxel.duch@nginx.com         match = (in_port >= base->port.start && in_port <= base->port.end);
18201324Saxel.duch@nginx.com         if (!match) {
18211324Saxel.duch@nginx.com             break;
18221324Saxel.duch@nginx.com         }
18231324Saxel.duch@nginx.com 
18241324Saxel.duch@nginx.com         switch (base->match_type) {
18251324Saxel.duch@nginx.com 
18261324Saxel.duch@nginx.com         case NXT_HTTP_ROUTE_ADDR_ANY:
18271324Saxel.duch@nginx.com             break;
18281324Saxel.duch@nginx.com 
18291324Saxel.duch@nginx.com         case NXT_HTTP_ROUTE_ADDR_EXACT:
18302231Salx@nginx.com             match = (memcmp(&sin6->sin6_addr, &p->addr.v6.start,
18311324Saxel.duch@nginx.com                                 sizeof(struct in6_addr))
18321324Saxel.duch@nginx.com                      == 0);
18331324Saxel.duch@nginx.com             break;
18341324Saxel.duch@nginx.com 
18351324Saxel.duch@nginx.com         case NXT_HTTP_ROUTE_ADDR_RANGE:
18362231Salx@nginx.com             match = (memcmp(&sin6->sin6_addr, &p->addr.v6.start,
18371324Saxel.duch@nginx.com                                 sizeof(struct in6_addr)) >= 0
18382231Salx@nginx.com                      && memcmp(&sin6->sin6_addr, &p->addr.v6.end,
18391324Saxel.duch@nginx.com                                    sizeof(struct in6_addr)) <= 0);
18401324Saxel.duch@nginx.com             break;
18411324Saxel.duch@nginx.com 
18421324Saxel.duch@nginx.com         case NXT_HTTP_ROUTE_ADDR_CIDR:
18431324Saxel.duch@nginx.com             for (i = 0; i < 16; i++) {
18441324Saxel.duch@nginx.com                 match = ((sin6->sin6_addr.s6_addr[i]
18451324Saxel.duch@nginx.com                           & p->addr.v6.end.s6_addr[i])
18461324Saxel.duch@nginx.com                          == p->addr.v6.start.s6_addr[i]);
18471324Saxel.duch@nginx.com 
18481324Saxel.duch@nginx.com                 if (!match) {
18491324Saxel.duch@nginx.com                     break;
18501324Saxel.duch@nginx.com                 }
18511324Saxel.duch@nginx.com             }
18521324Saxel.duch@nginx.com 
18531324Saxel.duch@nginx.com             break;
18541324Saxel.duch@nginx.com 
18551324Saxel.duch@nginx.com         default:
18561324Saxel.duch@nginx.com             nxt_unreachable();
18571324Saxel.duch@nginx.com         }
18581324Saxel.duch@nginx.com 
18591324Saxel.duch@nginx.com         break;
18601324Saxel.duch@nginx.com #endif
18611324Saxel.duch@nginx.com 
18622161Salx.manpages@gmail.com #if (NXT_HAVE_UNIX_DOMAIN)
18632161Salx.manpages@gmail.com     case AF_UNIX:
18642161Salx.manpages@gmail.com 
18652161Salx.manpages@gmail.com         match = (base->addr_family == AF_UNIX);
18662161Salx.manpages@gmail.com         break;
18672161Salx.manpages@gmail.com #endif
18682161Salx.manpages@gmail.com 
18691324Saxel.duch@nginx.com     default:
18701324Saxel.duch@nginx.com         match = 0;
18711324Saxel.duch@nginx.com         break;
18721324Saxel.duch@nginx.com     }
18731324Saxel.duch@nginx.com 
18741324Saxel.duch@nginx.com     return match ^ base->negative;
18751324Saxel.duch@nginx.com }
18761324Saxel.duch@nginx.com 
18771324Saxel.duch@nginx.com 
18781936So.canty@f5.com nxt_int_t
nxt_http_route_addr_rule(nxt_http_request_t * r,nxt_http_route_addr_rule_t * addr_rule,nxt_sockaddr_t * sa)18791324Saxel.duch@nginx.com nxt_http_route_addr_rule(nxt_http_request_t *r,
18801324Saxel.duch@nginx.com     nxt_http_route_addr_rule_t *addr_rule, nxt_sockaddr_t *sa)
18811324Saxel.duch@nginx.com {
18821390Saxel.duch@nginx.com     uint32_t                       n;
18831390Saxel.duch@nginx.com     nxt_bool_t                     matches;
18841324Saxel.duch@nginx.com     nxt_http_route_addr_pattern_t  *p;
18851324Saxel.duch@nginx.com 
18861324Saxel.duch@nginx.com     n = addr_rule->items;
18871930So.canty@f5.com 
18881930So.canty@f5.com     if (n == 0) {
18891930So.canty@f5.com         return 0;
18901930So.canty@f5.com     }
18911930So.canty@f5.com 
18921390Saxel.duch@nginx.com     p = &addr_rule->addr_pattern[0] - 1;
18931324Saxel.duch@nginx.com 
18941390Saxel.duch@nginx.com     do {
18951390Saxel.duch@nginx.com         p++;
18961390Saxel.duch@nginx.com         n--;
18971390Saxel.duch@nginx.com 
18981390Saxel.duch@nginx.com         matches = nxt_http_route_addr_pattern_match(p, sa);
18991390Saxel.duch@nginx.com 
19001390Saxel.duch@nginx.com         if (p->base.negative) {
19011390Saxel.duch@nginx.com             if (matches) {
19021390Saxel.duch@nginx.com                 continue;
19031390Saxel.duch@nginx.com             }
19041390Saxel.duch@nginx.com 
19051390Saxel.duch@nginx.com             return 0;
19061390Saxel.duch@nginx.com         }
19071390Saxel.duch@nginx.com 
19081390Saxel.duch@nginx.com         if (matches) {
19091324Saxel.duch@nginx.com             return 1;
19101324Saxel.duch@nginx.com         }
19111324Saxel.duch@nginx.com 
19121390Saxel.duch@nginx.com     } while (n > 0);
19131390Saxel.duch@nginx.com 
19141390Saxel.duch@nginx.com     return p->base.negative;
19151324Saxel.duch@nginx.com }
19161324Saxel.duch@nginx.com 
19171324Saxel.duch@nginx.com 
19181324Saxel.duch@nginx.com static nxt_int_t
nxt_http_route_header(nxt_http_request_t * r,nxt_http_route_rule_t * rule)19191059Sigor@sysoev.ru nxt_http_route_header(nxt_http_request_t *r, nxt_http_route_rule_t *rule)
19201059Sigor@sysoev.ru {
19211060Sigor@sysoev.ru     nxt_int_t         ret;
19221059Sigor@sysoev.ru     nxt_http_field_t  *f;
19231059Sigor@sysoev.ru 
19241059Sigor@sysoev.ru     ret = 0;
19251059Sigor@sysoev.ru 
19261059Sigor@sysoev.ru     nxt_list_each(f, r->fields) {
19271059Sigor@sysoev.ru 
19281059Sigor@sysoev.ru         if (rule->u.name.hash != f->hash
19291059Sigor@sysoev.ru             || rule->u.name.length != f->name_length
19301059Sigor@sysoev.ru             || nxt_strncasecmp(rule->u.name.start, f->name, f->name_length)
19311059Sigor@sysoev.ru                != 0)
19321059Sigor@sysoev.ru         {
19331059Sigor@sysoev.ru             continue;
19341059Sigor@sysoev.ru         }
19351059Sigor@sysoev.ru 
19361059Sigor@sysoev.ru         ret = nxt_http_route_test_rule(r, rule, f->value, f->value_length);
19371721Saxel.duch@nginx.com         if (nxt_slow_path(ret == NXT_ERROR)) {
19381721Saxel.duch@nginx.com             return NXT_ERROR;
19391721Saxel.duch@nginx.com         }
19401059Sigor@sysoev.ru 
19411060Sigor@sysoev.ru         if (ret == 0) {
19421059Sigor@sysoev.ru             return ret;
19431059Sigor@sysoev.ru         }
19441059Sigor@sysoev.ru 
19451059Sigor@sysoev.ru     } nxt_list_loop;
19461059Sigor@sysoev.ru 
19471059Sigor@sysoev.ru     return ret;
19481059Sigor@sysoev.ru }
19491059Sigor@sysoev.ru 
19501059Sigor@sysoev.ru 
19511060Sigor@sysoev.ru static nxt_int_t
nxt_http_route_arguments(nxt_http_request_t * r,nxt_http_route_rule_t * rule)19521061Sigor@sysoev.ru nxt_http_route_arguments(nxt_http_request_t *r, nxt_http_route_rule_t *rule)
19531061Sigor@sysoev.ru {
19541061Sigor@sysoev.ru     nxt_array_t  *arguments;
19551061Sigor@sysoev.ru 
19562104Sz.hong@f5.com     arguments = nxt_http_arguments_parse(r);
19571061Sigor@sysoev.ru     if (nxt_slow_path(arguments == NULL)) {
19581061Sigor@sysoev.ru         return -1;
19591061Sigor@sysoev.ru     }
19601061Sigor@sysoev.ru 
19611061Sigor@sysoev.ru     return nxt_http_route_test_argument(r, rule, arguments);
19621061Sigor@sysoev.ru }
19631061Sigor@sysoev.ru 
19641061Sigor@sysoev.ru 
19651061Sigor@sysoev.ru static nxt_int_t
nxt_http_route_test_argument(nxt_http_request_t * r,nxt_http_route_rule_t * rule,nxt_array_t * array)19661061Sigor@sysoev.ru nxt_http_route_test_argument(nxt_http_request_t *r,
19671061Sigor@sysoev.ru     nxt_http_route_rule_t *rule, nxt_array_t *array)
19681061Sigor@sysoev.ru {
19691721Saxel.duch@nginx.com     nxt_int_t              ret;
19701061Sigor@sysoev.ru     nxt_http_name_value_t  *nv, *end;
19711061Sigor@sysoev.ru 
19721061Sigor@sysoev.ru     ret = 0;
19731061Sigor@sysoev.ru 
19741061Sigor@sysoev.ru     nv = array->elts;
19751061Sigor@sysoev.ru     end = nv + array->nelts;
19761061Sigor@sysoev.ru 
19771061Sigor@sysoev.ru     while (nv < end) {
19781061Sigor@sysoev.ru 
19791061Sigor@sysoev.ru         if (rule->u.name.hash == nv->hash
19801061Sigor@sysoev.ru             && rule->u.name.length == nv->name_length
19812231Salx@nginx.com             && memcmp(rule->u.name.start, nv->name, nv->name_length) == 0)
19821061Sigor@sysoev.ru         {
19831061Sigor@sysoev.ru             ret = nxt_http_route_test_rule(r, rule, nv->value,
19841061Sigor@sysoev.ru                                            nv->value_length);
19851721Saxel.duch@nginx.com             if (nxt_slow_path(ret == NXT_ERROR)) {
19861721Saxel.duch@nginx.com                 return NXT_ERROR;
19871721Saxel.duch@nginx.com             }
19881721Saxel.duch@nginx.com 
19891061Sigor@sysoev.ru             if (ret == 0) {
19901061Sigor@sysoev.ru                 break;
19911061Sigor@sysoev.ru             }
19921061Sigor@sysoev.ru         }
19931061Sigor@sysoev.ru 
19941061Sigor@sysoev.ru         nv++;
19951061Sigor@sysoev.ru     }
19961061Sigor@sysoev.ru 
19971061Sigor@sysoev.ru     return ret;
19981061Sigor@sysoev.ru }
19991061Sigor@sysoev.ru 
20001061Sigor@sysoev.ru 
20011061Sigor@sysoev.ru static nxt_int_t
nxt_http_route_scheme(nxt_http_request_t * r,nxt_http_route_rule_t * rule)20021110Saxel.duch@nginx.com nxt_http_route_scheme(nxt_http_request_t *r, nxt_http_route_rule_t *rule)
20031110Saxel.duch@nginx.com {
20042133Sz.hong@f5.com     nxt_bool_t                      https;
20051508Saxel.duch@nginx.com     nxt_http_route_pattern_slice_t  *pattern_slice;
20061508Saxel.duch@nginx.com 
20071721Saxel.duch@nginx.com     pattern_slice = rule->pattern[0].u.pattern_slices->elts;
20081508Saxel.duch@nginx.com     https = (pattern_slice->length == nxt_length("https"));
20092133Sz.hong@f5.com 
20102133Sz.hong@f5.com     return (r->tls == https);
20111110Saxel.duch@nginx.com }
20121110Saxel.duch@nginx.com 
20131110Saxel.duch@nginx.com 
20141110Saxel.duch@nginx.com static nxt_int_t
nxt_http_route_query(nxt_http_request_t * r,nxt_http_route_rule_t * rule)20151991Sz.hong@f5.com nxt_http_route_query(nxt_http_request_t *r, nxt_http_route_rule_t *rule)
20161991Sz.hong@f5.com {
20171991Sz.hong@f5.com     nxt_array_t  *arguments;
20181991Sz.hong@f5.com 
20192104Sz.hong@f5.com     arguments = nxt_http_arguments_parse(r);
20201991Sz.hong@f5.com     if (nxt_slow_path(arguments == NULL)) {
20211991Sz.hong@f5.com         return -1;
20221991Sz.hong@f5.com     }
20231991Sz.hong@f5.com 
20241991Sz.hong@f5.com     return nxt_http_route_test_rule(r, rule, r->args_decoded.start,
20251991Sz.hong@f5.com                                     r->args_decoded.length);
20261991Sz.hong@f5.com }
20271991Sz.hong@f5.com 
20281991Sz.hong@f5.com 
20291991Sz.hong@f5.com static nxt_int_t
nxt_http_route_cookies(nxt_http_request_t * r,nxt_http_route_rule_t * rule)20301062Sigor@sysoev.ru nxt_http_route_cookies(nxt_http_request_t *r, nxt_http_route_rule_t *rule)
20311062Sigor@sysoev.ru {
20321062Sigor@sysoev.ru     nxt_array_t  *cookies;
20331062Sigor@sysoev.ru 
20342104Sz.hong@f5.com     cookies = nxt_http_cookies_parse(r);
20351062Sigor@sysoev.ru     if (nxt_slow_path(cookies == NULL)) {
20361062Sigor@sysoev.ru         return -1;
20371062Sigor@sysoev.ru     }
20381062Sigor@sysoev.ru 
20391062Sigor@sysoev.ru     return nxt_http_route_test_cookie(r, rule, cookies);
20401062Sigor@sysoev.ru }
20411062Sigor@sysoev.ru 
20421062Sigor@sysoev.ru 
20431062Sigor@sysoev.ru static nxt_int_t
nxt_http_route_test_cookie(nxt_http_request_t * r,nxt_http_route_rule_t * rule,nxt_array_t * array)20441062Sigor@sysoev.ru nxt_http_route_test_cookie(nxt_http_request_t *r,
20451062Sigor@sysoev.ru     nxt_http_route_rule_t *rule, nxt_array_t *array)
20461062Sigor@sysoev.ru {
20471721Saxel.duch@nginx.com     nxt_int_t              ret;
20481062Sigor@sysoev.ru     nxt_http_name_value_t  *nv, *end;
20491062Sigor@sysoev.ru 
20501062Sigor@sysoev.ru     ret = 0;
20511062Sigor@sysoev.ru 
20521062Sigor@sysoev.ru     nv = array->elts;
20531062Sigor@sysoev.ru     end = nv + array->nelts;
20541062Sigor@sysoev.ru 
20551062Sigor@sysoev.ru     while (nv < end) {
20561062Sigor@sysoev.ru 
20571062Sigor@sysoev.ru         if (rule->u.name.hash == nv->hash
20581062Sigor@sysoev.ru             && rule->u.name.length == nv->name_length
20592231Salx@nginx.com             && memcmp(rule->u.name.start, nv->name, nv->name_length) == 0)
20601062Sigor@sysoev.ru         {
20611062Sigor@sysoev.ru             ret = nxt_http_route_test_rule(r, rule, nv->value,
20621062Sigor@sysoev.ru                                            nv->value_length);
20631721Saxel.duch@nginx.com             if (nxt_slow_path(ret == NXT_ERROR)) {
20641721Saxel.duch@nginx.com                 return NXT_ERROR;
20651721Saxel.duch@nginx.com             }
20661721Saxel.duch@nginx.com 
20671062Sigor@sysoev.ru             if (ret == 0) {
20681062Sigor@sysoev.ru                 break;
20691062Sigor@sysoev.ru             }
20701062Sigor@sysoev.ru         }
20711062Sigor@sysoev.ru 
20721062Sigor@sysoev.ru         nv++;
20731062Sigor@sysoev.ru     }
20741062Sigor@sysoev.ru 
20751062Sigor@sysoev.ru     return ret;
20761062Sigor@sysoev.ru }
20771062Sigor@sysoev.ru 
20781062Sigor@sysoev.ru 
20791859So.canty@f5.com nxt_int_t
nxt_http_route_test_rule(nxt_http_request_t * r,nxt_http_route_rule_t * rule,u_char * start,size_t length)20801059Sigor@sysoev.ru nxt_http_route_test_rule(nxt_http_request_t *r, nxt_http_route_rule_t *rule,
20811059Sigor@sysoev.ru     u_char *start, size_t length)
20821059Sigor@sysoev.ru {
20831060Sigor@sysoev.ru     nxt_int_t                 ret;
20841059Sigor@sysoev.ru     nxt_http_route_pattern_t  *pattern, *end;
20851059Sigor@sysoev.ru 
20861057Sigor@sysoev.ru     ret = 1;
2087964Sigor@sysoev.ru     pattern = &rule->pattern[0];
20881033Svbart@nginx.com     end = pattern + rule->items;
2089964Sigor@sysoev.ru 
20901057Sigor@sysoev.ru     while (pattern < end) {
2091964Sigor@sysoev.ru         ret = nxt_http_route_pattern(r, pattern, start, length);
20921721Saxel.duch@nginx.com         if (nxt_slow_path(ret == NXT_ERROR)) {
20931721Saxel.duch@nginx.com             return NXT_ERROR;
20941721Saxel.duch@nginx.com         }
2095964Sigor@sysoev.ru 
20961060Sigor@sysoev.ru         /* nxt_http_route_pattern() returns either 1 or 0. */
2097964Sigor@sysoev.ru         ret ^= pattern->negative;
2098964Sigor@sysoev.ru 
2099964Sigor@sysoev.ru         if (pattern->any == ret) {
2100964Sigor@sysoev.ru             return ret;
2101964Sigor@sysoev.ru         }
2102964Sigor@sysoev.ru 
2103964Sigor@sysoev.ru         pattern++;
21041057Sigor@sysoev.ru     }
2105964Sigor@sysoev.ru 
2106964Sigor@sysoev.ru     return ret;
2107964Sigor@sysoev.ru }
2108964Sigor@sysoev.ru 
2109964Sigor@sysoev.ru 
21101060Sigor@sysoev.ru static nxt_int_t
nxt_http_route_pattern(nxt_http_request_t * r,nxt_http_route_pattern_t * pattern,u_char * start,size_t length)2111964Sigor@sysoev.ru nxt_http_route_pattern(nxt_http_request_t *r, nxt_http_route_pattern_t *pattern,
2112964Sigor@sysoev.ru     u_char *start, size_t length)
2113964Sigor@sysoev.ru {
21141508Saxel.duch@nginx.com     u_char                          *p, *end, *test;
21151508Saxel.duch@nginx.com     size_t                          test_length;
21161508Saxel.duch@nginx.com     uint32_t                        i;
21171508Saxel.duch@nginx.com     nxt_array_t                     *pattern_slices;
21181508Saxel.duch@nginx.com     nxt_http_route_pattern_slice_t  *pattern_slice;
2119964Sigor@sysoev.ru 
21201721Saxel.duch@nginx.com #if (NXT_HAVE_REGEX)
21211721Saxel.duch@nginx.com     if (pattern->regex) {
21221721Saxel.duch@nginx.com         if (r->regex_match == NULL) {
21231721Saxel.duch@nginx.com             r->regex_match = nxt_regex_match_create(r->mem_pool, 0);
21241721Saxel.duch@nginx.com             if (nxt_slow_path(r->regex_match == NULL)) {
21251721Saxel.duch@nginx.com                 return NXT_ERROR;
21261721Saxel.duch@nginx.com             }
21271721Saxel.duch@nginx.com         }
21281721Saxel.duch@nginx.com 
21291721Saxel.duch@nginx.com         return nxt_regex_match(pattern->u.regex, start, length, r->regex_match);
21301721Saxel.duch@nginx.com     }
21311721Saxel.duch@nginx.com #endif
21321721Saxel.duch@nginx.com 
2133964Sigor@sysoev.ru     if (length < pattern->min_length) {
2134964Sigor@sysoev.ru         return 0;
2135964Sigor@sysoev.ru     }
2136964Sigor@sysoev.ru 
2137*2743Szelenkov@nginx.com     nxt_assert(pattern->u.pattern_slices != NULL);
2138*2743Szelenkov@nginx.com 
2139*2743Szelenkov@nginx.com     pattern_slices = pattern->u.pattern_slices;
2140*2743Szelenkov@nginx.com     pattern_slice = pattern_slices->elts;
21411721Saxel.duch@nginx.com     end = start + length;
21421721Saxel.duch@nginx.com 
21431721Saxel.duch@nginx.com     for (i = 0; i < pattern_slices->nelts; i++, pattern_slice++) {
21441508Saxel.duch@nginx.com         test = pattern_slice->start;
21451510Saxel.duch@nginx.com         test_length = pattern_slice->length;
21461508Saxel.duch@nginx.com 
21471508Saxel.duch@nginx.com         switch (pattern_slice->type) {
21481508Saxel.duch@nginx.com         case NXT_HTTP_ROUTE_PATTERN_EXACT:
21491508Saxel.duch@nginx.com             return ((length == pattern->min_length) &&
21501508Saxel.duch@nginx.com                     nxt_http_route_memcmp(start, test, test_length,
21511508Saxel.duch@nginx.com                                           pattern->case_sensitive));
21521508Saxel.duch@nginx.com 
21531508Saxel.duch@nginx.com         case NXT_HTTP_ROUTE_PATTERN_BEGIN:
21541508Saxel.duch@nginx.com             if (nxt_http_route_memcmp(start, test, test_length,
21551508Saxel.duch@nginx.com                                       pattern->case_sensitive))
21561508Saxel.duch@nginx.com             {
21571508Saxel.duch@nginx.com                 start += test_length;
21581508Saxel.duch@nginx.com                 break;
21591508Saxel.duch@nginx.com             }
21601508Saxel.duch@nginx.com 
21611510Saxel.duch@nginx.com             return 0;
21621508Saxel.duch@nginx.com 
21631508Saxel.duch@nginx.com         case NXT_HTTP_ROUTE_PATTERN_END:
21641508Saxel.duch@nginx.com             p = end - test_length;
2165964Sigor@sysoev.ru 
21661508Saxel.duch@nginx.com             if (nxt_http_route_memcmp(p, test, test_length,
21671508Saxel.duch@nginx.com                                       pattern->case_sensitive))
21681510Saxel.duch@nginx.com             {
21691508Saxel.duch@nginx.com                 end = p;
21701508Saxel.duch@nginx.com                 break;
21711508Saxel.duch@nginx.com             }
21721508Saxel.duch@nginx.com 
21731510Saxel.duch@nginx.com             return 0;
21741508Saxel.duch@nginx.com 
21751508Saxel.duch@nginx.com         case NXT_HTTP_ROUTE_PATTERN_SUBSTRING:
21761508Saxel.duch@nginx.com             if (pattern->case_sensitive) {
21771508Saxel.duch@nginx.com                 p = nxt_memstrn(start, end, (char *) test, test_length);
21781508Saxel.duch@nginx.com 
21791508Saxel.duch@nginx.com             } else {
21801508Saxel.duch@nginx.com                 p = nxt_memcasestrn(start, end, (char *) test, test_length);
21811508Saxel.duch@nginx.com             }
21821508Saxel.duch@nginx.com 
21831508Saxel.duch@nginx.com             if (p == NULL) {
21841508Saxel.duch@nginx.com                 return 0;
21851508Saxel.duch@nginx.com             }
21861508Saxel.duch@nginx.com 
21871508Saxel.duch@nginx.com             start = p + test_length;
21881508Saxel.duch@nginx.com         }
21891508Saxel.duch@nginx.com     }
21901510Saxel.duch@nginx.com 
21911510Saxel.duch@nginx.com     return 1;
21921032Sigor@sysoev.ru }
2193964Sigor@sysoev.ru 
2194964Sigor@sysoev.ru 
21951508Saxel.duch@nginx.com static nxt_int_t
nxt_http_route_memcmp(u_char * start,u_char * test,size_t test_length,nxt_bool_t case_sensitive)21961032Sigor@sysoev.ru nxt_http_route_memcmp(u_char *start, u_char *test, size_t test_length,
21971032Sigor@sysoev.ru     nxt_bool_t case_sensitive)
21981032Sigor@sysoev.ru {
21991060Sigor@sysoev.ru     nxt_int_t  n;
22001032Sigor@sysoev.ru 
22011032Sigor@sysoev.ru     if (case_sensitive) {
22021032Sigor@sysoev.ru         n = memcmp(start, test, test_length);
22031032Sigor@sysoev.ru 
22041032Sigor@sysoev.ru     } else {
22051032Sigor@sysoev.ru         n = nxt_memcasecmp(start, test, test_length);
22062231Salx@nginx.com     }
22071032Sigor@sysoev.ru 
22081032Sigor@sysoev.ru     return (n == 0);
22091032Sigor@sysoev.ru }
2210964Sigor@sysoev.ru