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 431474Saxel.duch@nginx.com typedef enum { 441474Saxel.duch@nginx.com NXT_HTTP_ROUTE_ENCODING_NONE = 0, 451474Saxel.duch@nginx.com NXT_HTTP_ROUTE_ENCODING_URI, 461474Saxel.duch@nginx.com NXT_HTTP_ROUTE_ENCODING_URI_PLUS 471474Saxel.duch@nginx.com } nxt_http_route_encoding_t; 481474Saxel.duch@nginx.com 491474Saxel.duch@nginx.com 50964Sigor@sysoev.ru typedef struct { 51964Sigor@sysoev.ru nxt_conf_value_t *host; 52964Sigor@sysoev.ru nxt_conf_value_t *uri; 53964Sigor@sysoev.ru nxt_conf_value_t *method; 541059Sigor@sysoev.ru nxt_conf_value_t *headers; 551061Sigor@sysoev.ru nxt_conf_value_t *arguments; 561062Sigor@sysoev.ru nxt_conf_value_t *cookies; 571110Saxel.duch@nginx.com nxt_conf_value_t *scheme; 581991Sz.hong@f5.com nxt_conf_value_t *query; 591324Saxel.duch@nginx.com nxt_conf_value_t *source; 601326Saxel.duch@nginx.com nxt_conf_value_t *destination; 61964Sigor@sysoev.ru } nxt_http_route_match_conf_t; 62964Sigor@sysoev.ru 63964Sigor@sysoev.ru 64964Sigor@sysoev.ru typedef struct { 651508Saxel.duch@nginx.com u_char *start; 661508Saxel.duch@nginx.com uint32_t length; 671508Saxel.duch@nginx.com nxt_http_route_pattern_type_t type:8; 681508Saxel.duch@nginx.com } nxt_http_route_pattern_slice_t; 691508Saxel.duch@nginx.com 701508Saxel.duch@nginx.com 711508Saxel.duch@nginx.com typedef struct { 721721Saxel.duch@nginx.com union { 731721Saxel.duch@nginx.com nxt_array_t *pattern_slices; 741721Saxel.duch@nginx.com #if (NXT_HAVE_REGEX) 751721Saxel.duch@nginx.com nxt_regex_t *regex; 761721Saxel.duch@nginx.com #endif 771721Saxel.duch@nginx.com } u; 78964Sigor@sysoev.ru uint32_t min_length; 791508Saxel.duch@nginx.com 80964Sigor@sysoev.ru uint8_t case_sensitive; /* 1 bit */ 81964Sigor@sysoev.ru uint8_t negative; /* 1 bit */ 82964Sigor@sysoev.ru uint8_t any; /* 1 bit */ 831721Saxel.duch@nginx.com #if (NXT_HAVE_REGEX) 841721Saxel.duch@nginx.com uint8_t regex; /* 1 bit */ 851721Saxel.duch@nginx.com #endif 86964Sigor@sysoev.ru } nxt_http_route_pattern_t; 87964Sigor@sysoev.ru 88964Sigor@sysoev.ru 89964Sigor@sysoev.ru typedef struct { 901061Sigor@sysoev.ru uint16_t hash; 911061Sigor@sysoev.ru uint16_t name_length; 921061Sigor@sysoev.ru uint32_t value_length; 931061Sigor@sysoev.ru u_char *name; 941061Sigor@sysoev.ru u_char *value; 951061Sigor@sysoev.ru } nxt_http_name_value_t; 961061Sigor@sysoev.ru 971061Sigor@sysoev.ru 981061Sigor@sysoev.ru typedef struct { 991062Sigor@sysoev.ru uint16_t hash; 1001062Sigor@sysoev.ru uint16_t name_length; 1011062Sigor@sysoev.ru uint32_t value_length; 1021062Sigor@sysoev.ru u_char *name; 1031062Sigor@sysoev.ru u_char *value; 1041062Sigor@sysoev.ru } nxt_http_cookie_t; 1051062Sigor@sysoev.ru 1061062Sigor@sysoev.ru 1071859So.canty@f5.com struct nxt_http_route_rule_s { 1081059Sigor@sysoev.ru /* The object must be the first field. */ 1091059Sigor@sysoev.ru nxt_http_route_object_t object:8; 110964Sigor@sysoev.ru uint32_t items; 1111059Sigor@sysoev.ru 1121059Sigor@sysoev.ru union { 1131059Sigor@sysoev.ru uintptr_t offset; 1141059Sigor@sysoev.ru 1151059Sigor@sysoev.ru struct { 1161059Sigor@sysoev.ru u_char *start; 1171059Sigor@sysoev.ru uint16_t hash; 1181059Sigor@sysoev.ru uint16_t length; 1191059Sigor@sysoev.ru } name; 1201059Sigor@sysoev.ru } u; 1211059Sigor@sysoev.ru 122964Sigor@sysoev.ru nxt_http_route_pattern_t pattern[0]; 1231859So.canty@f5.com }; 124964Sigor@sysoev.ru 125964Sigor@sysoev.ru 126964Sigor@sysoev.ru typedef struct { 127964Sigor@sysoev.ru uint32_t items; 1281059Sigor@sysoev.ru nxt_http_route_rule_t *rule[0]; 1291059Sigor@sysoev.ru } nxt_http_route_ruleset_t; 1301059Sigor@sysoev.ru 1311059Sigor@sysoev.ru 1321059Sigor@sysoev.ru typedef struct { 1331059Sigor@sysoev.ru /* The object must be the first field. */ 1341059Sigor@sysoev.ru nxt_http_route_object_t object:8; 1351059Sigor@sysoev.ru uint32_t items; 1361059Sigor@sysoev.ru nxt_http_route_ruleset_t *ruleset[0]; 1371059Sigor@sysoev.ru } nxt_http_route_table_t; 1381059Sigor@sysoev.ru 1391059Sigor@sysoev.ru 1401936So.canty@f5.com struct nxt_http_route_addr_rule_s { 1411324Saxel.duch@nginx.com /* The object must be the first field. */ 1421324Saxel.duch@nginx.com nxt_http_route_object_t object:8; 1431324Saxel.duch@nginx.com uint32_t items; 1441324Saxel.duch@nginx.com nxt_http_route_addr_pattern_t addr_pattern[0]; 1451936So.canty@f5.com }; 1461324Saxel.duch@nginx.com 1471324Saxel.duch@nginx.com 1481059Sigor@sysoev.ru typedef union { 1491059Sigor@sysoev.ru nxt_http_route_rule_t *rule; 1501059Sigor@sysoev.ru nxt_http_route_table_t *table; 1511324Saxel.duch@nginx.com nxt_http_route_addr_rule_t *addr_rule; 1521059Sigor@sysoev.ru } nxt_http_route_test_t; 1531059Sigor@sysoev.ru 1541059Sigor@sysoev.ru 1551059Sigor@sysoev.ru typedef struct { 1561059Sigor@sysoev.ru uint32_t items; 1571264Sigor@sysoev.ru nxt_http_action_t action; 1581059Sigor@sysoev.ru nxt_http_route_test_t test[0]; 159964Sigor@sysoev.ru } nxt_http_route_match_t; 160964Sigor@sysoev.ru 161964Sigor@sysoev.ru 162964Sigor@sysoev.ru struct nxt_http_route_s { 163964Sigor@sysoev.ru nxt_str_t name; 164964Sigor@sysoev.ru uint32_t items; 165964Sigor@sysoev.ru nxt_http_route_match_t *match[0]; 166964Sigor@sysoev.ru }; 167964Sigor@sysoev.ru 168964Sigor@sysoev.ru 169964Sigor@sysoev.ru struct nxt_http_routes_s { 170964Sigor@sysoev.ru uint32_t items; 171964Sigor@sysoev.ru nxt_http_route_t *route[0]; 172964Sigor@sysoev.ru }; 173964Sigor@sysoev.ru 174964Sigor@sysoev.ru 1751522Saxel.duch@nginx.com #define NXT_COOKIE_HASH \ 1761062Sigor@sysoev.ru (nxt_http_field_hash_end( \ 1771062Sigor@sysoev.ru nxt_http_field_hash_char( \ 1781062Sigor@sysoev.ru nxt_http_field_hash_char( \ 1791062Sigor@sysoev.ru nxt_http_field_hash_char( \ 1801062Sigor@sysoev.ru nxt_http_field_hash_char( \ 1811062Sigor@sysoev.ru nxt_http_field_hash_char( \ 1821062Sigor@sysoev.ru nxt_http_field_hash_char(NXT_HTTP_FIELD_HASH_INIT, \ 1831062Sigor@sysoev.ru 'c'), 'o'), 'o'), 'k'), 'i'), 'e')) & 0xFFFF) 1841062Sigor@sysoev.ru 1851062Sigor@sysoev.ru 186964Sigor@sysoev.ru static nxt_http_route_t *nxt_http_route_create(nxt_task_t *task, 187964Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf, nxt_conf_value_t *cv); 188964Sigor@sysoev.ru static nxt_http_route_match_t *nxt_http_route_match_create(nxt_task_t *task, 189964Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf, nxt_conf_value_t *cv); 1901059Sigor@sysoev.ru static nxt_http_route_table_t *nxt_http_route_table_create(nxt_task_t *task, 1911061Sigor@sysoev.ru nxt_mp_t *mp, nxt_conf_value_t *table_cv, nxt_http_route_object_t object, 1921474Saxel.duch@nginx.com nxt_bool_t case_sensitive, nxt_http_route_encoding_t encoding); 1931059Sigor@sysoev.ru static nxt_http_route_ruleset_t *nxt_http_route_ruleset_create(nxt_task_t *task, 1941061Sigor@sysoev.ru nxt_mp_t *mp, nxt_conf_value_t *ruleset_cv, nxt_http_route_object_t object, 1951474Saxel.duch@nginx.com nxt_bool_t case_sensitive, nxt_http_route_encoding_t encoding); 1961061Sigor@sysoev.ru static nxt_http_route_rule_t *nxt_http_route_rule_name_create(nxt_task_t *task, 1971061Sigor@sysoev.ru nxt_mp_t *mp, nxt_conf_value_t *rule_cv, nxt_str_t *name, 1981474Saxel.duch@nginx.com nxt_bool_t case_sensitive, nxt_http_route_encoding_t encoding); 199964Sigor@sysoev.ru static nxt_http_route_rule_t *nxt_http_route_rule_create(nxt_task_t *task, 2001059Sigor@sysoev.ru nxt_mp_t *mp, nxt_conf_value_t *cv, nxt_bool_t case_sensitive, 2011474Saxel.duch@nginx.com nxt_http_route_pattern_case_t pattern_case, 2021474Saxel.duch@nginx.com nxt_http_route_encoding_t encoding); 203964Sigor@sysoev.ru static int nxt_http_pattern_compare(const void *one, const void *two); 2041390Saxel.duch@nginx.com static int nxt_http_addr_pattern_compare(const void *one, const void *two); 205964Sigor@sysoev.ru static nxt_int_t nxt_http_route_pattern_create(nxt_task_t *task, nxt_mp_t *mp, 206964Sigor@sysoev.ru nxt_conf_value_t *cv, nxt_http_route_pattern_t *pattern, 2071474Saxel.duch@nginx.com nxt_http_route_pattern_case_t pattern_case, 2081474Saxel.duch@nginx.com nxt_http_route_encoding_t encoding); 2091474Saxel.duch@nginx.com static nxt_int_t nxt_http_route_decode_str(nxt_str_t *str, 2101474Saxel.duch@nginx.com nxt_http_route_encoding_t encoding); 2111508Saxel.duch@nginx.com static nxt_int_t nxt_http_route_pattern_slice(nxt_array_t *slices, 2121508Saxel.duch@nginx.com nxt_str_t *test, 2131508Saxel.duch@nginx.com nxt_http_route_pattern_type_t type, 2141508Saxel.duch@nginx.com nxt_http_route_encoding_t encoding, 2151032Sigor@sysoev.ru nxt_http_route_pattern_case_t pattern_case); 216964Sigor@sysoev.ru 2171472Svbart@nginx.com static nxt_int_t nxt_http_route_resolve(nxt_task_t *task, 218964Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf, nxt_http_route_t *route); 2191472Svbart@nginx.com static nxt_int_t nxt_http_action_resolve(nxt_task_t *task, 2201264Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf, nxt_http_action_t *action); 2211954Sz.hong@f5.com static nxt_http_action_t *nxt_http_pass_var(nxt_task_t *task, 2221563Svbart@nginx.com nxt_http_request_t *r, nxt_http_action_t *action); 2231954Sz.hong@f5.com static void nxt_http_pass_var_ready(nxt_task_t *task, void *obj, void *data); 2241954Sz.hong@f5.com static void nxt_http_pass_var_error(nxt_task_t *task, void *obj, void *data); 2251954Sz.hong@f5.com static nxt_int_t nxt_http_pass_find(nxt_mp_t *mp, nxt_router_conf_t *rtcf, 2261954Sz.hong@f5.com nxt_str_t *pass, nxt_http_action_t *action); 2271563Svbart@nginx.com static nxt_int_t nxt_http_route_find(nxt_http_routes_t *routes, nxt_str_t *name, 2281392Sigor@sysoev.ru nxt_http_action_t *action); 229964Sigor@sysoev.ru 2301264Sigor@sysoev.ru static nxt_http_action_t *nxt_http_route_handler(nxt_task_t *task, 2311264Sigor@sysoev.ru nxt_http_request_t *r, nxt_http_action_t *start); 2321326Saxel.duch@nginx.com static nxt_http_action_t *nxt_http_route_match(nxt_task_t *task, 2331326Saxel.duch@nginx.com nxt_http_request_t *r, nxt_http_route_match_t *match); 2341060Sigor@sysoev.ru static nxt_int_t nxt_http_route_table(nxt_http_request_t *r, 2351059Sigor@sysoev.ru nxt_http_route_table_t *table); 2361060Sigor@sysoev.ru static nxt_int_t nxt_http_route_ruleset(nxt_http_request_t *r, 2371059Sigor@sysoev.ru nxt_http_route_ruleset_t *ruleset); 2381060Sigor@sysoev.ru static nxt_int_t nxt_http_route_rule(nxt_http_request_t *r, 239964Sigor@sysoev.ru nxt_http_route_rule_t *rule); 2401060Sigor@sysoev.ru static nxt_int_t nxt_http_route_header(nxt_http_request_t *r, 2411059Sigor@sysoev.ru nxt_http_route_rule_t *rule); 2421061Sigor@sysoev.ru static nxt_int_t nxt_http_route_arguments(nxt_http_request_t *r, 2431061Sigor@sysoev.ru nxt_http_route_rule_t *rule); 2441061Sigor@sysoev.ru static nxt_array_t *nxt_http_route_arguments_parse(nxt_http_request_t *r); 2451061Sigor@sysoev.ru static nxt_http_name_value_t *nxt_http_route_argument(nxt_array_t *array, 2461061Sigor@sysoev.ru u_char *name, size_t name_length, uint32_t hash, u_char *start, 2471061Sigor@sysoev.ru u_char *end); 2481061Sigor@sysoev.ru static nxt_int_t nxt_http_route_test_argument(nxt_http_request_t *r, 2491061Sigor@sysoev.ru nxt_http_route_rule_t *rule, nxt_array_t *array); 2501110Saxel.duch@nginx.com static nxt_int_t nxt_http_route_scheme(nxt_http_request_t *r, 2511110Saxel.duch@nginx.com nxt_http_route_rule_t *rule); 2521991Sz.hong@f5.com static nxt_int_t nxt_http_route_query(nxt_http_request_t *r, 2531991Sz.hong@f5.com nxt_http_route_rule_t *rule); 2541062Sigor@sysoev.ru static nxt_int_t nxt_http_route_cookies(nxt_http_request_t *r, 2551062Sigor@sysoev.ru nxt_http_route_rule_t *rule); 2561062Sigor@sysoev.ru static nxt_array_t *nxt_http_route_cookies_parse(nxt_http_request_t *r); 2571062Sigor@sysoev.ru static nxt_int_t nxt_http_route_cookie_parse(nxt_array_t *cookies, 2581062Sigor@sysoev.ru u_char *start, u_char *end); 2591062Sigor@sysoev.ru static nxt_http_name_value_t *nxt_http_route_cookie(nxt_array_t *array, 2601062Sigor@sysoev.ru u_char *name, size_t name_length, u_char *start, u_char *end); 2611062Sigor@sysoev.ru static nxt_int_t nxt_http_route_test_cookie(nxt_http_request_t *r, 2621062Sigor@sysoev.ru nxt_http_route_rule_t *rule, nxt_array_t *array); 2631060Sigor@sysoev.ru static nxt_int_t nxt_http_route_pattern(nxt_http_request_t *r, 264964Sigor@sysoev.ru nxt_http_route_pattern_t *pattern, u_char *start, size_t length); 2651060Sigor@sysoev.ru static nxt_int_t nxt_http_route_memcmp(u_char *start, u_char *test, 2661032Sigor@sysoev.ru size_t length, nxt_bool_t case_sensitive); 267964Sigor@sysoev.ru 268964Sigor@sysoev.ru 269964Sigor@sysoev.ru nxt_http_routes_t * 270964Sigor@sysoev.ru nxt_http_routes_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, 271964Sigor@sysoev.ru nxt_conf_value_t *routes_conf) 272964Sigor@sysoev.ru { 273964Sigor@sysoev.ru size_t size; 274964Sigor@sysoev.ru uint32_t i, n, next; 275964Sigor@sysoev.ru nxt_mp_t *mp; 276964Sigor@sysoev.ru nxt_str_t name, *string; 277964Sigor@sysoev.ru nxt_bool_t object; 278964Sigor@sysoev.ru nxt_conf_value_t *route_conf; 279964Sigor@sysoev.ru nxt_http_route_t *route; 280964Sigor@sysoev.ru nxt_http_routes_t *routes; 281964Sigor@sysoev.ru 282964Sigor@sysoev.ru object = (nxt_conf_type(routes_conf) == NXT_CONF_OBJECT); 283964Sigor@sysoev.ru n = object ? nxt_conf_object_members_count(routes_conf) : 1; 284964Sigor@sysoev.ru size = sizeof(nxt_http_routes_t) + n * sizeof(nxt_http_route_t *); 285964Sigor@sysoev.ru 286964Sigor@sysoev.ru mp = tmcf->router_conf->mem_pool; 287964Sigor@sysoev.ru 288964Sigor@sysoev.ru routes = nxt_mp_alloc(mp, size); 289964Sigor@sysoev.ru if (nxt_slow_path(routes == NULL)) { 290964Sigor@sysoev.ru return NULL; 291964Sigor@sysoev.ru } 292964Sigor@sysoev.ru 293964Sigor@sysoev.ru routes->items = n; 294964Sigor@sysoev.ru 295964Sigor@sysoev.ru if (object) { 296964Sigor@sysoev.ru next = 0; 297964Sigor@sysoev.ru 298964Sigor@sysoev.ru for (i = 0; i < n; i++) { 299964Sigor@sysoev.ru route_conf = nxt_conf_next_object_member(routes_conf, &name, &next); 300964Sigor@sysoev.ru 301964Sigor@sysoev.ru route = nxt_http_route_create(task, tmcf, route_conf); 302964Sigor@sysoev.ru if (nxt_slow_path(route == NULL)) { 303964Sigor@sysoev.ru return NULL; 304964Sigor@sysoev.ru } 305964Sigor@sysoev.ru 306964Sigor@sysoev.ru routes->route[i] = route; 307964Sigor@sysoev.ru 308964Sigor@sysoev.ru string = nxt_str_dup(mp, &route->name, &name); 309964Sigor@sysoev.ru if (nxt_slow_path(string == NULL)) { 310964Sigor@sysoev.ru return NULL; 311964Sigor@sysoev.ru } 312964Sigor@sysoev.ru } 313964Sigor@sysoev.ru 314964Sigor@sysoev.ru } else { 315964Sigor@sysoev.ru route = nxt_http_route_create(task, tmcf, routes_conf); 316964Sigor@sysoev.ru if (nxt_slow_path(route == NULL)) { 317964Sigor@sysoev.ru return NULL; 318964Sigor@sysoev.ru } 319964Sigor@sysoev.ru 320964Sigor@sysoev.ru routes->route[0] = route; 321964Sigor@sysoev.ru 322964Sigor@sysoev.ru route->name.length = 0; 323964Sigor@sysoev.ru route->name.start = NULL; 324964Sigor@sysoev.ru } 325964Sigor@sysoev.ru 326964Sigor@sysoev.ru return routes; 327964Sigor@sysoev.ru } 328964Sigor@sysoev.ru 329964Sigor@sysoev.ru 330964Sigor@sysoev.ru static nxt_conf_map_t nxt_http_route_match_conf[] = { 331964Sigor@sysoev.ru { 3321110Saxel.duch@nginx.com nxt_string("scheme"), 3331110Saxel.duch@nginx.com NXT_CONF_MAP_PTR, 3341110Saxel.duch@nginx.com offsetof(nxt_http_route_match_conf_t, scheme) 3351110Saxel.duch@nginx.com }, 3361110Saxel.duch@nginx.com { 337964Sigor@sysoev.ru nxt_string("host"), 338964Sigor@sysoev.ru NXT_CONF_MAP_PTR, 339964Sigor@sysoev.ru offsetof(nxt_http_route_match_conf_t, host), 340964Sigor@sysoev.ru }, 341964Sigor@sysoev.ru 342964Sigor@sysoev.ru { 343964Sigor@sysoev.ru nxt_string("uri"), 344964Sigor@sysoev.ru NXT_CONF_MAP_PTR, 345964Sigor@sysoev.ru offsetof(nxt_http_route_match_conf_t, uri), 346964Sigor@sysoev.ru }, 347964Sigor@sysoev.ru 348964Sigor@sysoev.ru { 349964Sigor@sysoev.ru nxt_string("method"), 350964Sigor@sysoev.ru NXT_CONF_MAP_PTR, 351964Sigor@sysoev.ru offsetof(nxt_http_route_match_conf_t, method), 352964Sigor@sysoev.ru }, 3531059Sigor@sysoev.ru 3541059Sigor@sysoev.ru { 3551059Sigor@sysoev.ru nxt_string("headers"), 3561059Sigor@sysoev.ru NXT_CONF_MAP_PTR, 3571059Sigor@sysoev.ru offsetof(nxt_http_route_match_conf_t, headers), 3581059Sigor@sysoev.ru }, 3591061Sigor@sysoev.ru 3601061Sigor@sysoev.ru { 3611061Sigor@sysoev.ru nxt_string("arguments"), 3621061Sigor@sysoev.ru NXT_CONF_MAP_PTR, 3631061Sigor@sysoev.ru offsetof(nxt_http_route_match_conf_t, arguments), 3641061Sigor@sysoev.ru }, 3651062Sigor@sysoev.ru 3661062Sigor@sysoev.ru { 3671062Sigor@sysoev.ru nxt_string("cookies"), 3681062Sigor@sysoev.ru NXT_CONF_MAP_PTR, 3691062Sigor@sysoev.ru offsetof(nxt_http_route_match_conf_t, cookies), 3701062Sigor@sysoev.ru }, 3711324Saxel.duch@nginx.com 3721324Saxel.duch@nginx.com { 3731991Sz.hong@f5.com nxt_string("query"), 3741991Sz.hong@f5.com NXT_CONF_MAP_PTR, 3751991Sz.hong@f5.com offsetof(nxt_http_route_match_conf_t, query), 3761991Sz.hong@f5.com }, 3771991Sz.hong@f5.com 3781991Sz.hong@f5.com { 3791324Saxel.duch@nginx.com nxt_string("source"), 3801324Saxel.duch@nginx.com NXT_CONF_MAP_PTR, 3811324Saxel.duch@nginx.com offsetof(nxt_http_route_match_conf_t, source), 3821324Saxel.duch@nginx.com }, 3831326Saxel.duch@nginx.com 3841326Saxel.duch@nginx.com { 3851326Saxel.duch@nginx.com nxt_string("destination"), 3861326Saxel.duch@nginx.com NXT_CONF_MAP_PTR, 3871326Saxel.duch@nginx.com offsetof(nxt_http_route_match_conf_t, destination), 3881326Saxel.duch@nginx.com }, 389964Sigor@sysoev.ru }; 390964Sigor@sysoev.ru 391964Sigor@sysoev.ru 392964Sigor@sysoev.ru static nxt_http_route_t * 393964Sigor@sysoev.ru nxt_http_route_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 i, n; 398964Sigor@sysoev.ru nxt_conf_value_t *value; 399964Sigor@sysoev.ru nxt_http_route_t *route; 400964Sigor@sysoev.ru nxt_http_route_match_t *match, **m; 401964Sigor@sysoev.ru 402964Sigor@sysoev.ru n = nxt_conf_array_elements_count(cv); 403964Sigor@sysoev.ru size = sizeof(nxt_http_route_t) + n * sizeof(nxt_http_route_match_t *); 404964Sigor@sysoev.ru 405964Sigor@sysoev.ru route = nxt_mp_alloc(tmcf->router_conf->mem_pool, size); 406964Sigor@sysoev.ru if (nxt_slow_path(route == NULL)) { 407964Sigor@sysoev.ru return NULL; 408964Sigor@sysoev.ru } 409964Sigor@sysoev.ru 410964Sigor@sysoev.ru route->items = n; 411964Sigor@sysoev.ru m = &route->match[0]; 412964Sigor@sysoev.ru 413964Sigor@sysoev.ru for (i = 0; i < n; i++) { 414964Sigor@sysoev.ru value = nxt_conf_get_array_element(cv, i); 415964Sigor@sysoev.ru 416964Sigor@sysoev.ru match = nxt_http_route_match_create(task, tmcf, value); 417964Sigor@sysoev.ru if (match == NULL) { 418964Sigor@sysoev.ru return NULL; 419964Sigor@sysoev.ru } 420964Sigor@sysoev.ru 421964Sigor@sysoev.ru *m++ = match; 422964Sigor@sysoev.ru } 423964Sigor@sysoev.ru 424964Sigor@sysoev.ru return route; 425964Sigor@sysoev.ru } 426964Sigor@sysoev.ru 427964Sigor@sysoev.ru 428964Sigor@sysoev.ru static nxt_http_route_match_t * 429964Sigor@sysoev.ru nxt_http_route_match_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, 430964Sigor@sysoev.ru nxt_conf_value_t *cv) 431964Sigor@sysoev.ru { 432964Sigor@sysoev.ru size_t size; 433964Sigor@sysoev.ru uint32_t n; 4341059Sigor@sysoev.ru nxt_mp_t *mp; 435964Sigor@sysoev.ru nxt_int_t ret; 4361378Svbart@nginx.com nxt_conf_value_t *match_conf, *action_conf; 4371059Sigor@sysoev.ru nxt_http_route_test_t *test; 4381059Sigor@sysoev.ru nxt_http_route_rule_t *rule; 4391059Sigor@sysoev.ru nxt_http_route_table_t *table; 440964Sigor@sysoev.ru nxt_http_route_match_t *match; 4411324Saxel.duch@nginx.com nxt_http_route_addr_rule_t *addr_rule; 442964Sigor@sysoev.ru nxt_http_route_match_conf_t mtcf; 443964Sigor@sysoev.ru 444964Sigor@sysoev.ru static nxt_str_t match_path = nxt_string("/match"); 4451378Svbart@nginx.com static nxt_str_t action_path = nxt_string("/action"); 446964Sigor@sysoev.ru 447964Sigor@sysoev.ru match_conf = nxt_conf_get_path(cv, &match_path); 448964Sigor@sysoev.ru 449964Sigor@sysoev.ru n = (match_conf != NULL) ? nxt_conf_object_members_count(match_conf) : 0; 4501859So.canty@f5.com size = sizeof(nxt_http_route_match_t) + n * sizeof(nxt_http_route_test_t *); 451964Sigor@sysoev.ru 4521059Sigor@sysoev.ru mp = tmcf->router_conf->mem_pool; 4531059Sigor@sysoev.ru 4541059Sigor@sysoev.ru match = nxt_mp_alloc(mp, size); 455964Sigor@sysoev.ru if (nxt_slow_path(match == NULL)) { 456964Sigor@sysoev.ru return NULL; 457964Sigor@sysoev.ru } 458964Sigor@sysoev.ru 459964Sigor@sysoev.ru match->items = n; 460964Sigor@sysoev.ru 4611378Svbart@nginx.com action_conf = nxt_conf_get_path(cv, &action_path); 4621378Svbart@nginx.com if (nxt_slow_path(action_conf == NULL)) { 4631378Svbart@nginx.com return NULL; 4641378Svbart@nginx.com } 4651378Svbart@nginx.com 4661903Sz.hong@f5.com ret = nxt_http_action_init(task, tmcf, action_conf, &match->action); 4671264Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 468964Sigor@sysoev.ru return NULL; 469964Sigor@sysoev.ru } 470964Sigor@sysoev.ru 471964Sigor@sysoev.ru if (n == 0) { 472964Sigor@sysoev.ru return match; 473964Sigor@sysoev.ru } 474964Sigor@sysoev.ru 475964Sigor@sysoev.ru nxt_memzero(&mtcf, sizeof(mtcf)); 476964Sigor@sysoev.ru 477964Sigor@sysoev.ru ret = nxt_conf_map_object(tmcf->mem_pool, 478964Sigor@sysoev.ru match_conf, nxt_http_route_match_conf, 479964Sigor@sysoev.ru nxt_nitems(nxt_http_route_match_conf), &mtcf); 480964Sigor@sysoev.ru if (ret != NXT_OK) { 481964Sigor@sysoev.ru return NULL; 482964Sigor@sysoev.ru } 483964Sigor@sysoev.ru 4841059Sigor@sysoev.ru test = &match->test[0]; 485964Sigor@sysoev.ru 4861110Saxel.duch@nginx.com if (mtcf.scheme != NULL) { 4871110Saxel.duch@nginx.com rule = nxt_http_route_rule_create(task, mp, mtcf.scheme, 1, 4881474Saxel.duch@nginx.com NXT_HTTP_ROUTE_PATTERN_NOCASE, 4891474Saxel.duch@nginx.com NXT_HTTP_ROUTE_ENCODING_NONE); 4901110Saxel.duch@nginx.com if (rule == NULL) { 4911110Saxel.duch@nginx.com return NULL; 4921110Saxel.duch@nginx.com } 4931110Saxel.duch@nginx.com 4941110Saxel.duch@nginx.com rule->object = NXT_HTTP_ROUTE_SCHEME; 4951110Saxel.duch@nginx.com test->rule = rule; 4961110Saxel.duch@nginx.com test++; 4971110Saxel.duch@nginx.com } 4981110Saxel.duch@nginx.com 499964Sigor@sysoev.ru if (mtcf.host != NULL) { 5001059Sigor@sysoev.ru rule = nxt_http_route_rule_create(task, mp, mtcf.host, 1, 5011474Saxel.duch@nginx.com NXT_HTTP_ROUTE_PATTERN_LOWCASE, 5021474Saxel.duch@nginx.com NXT_HTTP_ROUTE_ENCODING_NONE); 503964Sigor@sysoev.ru if (rule == NULL) { 504964Sigor@sysoev.ru return NULL; 505964Sigor@sysoev.ru } 506964Sigor@sysoev.ru 5071059Sigor@sysoev.ru rule->u.offset = offsetof(nxt_http_request_t, host); 508964Sigor@sysoev.ru rule->object = NXT_HTTP_ROUTE_STRING; 5091059Sigor@sysoev.ru test->rule = rule; 5101059Sigor@sysoev.ru test++; 511964Sigor@sysoev.ru } 512964Sigor@sysoev.ru 513964Sigor@sysoev.ru if (mtcf.uri != NULL) { 5141059Sigor@sysoev.ru rule = nxt_http_route_rule_create(task, mp, mtcf.uri, 1, 5151474Saxel.duch@nginx.com NXT_HTTP_ROUTE_PATTERN_NOCASE, 5161474Saxel.duch@nginx.com NXT_HTTP_ROUTE_ENCODING_URI); 517964Sigor@sysoev.ru if (rule == NULL) { 518964Sigor@sysoev.ru return NULL; 519964Sigor@sysoev.ru } 520964Sigor@sysoev.ru 5211059Sigor@sysoev.ru rule->u.offset = offsetof(nxt_http_request_t, path); 522964Sigor@sysoev.ru rule->object = NXT_HTTP_ROUTE_STRING_PTR; 5231059Sigor@sysoev.ru test->rule = rule; 5241059Sigor@sysoev.ru test++; 525964Sigor@sysoev.ru } 526964Sigor@sysoev.ru 527964Sigor@sysoev.ru if (mtcf.method != NULL) { 5281059Sigor@sysoev.ru rule = nxt_http_route_rule_create(task, mp, mtcf.method, 1, 5291474Saxel.duch@nginx.com NXT_HTTP_ROUTE_PATTERN_UPCASE, 5301474Saxel.duch@nginx.com NXT_HTTP_ROUTE_ENCODING_NONE); 531964Sigor@sysoev.ru if (rule == NULL) { 532964Sigor@sysoev.ru return NULL; 533964Sigor@sysoev.ru } 534964Sigor@sysoev.ru 5351059Sigor@sysoev.ru rule->u.offset = offsetof(nxt_http_request_t, method); 536964Sigor@sysoev.ru rule->object = NXT_HTTP_ROUTE_STRING_PTR; 5371059Sigor@sysoev.ru test->rule = rule; 5381059Sigor@sysoev.ru test++; 5391059Sigor@sysoev.ru } 5401059Sigor@sysoev.ru 5411059Sigor@sysoev.ru if (mtcf.headers != NULL) { 5421061Sigor@sysoev.ru table = nxt_http_route_table_create(task, mp, mtcf.headers, 5431474Saxel.duch@nginx.com NXT_HTTP_ROUTE_HEADER, 0, 5441474Saxel.duch@nginx.com NXT_HTTP_ROUTE_ENCODING_NONE); 5451061Sigor@sysoev.ru if (table == NULL) { 5461061Sigor@sysoev.ru return NULL; 5471061Sigor@sysoev.ru } 5481061Sigor@sysoev.ru 5491061Sigor@sysoev.ru test->table = table; 5501061Sigor@sysoev.ru test++; 5511061Sigor@sysoev.ru } 5521061Sigor@sysoev.ru 5531061Sigor@sysoev.ru if (mtcf.arguments != NULL) { 5541061Sigor@sysoev.ru table = nxt_http_route_table_create(task, mp, mtcf.arguments, 5551474Saxel.duch@nginx.com NXT_HTTP_ROUTE_ARGUMENT, 1, 5561474Saxel.duch@nginx.com NXT_HTTP_ROUTE_ENCODING_URI_PLUS); 5571059Sigor@sysoev.ru if (table == NULL) { 5581059Sigor@sysoev.ru return NULL; 5591059Sigor@sysoev.ru } 5601059Sigor@sysoev.ru 5611059Sigor@sysoev.ru test->table = table; 5621059Sigor@sysoev.ru test++; 563964Sigor@sysoev.ru } 564964Sigor@sysoev.ru 5651062Sigor@sysoev.ru if (mtcf.cookies != NULL) { 5661062Sigor@sysoev.ru table = nxt_http_route_table_create(task, mp, mtcf.cookies, 5671474Saxel.duch@nginx.com NXT_HTTP_ROUTE_COOKIE, 1, 5681474Saxel.duch@nginx.com NXT_HTTP_ROUTE_ENCODING_NONE); 5691062Sigor@sysoev.ru if (table == NULL) { 5701062Sigor@sysoev.ru return NULL; 5711062Sigor@sysoev.ru } 5721062Sigor@sysoev.ru 5731062Sigor@sysoev.ru test->table = table; 5741062Sigor@sysoev.ru test++; 5751062Sigor@sysoev.ru } 5761062Sigor@sysoev.ru 5771991Sz.hong@f5.com if (mtcf.query != NULL) { 5781991Sz.hong@f5.com rule = nxt_http_route_rule_create(task, mp, mtcf.query, 1, 5791991Sz.hong@f5.com NXT_HTTP_ROUTE_PATTERN_NOCASE, 5801991Sz.hong@f5.com NXT_HTTP_ROUTE_ENCODING_URI_PLUS); 5811991Sz.hong@f5.com if (rule == NULL) { 5821991Sz.hong@f5.com return NULL; 5831991Sz.hong@f5.com } 5841991Sz.hong@f5.com 5851991Sz.hong@f5.com rule->object = NXT_HTTP_ROUTE_QUERY; 5861991Sz.hong@f5.com test->rule = rule; 5871991Sz.hong@f5.com test++; 5881991Sz.hong@f5.com } 5891991Sz.hong@f5.com 5901324Saxel.duch@nginx.com if (mtcf.source != NULL) { 5911324Saxel.duch@nginx.com addr_rule = nxt_http_route_addr_rule_create(task, mp, mtcf.source); 5921324Saxel.duch@nginx.com if (addr_rule == NULL) { 5931324Saxel.duch@nginx.com return NULL; 5941324Saxel.duch@nginx.com } 5951324Saxel.duch@nginx.com 5961324Saxel.duch@nginx.com addr_rule->object = NXT_HTTP_ROUTE_SOURCE; 5971324Saxel.duch@nginx.com test->addr_rule = addr_rule; 5981324Saxel.duch@nginx.com test++; 5991324Saxel.duch@nginx.com } 6001324Saxel.duch@nginx.com 6011326Saxel.duch@nginx.com if (mtcf.destination != NULL) { 6021326Saxel.duch@nginx.com addr_rule = nxt_http_route_addr_rule_create(task, mp, mtcf.destination); 6031326Saxel.duch@nginx.com if (addr_rule == NULL) { 6041326Saxel.duch@nginx.com return NULL; 6051326Saxel.duch@nginx.com } 6061326Saxel.duch@nginx.com 6071326Saxel.duch@nginx.com addr_rule->object = NXT_HTTP_ROUTE_DESTINATION; 6081326Saxel.duch@nginx.com test->addr_rule = addr_rule; 6091326Saxel.duch@nginx.com test++; 6101326Saxel.duch@nginx.com } 6111326Saxel.duch@nginx.com 612964Sigor@sysoev.ru return match; 613964Sigor@sysoev.ru } 614964Sigor@sysoev.ru 615964Sigor@sysoev.ru 6161264Sigor@sysoev.ru static nxt_conf_map_t nxt_http_route_action_conf[] = { 6171264Sigor@sysoev.ru { 6181264Sigor@sysoev.ru nxt_string("pass"), 6191264Sigor@sysoev.ru NXT_CONF_MAP_PTR, 6201903Sz.hong@f5.com offsetof(nxt_http_action_conf_t, pass) 6211264Sigor@sysoev.ru }, 6221264Sigor@sysoev.ru { 6231429Svbart@nginx.com nxt_string("return"), 6241429Svbart@nginx.com NXT_CONF_MAP_PTR, 6251903Sz.hong@f5.com offsetof(nxt_http_action_conf_t, ret) 6261429Svbart@nginx.com }, 6271429Svbart@nginx.com { 6281432Svbart@nginx.com nxt_string("location"), 6291432Svbart@nginx.com NXT_CONF_MAP_STR, 6301903Sz.hong@f5.com offsetof(nxt_http_action_conf_t, location) 6311432Svbart@nginx.com }, 6321432Svbart@nginx.com { 6331854Sz.hong@f5.com nxt_string("proxy"), 6341854Sz.hong@f5.com NXT_CONF_MAP_PTR, 6351903Sz.hong@f5.com offsetof(nxt_http_action_conf_t, proxy) 6361854Sz.hong@f5.com }, 6371854Sz.hong@f5.com { 6381264Sigor@sysoev.ru nxt_string("share"), 6391264Sigor@sysoev.ru NXT_CONF_MAP_PTR, 6401903Sz.hong@f5.com offsetof(nxt_http_action_conf_t, share) 6411264Sigor@sysoev.ru }, 6421270Sigor@sysoev.ru { 6431855Sz.hong@f5.com nxt_string("chroot"), 6441855Sz.hong@f5.com NXT_CONF_MAP_STR, 6451903Sz.hong@f5.com offsetof(nxt_http_action_conf_t, chroot) 6461855Sz.hong@f5.com }, 6471855Sz.hong@f5.com { 6481855Sz.hong@f5.com nxt_string("follow_symlinks"), 6491855Sz.hong@f5.com NXT_CONF_MAP_PTR, 6501903Sz.hong@f5.com offsetof(nxt_http_action_conf_t, follow_symlinks) 6511855Sz.hong@f5.com }, 6521855Sz.hong@f5.com { 6531855Sz.hong@f5.com nxt_string("traverse_mounts"), 6541855Sz.hong@f5.com NXT_CONF_MAP_PTR, 6551903Sz.hong@f5.com offsetof(nxt_http_action_conf_t, traverse_mounts) 6561855Sz.hong@f5.com }, 6571855Sz.hong@f5.com { 6581859So.canty@f5.com nxt_string("types"), 6591859So.canty@f5.com NXT_CONF_MAP_PTR, 6601903Sz.hong@f5.com offsetof(nxt_http_action_conf_t, types) 6611859So.canty@f5.com }, 6621859So.canty@f5.com { 6631378Svbart@nginx.com nxt_string("fallback"), 6641378Svbart@nginx.com NXT_CONF_MAP_PTR, 6651903Sz.hong@f5.com offsetof(nxt_http_action_conf_t, fallback) 6661378Svbart@nginx.com }, 6671264Sigor@sysoev.ru }; 6681264Sigor@sysoev.ru 6691264Sigor@sysoev.ru 6701923Sz.hong@f5.com nxt_int_t 6711903Sz.hong@f5.com nxt_http_action_init(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, 6721859So.canty@f5.com nxt_conf_value_t *cv, nxt_http_action_t *action) 6731264Sigor@sysoev.ru { 6741903Sz.hong@f5.com nxt_mp_t *mp; 6751903Sz.hong@f5.com nxt_int_t ret; 6761954Sz.hong@f5.com nxt_str_t pass; 6771903Sz.hong@f5.com nxt_http_action_conf_t acf; 6781903Sz.hong@f5.com 6791903Sz.hong@f5.com nxt_memzero(&acf, sizeof(acf)); 6801264Sigor@sysoev.ru 6811378Svbart@nginx.com ret = nxt_conf_map_object(tmcf->mem_pool, cv, nxt_http_route_action_conf, 6821903Sz.hong@f5.com nxt_nitems(nxt_http_route_action_conf), &acf); 6831264Sigor@sysoev.ru if (ret != NXT_OK) { 6841264Sigor@sysoev.ru return ret; 6851264Sigor@sysoev.ru } 6861264Sigor@sysoev.ru 6871428Svbart@nginx.com nxt_memzero(action, sizeof(nxt_http_action_t)); 6881428Svbart@nginx.com 6891432Svbart@nginx.com mp = tmcf->router_conf->mem_pool; 6901432Svbart@nginx.com 6911903Sz.hong@f5.com if (acf.ret != NULL) { 6921903Sz.hong@f5.com return nxt_http_return_init(mp, action, &acf); 6931429Svbart@nginx.com } 6941429Svbart@nginx.com 6951903Sz.hong@f5.com if (acf.share != NULL) { 6961923Sz.hong@f5.com return nxt_http_static_init(task, tmcf, action, &acf); 6971923Sz.hong@f5.com } 6981923Sz.hong@f5.com 6991923Sz.hong@f5.com if (acf.proxy != NULL) { 7001924Sz.hong@f5.com return nxt_http_proxy_init(mp, action, &acf); 7011264Sigor@sysoev.ru } 7021264Sigor@sysoev.ru 7031954Sz.hong@f5.com nxt_conf_get_string(acf.pass, &pass); 7041954Sz.hong@f5.com 7051959Sz.hong@f5.com action->u.var = nxt_var_compile(&pass, mp, 0); 7061954Sz.hong@f5.com if (nxt_slow_path(action->u.var == NULL)) { 7071264Sigor@sysoev.ru return NXT_ERROR; 7081264Sigor@sysoev.ru } 7091264Sigor@sysoev.ru 7101264Sigor@sysoev.ru return NXT_OK; 7111264Sigor@sysoev.ru } 7121264Sigor@sysoev.ru 7131264Sigor@sysoev.ru 7141059Sigor@sysoev.ru static nxt_http_route_table_t * 7151059Sigor@sysoev.ru nxt_http_route_table_create(nxt_task_t *task, nxt_mp_t *mp, 7161061Sigor@sysoev.ru nxt_conf_value_t *table_cv, nxt_http_route_object_t object, 7171474Saxel.duch@nginx.com nxt_bool_t case_sensitive, nxt_http_route_encoding_t encoding) 7181059Sigor@sysoev.ru { 7191059Sigor@sysoev.ru size_t size; 7201059Sigor@sysoev.ru uint32_t i, n; 7211059Sigor@sysoev.ru nxt_conf_value_t *ruleset_cv; 7221059Sigor@sysoev.ru nxt_http_route_table_t *table; 7231059Sigor@sysoev.ru nxt_http_route_ruleset_t *ruleset; 7241059Sigor@sysoev.ru 7252077Salx.manpages@gmail.com n = nxt_conf_array_elements_count_or_1(table_cv); 7261059Sigor@sysoev.ru size = sizeof(nxt_http_route_table_t) 7271059Sigor@sysoev.ru + n * sizeof(nxt_http_route_ruleset_t *); 7281059Sigor@sysoev.ru 7291059Sigor@sysoev.ru table = nxt_mp_alloc(mp, size); 7301059Sigor@sysoev.ru if (nxt_slow_path(table == NULL)) { 7311059Sigor@sysoev.ru return NULL; 7321059Sigor@sysoev.ru } 7331059Sigor@sysoev.ru 7341059Sigor@sysoev.ru table->items = n; 7351059Sigor@sysoev.ru table->object = NXT_HTTP_ROUTE_TABLE; 7361059Sigor@sysoev.ru 7371059Sigor@sysoev.ru for (i = 0; i < n; i++) { 7382077Salx.manpages@gmail.com ruleset_cv = nxt_conf_get_array_element_or_itself(table_cv, i); 7391059Sigor@sysoev.ru 7401474Saxel.duch@nginx.com ruleset = nxt_http_route_ruleset_create(task, mp, ruleset_cv, object, 7411474Saxel.duch@nginx.com case_sensitive, encoding); 7421059Sigor@sysoev.ru if (nxt_slow_path(ruleset == NULL)) { 7431059Sigor@sysoev.ru return NULL; 7441059Sigor@sysoev.ru } 7451059Sigor@sysoev.ru 7461059Sigor@sysoev.ru table->ruleset[i] = ruleset; 7471059Sigor@sysoev.ru } 7481059Sigor@sysoev.ru 7491059Sigor@sysoev.ru return table; 7501059Sigor@sysoev.ru } 7511059Sigor@sysoev.ru 7521059Sigor@sysoev.ru 7531059Sigor@sysoev.ru static nxt_http_route_ruleset_t * 7541059Sigor@sysoev.ru nxt_http_route_ruleset_create(nxt_task_t *task, nxt_mp_t *mp, 7551061Sigor@sysoev.ru nxt_conf_value_t *ruleset_cv, nxt_http_route_object_t object, 7561474Saxel.duch@nginx.com nxt_bool_t case_sensitive, nxt_http_route_encoding_t encoding) 7571059Sigor@sysoev.ru { 7581059Sigor@sysoev.ru size_t size; 7591059Sigor@sysoev.ru uint32_t i, n, next; 7601059Sigor@sysoev.ru nxt_str_t name; 7611059Sigor@sysoev.ru nxt_conf_value_t *rule_cv; 7621059Sigor@sysoev.ru nxt_http_route_rule_t *rule; 7631059Sigor@sysoev.ru nxt_http_route_ruleset_t *ruleset; 7641059Sigor@sysoev.ru 7651059Sigor@sysoev.ru n = nxt_conf_object_members_count(ruleset_cv); 7661059Sigor@sysoev.ru size = sizeof(nxt_http_route_ruleset_t) 7671059Sigor@sysoev.ru + n * sizeof(nxt_http_route_rule_t *); 7681059Sigor@sysoev.ru 7691059Sigor@sysoev.ru ruleset = nxt_mp_alloc(mp, size); 7701059Sigor@sysoev.ru if (nxt_slow_path(ruleset == NULL)) { 7711059Sigor@sysoev.ru return NULL; 7721059Sigor@sysoev.ru } 7731059Sigor@sysoev.ru 7741059Sigor@sysoev.ru ruleset->items = n; 7751059Sigor@sysoev.ru 7761059Sigor@sysoev.ru next = 0; 7771059Sigor@sysoev.ru 7781785Svbart@nginx.com /* 7791785Svbart@nginx.com * A workaround for GCC 10 with -flto -O2 flags that warns about "name" 7801785Svbart@nginx.com * may be uninitialized in nxt_http_route_rule_name_create(). 7811785Svbart@nginx.com */ 7821785Svbart@nginx.com nxt_str_null(&name); 7831785Svbart@nginx.com 7841059Sigor@sysoev.ru for (i = 0; i < n; i++) { 7851059Sigor@sysoev.ru rule_cv = nxt_conf_next_object_member(ruleset_cv, &name, &next); 7861059Sigor@sysoev.ru 7871061Sigor@sysoev.ru rule = nxt_http_route_rule_name_create(task, mp, rule_cv, &name, 7881474Saxel.duch@nginx.com case_sensitive, encoding); 7891059Sigor@sysoev.ru if (nxt_slow_path(rule == NULL)) { 7901059Sigor@sysoev.ru return NULL; 7911059Sigor@sysoev.ru } 7921059Sigor@sysoev.ru 7931061Sigor@sysoev.ru rule->object = object; 7941059Sigor@sysoev.ru ruleset->rule[i] = rule; 7951059Sigor@sysoev.ru } 7961059Sigor@sysoev.ru 7971059Sigor@sysoev.ru return ruleset; 7981059Sigor@sysoev.ru } 7991059Sigor@sysoev.ru 8001059Sigor@sysoev.ru 801964Sigor@sysoev.ru static nxt_http_route_rule_t * 8021061Sigor@sysoev.ru nxt_http_route_rule_name_create(nxt_task_t *task, nxt_mp_t *mp, 8031474Saxel.duch@nginx.com nxt_conf_value_t *rule_cv, nxt_str_t *name, nxt_bool_t case_sensitive, 8041474Saxel.duch@nginx.com nxt_http_route_encoding_t encoding) 8051059Sigor@sysoev.ru { 8061474Saxel.duch@nginx.com u_char c, *p, *src, *start, *end, plus; 8071474Saxel.duch@nginx.com uint8_t d0, d1; 8081059Sigor@sysoev.ru uint32_t hash; 8091059Sigor@sysoev.ru nxt_uint_t i; 8101059Sigor@sysoev.ru nxt_http_route_rule_t *rule; 8111059Sigor@sysoev.ru 8121061Sigor@sysoev.ru rule = nxt_http_route_rule_create(task, mp, rule_cv, case_sensitive, 8131474Saxel.duch@nginx.com NXT_HTTP_ROUTE_PATTERN_NOCASE, 8141474Saxel.duch@nginx.com encoding); 8151059Sigor@sysoev.ru if (nxt_slow_path(rule == NULL)) { 8161059Sigor@sysoev.ru return NULL; 8171059Sigor@sysoev.ru } 8181059Sigor@sysoev.ru 8191059Sigor@sysoev.ru rule->u.name.length = name->length; 8201059Sigor@sysoev.ru 8211059Sigor@sysoev.ru p = nxt_mp_nget(mp, name->length); 8221059Sigor@sysoev.ru if (nxt_slow_path(p == NULL)) { 8231059Sigor@sysoev.ru return NULL; 8241059Sigor@sysoev.ru } 8251059Sigor@sysoev.ru 8261474Saxel.duch@nginx.com hash = NXT_HTTP_FIELD_HASH_INIT; 8271059Sigor@sysoev.ru rule->u.name.start = p; 8281059Sigor@sysoev.ru 8291474Saxel.duch@nginx.com if (encoding == NXT_HTTP_ROUTE_ENCODING_NONE) { 8301474Saxel.duch@nginx.com for (i = 0; i < name->length; i++) { 8311474Saxel.duch@nginx.com c = name->start[i]; 8321474Saxel.duch@nginx.com *p++ = c; 8331474Saxel.duch@nginx.com 8341474Saxel.duch@nginx.com c = case_sensitive ? c : nxt_lowcase(c); 8351474Saxel.duch@nginx.com hash = nxt_http_field_hash_char(hash, c); 8361474Saxel.duch@nginx.com } 8371474Saxel.duch@nginx.com 8381474Saxel.duch@nginx.com goto end; 8391474Saxel.duch@nginx.com } 8401474Saxel.duch@nginx.com 8411474Saxel.duch@nginx.com plus = (encoding == NXT_HTTP_ROUTE_ENCODING_URI_PLUS) ? ' ' : '+'; 8421474Saxel.duch@nginx.com 8431474Saxel.duch@nginx.com start = name->start; 8441474Saxel.duch@nginx.com end = start + name->length; 8451474Saxel.duch@nginx.com 8461474Saxel.duch@nginx.com for (src = start; src < end; src++) { 8471474Saxel.duch@nginx.com c = *src; 8481474Saxel.duch@nginx.com 8491474Saxel.duch@nginx.com switch (c) { 8501474Saxel.duch@nginx.com case '%': 8511474Saxel.duch@nginx.com if (nxt_slow_path(end - src <= 2)) { 8521474Saxel.duch@nginx.com return NULL; 8531474Saxel.duch@nginx.com } 8541474Saxel.duch@nginx.com 8551474Saxel.duch@nginx.com d0 = nxt_hex2int[src[1]]; 8561474Saxel.duch@nginx.com d1 = nxt_hex2int[src[2]]; 8571474Saxel.duch@nginx.com src += 2; 8581474Saxel.duch@nginx.com 8591474Saxel.duch@nginx.com if (nxt_slow_path((d0 | d1) >= 16)) { 8601474Saxel.duch@nginx.com return NULL; 8611474Saxel.duch@nginx.com } 8621474Saxel.duch@nginx.com 8631474Saxel.duch@nginx.com c = (d0 << 4) + d1; 8641474Saxel.duch@nginx.com *p++ = c; 8651474Saxel.duch@nginx.com break; 8661474Saxel.duch@nginx.com 8671474Saxel.duch@nginx.com case '+': 8681474Saxel.duch@nginx.com c = plus; 8691474Saxel.duch@nginx.com *p++ = c; 8701474Saxel.duch@nginx.com break; 8711474Saxel.duch@nginx.com 8721474Saxel.duch@nginx.com default: 8731474Saxel.duch@nginx.com *p++ = c; 8741474Saxel.duch@nginx.com break; 8751474Saxel.duch@nginx.com } 8761059Sigor@sysoev.ru 8771079Sigor@sysoev.ru c = case_sensitive ? c : nxt_lowcase(c); 8781059Sigor@sysoev.ru hash = nxt_http_field_hash_char(hash, c); 8791059Sigor@sysoev.ru } 8801059Sigor@sysoev.ru 8811474Saxel.duch@nginx.com rule->u.name.length = p - rule->u.name.start; 8821474Saxel.duch@nginx.com 8831474Saxel.duch@nginx.com end: 8841474Saxel.duch@nginx.com 8851059Sigor@sysoev.ru rule->u.name.hash = nxt_http_field_hash_end(hash) & 0xFFFF; 8861059Sigor@sysoev.ru 8871059Sigor@sysoev.ru return rule; 8881059Sigor@sysoev.ru } 8891059Sigor@sysoev.ru 8901059Sigor@sysoev.ru 8911059Sigor@sysoev.ru static nxt_http_route_rule_t * 8921059Sigor@sysoev.ru nxt_http_route_rule_create(nxt_task_t *task, nxt_mp_t *mp, 893964Sigor@sysoev.ru nxt_conf_value_t *cv, nxt_bool_t case_sensitive, 8941474Saxel.duch@nginx.com nxt_http_route_pattern_case_t pattern_case, 8951474Saxel.duch@nginx.com nxt_http_route_encoding_t encoding) 896964Sigor@sysoev.ru { 897964Sigor@sysoev.ru size_t size; 898964Sigor@sysoev.ru uint32_t i, n; 899964Sigor@sysoev.ru nxt_int_t ret; 900964Sigor@sysoev.ru nxt_conf_value_t *value; 901964Sigor@sysoev.ru nxt_http_route_rule_t *rule; 902964Sigor@sysoev.ru nxt_http_route_pattern_t *pattern; 903964Sigor@sysoev.ru 9042077Salx.manpages@gmail.com n = nxt_conf_array_elements_count_or_1(cv); 905964Sigor@sysoev.ru size = sizeof(nxt_http_route_rule_t) + n * sizeof(nxt_http_route_pattern_t); 906964Sigor@sysoev.ru 907964Sigor@sysoev.ru rule = nxt_mp_alloc(mp, size); 908964Sigor@sysoev.ru if (nxt_slow_path(rule == NULL)) { 909964Sigor@sysoev.ru return NULL; 910964Sigor@sysoev.ru } 911964Sigor@sysoev.ru 912964Sigor@sysoev.ru rule->items = n; 913964Sigor@sysoev.ru 914964Sigor@sysoev.ru pattern = &rule->pattern[0]; 915964Sigor@sysoev.ru 916964Sigor@sysoev.ru nxt_conf_array_qsort(cv, nxt_http_pattern_compare); 917964Sigor@sysoev.ru 918964Sigor@sysoev.ru for (i = 0; i < n; i++) { 919964Sigor@sysoev.ru pattern[i].case_sensitive = case_sensitive; 9202077Salx.manpages@gmail.com value = nxt_conf_get_array_element_or_itself(cv, i); 921964Sigor@sysoev.ru 922964Sigor@sysoev.ru ret = nxt_http_route_pattern_create(task, mp, value, &pattern[i], 9231474Saxel.duch@nginx.com pattern_case, encoding); 924964Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 925964Sigor@sysoev.ru return NULL; 926964Sigor@sysoev.ru } 927964Sigor@sysoev.ru } 928964Sigor@sysoev.ru 929964Sigor@sysoev.ru return rule; 930964Sigor@sysoev.ru } 931964Sigor@sysoev.ru 932964Sigor@sysoev.ru 9331936So.canty@f5.com nxt_http_route_addr_rule_t * 9341324Saxel.duch@nginx.com nxt_http_route_addr_rule_create(nxt_task_t *task, nxt_mp_t *mp, 935*2078Salx.manpages@gmail.com nxt_conf_value_t *cv) 9361324Saxel.duch@nginx.com { 9371324Saxel.duch@nginx.com size_t size; 9381324Saxel.duch@nginx.com uint32_t i, n; 9391324Saxel.duch@nginx.com nxt_conf_value_t *value; 9401324Saxel.duch@nginx.com nxt_http_route_addr_rule_t *addr_rule; 9411324Saxel.duch@nginx.com nxt_http_route_addr_pattern_t *pattern; 9421324Saxel.duch@nginx.com 9432077Salx.manpages@gmail.com n = nxt_conf_array_elements_count_or_1(cv); 9441324Saxel.duch@nginx.com 9451324Saxel.duch@nginx.com size = sizeof(nxt_http_route_addr_rule_t) 9461324Saxel.duch@nginx.com + n * sizeof(nxt_http_route_addr_pattern_t); 9471324Saxel.duch@nginx.com 9481324Saxel.duch@nginx.com addr_rule = nxt_mp_alloc(mp, size); 9491324Saxel.duch@nginx.com if (nxt_slow_path(addr_rule == NULL)) { 9501324Saxel.duch@nginx.com return NULL; 9511324Saxel.duch@nginx.com } 9521324Saxel.duch@nginx.com 9531324Saxel.duch@nginx.com addr_rule->items = n; 9541324Saxel.duch@nginx.com 9551324Saxel.duch@nginx.com for (i = 0; i < n; i++) { 9561324Saxel.duch@nginx.com pattern = &addr_rule->addr_pattern[i]; 9572077Salx.manpages@gmail.com value = nxt_conf_get_array_element_or_itself(cv, i); 9581324Saxel.duch@nginx.com 9591324Saxel.duch@nginx.com if (nxt_http_route_addr_pattern_parse(mp, pattern, value) != NXT_OK) { 9601324Saxel.duch@nginx.com return NULL; 9611324Saxel.duch@nginx.com } 9621324Saxel.duch@nginx.com } 9631324Saxel.duch@nginx.com 9641390Saxel.duch@nginx.com if (n > 1) { 9651390Saxel.duch@nginx.com nxt_qsort(addr_rule->addr_pattern, addr_rule->items, 9661390Saxel.duch@nginx.com sizeof(nxt_http_route_addr_pattern_t), 9671390Saxel.duch@nginx.com nxt_http_addr_pattern_compare); 9681390Saxel.duch@nginx.com } 9691390Saxel.duch@nginx.com 9701324Saxel.duch@nginx.com return addr_rule; 9711324Saxel.duch@nginx.com } 9721324Saxel.duch@nginx.com 9731324Saxel.duch@nginx.com 9741923Sz.hong@f5.com nxt_http_route_rule_t * 9751923Sz.hong@f5.com nxt_http_route_types_rule_create(nxt_task_t *task, nxt_mp_t *mp, 9761923Sz.hong@f5.com nxt_conf_value_t *types) 9771923Sz.hong@f5.com { 9781923Sz.hong@f5.com return nxt_http_route_rule_create(task, mp, types, 0, 9791923Sz.hong@f5.com NXT_HTTP_ROUTE_PATTERN_LOWCASE, 9801923Sz.hong@f5.com NXT_HTTP_ROUTE_ENCODING_NONE); 9811923Sz.hong@f5.com } 9821923Sz.hong@f5.com 9831923Sz.hong@f5.com 984964Sigor@sysoev.ru static int 985964Sigor@sysoev.ru nxt_http_pattern_compare(const void *one, const void *two) 986964Sigor@sysoev.ru { 987964Sigor@sysoev.ru nxt_str_t test; 988964Sigor@sysoev.ru nxt_bool_t negative1, negative2; 989964Sigor@sysoev.ru nxt_conf_value_t *value; 990964Sigor@sysoev.ru 991964Sigor@sysoev.ru value = (nxt_conf_value_t *) one; 992964Sigor@sysoev.ru nxt_conf_get_string(value, &test); 993964Sigor@sysoev.ru negative1 = (test.length != 0 && test.start[0] == '!'); 994964Sigor@sysoev.ru 995964Sigor@sysoev.ru value = (nxt_conf_value_t *) two; 996964Sigor@sysoev.ru nxt_conf_get_string(value, &test); 997964Sigor@sysoev.ru negative2 = (test.length != 0 && test.start[0] == '!'); 998964Sigor@sysoev.ru 999964Sigor@sysoev.ru return (negative2 - negative1); 1000964Sigor@sysoev.ru } 1001964Sigor@sysoev.ru 1002964Sigor@sysoev.ru 10031390Saxel.duch@nginx.com static int 10041390Saxel.duch@nginx.com nxt_http_addr_pattern_compare(const void *one, const void *two) 10051390Saxel.duch@nginx.com { 10061390Saxel.duch@nginx.com const nxt_http_route_addr_pattern_t *p1, *p2; 10071390Saxel.duch@nginx.com 10081390Saxel.duch@nginx.com p1 = one; 10091390Saxel.duch@nginx.com p2 = two; 10101390Saxel.duch@nginx.com 10111390Saxel.duch@nginx.com return (p2->base.negative - p1->base.negative); 10121390Saxel.duch@nginx.com } 10131390Saxel.duch@nginx.com 10141390Saxel.duch@nginx.com 1015964Sigor@sysoev.ru static nxt_int_t 1016964Sigor@sysoev.ru nxt_http_route_pattern_create(nxt_task_t *task, nxt_mp_t *mp, 1017964Sigor@sysoev.ru nxt_conf_value_t *cv, nxt_http_route_pattern_t *pattern, 10181474Saxel.duch@nginx.com nxt_http_route_pattern_case_t pattern_case, 10191474Saxel.duch@nginx.com nxt_http_route_encoding_t encoding) 1020964Sigor@sysoev.ru { 10211508Saxel.duch@nginx.com u_char c, *p, *end; 10221508Saxel.duch@nginx.com nxt_str_t test, tmp; 10231508Saxel.duch@nginx.com nxt_int_t ret; 10241508Saxel.duch@nginx.com nxt_array_t *slices; 10251721Saxel.duch@nginx.com #if (NXT_HAVE_REGEX) 10261721Saxel.duch@nginx.com nxt_regex_t *re; 10271721Saxel.duch@nginx.com nxt_regex_err_t err; 10281721Saxel.duch@nginx.com #endif 10291508Saxel.duch@nginx.com nxt_http_route_pattern_type_t type; 10301508Saxel.duch@nginx.com nxt_http_route_pattern_slice_t *slice; 1031964Sigor@sysoev.ru 1032964Sigor@sysoev.ru type = NXT_HTTP_ROUTE_PATTERN_EXACT; 1033964Sigor@sysoev.ru 1034964Sigor@sysoev.ru nxt_conf_get_string(cv, &test); 1035964Sigor@sysoev.ru 10361721Saxel.duch@nginx.com pattern->u.pattern_slices = NULL; 1037964Sigor@sysoev.ru pattern->negative = 0; 1038964Sigor@sysoev.ru pattern->any = 1; 10391474Saxel.duch@nginx.com pattern->min_length = 0; 10401721Saxel.duch@nginx.com #if (NXT_HAVE_REGEX) 10411721Saxel.duch@nginx.com pattern->regex = 0; 10421721Saxel.duch@nginx.com #endif 1043964Sigor@sysoev.ru 10441508Saxel.duch@nginx.com if (test.length != 0 && test.start[0] == '!') { 10451508Saxel.duch@nginx.com test.start++; 10461508Saxel.duch@nginx.com test.length--; 10471508Saxel.duch@nginx.com 10481508Saxel.duch@nginx.com pattern->negative = 1; 10491508Saxel.duch@nginx.com pattern->any = 0; 10501508Saxel.duch@nginx.com } 10511508Saxel.duch@nginx.com 10521721Saxel.duch@nginx.com if (test.length > 0 && test.start[0] == '~') { 10531721Saxel.duch@nginx.com #if (NXT_HAVE_REGEX) 10541721Saxel.duch@nginx.com test.start++; 10551721Saxel.duch@nginx.com test.length--; 10561721Saxel.duch@nginx.com 10571721Saxel.duch@nginx.com re = nxt_regex_compile(mp, &test, &err); 10581721Saxel.duch@nginx.com if (nxt_slow_path(re == NULL)) { 10591721Saxel.duch@nginx.com if (err.offset < test.length) { 10601721Saxel.duch@nginx.com nxt_alert(task, "nxt_regex_compile(%V) failed: %s at offset %d", 10611721Saxel.duch@nginx.com &test, err.msg, (int) err.offset); 10621721Saxel.duch@nginx.com return NXT_ERROR; 10631721Saxel.duch@nginx.com } 10641721Saxel.duch@nginx.com 10651721Saxel.duch@nginx.com nxt_alert(task, "nxt_regex_compile(%V) failed %s", &test, err.msg); 10661721Saxel.duch@nginx.com 10671721Saxel.duch@nginx.com return NXT_ERROR; 10681721Saxel.duch@nginx.com } 10691721Saxel.duch@nginx.com 10701721Saxel.duch@nginx.com pattern->u.regex = re; 10711721Saxel.duch@nginx.com pattern->regex = 1; 10721721Saxel.duch@nginx.com 10731721Saxel.duch@nginx.com return NXT_OK; 10741721Saxel.duch@nginx.com 10751721Saxel.duch@nginx.com #else 10761721Saxel.duch@nginx.com return NXT_ERROR; 10771721Saxel.duch@nginx.com #endif 10781721Saxel.duch@nginx.com } 10791721Saxel.duch@nginx.com 10801721Saxel.duch@nginx.com slices = nxt_array_create(mp, 1, sizeof(nxt_http_route_pattern_slice_t)); 10811721Saxel.duch@nginx.com if (nxt_slow_path(slices == NULL)) { 10821721Saxel.duch@nginx.com return NXT_ERROR; 10831721Saxel.duch@nginx.com } 10841721Saxel.duch@nginx.com 10851721Saxel.duch@nginx.com pattern->u.pattern_slices = slices; 10861721Saxel.duch@nginx.com 10871508Saxel.duch@nginx.com if (test.length == 0) { 10881508Saxel.duch@nginx.com slice = nxt_array_add(slices); 10891508Saxel.duch@nginx.com if (nxt_slow_path(slice == NULL)) { 10901508Saxel.duch@nginx.com return NXT_ERROR; 1091964Sigor@sysoev.ru } 1092964Sigor@sysoev.ru 10931508Saxel.duch@nginx.com slice->type = NXT_HTTP_ROUTE_PATTERN_EXACT; 10941508Saxel.duch@nginx.com slice->start = NULL; 10951508Saxel.duch@nginx.com slice->length = 0; 10961508Saxel.duch@nginx.com 10971508Saxel.duch@nginx.com return NXT_OK; 10981508Saxel.duch@nginx.com } 10991508Saxel.duch@nginx.com 11001508Saxel.duch@nginx.com if (test.start[0] == '*') { 11011508Saxel.duch@nginx.com /* 'type' is no longer 'EXACT', assume 'END'. */ 11021508Saxel.duch@nginx.com type = NXT_HTTP_ROUTE_PATTERN_END; 11031508Saxel.duch@nginx.com test.start++; 11041508Saxel.duch@nginx.com test.length--; 11051508Saxel.duch@nginx.com } 11061508Saxel.duch@nginx.com 11071522Saxel.duch@nginx.com if (type == NXT_HTTP_ROUTE_PATTERN_EXACT) { 11081508Saxel.duch@nginx.com tmp.start = test.start; 11091508Saxel.duch@nginx.com 11101508Saxel.duch@nginx.com p = nxt_memchr(test.start, '*', test.length); 11111508Saxel.duch@nginx.com 11121508Saxel.duch@nginx.com if (p == NULL) { 11131508Saxel.duch@nginx.com /* No '*' found - EXACT pattern. */ 11141508Saxel.duch@nginx.com tmp.length = test.length; 11151508Saxel.duch@nginx.com type = NXT_HTTP_ROUTE_PATTERN_EXACT; 11161508Saxel.duch@nginx.com 11171508Saxel.duch@nginx.com test.start += test.length; 11181508Saxel.duch@nginx.com test.length = 0; 11191508Saxel.duch@nginx.com 11201508Saxel.duch@nginx.com } else { 11211508Saxel.duch@nginx.com /* '*' found - BEGIN pattern. */ 11221508Saxel.duch@nginx.com tmp.length = p - test.start; 11231508Saxel.duch@nginx.com type = NXT_HTTP_ROUTE_PATTERN_BEGIN; 11241508Saxel.duch@nginx.com 11251508Saxel.duch@nginx.com test.start = p + 1; 11261508Saxel.duch@nginx.com test.length -= tmp.length + 1; 11271508Saxel.duch@nginx.com } 11281508Saxel.duch@nginx.com 11291508Saxel.duch@nginx.com ret = nxt_http_route_pattern_slice(slices, &tmp, type, encoding, 11301508Saxel.duch@nginx.com pattern_case); 11311508Saxel.duch@nginx.com if (nxt_slow_path(ret != NXT_OK)) { 11321508Saxel.duch@nginx.com return ret; 11331508Saxel.duch@nginx.com } 11341508Saxel.duch@nginx.com 11351508Saxel.duch@nginx.com pattern->min_length += tmp.length; 11361508Saxel.duch@nginx.com } 11371508Saxel.duch@nginx.com 11381508Saxel.duch@nginx.com end = test.start + test.length; 11391508Saxel.duch@nginx.com 11401508Saxel.duch@nginx.com if (test.length != 0 && end[-1] != '*') { 11411508Saxel.duch@nginx.com p = end - 1; 11421508Saxel.duch@nginx.com 11431508Saxel.duch@nginx.com while (p != test.start) { 11441508Saxel.duch@nginx.com c = *p--; 11451508Saxel.duch@nginx.com 11461508Saxel.duch@nginx.com if (c == '*') { 11471508Saxel.duch@nginx.com p += 2; 11481508Saxel.duch@nginx.com break; 11491474Saxel.duch@nginx.com } 1150964Sigor@sysoev.ru } 11511508Saxel.duch@nginx.com 11521508Saxel.duch@nginx.com tmp.start = p; 11531508Saxel.duch@nginx.com tmp.length = end - p; 11541508Saxel.duch@nginx.com 11551508Saxel.duch@nginx.com test.length -= tmp.length; 11561508Saxel.duch@nginx.com end = p; 11571508Saxel.duch@nginx.com 11581508Saxel.duch@nginx.com ret = nxt_http_route_pattern_slice(slices, &tmp, 11591508Saxel.duch@nginx.com NXT_HTTP_ROUTE_PATTERN_END, 11601508Saxel.duch@nginx.com encoding, pattern_case); 11611508Saxel.duch@nginx.com if (nxt_slow_path(ret != NXT_OK)) { 11621508Saxel.duch@nginx.com return ret; 11631508Saxel.duch@nginx.com } 11641508Saxel.duch@nginx.com 11651508Saxel.duch@nginx.com pattern->min_length += tmp.length; 1166964Sigor@sysoev.ru } 1167964Sigor@sysoev.ru 11681508Saxel.duch@nginx.com tmp.start = test.start; 11691508Saxel.duch@nginx.com tmp.length = 0; 11701508Saxel.duch@nginx.com 11711508Saxel.duch@nginx.com p = tmp.start; 11721508Saxel.duch@nginx.com 11731508Saxel.duch@nginx.com while (p != end) { 11741508Saxel.duch@nginx.com c = *p++; 11751508Saxel.duch@nginx.com 11761508Saxel.duch@nginx.com if (c != '*') { 11771508Saxel.duch@nginx.com tmp.length++; 11781508Saxel.duch@nginx.com continue; 11791508Saxel.duch@nginx.com } 11801508Saxel.duch@nginx.com 11811508Saxel.duch@nginx.com if (tmp.length == 0) { 11821508Saxel.duch@nginx.com tmp.start = p; 11831508Saxel.duch@nginx.com continue; 11841508Saxel.duch@nginx.com } 11851508Saxel.duch@nginx.com 11861508Saxel.duch@nginx.com ret = nxt_http_route_pattern_slice(slices, &tmp, 11871508Saxel.duch@nginx.com NXT_HTTP_ROUTE_PATTERN_SUBSTRING, 11881508Saxel.duch@nginx.com encoding, pattern_case); 11891508Saxel.duch@nginx.com if (nxt_slow_path(ret != NXT_OK)) { 11901508Saxel.duch@nginx.com return ret; 11911508Saxel.duch@nginx.com } 11921508Saxel.duch@nginx.com 11931508Saxel.duch@nginx.com pattern->min_length += tmp.length; 11941508Saxel.duch@nginx.com 11951508Saxel.duch@nginx.com tmp.start = p; 11961508Saxel.duch@nginx.com tmp.length = 0; 1197964Sigor@sysoev.ru } 1198964Sigor@sysoev.ru 11991508Saxel.duch@nginx.com if (tmp.length != 0) { 12001508Saxel.duch@nginx.com ret = nxt_http_route_pattern_slice(slices, &tmp, 12011508Saxel.duch@nginx.com NXT_HTTP_ROUTE_PATTERN_SUBSTRING, 12021508Saxel.duch@nginx.com encoding, pattern_case); 12031508Saxel.duch@nginx.com if (nxt_slow_path(ret != NXT_OK)) { 12041508Saxel.duch@nginx.com return ret; 12051508Saxel.duch@nginx.com } 12061508Saxel.duch@nginx.com 12071508Saxel.duch@nginx.com pattern->min_length += tmp.length; 12081508Saxel.duch@nginx.com } 12091032Sigor@sysoev.ru 12101474Saxel.duch@nginx.com return NXT_OK; 12111474Saxel.duch@nginx.com } 12121474Saxel.duch@nginx.com 12131474Saxel.duch@nginx.com 12141474Saxel.duch@nginx.com static nxt_int_t 12151474Saxel.duch@nginx.com nxt_http_route_decode_str(nxt_str_t *str, nxt_http_route_encoding_t encoding) 12161474Saxel.duch@nginx.com { 12171474Saxel.duch@nginx.com u_char *start, *end; 12181474Saxel.duch@nginx.com 12191474Saxel.duch@nginx.com switch (encoding) { 12201474Saxel.duch@nginx.com case NXT_HTTP_ROUTE_ENCODING_NONE: 12211474Saxel.duch@nginx.com break; 12221474Saxel.duch@nginx.com 12231474Saxel.duch@nginx.com case NXT_HTTP_ROUTE_ENCODING_URI: 12241474Saxel.duch@nginx.com start = str->start; 12251474Saxel.duch@nginx.com 12261474Saxel.duch@nginx.com end = nxt_decode_uri(start, start, str->length); 12271474Saxel.duch@nginx.com if (nxt_slow_path(end == NULL)) { 12281032Sigor@sysoev.ru return NXT_ERROR; 12291032Sigor@sysoev.ru } 12301032Sigor@sysoev.ru 12311474Saxel.duch@nginx.com str->length = end - start; 12321474Saxel.duch@nginx.com break; 12331474Saxel.duch@nginx.com 12341474Saxel.duch@nginx.com case NXT_HTTP_ROUTE_ENCODING_URI_PLUS: 12351474Saxel.duch@nginx.com start = str->start; 12361474Saxel.duch@nginx.com 12371474Saxel.duch@nginx.com end = nxt_decode_uri_plus(start, start, str->length); 12381474Saxel.duch@nginx.com if (nxt_slow_path(end == NULL)) { 12391474Saxel.duch@nginx.com return NXT_ERROR; 12401474Saxel.duch@nginx.com } 12411474Saxel.duch@nginx.com 12421474Saxel.duch@nginx.com str->length = end - start; 12431474Saxel.duch@nginx.com break; 12441474Saxel.duch@nginx.com 12451474Saxel.duch@nginx.com default: 12461474Saxel.duch@nginx.com nxt_unreachable(); 12471032Sigor@sysoev.ru } 12481032Sigor@sysoev.ru 12491032Sigor@sysoev.ru return NXT_OK; 12501032Sigor@sysoev.ru } 12511032Sigor@sysoev.ru 12521032Sigor@sysoev.ru 12531508Saxel.duch@nginx.com static nxt_int_t 12541508Saxel.duch@nginx.com nxt_http_route_pattern_slice(nxt_array_t *slices, 12551508Saxel.duch@nginx.com nxt_str_t *test, 12561508Saxel.duch@nginx.com nxt_http_route_pattern_type_t type, 12571508Saxel.duch@nginx.com nxt_http_route_encoding_t encoding, 12581032Sigor@sysoev.ru nxt_http_route_pattern_case_t pattern_case) 12591032Sigor@sysoev.ru { 12601508Saxel.duch@nginx.com u_char *start; 12611508Saxel.duch@nginx.com nxt_int_t ret; 12621508Saxel.duch@nginx.com nxt_http_route_pattern_slice_t *slice; 12631508Saxel.duch@nginx.com 12641508Saxel.duch@nginx.com ret = nxt_http_route_decode_str(test, encoding); 12651508Saxel.duch@nginx.com if (nxt_slow_path(ret != NXT_OK)) { 12661508Saxel.duch@nginx.com return ret; 12671508Saxel.duch@nginx.com } 12681508Saxel.duch@nginx.com 12691508Saxel.duch@nginx.com start = nxt_mp_nget(slices->mem_pool, test->length); 12701032Sigor@sysoev.ru if (nxt_slow_path(start == NULL)) { 12711508Saxel.duch@nginx.com return NXT_ERROR; 12721032Sigor@sysoev.ru } 1273964Sigor@sysoev.ru 1274964Sigor@sysoev.ru switch (pattern_case) { 1275964Sigor@sysoev.ru 1276964Sigor@sysoev.ru case NXT_HTTP_ROUTE_PATTERN_UPCASE: 12771032Sigor@sysoev.ru nxt_memcpy_upcase(start, test->start, test->length); 1278964Sigor@sysoev.ru break; 1279964Sigor@sysoev.ru 1280964Sigor@sysoev.ru case NXT_HTTP_ROUTE_PATTERN_LOWCASE: 12811032Sigor@sysoev.ru nxt_memcpy_lowcase(start, test->start, test->length); 1282964Sigor@sysoev.ru break; 1283964Sigor@sysoev.ru 1284964Sigor@sysoev.ru case NXT_HTTP_ROUTE_PATTERN_NOCASE: 12851032Sigor@sysoev.ru nxt_memcpy(start, test->start, test->length); 1286964Sigor@sysoev.ru break; 1287964Sigor@sysoev.ru } 1288964Sigor@sysoev.ru 12891508Saxel.duch@nginx.com slice = nxt_array_add(slices); 12901564Svbart@nginx.com if (nxt_slow_path(slice == NULL)) { 12911508Saxel.duch@nginx.com return NXT_ERROR; 12921508Saxel.duch@nginx.com } 12931508Saxel.duch@nginx.com 12941508Saxel.duch@nginx.com slice->type = type; 12951508Saxel.duch@nginx.com slice->start = start; 12961508Saxel.duch@nginx.com slice->length = test->length; 12971508Saxel.duch@nginx.com 12981508Saxel.duch@nginx.com return NXT_OK; 1299964Sigor@sysoev.ru } 1300964Sigor@sysoev.ru 1301964Sigor@sysoev.ru 13021472Svbart@nginx.com nxt_int_t 1303964Sigor@sysoev.ru nxt_http_routes_resolve(nxt_task_t *task, nxt_router_temp_conf_t *tmcf) 1304964Sigor@sysoev.ru { 13051472Svbart@nginx.com nxt_int_t ret; 13061033Svbart@nginx.com nxt_http_route_t **route, **end; 1307964Sigor@sysoev.ru nxt_http_routes_t *routes; 1308964Sigor@sysoev.ru 1309964Sigor@sysoev.ru routes = tmcf->router_conf->routes; 13101059Sigor@sysoev.ru 1311964Sigor@sysoev.ru if (routes != NULL) { 1312964Sigor@sysoev.ru route = &routes->route[0]; 13131033Svbart@nginx.com end = route + routes->items; 1314964Sigor@sysoev.ru 13151033Svbart@nginx.com while (route < end) { 13161472Svbart@nginx.com ret = nxt_http_route_resolve(task, tmcf, *route); 13171472Svbart@nginx.com if (nxt_slow_path(ret != NXT_OK)) { 13181472Svbart@nginx.com return NXT_ERROR; 13191472Svbart@nginx.com } 1320964Sigor@sysoev.ru 1321964Sigor@sysoev.ru route++; 1322964Sigor@sysoev.ru } 1323964Sigor@sysoev.ru } 13241472Svbart@nginx.com 13251472Svbart@nginx.com return NXT_OK; 1326964Sigor@sysoev.ru } 1327964Sigor@sysoev.ru 1328964Sigor@sysoev.ru 13291472Svbart@nginx.com static nxt_int_t 1330964Sigor@sysoev.ru nxt_http_route_resolve(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, 1331964Sigor@sysoev.ru nxt_http_route_t *route) 1332964Sigor@sysoev.ru { 13331472Svbart@nginx.com nxt_int_t ret; 13341033Svbart@nginx.com nxt_http_route_match_t **match, **end; 1335964Sigor@sysoev.ru 1336964Sigor@sysoev.ru match = &route->match[0]; 13371033Svbart@nginx.com end = match + route->items; 1338964Sigor@sysoev.ru 13391033Svbart@nginx.com while (match < end) { 13401472Svbart@nginx.com ret = nxt_http_action_resolve(task, tmcf, &(*match)->action); 13411472Svbart@nginx.com if (nxt_slow_path(ret != NXT_OK)) { 13421472Svbart@nginx.com return NXT_ERROR; 13431472Svbart@nginx.com } 1344964Sigor@sysoev.ru 1345964Sigor@sysoev.ru match++; 1346964Sigor@sysoev.ru } 13471472Svbart@nginx.com 13481472Svbart@nginx.com return NXT_OK; 1349964Sigor@sysoev.ru } 1350964Sigor@sysoev.ru 1351964Sigor@sysoev.ru 13521472Svbart@nginx.com static nxt_int_t 13531264Sigor@sysoev.ru nxt_http_action_resolve(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, 13541264Sigor@sysoev.ru nxt_http_action_t *action) 1355964Sigor@sysoev.ru { 13561923Sz.hong@f5.com nxt_int_t ret; 13571954Sz.hong@f5.com nxt_str_t pass; 1358964Sigor@sysoev.ru 13591378Svbart@nginx.com if (action->handler != NULL) { 13601923Sz.hong@f5.com if (action->fallback != NULL) { 13611923Sz.hong@f5.com return nxt_http_action_resolve(task, tmcf, action->fallback); 13621378Svbart@nginx.com } 13631378Svbart@nginx.com 13641472Svbart@nginx.com return NXT_OK; 13651378Svbart@nginx.com } 13661378Svbart@nginx.com 13671954Sz.hong@f5.com if (nxt_var_is_const(action->u.var)) { 13681954Sz.hong@f5.com nxt_var_raw(action->u.var, &pass); 13691954Sz.hong@f5.com 13701954Sz.hong@f5.com ret = nxt_http_pass_find(tmcf->mem_pool, tmcf->router_conf, &pass, 13711954Sz.hong@f5.com action); 13721954Sz.hong@f5.com if (nxt_slow_path(ret != NXT_OK)) { 13731563Svbart@nginx.com return NXT_ERROR; 13741563Svbart@nginx.com } 13751563Svbart@nginx.com 13761954Sz.hong@f5.com } else { 13771954Sz.hong@f5.com action->handler = nxt_http_pass_var; 13781472Svbart@nginx.com } 13791472Svbart@nginx.com 13801563Svbart@nginx.com return NXT_OK; 13811563Svbart@nginx.com } 13821563Svbart@nginx.com 13831563Svbart@nginx.com 13841563Svbart@nginx.com static nxt_http_action_t * 13851954Sz.hong@f5.com nxt_http_pass_var(nxt_task_t *task, nxt_http_request_t *r, 13861563Svbart@nginx.com nxt_http_action_t *action) 13871563Svbart@nginx.com { 13881954Sz.hong@f5.com nxt_int_t ret; 13891954Sz.hong@f5.com nxt_str_t str; 13901563Svbart@nginx.com nxt_var_t *var; 13911954Sz.hong@f5.com 13921954Sz.hong@f5.com var = action->u.var; 13931954Sz.hong@f5.com 13941954Sz.hong@f5.com nxt_var_raw(var, &str); 13951954Sz.hong@f5.com 13961954Sz.hong@f5.com nxt_debug(task, "http pass: \"%V\"", &str); 13971563Svbart@nginx.com 13981563Svbart@nginx.com ret = nxt_var_query_init(&r->var_query, r, r->mem_pool); 13991563Svbart@nginx.com if (nxt_slow_path(ret != NXT_OK)) { 14001563Svbart@nginx.com goto fail; 14011563Svbart@nginx.com } 14021563Svbart@nginx.com 14031954Sz.hong@f5.com action = nxt_mp_get(r->mem_pool, 14041954Sz.hong@f5.com sizeof(nxt_http_action_t) + sizeof(nxt_str_t)); 14051563Svbart@nginx.com if (nxt_slow_path(action == NULL)) { 14061563Svbart@nginx.com goto fail; 14071563Svbart@nginx.com } 14081563Svbart@nginx.com 14091954Sz.hong@f5.com action->u.pass = nxt_pointer_to(action, sizeof(nxt_http_action_t)); 14101954Sz.hong@f5.com 14111954Sz.hong@f5.com nxt_var_query(task, r->var_query, var, action->u.pass); 14121563Svbart@nginx.com nxt_var_query_resolve(task, r->var_query, action, 14131954Sz.hong@f5.com nxt_http_pass_var_ready, 14141954Sz.hong@f5.com nxt_http_pass_var_error); 14151563Svbart@nginx.com return NULL; 14161563Svbart@nginx.com 14171563Svbart@nginx.com fail: 14181563Svbart@nginx.com 14191563Svbart@nginx.com nxt_http_request_error(task, r, NXT_HTTP_INTERNAL_SERVER_ERROR); 14201563Svbart@nginx.com return NULL; 14211563Svbart@nginx.com } 14221563Svbart@nginx.com 14231563Svbart@nginx.com 14241563Svbart@nginx.com static void 14251954Sz.hong@f5.com nxt_http_pass_var_ready(nxt_task_t *task, void *obj, void *data) 14261563Svbart@nginx.com { 14271563Svbart@nginx.com nxt_int_t ret; 14281563Svbart@nginx.com nxt_router_conf_t *rtcf; 14291563Svbart@nginx.com nxt_http_action_t *action; 14301563Svbart@nginx.com nxt_http_status_t status; 14311563Svbart@nginx.com nxt_http_request_t *r; 14321563Svbart@nginx.com 14331563Svbart@nginx.com r = obj; 14341563Svbart@nginx.com action = data; 14351563Svbart@nginx.com rtcf = r->conf->socket_conf->router_conf; 14361563Svbart@nginx.com 14371954Sz.hong@f5.com nxt_debug(task, "http pass lookup: %V", action->u.pass); 14381954Sz.hong@f5.com 14391954Sz.hong@f5.com ret = nxt_http_pass_find(r->mem_pool, rtcf, action->u.pass, action); 14401563Svbart@nginx.com 14411563Svbart@nginx.com if (ret != NXT_OK) { 14421563Svbart@nginx.com status = (ret == NXT_DECLINED) ? NXT_HTTP_NOT_FOUND 14431563Svbart@nginx.com : NXT_HTTP_INTERNAL_SERVER_ERROR; 14441563Svbart@nginx.com 14451563Svbart@nginx.com nxt_http_request_error(task, r, status); 14461563Svbart@nginx.com return; 14471563Svbart@nginx.com } 14481563Svbart@nginx.com 14491563Svbart@nginx.com nxt_http_request_action(task, r, action); 14501563Svbart@nginx.com } 14511563Svbart@nginx.com 14521563Svbart@nginx.com 14531563Svbart@nginx.com static void 14541954Sz.hong@f5.com nxt_http_pass_var_error(nxt_task_t *task, void *obj, void *data) 14551563Svbart@nginx.com { 14561563Svbart@nginx.com nxt_http_request_t *r; 14571563Svbart@nginx.com 14581563Svbart@nginx.com r = obj; 14591563Svbart@nginx.com 14601563Svbart@nginx.com nxt_http_request_error(task, r, NXT_HTTP_INTERNAL_SERVER_ERROR); 14611563Svbart@nginx.com } 14621563Svbart@nginx.com 14631563Svbart@nginx.com 14641563Svbart@nginx.com static nxt_int_t 14651954Sz.hong@f5.com nxt_http_pass_find(nxt_mp_t *mp, nxt_router_conf_t *rtcf, nxt_str_t *pass, 14661563Svbart@nginx.com nxt_http_action_t *action) 14671563Svbart@nginx.com { 14681954Sz.hong@f5.com nxt_int_t ret; 14691954Sz.hong@f5.com nxt_str_t segments[3]; 14701954Sz.hong@f5.com 14711954Sz.hong@f5.com ret = nxt_http_pass_segments(mp, pass, segments, 3); 14721563Svbart@nginx.com if (nxt_slow_path(ret != NXT_OK)) { 14731563Svbart@nginx.com return ret; 14741563Svbart@nginx.com } 14751563Svbart@nginx.com 14761472Svbart@nginx.com if (nxt_str_eq(&segments[0], "applications", 12)) { 14771925Sz.hong@f5.com return nxt_router_application_init(rtcf, &segments[1], &segments[2], 14781925Sz.hong@f5.com action); 14791472Svbart@nginx.com } 14801472Svbart@nginx.com 14811563Svbart@nginx.com if (segments[2].length == 0) { 14821563Svbart@nginx.com if (nxt_str_eq(&segments[0], "upstreams", 9)) { 14831563Svbart@nginx.com return nxt_upstream_find(rtcf->upstreams, &segments[1], action); 14841563Svbart@nginx.com } 14851563Svbart@nginx.com 14861563Svbart@nginx.com if (nxt_str_eq(&segments[0], "routes", 6)) { 14871563Svbart@nginx.com return nxt_http_route_find(rtcf->routes, &segments[1], action); 14881563Svbart@nginx.com } 14891563Svbart@nginx.com } 14901563Svbart@nginx.com 14911563Svbart@nginx.com return NXT_DECLINED; 14921472Svbart@nginx.com } 14931472Svbart@nginx.com 14941472Svbart@nginx.com 14951472Svbart@nginx.com nxt_int_t 14961472Svbart@nginx.com nxt_http_pass_segments(nxt_mp_t *mp, nxt_str_t *pass, nxt_str_t *segments, 14971472Svbart@nginx.com nxt_uint_t n) 14981472Svbart@nginx.com { 14991472Svbart@nginx.com u_char *p; 15001472Svbart@nginx.com nxt_str_t rest; 15011472Svbart@nginx.com 15021472Svbart@nginx.com if (nxt_slow_path(nxt_str_dup(mp, &rest, pass) == NULL)) { 15031472Svbart@nginx.com return NXT_ERROR; 15041472Svbart@nginx.com } 15051472Svbart@nginx.com 15061472Svbart@nginx.com nxt_memzero(segments, n * sizeof(nxt_str_t)); 15071472Svbart@nginx.com 15081472Svbart@nginx.com do { 15091472Svbart@nginx.com p = nxt_memchr(rest.start, '/', rest.length); 15101472Svbart@nginx.com 15111472Svbart@nginx.com if (p != NULL) { 15121472Svbart@nginx.com n--; 15131472Svbart@nginx.com 15141472Svbart@nginx.com if (n == 0) { 15151472Svbart@nginx.com return NXT_DECLINED; 15161472Svbart@nginx.com } 15171472Svbart@nginx.com 15181472Svbart@nginx.com segments->length = p - rest.start; 15191472Svbart@nginx.com segments->start = rest.start; 15201472Svbart@nginx.com 15211472Svbart@nginx.com rest.length -= segments->length + 1; 15221472Svbart@nginx.com rest.start = p + 1; 15231472Svbart@nginx.com 15241472Svbart@nginx.com } else { 15251472Svbart@nginx.com n = 0; 15261472Svbart@nginx.com *segments = rest; 1527964Sigor@sysoev.ru } 1528964Sigor@sysoev.ru 15291472Svbart@nginx.com if (segments->length == 0) { 15301472Svbart@nginx.com return NXT_DECLINED; 15311472Svbart@nginx.com } 15321472Svbart@nginx.com 15331472Svbart@nginx.com p = nxt_decode_uri(segments->start, segments->start, segments->length); 15341472Svbart@nginx.com if (p == NULL) { 15351472Svbart@nginx.com return NXT_DECLINED; 15361472Svbart@nginx.com } 15371472Svbart@nginx.com 15381472Svbart@nginx.com segments->length = p - segments->start; 15391472Svbart@nginx.com segments++; 15401472Svbart@nginx.com 15411472Svbart@nginx.com } while (n); 15421472Svbart@nginx.com 15431472Svbart@nginx.com return NXT_OK; 1544964Sigor@sysoev.ru } 1545964Sigor@sysoev.ru 1546964Sigor@sysoev.ru 15471563Svbart@nginx.com static nxt_int_t 15481392Sigor@sysoev.ru nxt_http_route_find(nxt_http_routes_t *routes, nxt_str_t *name, 15491392Sigor@sysoev.ru nxt_http_action_t *action) 1550964Sigor@sysoev.ru { 15511033Svbart@nginx.com nxt_http_route_t **route, **end; 1552964Sigor@sysoev.ru 15531928Sz.hong@f5.com if (routes == NULL) { 15541928Sz.hong@f5.com return NXT_DECLINED; 15551928Sz.hong@f5.com } 15561928Sz.hong@f5.com 1557964Sigor@sysoev.ru route = &routes->route[0]; 15581033Svbart@nginx.com end = route + routes->items; 1559964Sigor@sysoev.ru 15601058Sigor@sysoev.ru while (route < end) { 1561964Sigor@sysoev.ru if (nxt_strstr_eq(&(*route)->name, name)) { 15621392Sigor@sysoev.ru action->u.route = *route; 15631392Sigor@sysoev.ru action->handler = nxt_http_route_handler; 15641392Sigor@sysoev.ru 15651563Svbart@nginx.com return NXT_OK; 1566964Sigor@sysoev.ru } 1567964Sigor@sysoev.ru 1568964Sigor@sysoev.ru route++; 15691058Sigor@sysoev.ru } 15701563Svbart@nginx.com 15711563Svbart@nginx.com return NXT_DECLINED; 1572964Sigor@sysoev.ru } 1573964Sigor@sysoev.ru 1574964Sigor@sysoev.ru 15751264Sigor@sysoev.ru nxt_http_action_t * 15761264Sigor@sysoev.ru nxt_http_action_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, 15771954Sz.hong@f5.com nxt_str_t *pass) 1578964Sigor@sysoev.ru { 15791954Sz.hong@f5.com nxt_mp_t *mp; 15801597Shongzhidao@gmail.com nxt_int_t ret; 15811264Sigor@sysoev.ru nxt_http_action_t *action; 1582964Sigor@sysoev.ru 15831954Sz.hong@f5.com mp = tmcf->router_conf->mem_pool; 15841954Sz.hong@f5.com 15851954Sz.hong@f5.com action = nxt_mp_alloc(mp, sizeof(nxt_http_action_t)); 15861264Sigor@sysoev.ru if (nxt_slow_path(action == NULL)) { 1587964Sigor@sysoev.ru return NULL; 1588964Sigor@sysoev.ru } 1589964Sigor@sysoev.ru 15901959Sz.hong@f5.com action->u.var = nxt_var_compile(pass, mp, 0); 15911954Sz.hong@f5.com if (nxt_slow_path(action->u.var == NULL)) { 15921954Sz.hong@f5.com return NULL; 15931954Sz.hong@f5.com } 15941954Sz.hong@f5.com 15951270Sigor@sysoev.ru action->handler = NULL; 1596964Sigor@sysoev.ru 15971597Shongzhidao@gmail.com ret = nxt_http_action_resolve(task, tmcf, action); 15981597Shongzhidao@gmail.com if (nxt_slow_path(ret != NXT_OK)) { 15991597Shongzhidao@gmail.com return NULL; 16001597Shongzhidao@gmail.com } 1601964Sigor@sysoev.ru 16021264Sigor@sysoev.ru return action; 1603964Sigor@sysoev.ru } 1604964Sigor@sysoev.ru 1605964Sigor@sysoev.ru 1606964Sigor@sysoev.ru /* COMPATIBILITY: listener application. */ 1607964Sigor@sysoev.ru 16081264Sigor@sysoev.ru nxt_http_action_t * 16091563Svbart@nginx.com nxt_http_pass_application(nxt_task_t *task, nxt_router_conf_t *rtcf, 1610964Sigor@sysoev.ru nxt_str_t *name) 1611964Sigor@sysoev.ru { 16121264Sigor@sysoev.ru nxt_http_action_t *action; 1613964Sigor@sysoev.ru 16141563Svbart@nginx.com action = nxt_mp_alloc(rtcf->mem_pool, sizeof(nxt_http_action_t)); 16151264Sigor@sysoev.ru if (nxt_slow_path(action == NULL)) { 1616964Sigor@sysoev.ru return NULL; 1617964Sigor@sysoev.ru } 1618964Sigor@sysoev.ru 16191925Sz.hong@f5.com (void) nxt_router_application_init(rtcf, name, NULL, action); 16201473Svbart@nginx.com 16211264Sigor@sysoev.ru return action; 1622964Sigor@sysoev.ru } 1623964Sigor@sysoev.ru 1624964Sigor@sysoev.ru 16251264Sigor@sysoev.ru static nxt_http_action_t * 16261264Sigor@sysoev.ru nxt_http_route_handler(nxt_task_t *task, nxt_http_request_t *r, 16271264Sigor@sysoev.ru nxt_http_action_t *start) 1628964Sigor@sysoev.ru { 1629964Sigor@sysoev.ru nxt_http_route_t *route; 16301264Sigor@sysoev.ru nxt_http_action_t *action; 16311033Svbart@nginx.com nxt_http_route_match_t **match, **end; 1632964Sigor@sysoev.ru 1633964Sigor@sysoev.ru route = start->u.route; 1634964Sigor@sysoev.ru match = &route->match[0]; 16351033Svbart@nginx.com end = match + route->items; 1636964Sigor@sysoev.ru 16371033Svbart@nginx.com while (match < end) { 16381326Saxel.duch@nginx.com action = nxt_http_route_match(task, r, *match); 16391264Sigor@sysoev.ru if (action != NULL) { 16401264Sigor@sysoev.ru return action; 1641964Sigor@sysoev.ru } 1642964Sigor@sysoev.ru 1643964Sigor@sysoev.ru match++; 1644964Sigor@sysoev.ru } 1645964Sigor@sysoev.ru 1646964Sigor@sysoev.ru nxt_http_request_error(task, r, NXT_HTTP_NOT_FOUND); 1647964Sigor@sysoev.ru 1648964Sigor@sysoev.ru return NULL; 1649964Sigor@sysoev.ru } 1650964Sigor@sysoev.ru 1651964Sigor@sysoev.ru 16521264Sigor@sysoev.ru static nxt_http_action_t * 16531326Saxel.duch@nginx.com nxt_http_route_match(nxt_task_t *task, nxt_http_request_t *r, 16541326Saxel.duch@nginx.com nxt_http_route_match_t *match) 1655964Sigor@sysoev.ru { 16561060Sigor@sysoev.ru nxt_int_t ret; 16571059Sigor@sysoev.ru nxt_http_route_test_t *test, *end; 16581059Sigor@sysoev.ru 16591059Sigor@sysoev.ru test = &match->test[0]; 16601059Sigor@sysoev.ru end = test + match->items; 1661964Sigor@sysoev.ru 16621059Sigor@sysoev.ru while (test < end) { 16631324Saxel.duch@nginx.com switch (test->rule->object) { 16641324Saxel.duch@nginx.com case NXT_HTTP_ROUTE_TABLE: 16651324Saxel.duch@nginx.com ret = nxt_http_route_table(r, test->table); 16661324Saxel.duch@nginx.com break; 16671324Saxel.duch@nginx.com case NXT_HTTP_ROUTE_SOURCE: 16681324Saxel.duch@nginx.com ret = nxt_http_route_addr_rule(r, test->addr_rule, r->remote); 16691324Saxel.duch@nginx.com break; 16701326Saxel.duch@nginx.com case NXT_HTTP_ROUTE_DESTINATION: 16711326Saxel.duch@nginx.com if (r->local == NULL && nxt_fast_path(r->proto.any != NULL)) { 16721326Saxel.duch@nginx.com nxt_http_proto[r->protocol].local_addr(task, r); 16731326Saxel.duch@nginx.com } 16741326Saxel.duch@nginx.com 16751326Saxel.duch@nginx.com ret = nxt_http_route_addr_rule(r, test->addr_rule, r->local); 16761326Saxel.duch@nginx.com break; 16771324Saxel.duch@nginx.com default: 16781059Sigor@sysoev.ru ret = nxt_http_route_rule(r, test->rule); 16791324Saxel.duch@nginx.com break; 16801059Sigor@sysoev.ru } 16811059Sigor@sysoev.ru 16821060Sigor@sysoev.ru if (ret <= 0) { 16831264Sigor@sysoev.ru /* 0 => NULL, -1 => NXT_HTTP_ACTION_ERROR. */ 16841264Sigor@sysoev.ru return (nxt_http_action_t *) (intptr_t) ret; 1685964Sigor@sysoev.ru } 1686964Sigor@sysoev.ru 16871059Sigor@sysoev.ru test++; 1688964Sigor@sysoev.ru } 1689964Sigor@sysoev.ru 16901264Sigor@sysoev.ru return &match->action; 1691964Sigor@sysoev.ru } 1692964Sigor@sysoev.ru 1693964Sigor@sysoev.ru 16941060Sigor@sysoev.ru static nxt_int_t 16951059Sigor@sysoev.ru nxt_http_route_table(nxt_http_request_t *r, nxt_http_route_table_t *table) 1696964Sigor@sysoev.ru { 16971060Sigor@sysoev.ru nxt_int_t ret; 16981059Sigor@sysoev.ru nxt_http_route_ruleset_t **ruleset, **end; 16991059Sigor@sysoev.ru 17001059Sigor@sysoev.ru ret = 1; 17011059Sigor@sysoev.ru ruleset = &table->ruleset[0]; 17021059Sigor@sysoev.ru end = ruleset + table->items; 17031059Sigor@sysoev.ru 17041059Sigor@sysoev.ru while (ruleset < end) { 17051059Sigor@sysoev.ru ret = nxt_http_route_ruleset(r, *ruleset); 17061059Sigor@sysoev.ru 17071060Sigor@sysoev.ru if (ret != 0) { 17081059Sigor@sysoev.ru return ret; 17091059Sigor@sysoev.ru } 1710964Sigor@sysoev.ru 17111059Sigor@sysoev.ru ruleset++; 17121059Sigor@sysoev.ru } 17131059Sigor@sysoev.ru 17141059Sigor@sysoev.ru return ret; 17151059Sigor@sysoev.ru } 17161059Sigor@sysoev.ru 1717964Sigor@sysoev.ru 17181060Sigor@sysoev.ru static nxt_int_t 17191059Sigor@sysoev.ru nxt_http_route_ruleset(nxt_http_request_t *r, nxt_http_route_ruleset_t *ruleset) 17201059Sigor@sysoev.ru { 17211060Sigor@sysoev.ru nxt_int_t ret; 17221059Sigor@sysoev.ru nxt_http_route_rule_t **rule, **end; 1723964Sigor@sysoev.ru 17241059Sigor@sysoev.ru rule = &ruleset->rule[0]; 17251059Sigor@sysoev.ru end = rule + ruleset->items; 1726964Sigor@sysoev.ru 17271059Sigor@sysoev.ru while (rule < end) { 17281060Sigor@sysoev.ru ret = nxt_http_route_rule(r, *rule); 17291060Sigor@sysoev.ru 17301060Sigor@sysoev.ru if (ret <= 0) { 17311060Sigor@sysoev.ru return ret; 1732964Sigor@sysoev.ru } 1733964Sigor@sysoev.ru 17341059Sigor@sysoev.ru rule++; 17351059Sigor@sysoev.ru } 17361059Sigor@sysoev.ru 17371059Sigor@sysoev.ru return 1; 17381059Sigor@sysoev.ru } 17391059Sigor@sysoev.ru 1740964Sigor@sysoev.ru 17411060Sigor@sysoev.ru static nxt_int_t 17421059Sigor@sysoev.ru nxt_http_route_rule(nxt_http_request_t *r, nxt_http_route_rule_t *rule) 17431059Sigor@sysoev.ru { 17441059Sigor@sysoev.ru void *p, **pp; 17451059Sigor@sysoev.ru u_char *start; 17461059Sigor@sysoev.ru size_t length; 17471059Sigor@sysoev.ru nxt_str_t *s; 17481059Sigor@sysoev.ru 17491059Sigor@sysoev.ru switch (rule->object) { 17501059Sigor@sysoev.ru 17511059Sigor@sysoev.ru case NXT_HTTP_ROUTE_HEADER: 17521059Sigor@sysoev.ru return nxt_http_route_header(r, rule); 1753964Sigor@sysoev.ru 17541059Sigor@sysoev.ru case NXT_HTTP_ROUTE_ARGUMENT: 17551061Sigor@sysoev.ru return nxt_http_route_arguments(r, rule); 1756964Sigor@sysoev.ru 17571059Sigor@sysoev.ru case NXT_HTTP_ROUTE_COOKIE: 17581062Sigor@sysoev.ru return nxt_http_route_cookies(r, rule); 17591059Sigor@sysoev.ru 17601110Saxel.duch@nginx.com case NXT_HTTP_ROUTE_SCHEME: 17611110Saxel.duch@nginx.com return nxt_http_route_scheme(r, rule); 17621110Saxel.duch@nginx.com 17631991Sz.hong@f5.com case NXT_HTTP_ROUTE_QUERY: 17641991Sz.hong@f5.com return nxt_http_route_query(r, rule); 17651991Sz.hong@f5.com 17661059Sigor@sysoev.ru default: 17671059Sigor@sysoev.ru break; 17681059Sigor@sysoev.ru } 1769964Sigor@sysoev.ru 17701059Sigor@sysoev.ru p = nxt_pointer_to(r, rule->u.offset); 17711059Sigor@sysoev.ru 17721059Sigor@sysoev.ru if (rule->object == NXT_HTTP_ROUTE_STRING) { 17731059Sigor@sysoev.ru s = p; 1774964Sigor@sysoev.ru 17751059Sigor@sysoev.ru } else { 17761059Sigor@sysoev.ru /* NXT_HTTP_ROUTE_STRING_PTR */ 17771059Sigor@sysoev.ru pp = p; 17781059Sigor@sysoev.ru s = *pp; 1779964Sigor@sysoev.ru 17801059Sigor@sysoev.ru if (s == NULL) { 1781964Sigor@sysoev.ru return 0; 1782964Sigor@sysoev.ru } 1783964Sigor@sysoev.ru } 1784964Sigor@sysoev.ru 17851059Sigor@sysoev.ru length = s->length; 17861059Sigor@sysoev.ru start = s->start; 17871059Sigor@sysoev.ru 17881059Sigor@sysoev.ru return nxt_http_route_test_rule(r, rule, start, length); 17891059Sigor@sysoev.ru } 17901059Sigor@sysoev.ru 17911059Sigor@sysoev.ru 17921060Sigor@sysoev.ru static nxt_int_t 17931324Saxel.duch@nginx.com nxt_http_route_addr_pattern_match(nxt_http_route_addr_pattern_t *p, 17941324Saxel.duch@nginx.com nxt_sockaddr_t *sa) 17951324Saxel.duch@nginx.com { 17961324Saxel.duch@nginx.com #if (NXT_INET6) 17971324Saxel.duch@nginx.com uint32_t i; 17981324Saxel.duch@nginx.com #endif 17991324Saxel.duch@nginx.com in_port_t in_port; 18001324Saxel.duch@nginx.com nxt_int_t match; 18011324Saxel.duch@nginx.com struct sockaddr_in *sin; 18021324Saxel.duch@nginx.com #if (NXT_INET6) 18031324Saxel.duch@nginx.com struct sockaddr_in6 *sin6; 18041324Saxel.duch@nginx.com #endif 18051324Saxel.duch@nginx.com nxt_http_route_addr_base_t *base; 18061324Saxel.duch@nginx.com 18071324Saxel.duch@nginx.com base = &p->base; 18081324Saxel.duch@nginx.com 18091324Saxel.duch@nginx.com switch (sa->u.sockaddr.sa_family) { 18101324Saxel.duch@nginx.com 18111324Saxel.duch@nginx.com case AF_INET: 18121324Saxel.duch@nginx.com 18131324Saxel.duch@nginx.com match = (base->addr_family == AF_INET 18141324Saxel.duch@nginx.com || base->addr_family == AF_UNSPEC); 18151324Saxel.duch@nginx.com if (!match) { 18161324Saxel.duch@nginx.com break; 18171324Saxel.duch@nginx.com } 18181324Saxel.duch@nginx.com 18191324Saxel.duch@nginx.com sin = &sa->u.sockaddr_in; 18201324Saxel.duch@nginx.com in_port = ntohs(sin->sin_port); 18211324Saxel.duch@nginx.com 18221324Saxel.duch@nginx.com match = (in_port >= base->port.start && in_port <= base->port.end); 18231324Saxel.duch@nginx.com if (!match) { 18241324Saxel.duch@nginx.com break; 18251324Saxel.duch@nginx.com } 18261324Saxel.duch@nginx.com 18271324Saxel.duch@nginx.com switch (base->match_type) { 18281324Saxel.duch@nginx.com 18291324Saxel.duch@nginx.com case NXT_HTTP_ROUTE_ADDR_ANY: 18301324Saxel.duch@nginx.com break; 18311324Saxel.duch@nginx.com 18321324Saxel.duch@nginx.com case NXT_HTTP_ROUTE_ADDR_EXACT: 18331324Saxel.duch@nginx.com match = (nxt_memcmp(&sin->sin_addr, &p->addr.v4.start, 18341324Saxel.duch@nginx.com sizeof(struct in_addr)) 18351324Saxel.duch@nginx.com == 0); 18361324Saxel.duch@nginx.com break; 18371324Saxel.duch@nginx.com 18381324Saxel.duch@nginx.com case NXT_HTTP_ROUTE_ADDR_RANGE: 18391324Saxel.duch@nginx.com match = (nxt_memcmp(&sin->sin_addr, &p->addr.v4.start, 18401324Saxel.duch@nginx.com sizeof(struct in_addr)) >= 0 18411324Saxel.duch@nginx.com && nxt_memcmp(&sin->sin_addr, &p->addr.v4.end, 18421324Saxel.duch@nginx.com sizeof(struct in_addr)) <= 0); 18431324Saxel.duch@nginx.com break; 18441324Saxel.duch@nginx.com 18451324Saxel.duch@nginx.com case NXT_HTTP_ROUTE_ADDR_CIDR: 18461324Saxel.duch@nginx.com match = ((sin->sin_addr.s_addr & p->addr.v4.end) 18471324Saxel.duch@nginx.com == p->addr.v4.start); 18481324Saxel.duch@nginx.com break; 18491324Saxel.duch@nginx.com 18501324Saxel.duch@nginx.com default: 18511324Saxel.duch@nginx.com nxt_unreachable(); 18521324Saxel.duch@nginx.com } 18531324Saxel.duch@nginx.com 18541324Saxel.duch@nginx.com break; 18551324Saxel.duch@nginx.com 18561324Saxel.duch@nginx.com #if (NXT_INET6) 18571324Saxel.duch@nginx.com case AF_INET6: 18581324Saxel.duch@nginx.com 18591324Saxel.duch@nginx.com match = (base->addr_family == AF_INET6 18601324Saxel.duch@nginx.com || base->addr_family == AF_UNSPEC); 18611324Saxel.duch@nginx.com if (!match) { 18621324Saxel.duch@nginx.com break; 18631324Saxel.duch@nginx.com } 18641324Saxel.duch@nginx.com 18651324Saxel.duch@nginx.com sin6 = &sa->u.sockaddr_in6; 18661324Saxel.duch@nginx.com in_port = ntohs(sin6->sin6_port); 18671324Saxel.duch@nginx.com 18681324Saxel.duch@nginx.com match = (in_port >= base->port.start && in_port <= base->port.end); 18691324Saxel.duch@nginx.com if (!match) { 18701324Saxel.duch@nginx.com break; 18711324Saxel.duch@nginx.com } 18721324Saxel.duch@nginx.com 18731324Saxel.duch@nginx.com switch (base->match_type) { 18741324Saxel.duch@nginx.com 18751324Saxel.duch@nginx.com case NXT_HTTP_ROUTE_ADDR_ANY: 18761324Saxel.duch@nginx.com break; 18771324Saxel.duch@nginx.com 18781324Saxel.duch@nginx.com case NXT_HTTP_ROUTE_ADDR_EXACT: 18791324Saxel.duch@nginx.com match = (nxt_memcmp(&sin6->sin6_addr, &p->addr.v6.start, 18801324Saxel.duch@nginx.com sizeof(struct in6_addr)) 18811324Saxel.duch@nginx.com == 0); 18821324Saxel.duch@nginx.com break; 18831324Saxel.duch@nginx.com 18841324Saxel.duch@nginx.com case NXT_HTTP_ROUTE_ADDR_RANGE: 18851324Saxel.duch@nginx.com match = (nxt_memcmp(&sin6->sin6_addr, &p->addr.v6.start, 18861324Saxel.duch@nginx.com sizeof(struct in6_addr)) >= 0 18871324Saxel.duch@nginx.com && nxt_memcmp(&sin6->sin6_addr, &p->addr.v6.end, 18881324Saxel.duch@nginx.com sizeof(struct in6_addr)) <= 0); 18891324Saxel.duch@nginx.com break; 18901324Saxel.duch@nginx.com 18911324Saxel.duch@nginx.com case NXT_HTTP_ROUTE_ADDR_CIDR: 18921324Saxel.duch@nginx.com for (i = 0; i < 16; i++) { 18931324Saxel.duch@nginx.com match = ((sin6->sin6_addr.s6_addr[i] 18941324Saxel.duch@nginx.com & p->addr.v6.end.s6_addr[i]) 18951324Saxel.duch@nginx.com == p->addr.v6.start.s6_addr[i]); 18961324Saxel.duch@nginx.com 18971324Saxel.duch@nginx.com if (!match) { 18981324Saxel.duch@nginx.com break; 18991324Saxel.duch@nginx.com } 19001324Saxel.duch@nginx.com } 19011324Saxel.duch@nginx.com 19021324Saxel.duch@nginx.com break; 19031324Saxel.duch@nginx.com 19041324Saxel.duch@nginx.com default: 19051324Saxel.duch@nginx.com nxt_unreachable(); 19061324Saxel.duch@nginx.com } 19071324Saxel.duch@nginx.com 19081324Saxel.duch@nginx.com break; 19091324Saxel.duch@nginx.com #endif 19101324Saxel.duch@nginx.com 19111324Saxel.duch@nginx.com default: 19121324Saxel.duch@nginx.com match = 0; 19131324Saxel.duch@nginx.com break; 19141324Saxel.duch@nginx.com } 19151324Saxel.duch@nginx.com 19161324Saxel.duch@nginx.com return match ^ base->negative; 19171324Saxel.duch@nginx.com } 19181324Saxel.duch@nginx.com 19191324Saxel.duch@nginx.com 19201936So.canty@f5.com nxt_int_t 19211324Saxel.duch@nginx.com nxt_http_route_addr_rule(nxt_http_request_t *r, 19221324Saxel.duch@nginx.com nxt_http_route_addr_rule_t *addr_rule, nxt_sockaddr_t *sa) 19231324Saxel.duch@nginx.com { 19241390Saxel.duch@nginx.com uint32_t n; 19251390Saxel.duch@nginx.com nxt_bool_t matches; 19261324Saxel.duch@nginx.com nxt_http_route_addr_pattern_t *p; 19271324Saxel.duch@nginx.com 19281324Saxel.duch@nginx.com n = addr_rule->items; 19291930So.canty@f5.com 19301930So.canty@f5.com if (n == 0) { 19311930So.canty@f5.com return 0; 19321930So.canty@f5.com } 19331930So.canty@f5.com 19341390Saxel.duch@nginx.com p = &addr_rule->addr_pattern[0] - 1; 19351324Saxel.duch@nginx.com 19361390Saxel.duch@nginx.com do { 19371390Saxel.duch@nginx.com p++; 19381390Saxel.duch@nginx.com n--; 19391390Saxel.duch@nginx.com 19401390Saxel.duch@nginx.com matches = nxt_http_route_addr_pattern_match(p, sa); 19411390Saxel.duch@nginx.com 19421390Saxel.duch@nginx.com if (p->base.negative) { 19431390Saxel.duch@nginx.com if (matches) { 19441390Saxel.duch@nginx.com continue; 19451390Saxel.duch@nginx.com } 19461390Saxel.duch@nginx.com 19471390Saxel.duch@nginx.com return 0; 19481390Saxel.duch@nginx.com } 19491390Saxel.duch@nginx.com 19501390Saxel.duch@nginx.com if (matches) { 19511324Saxel.duch@nginx.com return 1; 19521324Saxel.duch@nginx.com } 19531324Saxel.duch@nginx.com 19541390Saxel.duch@nginx.com } while (n > 0); 19551390Saxel.duch@nginx.com 19561390Saxel.duch@nginx.com return p->base.negative; 19571324Saxel.duch@nginx.com } 19581324Saxel.duch@nginx.com 19591324Saxel.duch@nginx.com 19601324Saxel.duch@nginx.com static nxt_int_t 19611059Sigor@sysoev.ru nxt_http_route_header(nxt_http_request_t *r, nxt_http_route_rule_t *rule) 19621059Sigor@sysoev.ru { 19631060Sigor@sysoev.ru nxt_int_t ret; 19641059Sigor@sysoev.ru nxt_http_field_t *f; 19651059Sigor@sysoev.ru 19661059Sigor@sysoev.ru ret = 0; 19671059Sigor@sysoev.ru 19681059Sigor@sysoev.ru nxt_list_each(f, r->fields) { 19691059Sigor@sysoev.ru 19701059Sigor@sysoev.ru if (rule->u.name.hash != f->hash 19711059Sigor@sysoev.ru || rule->u.name.length != f->name_length 19721059Sigor@sysoev.ru || nxt_strncasecmp(rule->u.name.start, f->name, f->name_length) 19731059Sigor@sysoev.ru != 0) 19741059Sigor@sysoev.ru { 19751059Sigor@sysoev.ru continue; 19761059Sigor@sysoev.ru } 19771059Sigor@sysoev.ru 19781059Sigor@sysoev.ru ret = nxt_http_route_test_rule(r, rule, f->value, f->value_length); 19791721Saxel.duch@nginx.com if (nxt_slow_path(ret == NXT_ERROR)) { 19801721Saxel.duch@nginx.com return NXT_ERROR; 19811721Saxel.duch@nginx.com } 19821059Sigor@sysoev.ru 19831060Sigor@sysoev.ru if (ret == 0) { 19841059Sigor@sysoev.ru return ret; 19851059Sigor@sysoev.ru } 19861059Sigor@sysoev.ru 19871059Sigor@sysoev.ru } nxt_list_loop; 19881059Sigor@sysoev.ru 19891059Sigor@sysoev.ru return ret; 19901059Sigor@sysoev.ru } 19911059Sigor@sysoev.ru 19921059Sigor@sysoev.ru 19931060Sigor@sysoev.ru static nxt_int_t 19941061Sigor@sysoev.ru nxt_http_route_arguments(nxt_http_request_t *r, nxt_http_route_rule_t *rule) 19951061Sigor@sysoev.ru { 19961061Sigor@sysoev.ru nxt_array_t *arguments; 19971061Sigor@sysoev.ru 19981061Sigor@sysoev.ru arguments = nxt_http_route_arguments_parse(r); 19991061Sigor@sysoev.ru if (nxt_slow_path(arguments == NULL)) { 20001061Sigor@sysoev.ru return -1; 20011061Sigor@sysoev.ru } 20021061Sigor@sysoev.ru 20031061Sigor@sysoev.ru return nxt_http_route_test_argument(r, rule, arguments); 20041061Sigor@sysoev.ru } 20051061Sigor@sysoev.ru 20061061Sigor@sysoev.ru 20071061Sigor@sysoev.ru static nxt_array_t * 20081061Sigor@sysoev.ru nxt_http_route_arguments_parse(nxt_http_request_t *r) 20091061Sigor@sysoev.ru { 20101061Sigor@sysoev.ru size_t name_length; 20111989Sz.hong@f5.com u_char *p, *dst, *dst_start, *start, *end, *name; 20121474Saxel.duch@nginx.com uint8_t d0, d1; 20131061Sigor@sysoev.ru uint32_t hash; 20141061Sigor@sysoev.ru nxt_array_t *args; 20151061Sigor@sysoev.ru nxt_http_name_value_t *nv; 20161061Sigor@sysoev.ru 20171061Sigor@sysoev.ru if (r->arguments != NULL) { 20181061Sigor@sysoev.ru return r->arguments; 20191061Sigor@sysoev.ru } 20201061Sigor@sysoev.ru 20211061Sigor@sysoev.ru args = nxt_array_create(r->mem_pool, 2, sizeof(nxt_http_name_value_t)); 20221061Sigor@sysoev.ru if (nxt_slow_path(args == NULL)) { 20231061Sigor@sysoev.ru return NULL; 20241061Sigor@sysoev.ru } 20251061Sigor@sysoev.ru 20261061Sigor@sysoev.ru hash = NXT_HTTP_FIELD_HASH_INIT; 20271061Sigor@sysoev.ru name = NULL; 20281061Sigor@sysoev.ru name_length = 0; 20291061Sigor@sysoev.ru 20301474Saxel.duch@nginx.com dst_start = nxt_mp_nget(r->mem_pool, r->args->length); 20311474Saxel.duch@nginx.com if (nxt_slow_path(dst_start == NULL)) { 20321474Saxel.duch@nginx.com return NULL; 20331474Saxel.duch@nginx.com } 20341474Saxel.duch@nginx.com 20351991Sz.hong@f5.com r->args_decoded.start = dst_start; 20361991Sz.hong@f5.com 20371061Sigor@sysoev.ru start = r->args->start; 20381061Sigor@sysoev.ru end = start + r->args->length; 20391061Sigor@sysoev.ru 20401474Saxel.duch@nginx.com for (p = start, dst = dst_start; p < end; p++, dst++) { 20411989Sz.hong@f5.com *dst = *p; 20421989Sz.hong@f5.com 20431989Sz.hong@f5.com switch (*p) { 20441474Saxel.duch@nginx.com case '=': 20451989Sz.hong@f5.com if (name == NULL) { 20461989Sz.hong@f5.com name_length = dst - dst_start; 20471989Sz.hong@f5.com name = dst_start; 20481989Sz.hong@f5.com dst_start = dst + 1; 20491474Saxel.duch@nginx.com } 20501474Saxel.duch@nginx.com 20511474Saxel.duch@nginx.com continue; 20521474Saxel.duch@nginx.com 20531474Saxel.duch@nginx.com case '&': 20541989Sz.hong@f5.com if (name_length != 0 || dst != dst_start) { 20551061Sigor@sysoev.ru nv = nxt_http_route_argument(args, name, name_length, hash, 20561474Saxel.duch@nginx.com dst_start, dst); 20571061Sigor@sysoev.ru if (nxt_slow_path(nv == NULL)) { 20581061Sigor@sysoev.ru return NULL; 20591061Sigor@sysoev.ru } 20601061Sigor@sysoev.ru } 20611061Sigor@sysoev.ru 20621061Sigor@sysoev.ru hash = NXT_HTTP_FIELD_HASH_INIT; 20631474Saxel.duch@nginx.com name_length = 0; 20641061Sigor@sysoev.ru name = NULL; 20651474Saxel.duch@nginx.com dst_start = dst + 1; 20661474Saxel.duch@nginx.com 20671474Saxel.duch@nginx.com continue; 20681474Saxel.duch@nginx.com 20691474Saxel.duch@nginx.com case '+': 20701474Saxel.duch@nginx.com *dst = ' '; 20711474Saxel.duch@nginx.com 20721474Saxel.duch@nginx.com break; 20731474Saxel.duch@nginx.com 20741474Saxel.duch@nginx.com case '%': 20751474Saxel.duch@nginx.com if (nxt_slow_path(end - p <= 2)) { 20761474Saxel.duch@nginx.com break; 20771474Saxel.duch@nginx.com } 20781474Saxel.duch@nginx.com 20791474Saxel.duch@nginx.com d0 = nxt_hex2int[p[1]]; 20801474Saxel.duch@nginx.com d1 = nxt_hex2int[p[2]]; 20811474Saxel.duch@nginx.com 20821474Saxel.duch@nginx.com if (nxt_slow_path((d0 | d1) >= 16)) { 20831474Saxel.duch@nginx.com break; 20841474Saxel.duch@nginx.com } 20851474Saxel.duch@nginx.com 20861474Saxel.duch@nginx.com p += 2; 20871989Sz.hong@f5.com *dst = (d0 << 4) + d1; 20881474Saxel.duch@nginx.com 20891474Saxel.duch@nginx.com break; 20901474Saxel.duch@nginx.com } 20911474Saxel.duch@nginx.com 20921474Saxel.duch@nginx.com if (name == NULL) { 20931989Sz.hong@f5.com hash = nxt_http_field_hash_char(hash, *dst); 20941061Sigor@sysoev.ru } 20951061Sigor@sysoev.ru } 20961061Sigor@sysoev.ru 20971991Sz.hong@f5.com r->args_decoded.length = dst - r->args_decoded.start; 20981991Sz.hong@f5.com 20991989Sz.hong@f5.com if (name_length != 0 || dst != dst_start) { 21001474Saxel.duch@nginx.com nv = nxt_http_route_argument(args, name, name_length, hash, dst_start, 21011474Saxel.duch@nginx.com dst); 21021061Sigor@sysoev.ru if (nxt_slow_path(nv == NULL)) { 21031061Sigor@sysoev.ru return NULL; 21041061Sigor@sysoev.ru } 21051061Sigor@sysoev.ru } 21061061Sigor@sysoev.ru 21071061Sigor@sysoev.ru r->arguments = args; 21081061Sigor@sysoev.ru 21091061Sigor@sysoev.ru return args; 21101061Sigor@sysoev.ru } 21111061Sigor@sysoev.ru 21121061Sigor@sysoev.ru 21131061Sigor@sysoev.ru static nxt_http_name_value_t * 21141061Sigor@sysoev.ru nxt_http_route_argument(nxt_array_t *array, u_char *name, size_t name_length, 21151061Sigor@sysoev.ru uint32_t hash, u_char *start, u_char *end) 21161061Sigor@sysoev.ru { 21171061Sigor@sysoev.ru size_t length; 21181061Sigor@sysoev.ru nxt_http_name_value_t *nv; 21191061Sigor@sysoev.ru 21201061Sigor@sysoev.ru nv = nxt_array_add(array); 21211061Sigor@sysoev.ru if (nxt_slow_path(nv == NULL)) { 21221061Sigor@sysoev.ru return NULL; 21231061Sigor@sysoev.ru } 21241061Sigor@sysoev.ru 21251061Sigor@sysoev.ru nv->hash = nxt_http_field_hash_end(hash) & 0xFFFF; 21261061Sigor@sysoev.ru 21271061Sigor@sysoev.ru length = end - start; 21281061Sigor@sysoev.ru 21291061Sigor@sysoev.ru if (name == NULL) { 21301061Sigor@sysoev.ru name_length = length; 21311061Sigor@sysoev.ru name = start; 21321061Sigor@sysoev.ru length = 0; 21331061Sigor@sysoev.ru } 21341061Sigor@sysoev.ru 21351061Sigor@sysoev.ru nv->name_length = name_length; 21361061Sigor@sysoev.ru nv->value_length = length; 21371061Sigor@sysoev.ru nv->name = name; 21381061Sigor@sysoev.ru nv->value = start; 21391061Sigor@sysoev.ru 21401061Sigor@sysoev.ru return nv; 21411061Sigor@sysoev.ru } 21421061Sigor@sysoev.ru 21431061Sigor@sysoev.ru 21441061Sigor@sysoev.ru static nxt_int_t 21451061Sigor@sysoev.ru nxt_http_route_test_argument(nxt_http_request_t *r, 21461061Sigor@sysoev.ru nxt_http_route_rule_t *rule, nxt_array_t *array) 21471061Sigor@sysoev.ru { 21481721Saxel.duch@nginx.com nxt_int_t ret; 21491061Sigor@sysoev.ru nxt_http_name_value_t *nv, *end; 21501061Sigor@sysoev.ru 21511061Sigor@sysoev.ru ret = 0; 21521061Sigor@sysoev.ru 21531061Sigor@sysoev.ru nv = array->elts; 21541061Sigor@sysoev.ru end = nv + array->nelts; 21551061Sigor@sysoev.ru 21561061Sigor@sysoev.ru while (nv < end) { 21571061Sigor@sysoev.ru 21581061Sigor@sysoev.ru if (rule->u.name.hash == nv->hash 21591061Sigor@sysoev.ru && rule->u.name.length == nv->name_length 21601061Sigor@sysoev.ru && nxt_memcmp(rule->u.name.start, nv->name, nv->name_length) == 0) 21611061Sigor@sysoev.ru { 21621061Sigor@sysoev.ru ret = nxt_http_route_test_rule(r, rule, nv->value, 21631061Sigor@sysoev.ru nv->value_length); 21641721Saxel.duch@nginx.com if (nxt_slow_path(ret == NXT_ERROR)) { 21651721Saxel.duch@nginx.com return NXT_ERROR; 21661721Saxel.duch@nginx.com } 21671721Saxel.duch@nginx.com 21681061Sigor@sysoev.ru if (ret == 0) { 21691061Sigor@sysoev.ru break; 21701061Sigor@sysoev.ru } 21711061Sigor@sysoev.ru } 21721061Sigor@sysoev.ru 21731061Sigor@sysoev.ru nv++; 21741061Sigor@sysoev.ru } 21751061Sigor@sysoev.ru 21761061Sigor@sysoev.ru return ret; 21771061Sigor@sysoev.ru } 21781061Sigor@sysoev.ru 21791061Sigor@sysoev.ru 21801061Sigor@sysoev.ru static nxt_int_t 21811110Saxel.duch@nginx.com nxt_http_route_scheme(nxt_http_request_t *r, nxt_http_route_rule_t *rule) 21821110Saxel.duch@nginx.com { 21831508Saxel.duch@nginx.com nxt_bool_t tls, https; 21841508Saxel.duch@nginx.com nxt_http_route_pattern_slice_t *pattern_slice; 21851508Saxel.duch@nginx.com 21861721Saxel.duch@nginx.com pattern_slice = rule->pattern[0].u.pattern_slices->elts; 21871508Saxel.duch@nginx.com https = (pattern_slice->length == nxt_length("https")); 21881110Saxel.duch@nginx.com tls = (r->tls != NULL); 21891110Saxel.duch@nginx.com 21901110Saxel.duch@nginx.com return (tls == https); 21911110Saxel.duch@nginx.com } 21921110Saxel.duch@nginx.com 21931110Saxel.duch@nginx.com 21941110Saxel.duch@nginx.com static nxt_int_t 21951991Sz.hong@f5.com nxt_http_route_query(nxt_http_request_t *r, nxt_http_route_rule_t *rule) 21961991Sz.hong@f5.com { 21971991Sz.hong@f5.com nxt_array_t *arguments; 21981991Sz.hong@f5.com 21991991Sz.hong@f5.com arguments = nxt_http_route_arguments_parse(r); 22001991Sz.hong@f5.com if (nxt_slow_path(arguments == NULL)) { 22011991Sz.hong@f5.com return -1; 22021991Sz.hong@f5.com } 22031991Sz.hong@f5.com 22041991Sz.hong@f5.com return nxt_http_route_test_rule(r, rule, r->args_decoded.start, 22051991Sz.hong@f5.com r->args_decoded.length); 22061991Sz.hong@f5.com } 22071991Sz.hong@f5.com 22081991Sz.hong@f5.com 22091991Sz.hong@f5.com static nxt_int_t 22101062Sigor@sysoev.ru nxt_http_route_cookies(nxt_http_request_t *r, nxt_http_route_rule_t *rule) 22111062Sigor@sysoev.ru { 22121062Sigor@sysoev.ru nxt_array_t *cookies; 22131062Sigor@sysoev.ru 22141062Sigor@sysoev.ru cookies = nxt_http_route_cookies_parse(r); 22151062Sigor@sysoev.ru if (nxt_slow_path(cookies == NULL)) { 22161062Sigor@sysoev.ru return -1; 22171062Sigor@sysoev.ru } 22181062Sigor@sysoev.ru 22191062Sigor@sysoev.ru return nxt_http_route_test_cookie(r, rule, cookies); 22201062Sigor@sysoev.ru } 22211062Sigor@sysoev.ru 22221062Sigor@sysoev.ru 22231062Sigor@sysoev.ru static nxt_array_t * 22241062Sigor@sysoev.ru nxt_http_route_cookies_parse(nxt_http_request_t *r) 22251062Sigor@sysoev.ru { 22261062Sigor@sysoev.ru nxt_int_t ret; 22271062Sigor@sysoev.ru nxt_array_t *cookies; 22281062Sigor@sysoev.ru nxt_http_field_t *f; 22291062Sigor@sysoev.ru 22301062Sigor@sysoev.ru if (r->cookies != NULL) { 22311062Sigor@sysoev.ru return r->cookies; 22321062Sigor@sysoev.ru } 22331062Sigor@sysoev.ru 22341062Sigor@sysoev.ru cookies = nxt_array_create(r->mem_pool, 2, sizeof(nxt_http_name_value_t)); 22351062Sigor@sysoev.ru if (nxt_slow_path(cookies == NULL)) { 22361062Sigor@sysoev.ru return NULL; 22371062Sigor@sysoev.ru } 22381062Sigor@sysoev.ru 22391062Sigor@sysoev.ru nxt_list_each(f, r->fields) { 22401062Sigor@sysoev.ru 22411522Saxel.duch@nginx.com if (f->hash != NXT_COOKIE_HASH 22421062Sigor@sysoev.ru || f->name_length != 6 22431062Sigor@sysoev.ru || nxt_strncasecmp(f->name, (u_char *) "Cookie", 6) != 0) 22441062Sigor@sysoev.ru { 22451062Sigor@sysoev.ru continue; 22461062Sigor@sysoev.ru } 22471062Sigor@sysoev.ru 22481062Sigor@sysoev.ru ret = nxt_http_route_cookie_parse(cookies, f->value, 22491062Sigor@sysoev.ru f->value + f->value_length); 22501062Sigor@sysoev.ru if (ret != NXT_OK) { 22511062Sigor@sysoev.ru return NULL; 22521062Sigor@sysoev.ru } 22531062Sigor@sysoev.ru 22541062Sigor@sysoev.ru } nxt_list_loop; 22551062Sigor@sysoev.ru 22561062Sigor@sysoev.ru r->cookies = cookies; 22571062Sigor@sysoev.ru 22581062Sigor@sysoev.ru return cookies; 22591062Sigor@sysoev.ru } 22601062Sigor@sysoev.ru 22611062Sigor@sysoev.ru 22621062Sigor@sysoev.ru static nxt_int_t 22631062Sigor@sysoev.ru nxt_http_route_cookie_parse(nxt_array_t *cookies, u_char *start, u_char *end) 22641062Sigor@sysoev.ru { 22651062Sigor@sysoev.ru size_t name_length; 22661062Sigor@sysoev.ru u_char c, *p, *name; 22671062Sigor@sysoev.ru nxt_http_name_value_t *nv; 22681062Sigor@sysoev.ru 22691062Sigor@sysoev.ru name = NULL; 22701062Sigor@sysoev.ru name_length = 0; 22711062Sigor@sysoev.ru 22721062Sigor@sysoev.ru for (p = start; p < end; p++) { 22731062Sigor@sysoev.ru c = *p; 22741062Sigor@sysoev.ru 22751062Sigor@sysoev.ru if (c == '=') { 22761062Sigor@sysoev.ru while (start[0] == ' ') { start++; } 22771062Sigor@sysoev.ru 22781062Sigor@sysoev.ru name_length = p - start; 22791062Sigor@sysoev.ru 22801062Sigor@sysoev.ru if (name_length != 0) { 22811062Sigor@sysoev.ru name = start; 22821062Sigor@sysoev.ru } 22831062Sigor@sysoev.ru 22841062Sigor@sysoev.ru start = p + 1; 22851062Sigor@sysoev.ru 22861062Sigor@sysoev.ru } else if (c == ';') { 22871062Sigor@sysoev.ru if (name != NULL) { 22881062Sigor@sysoev.ru nv = nxt_http_route_cookie(cookies, name, name_length, 22891062Sigor@sysoev.ru start, p); 22901062Sigor@sysoev.ru if (nxt_slow_path(nv == NULL)) { 22911062Sigor@sysoev.ru return NXT_ERROR; 22921062Sigor@sysoev.ru } 22931062Sigor@sysoev.ru } 22941062Sigor@sysoev.ru 22951062Sigor@sysoev.ru name = NULL; 22961062Sigor@sysoev.ru start = p + 1; 2297*2078Salx.manpages@gmail.com } 22981062Sigor@sysoev.ru } 22991062Sigor@sysoev.ru 23001062Sigor@sysoev.ru if (name != NULL) { 23011062Sigor@sysoev.ru nv = nxt_http_route_cookie(cookies, name, name_length, start, p); 23021062Sigor@sysoev.ru if (nxt_slow_path(nv == NULL)) { 23031062Sigor@sysoev.ru return NXT_ERROR; 23041062Sigor@sysoev.ru } 23051062Sigor@sysoev.ru } 23061062Sigor@sysoev.ru 23071062Sigor@sysoev.ru return NXT_OK; 23081062Sigor@sysoev.ru } 23091062Sigor@sysoev.ru 23101062Sigor@sysoev.ru 23111062Sigor@sysoev.ru static nxt_http_name_value_t * 23121062Sigor@sysoev.ru nxt_http_route_cookie(nxt_array_t *array, u_char *name, size_t name_length, 23131062Sigor@sysoev.ru u_char *start, u_char *end) 23141062Sigor@sysoev.ru { 23151062Sigor@sysoev.ru u_char c, *p; 23161062Sigor@sysoev.ru uint32_t hash; 23171062Sigor@sysoev.ru nxt_http_name_value_t *nv; 23181062Sigor@sysoev.ru 23191062Sigor@sysoev.ru nv = nxt_array_add(array); 23201062Sigor@sysoev.ru if (nxt_slow_path(nv == NULL)) { 23211062Sigor@sysoev.ru return NULL; 23221062Sigor@sysoev.ru } 23231062Sigor@sysoev.ru 23241062Sigor@sysoev.ru nv->name_length = name_length; 23251062Sigor@sysoev.ru nv->name = name; 23261062Sigor@sysoev.ru 23271062Sigor@sysoev.ru hash = NXT_HTTP_FIELD_HASH_INIT; 23281062Sigor@sysoev.ru 23291062Sigor@sysoev.ru for (p = name; p < name + name_length; p++) { 23301062Sigor@sysoev.ru c = *p; 23311062Sigor@sysoev.ru hash = nxt_http_field_hash_char(hash, c); 23321062Sigor@sysoev.ru } 23331062Sigor@sysoev.ru 23341062Sigor@sysoev.ru nv->hash = nxt_http_field_hash_end(hash) & 0xFFFF; 23351062Sigor@sysoev.ru 23361062Sigor@sysoev.ru while (start < end && end[-1] == ' ') { end--; } 23371062Sigor@sysoev.ru 23381062Sigor@sysoev.ru nv->value_length = end - start; 23391062Sigor@sysoev.ru nv->value = start; 23401062Sigor@sysoev.ru 23411062Sigor@sysoev.ru return nv; 23421062Sigor@sysoev.ru } 23431062Sigor@sysoev.ru 23441062Sigor@sysoev.ru 23451062Sigor@sysoev.ru static nxt_int_t 23461062Sigor@sysoev.ru nxt_http_route_test_cookie(nxt_http_request_t *r, 23471062Sigor@sysoev.ru nxt_http_route_rule_t *rule, nxt_array_t *array) 23481062Sigor@sysoev.ru { 23491721Saxel.duch@nginx.com nxt_int_t ret; 23501062Sigor@sysoev.ru nxt_http_name_value_t *nv, *end; 23511062Sigor@sysoev.ru 23521062Sigor@sysoev.ru ret = 0; 23531062Sigor@sysoev.ru 23541062Sigor@sysoev.ru nv = array->elts; 23551062Sigor@sysoev.ru end = nv + array->nelts; 23561062Sigor@sysoev.ru 23571062Sigor@sysoev.ru while (nv < end) { 23581062Sigor@sysoev.ru 23591062Sigor@sysoev.ru if (rule->u.name.hash == nv->hash 23601062Sigor@sysoev.ru && rule->u.name.length == nv->name_length 23611079Sigor@sysoev.ru && nxt_memcmp(rule->u.name.start, nv->name, nv->name_length) == 0) 23621062Sigor@sysoev.ru { 23631062Sigor@sysoev.ru ret = nxt_http_route_test_rule(r, rule, nv->value, 23641062Sigor@sysoev.ru nv->value_length); 23651721Saxel.duch@nginx.com if (nxt_slow_path(ret == NXT_ERROR)) { 23661721Saxel.duch@nginx.com return NXT_ERROR; 23671721Saxel.duch@nginx.com } 23681721Saxel.duch@nginx.com 23691062Sigor@sysoev.ru if (ret == 0) { 23701062Sigor@sysoev.ru break; 23711062Sigor@sysoev.ru } 23721062Sigor@sysoev.ru } 23731062Sigor@sysoev.ru 23741062Sigor@sysoev.ru nv++; 23751062Sigor@sysoev.ru } 23761062Sigor@sysoev.ru 23771062Sigor@sysoev.ru return ret; 23781062Sigor@sysoev.ru } 23791062Sigor@sysoev.ru 23801062Sigor@sysoev.ru 23811859So.canty@f5.com nxt_int_t 23821059Sigor@sysoev.ru nxt_http_route_test_rule(nxt_http_request_t *r, nxt_http_route_rule_t *rule, 23831059Sigor@sysoev.ru u_char *start, size_t length) 23841059Sigor@sysoev.ru { 23851060Sigor@sysoev.ru nxt_int_t ret; 23861059Sigor@sysoev.ru nxt_http_route_pattern_t *pattern, *end; 23871059Sigor@sysoev.ru 23881057Sigor@sysoev.ru ret = 1; 2389964Sigor@sysoev.ru pattern = &rule->pattern[0]; 23901033Svbart@nginx.com end = pattern + rule->items; 2391964Sigor@sysoev.ru 23921057Sigor@sysoev.ru while (pattern < end) { 2393964Sigor@sysoev.ru ret = nxt_http_route_pattern(r, pattern, start, length); 23941721Saxel.duch@nginx.com if (nxt_slow_path(ret == NXT_ERROR)) { 23951721Saxel.duch@nginx.com return NXT_ERROR; 23961721Saxel.duch@nginx.com } 2397964Sigor@sysoev.ru 23981060Sigor@sysoev.ru /* nxt_http_route_pattern() returns either 1 or 0. */ 2399964Sigor@sysoev.ru ret ^= pattern->negative; 2400964Sigor@sysoev.ru 2401964Sigor@sysoev.ru if (pattern->any == ret) { 2402964Sigor@sysoev.ru return ret; 2403964Sigor@sysoev.ru } 2404964Sigor@sysoev.ru 2405964Sigor@sysoev.ru pattern++; 24061057Sigor@sysoev.ru } 2407964Sigor@sysoev.ru 2408964Sigor@sysoev.ru return ret; 2409964Sigor@sysoev.ru } 2410964Sigor@sysoev.ru 2411964Sigor@sysoev.ru 24121060Sigor@sysoev.ru static nxt_int_t 2413964Sigor@sysoev.ru nxt_http_route_pattern(nxt_http_request_t *r, nxt_http_route_pattern_t *pattern, 2414964Sigor@sysoev.ru u_char *start, size_t length) 2415964Sigor@sysoev.ru { 24161508Saxel.duch@nginx.com u_char *p, *end, *test; 24171508Saxel.duch@nginx.com size_t test_length; 24181508Saxel.duch@nginx.com uint32_t i; 24191508Saxel.duch@nginx.com nxt_array_t *pattern_slices; 24201508Saxel.duch@nginx.com nxt_http_route_pattern_slice_t *pattern_slice; 2421964Sigor@sysoev.ru 24221721Saxel.duch@nginx.com #if (NXT_HAVE_REGEX) 24231721Saxel.duch@nginx.com if (pattern->regex) { 24241721Saxel.duch@nginx.com if (r->regex_match == NULL) { 24251721Saxel.duch@nginx.com r->regex_match = nxt_regex_match_create(r->mem_pool, 0); 24261721Saxel.duch@nginx.com if (nxt_slow_path(r->regex_match == NULL)) { 24271721Saxel.duch@nginx.com return NXT_ERROR; 24281721Saxel.duch@nginx.com } 24291721Saxel.duch@nginx.com } 24301721Saxel.duch@nginx.com 24311721Saxel.duch@nginx.com return nxt_regex_match(pattern->u.regex, start, length, r->regex_match); 24321721Saxel.duch@nginx.com } 24331721Saxel.duch@nginx.com #endif 24341721Saxel.duch@nginx.com 2435964Sigor@sysoev.ru if (length < pattern->min_length) { 2436964Sigor@sysoev.ru return 0; 2437964Sigor@sysoev.ru } 2438964Sigor@sysoev.ru 24391721Saxel.duch@nginx.com nxt_assert(pattern->u.pattern_slices != NULL); 24401721Saxel.duch@nginx.com 24411721Saxel.duch@nginx.com pattern_slices = pattern->u.pattern_slices; 24421508Saxel.duch@nginx.com pattern_slice = pattern_slices->elts; 24431510Saxel.duch@nginx.com end = start + length; 24441508Saxel.duch@nginx.com 24451508Saxel.duch@nginx.com for (i = 0; i < pattern_slices->nelts; i++, pattern_slice++) { 24461508Saxel.duch@nginx.com test = pattern_slice->start; 24471508Saxel.duch@nginx.com test_length = pattern_slice->length; 24481508Saxel.duch@nginx.com 24491508Saxel.duch@nginx.com switch (pattern_slice->type) { 24501508Saxel.duch@nginx.com case NXT_HTTP_ROUTE_PATTERN_EXACT: 24511508Saxel.duch@nginx.com return ((length == pattern->min_length) && 24521508Saxel.duch@nginx.com nxt_http_route_memcmp(start, test, test_length, 24531508Saxel.duch@nginx.com pattern->case_sensitive)); 24541508Saxel.duch@nginx.com 24551508Saxel.duch@nginx.com case NXT_HTTP_ROUTE_PATTERN_BEGIN: 24561508Saxel.duch@nginx.com if (nxt_http_route_memcmp(start, test, test_length, 24571508Saxel.duch@nginx.com pattern->case_sensitive)) 24581508Saxel.duch@nginx.com { 24591510Saxel.duch@nginx.com start += test_length; 24601508Saxel.duch@nginx.com break; 24611508Saxel.duch@nginx.com } 24621508Saxel.duch@nginx.com 2463964Sigor@sysoev.ru return 0; 24641508Saxel.duch@nginx.com 24651508Saxel.duch@nginx.com case NXT_HTTP_ROUTE_PATTERN_END: 24661510Saxel.duch@nginx.com p = end - test_length; 24671508Saxel.duch@nginx.com 24681508Saxel.duch@nginx.com if (nxt_http_route_memcmp(p, test, test_length, 24691508Saxel.duch@nginx.com pattern->case_sensitive)) 24701508Saxel.duch@nginx.com { 24711510Saxel.duch@nginx.com end = p; 24721508Saxel.duch@nginx.com break; 24731508Saxel.duch@nginx.com } 24741508Saxel.duch@nginx.com 24751508Saxel.duch@nginx.com return 0; 24761508Saxel.duch@nginx.com 24771508Saxel.duch@nginx.com case NXT_HTTP_ROUTE_PATTERN_SUBSTRING: 24781508Saxel.duch@nginx.com if (pattern->case_sensitive) { 24791508Saxel.duch@nginx.com p = nxt_memstrn(start, end, (char *) test, test_length); 24801508Saxel.duch@nginx.com 24811508Saxel.duch@nginx.com } else { 24821508Saxel.duch@nginx.com p = nxt_memcasestrn(start, end, (char *) test, test_length); 24831508Saxel.duch@nginx.com } 24841508Saxel.duch@nginx.com 24851508Saxel.duch@nginx.com if (p == NULL) { 24861508Saxel.duch@nginx.com return 0; 24871508Saxel.duch@nginx.com } 24881510Saxel.duch@nginx.com 24891510Saxel.duch@nginx.com start = p + test_length; 24901032Sigor@sysoev.ru } 2491964Sigor@sysoev.ru } 2492964Sigor@sysoev.ru 24931508Saxel.duch@nginx.com return 1; 24941032Sigor@sysoev.ru } 24951032Sigor@sysoev.ru 24961032Sigor@sysoev.ru 24971060Sigor@sysoev.ru static nxt_int_t 24981032Sigor@sysoev.ru nxt_http_route_memcmp(u_char *start, u_char *test, size_t test_length, 24991032Sigor@sysoev.ru nxt_bool_t case_sensitive) 25001032Sigor@sysoev.ru { 25011032Sigor@sysoev.ru nxt_int_t n; 25021032Sigor@sysoev.ru 25031032Sigor@sysoev.ru if (case_sensitive) { 25041032Sigor@sysoev.ru n = nxt_memcmp(start, test, test_length); 25051032Sigor@sysoev.ru 25061032Sigor@sysoev.ru } else { 25071032Sigor@sysoev.ru n = nxt_memcasecmp(start, test, test_length); 2508964Sigor@sysoev.ru } 2509964Sigor@sysoev.ru 25101032Sigor@sysoev.ru return (n == 0); 2511964Sigor@sysoev.ru } 2512