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, 221324Saxel.duch@nginx.com NXT_HTTP_ROUTE_SOURCE, 231326Saxel.duch@nginx.com NXT_HTTP_ROUTE_DESTINATION, 24964Sigor@sysoev.ru } nxt_http_route_object_t; 25964Sigor@sysoev.ru 26964Sigor@sysoev.ru 27964Sigor@sysoev.ru typedef enum { 28964Sigor@sysoev.ru NXT_HTTP_ROUTE_PATTERN_EXACT = 0, 29964Sigor@sysoev.ru NXT_HTTP_ROUTE_PATTERN_BEGIN, 30964Sigor@sysoev.ru NXT_HTTP_ROUTE_PATTERN_END, 31964Sigor@sysoev.ru NXT_HTTP_ROUTE_PATTERN_SUBSTRING, 32964Sigor@sysoev.ru } nxt_http_route_pattern_type_t; 33964Sigor@sysoev.ru 34964Sigor@sysoev.ru 35964Sigor@sysoev.ru typedef enum { 36964Sigor@sysoev.ru NXT_HTTP_ROUTE_PATTERN_NOCASE = 0, 37964Sigor@sysoev.ru NXT_HTTP_ROUTE_PATTERN_LOWCASE, 38964Sigor@sysoev.ru NXT_HTTP_ROUTE_PATTERN_UPCASE, 39964Sigor@sysoev.ru } nxt_http_route_pattern_case_t; 40964Sigor@sysoev.ru 41964Sigor@sysoev.ru 421474Saxel.duch@nginx.com typedef enum { 431474Saxel.duch@nginx.com NXT_HTTP_ROUTE_ENCODING_NONE = 0, 441474Saxel.duch@nginx.com NXT_HTTP_ROUTE_ENCODING_URI, 451474Saxel.duch@nginx.com NXT_HTTP_ROUTE_ENCODING_URI_PLUS 461474Saxel.duch@nginx.com } nxt_http_route_encoding_t; 471474Saxel.duch@nginx.com 481474Saxel.duch@nginx.com 49964Sigor@sysoev.ru typedef struct { 50964Sigor@sysoev.ru nxt_conf_value_t *host; 51964Sigor@sysoev.ru nxt_conf_value_t *uri; 52964Sigor@sysoev.ru nxt_conf_value_t *method; 531059Sigor@sysoev.ru nxt_conf_value_t *headers; 541061Sigor@sysoev.ru nxt_conf_value_t *arguments; 551062Sigor@sysoev.ru nxt_conf_value_t *cookies; 561110Saxel.duch@nginx.com nxt_conf_value_t *scheme; 571324Saxel.duch@nginx.com nxt_conf_value_t *source; 581326Saxel.duch@nginx.com nxt_conf_value_t *destination; 59964Sigor@sysoev.ru } nxt_http_route_match_conf_t; 60964Sigor@sysoev.ru 61964Sigor@sysoev.ru 62964Sigor@sysoev.ru typedef struct { 631508Saxel.duch@nginx.com u_char *start; 641508Saxel.duch@nginx.com uint32_t length; 651508Saxel.duch@nginx.com nxt_http_route_pattern_type_t type:8; 661508Saxel.duch@nginx.com } nxt_http_route_pattern_slice_t; 671508Saxel.duch@nginx.com 681508Saxel.duch@nginx.com 691508Saxel.duch@nginx.com typedef struct { 701721Saxel.duch@nginx.com union { 711721Saxel.duch@nginx.com nxt_array_t *pattern_slices; 721721Saxel.duch@nginx.com #if (NXT_HAVE_REGEX) 731721Saxel.duch@nginx.com nxt_regex_t *regex; 741721Saxel.duch@nginx.com #endif 751721Saxel.duch@nginx.com } u; 76964Sigor@sysoev.ru uint32_t min_length; 771508Saxel.duch@nginx.com 78964Sigor@sysoev.ru uint8_t case_sensitive; /* 1 bit */ 79964Sigor@sysoev.ru uint8_t negative; /* 1 bit */ 80964Sigor@sysoev.ru uint8_t any; /* 1 bit */ 811721Saxel.duch@nginx.com #if (NXT_HAVE_REGEX) 821721Saxel.duch@nginx.com uint8_t regex; /* 1 bit */ 831721Saxel.duch@nginx.com #endif 84964Sigor@sysoev.ru } nxt_http_route_pattern_t; 85964Sigor@sysoev.ru 86964Sigor@sysoev.ru 87964Sigor@sysoev.ru typedef struct { 881061Sigor@sysoev.ru uint16_t hash; 891061Sigor@sysoev.ru uint16_t name_length; 901061Sigor@sysoev.ru uint32_t value_length; 911061Sigor@sysoev.ru u_char *name; 921061Sigor@sysoev.ru u_char *value; 931061Sigor@sysoev.ru } nxt_http_name_value_t; 941061Sigor@sysoev.ru 951061Sigor@sysoev.ru 961061Sigor@sysoev.ru typedef struct { 971062Sigor@sysoev.ru uint16_t hash; 981062Sigor@sysoev.ru uint16_t name_length; 991062Sigor@sysoev.ru uint32_t value_length; 1001062Sigor@sysoev.ru u_char *name; 1011062Sigor@sysoev.ru u_char *value; 1021062Sigor@sysoev.ru } nxt_http_cookie_t; 1031062Sigor@sysoev.ru 1041062Sigor@sysoev.ru 1051859So.canty@f5.com struct nxt_http_route_rule_s { 1061059Sigor@sysoev.ru /* The object must be the first field. */ 1071059Sigor@sysoev.ru nxt_http_route_object_t object:8; 108964Sigor@sysoev.ru uint32_t items; 1091059Sigor@sysoev.ru 1101059Sigor@sysoev.ru union { 1111059Sigor@sysoev.ru uintptr_t offset; 1121059Sigor@sysoev.ru 1131059Sigor@sysoev.ru struct { 1141059Sigor@sysoev.ru u_char *start; 1151059Sigor@sysoev.ru uint16_t hash; 1161059Sigor@sysoev.ru uint16_t length; 1171059Sigor@sysoev.ru } name; 1181059Sigor@sysoev.ru } u; 1191059Sigor@sysoev.ru 120964Sigor@sysoev.ru nxt_http_route_pattern_t pattern[0]; 1211859So.canty@f5.com }; 122964Sigor@sysoev.ru 123964Sigor@sysoev.ru 124964Sigor@sysoev.ru typedef struct { 125964Sigor@sysoev.ru uint32_t items; 1261059Sigor@sysoev.ru nxt_http_route_rule_t *rule[0]; 1271059Sigor@sysoev.ru } nxt_http_route_ruleset_t; 1281059Sigor@sysoev.ru 1291059Sigor@sysoev.ru 1301059Sigor@sysoev.ru typedef struct { 1311059Sigor@sysoev.ru /* The object must be the first field. */ 1321059Sigor@sysoev.ru nxt_http_route_object_t object:8; 1331059Sigor@sysoev.ru uint32_t items; 1341059Sigor@sysoev.ru nxt_http_route_ruleset_t *ruleset[0]; 1351059Sigor@sysoev.ru } nxt_http_route_table_t; 1361059Sigor@sysoev.ru 1371059Sigor@sysoev.ru 1381324Saxel.duch@nginx.com typedef struct { 1391324Saxel.duch@nginx.com /* The object must be the first field. */ 1401324Saxel.duch@nginx.com nxt_http_route_object_t object:8; 1411324Saxel.duch@nginx.com uint32_t items; 1421324Saxel.duch@nginx.com nxt_http_route_addr_pattern_t addr_pattern[0]; 1431324Saxel.duch@nginx.com } nxt_http_route_addr_rule_t; 1441324Saxel.duch@nginx.com 1451324Saxel.duch@nginx.com 1461059Sigor@sysoev.ru typedef union { 1471059Sigor@sysoev.ru nxt_http_route_rule_t *rule; 1481059Sigor@sysoev.ru nxt_http_route_table_t *table; 1491324Saxel.duch@nginx.com nxt_http_route_addr_rule_t *addr_rule; 1501059Sigor@sysoev.ru } nxt_http_route_test_t; 1511059Sigor@sysoev.ru 1521059Sigor@sysoev.ru 1531059Sigor@sysoev.ru typedef struct { 1541059Sigor@sysoev.ru uint32_t items; 1551264Sigor@sysoev.ru nxt_http_action_t action; 1561059Sigor@sysoev.ru nxt_http_route_test_t test[0]; 157964Sigor@sysoev.ru } nxt_http_route_match_t; 158964Sigor@sysoev.ru 159964Sigor@sysoev.ru 160964Sigor@sysoev.ru struct nxt_http_route_s { 161964Sigor@sysoev.ru nxt_str_t name; 162964Sigor@sysoev.ru uint32_t items; 163964Sigor@sysoev.ru nxt_http_route_match_t *match[0]; 164964Sigor@sysoev.ru }; 165964Sigor@sysoev.ru 166964Sigor@sysoev.ru 167964Sigor@sysoev.ru struct nxt_http_routes_s { 168964Sigor@sysoev.ru uint32_t items; 169964Sigor@sysoev.ru nxt_http_route_t *route[0]; 170964Sigor@sysoev.ru }; 171964Sigor@sysoev.ru 172964Sigor@sysoev.ru 1731522Saxel.duch@nginx.com #define NXT_COOKIE_HASH \ 1741062Sigor@sysoev.ru (nxt_http_field_hash_end( \ 1751062Sigor@sysoev.ru nxt_http_field_hash_char( \ 1761062Sigor@sysoev.ru nxt_http_field_hash_char( \ 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(NXT_HTTP_FIELD_HASH_INIT, \ 1811062Sigor@sysoev.ru 'c'), 'o'), 'o'), 'k'), 'i'), 'e')) & 0xFFFF) 1821062Sigor@sysoev.ru 1831062Sigor@sysoev.ru 184964Sigor@sysoev.ru static nxt_http_route_t *nxt_http_route_create(nxt_task_t *task, 185964Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf, nxt_conf_value_t *cv); 186964Sigor@sysoev.ru static nxt_http_route_match_t *nxt_http_route_match_create(nxt_task_t *task, 187964Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf, nxt_conf_value_t *cv); 188*1903Sz.hong@f5.com static nxt_int_t nxt_http_action_init(nxt_task_t *task, 1891859So.canty@f5.com nxt_router_temp_conf_t *tmcf, nxt_conf_value_t *cv, 1901859So.canty@f5.com nxt_http_action_t *action); 1911059Sigor@sysoev.ru static nxt_http_route_table_t *nxt_http_route_table_create(nxt_task_t *task, 1921061Sigor@sysoev.ru nxt_mp_t *mp, nxt_conf_value_t *table_cv, nxt_http_route_object_t object, 1931474Saxel.duch@nginx.com nxt_bool_t case_sensitive, nxt_http_route_encoding_t encoding); 1941059Sigor@sysoev.ru static nxt_http_route_ruleset_t *nxt_http_route_ruleset_create(nxt_task_t *task, 1951061Sigor@sysoev.ru nxt_mp_t *mp, nxt_conf_value_t *ruleset_cv, nxt_http_route_object_t object, 1961474Saxel.duch@nginx.com nxt_bool_t case_sensitive, nxt_http_route_encoding_t encoding); 1971061Sigor@sysoev.ru static nxt_http_route_rule_t *nxt_http_route_rule_name_create(nxt_task_t *task, 1981061Sigor@sysoev.ru nxt_mp_t *mp, nxt_conf_value_t *rule_cv, nxt_str_t *name, 1991474Saxel.duch@nginx.com nxt_bool_t case_sensitive, nxt_http_route_encoding_t encoding); 2001324Saxel.duch@nginx.com static nxt_http_route_addr_rule_t *nxt_http_route_addr_rule_create( 2011324Saxel.duch@nginx.com nxt_task_t *task, nxt_mp_t *mp, nxt_conf_value_t *cv); 202964Sigor@sysoev.ru static nxt_http_route_rule_t *nxt_http_route_rule_create(nxt_task_t *task, 2031059Sigor@sysoev.ru nxt_mp_t *mp, nxt_conf_value_t *cv, nxt_bool_t case_sensitive, 2041474Saxel.duch@nginx.com nxt_http_route_pattern_case_t pattern_case, 2051474Saxel.duch@nginx.com nxt_http_route_encoding_t encoding); 206964Sigor@sysoev.ru static int nxt_http_pattern_compare(const void *one, const void *two); 2071390Saxel.duch@nginx.com static int nxt_http_addr_pattern_compare(const void *one, const void *two); 208964Sigor@sysoev.ru static nxt_int_t nxt_http_route_pattern_create(nxt_task_t *task, nxt_mp_t *mp, 209964Sigor@sysoev.ru nxt_conf_value_t *cv, nxt_http_route_pattern_t *pattern, 2101474Saxel.duch@nginx.com nxt_http_route_pattern_case_t pattern_case, 2111474Saxel.duch@nginx.com nxt_http_route_encoding_t encoding); 2121474Saxel.duch@nginx.com static nxt_int_t nxt_http_route_decode_str(nxt_str_t *str, 2131474Saxel.duch@nginx.com nxt_http_route_encoding_t encoding); 2141508Saxel.duch@nginx.com static nxt_int_t nxt_http_route_pattern_slice(nxt_array_t *slices, 2151508Saxel.duch@nginx.com nxt_str_t *test, 2161508Saxel.duch@nginx.com nxt_http_route_pattern_type_t type, 2171508Saxel.duch@nginx.com nxt_http_route_encoding_t encoding, 2181032Sigor@sysoev.ru nxt_http_route_pattern_case_t pattern_case); 219964Sigor@sysoev.ru 2201472Svbart@nginx.com static nxt_int_t nxt_http_route_resolve(nxt_task_t *task, 221964Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf, nxt_http_route_t *route); 2221472Svbart@nginx.com static nxt_int_t nxt_http_action_resolve(nxt_task_t *task, 2231264Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf, nxt_http_action_t *action); 2241563Svbart@nginx.com static nxt_http_action_t *nxt_http_action_pass_var(nxt_task_t *task, 2251563Svbart@nginx.com nxt_http_request_t *r, nxt_http_action_t *action); 2261563Svbart@nginx.com static void nxt_http_action_pass_var_ready(nxt_task_t *task, void *obj, 2271563Svbart@nginx.com void *data); 2281563Svbart@nginx.com static void nxt_http_action_pass_var_error(nxt_task_t *task, void *obj, 2291563Svbart@nginx.com void *data); 2301563Svbart@nginx.com static nxt_int_t nxt_http_pass_find(nxt_task_t *task, nxt_mp_t *mp, 2311563Svbart@nginx.com nxt_router_conf_t *rtcf, nxt_http_action_t *action); 2321563Svbart@nginx.com static nxt_int_t nxt_http_route_find(nxt_http_routes_t *routes, nxt_str_t *name, 2331392Sigor@sysoev.ru nxt_http_action_t *action); 234964Sigor@sysoev.ru 2351264Sigor@sysoev.ru static nxt_http_action_t *nxt_http_route_handler(nxt_task_t *task, 2361264Sigor@sysoev.ru nxt_http_request_t *r, nxt_http_action_t *start); 2371326Saxel.duch@nginx.com static nxt_http_action_t *nxt_http_route_match(nxt_task_t *task, 2381326Saxel.duch@nginx.com nxt_http_request_t *r, nxt_http_route_match_t *match); 2391060Sigor@sysoev.ru static nxt_int_t nxt_http_route_table(nxt_http_request_t *r, 2401059Sigor@sysoev.ru nxt_http_route_table_t *table); 2411060Sigor@sysoev.ru static nxt_int_t nxt_http_route_ruleset(nxt_http_request_t *r, 2421059Sigor@sysoev.ru nxt_http_route_ruleset_t *ruleset); 2431324Saxel.duch@nginx.com static nxt_int_t nxt_http_route_addr_rule(nxt_http_request_t *r, 2441324Saxel.duch@nginx.com nxt_http_route_addr_rule_t *addr_rule, nxt_sockaddr_t *sockaddr); 2451060Sigor@sysoev.ru static nxt_int_t nxt_http_route_rule(nxt_http_request_t *r, 246964Sigor@sysoev.ru nxt_http_route_rule_t *rule); 2471060Sigor@sysoev.ru static nxt_int_t nxt_http_route_header(nxt_http_request_t *r, 2481059Sigor@sysoev.ru nxt_http_route_rule_t *rule); 2491061Sigor@sysoev.ru static nxt_int_t nxt_http_route_arguments(nxt_http_request_t *r, 2501061Sigor@sysoev.ru nxt_http_route_rule_t *rule); 2511061Sigor@sysoev.ru static nxt_array_t *nxt_http_route_arguments_parse(nxt_http_request_t *r); 2521061Sigor@sysoev.ru static nxt_http_name_value_t *nxt_http_route_argument(nxt_array_t *array, 2531061Sigor@sysoev.ru u_char *name, size_t name_length, uint32_t hash, u_char *start, 2541061Sigor@sysoev.ru u_char *end); 2551061Sigor@sysoev.ru static nxt_int_t nxt_http_route_test_argument(nxt_http_request_t *r, 2561061Sigor@sysoev.ru nxt_http_route_rule_t *rule, nxt_array_t *array); 2571110Saxel.duch@nginx.com static nxt_int_t nxt_http_route_scheme(nxt_http_request_t *r, 2581110Saxel.duch@nginx.com nxt_http_route_rule_t *rule); 2591062Sigor@sysoev.ru static nxt_int_t nxt_http_route_cookies(nxt_http_request_t *r, 2601062Sigor@sysoev.ru nxt_http_route_rule_t *rule); 2611062Sigor@sysoev.ru static nxt_array_t *nxt_http_route_cookies_parse(nxt_http_request_t *r); 2621062Sigor@sysoev.ru static nxt_int_t nxt_http_route_cookie_parse(nxt_array_t *cookies, 2631062Sigor@sysoev.ru u_char *start, u_char *end); 2641062Sigor@sysoev.ru static nxt_http_name_value_t *nxt_http_route_cookie(nxt_array_t *array, 2651062Sigor@sysoev.ru u_char *name, size_t name_length, u_char *start, u_char *end); 2661062Sigor@sysoev.ru static nxt_int_t nxt_http_route_test_cookie(nxt_http_request_t *r, 2671062Sigor@sysoev.ru nxt_http_route_rule_t *rule, nxt_array_t *array); 2681060Sigor@sysoev.ru static nxt_int_t nxt_http_route_pattern(nxt_http_request_t *r, 269964Sigor@sysoev.ru nxt_http_route_pattern_t *pattern, u_char *start, size_t length); 2701060Sigor@sysoev.ru static nxt_int_t nxt_http_route_memcmp(u_char *start, u_char *test, 2711032Sigor@sysoev.ru size_t length, nxt_bool_t case_sensitive); 272964Sigor@sysoev.ru 273964Sigor@sysoev.ru 274964Sigor@sysoev.ru nxt_http_routes_t * 275964Sigor@sysoev.ru nxt_http_routes_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, 276964Sigor@sysoev.ru nxt_conf_value_t *routes_conf) 277964Sigor@sysoev.ru { 278964Sigor@sysoev.ru size_t size; 279964Sigor@sysoev.ru uint32_t i, n, next; 280964Sigor@sysoev.ru nxt_mp_t *mp; 281964Sigor@sysoev.ru nxt_str_t name, *string; 282964Sigor@sysoev.ru nxt_bool_t object; 283964Sigor@sysoev.ru nxt_conf_value_t *route_conf; 284964Sigor@sysoev.ru nxt_http_route_t *route; 285964Sigor@sysoev.ru nxt_http_routes_t *routes; 286964Sigor@sysoev.ru 287964Sigor@sysoev.ru object = (nxt_conf_type(routes_conf) == NXT_CONF_OBJECT); 288964Sigor@sysoev.ru n = object ? nxt_conf_object_members_count(routes_conf) : 1; 289964Sigor@sysoev.ru size = sizeof(nxt_http_routes_t) + n * sizeof(nxt_http_route_t *); 290964Sigor@sysoev.ru 291964Sigor@sysoev.ru mp = tmcf->router_conf->mem_pool; 292964Sigor@sysoev.ru 293964Sigor@sysoev.ru routes = nxt_mp_alloc(mp, size); 294964Sigor@sysoev.ru if (nxt_slow_path(routes == NULL)) { 295964Sigor@sysoev.ru return NULL; 296964Sigor@sysoev.ru } 297964Sigor@sysoev.ru 298964Sigor@sysoev.ru routes->items = n; 299964Sigor@sysoev.ru 300964Sigor@sysoev.ru if (object) { 301964Sigor@sysoev.ru next = 0; 302964Sigor@sysoev.ru 303964Sigor@sysoev.ru for (i = 0; i < n; i++) { 304964Sigor@sysoev.ru route_conf = nxt_conf_next_object_member(routes_conf, &name, &next); 305964Sigor@sysoev.ru 306964Sigor@sysoev.ru route = nxt_http_route_create(task, tmcf, route_conf); 307964Sigor@sysoev.ru if (nxt_slow_path(route == NULL)) { 308964Sigor@sysoev.ru return NULL; 309964Sigor@sysoev.ru } 310964Sigor@sysoev.ru 311964Sigor@sysoev.ru routes->route[i] = route; 312964Sigor@sysoev.ru 313964Sigor@sysoev.ru string = nxt_str_dup(mp, &route->name, &name); 314964Sigor@sysoev.ru if (nxt_slow_path(string == NULL)) { 315964Sigor@sysoev.ru return NULL; 316964Sigor@sysoev.ru } 317964Sigor@sysoev.ru } 318964Sigor@sysoev.ru 319964Sigor@sysoev.ru } else { 320964Sigor@sysoev.ru route = nxt_http_route_create(task, tmcf, routes_conf); 321964Sigor@sysoev.ru if (nxt_slow_path(route == NULL)) { 322964Sigor@sysoev.ru return NULL; 323964Sigor@sysoev.ru } 324964Sigor@sysoev.ru 325964Sigor@sysoev.ru routes->route[0] = route; 326964Sigor@sysoev.ru 327964Sigor@sysoev.ru route->name.length = 0; 328964Sigor@sysoev.ru route->name.start = NULL; 329964Sigor@sysoev.ru } 330964Sigor@sysoev.ru 331964Sigor@sysoev.ru return routes; 332964Sigor@sysoev.ru } 333964Sigor@sysoev.ru 334964Sigor@sysoev.ru 335964Sigor@sysoev.ru static nxt_conf_map_t nxt_http_route_match_conf[] = { 336964Sigor@sysoev.ru { 3371110Saxel.duch@nginx.com nxt_string("scheme"), 3381110Saxel.duch@nginx.com NXT_CONF_MAP_PTR, 3391110Saxel.duch@nginx.com offsetof(nxt_http_route_match_conf_t, scheme) 3401110Saxel.duch@nginx.com }, 3411110Saxel.duch@nginx.com { 342964Sigor@sysoev.ru nxt_string("host"), 343964Sigor@sysoev.ru NXT_CONF_MAP_PTR, 344964Sigor@sysoev.ru offsetof(nxt_http_route_match_conf_t, host), 345964Sigor@sysoev.ru }, 346964Sigor@sysoev.ru 347964Sigor@sysoev.ru { 348964Sigor@sysoev.ru nxt_string("uri"), 349964Sigor@sysoev.ru NXT_CONF_MAP_PTR, 350964Sigor@sysoev.ru offsetof(nxt_http_route_match_conf_t, uri), 351964Sigor@sysoev.ru }, 352964Sigor@sysoev.ru 353964Sigor@sysoev.ru { 354964Sigor@sysoev.ru nxt_string("method"), 355964Sigor@sysoev.ru NXT_CONF_MAP_PTR, 356964Sigor@sysoev.ru offsetof(nxt_http_route_match_conf_t, method), 357964Sigor@sysoev.ru }, 3581059Sigor@sysoev.ru 3591059Sigor@sysoev.ru { 3601059Sigor@sysoev.ru nxt_string("headers"), 3611059Sigor@sysoev.ru NXT_CONF_MAP_PTR, 3621059Sigor@sysoev.ru offsetof(nxt_http_route_match_conf_t, headers), 3631059Sigor@sysoev.ru }, 3641061Sigor@sysoev.ru 3651061Sigor@sysoev.ru { 3661061Sigor@sysoev.ru nxt_string("arguments"), 3671061Sigor@sysoev.ru NXT_CONF_MAP_PTR, 3681061Sigor@sysoev.ru offsetof(nxt_http_route_match_conf_t, arguments), 3691061Sigor@sysoev.ru }, 3701062Sigor@sysoev.ru 3711062Sigor@sysoev.ru { 3721062Sigor@sysoev.ru nxt_string("cookies"), 3731062Sigor@sysoev.ru NXT_CONF_MAP_PTR, 3741062Sigor@sysoev.ru offsetof(nxt_http_route_match_conf_t, cookies), 3751062Sigor@sysoev.ru }, 3761324Saxel.duch@nginx.com 3771324Saxel.duch@nginx.com { 3781324Saxel.duch@nginx.com nxt_string("source"), 3791324Saxel.duch@nginx.com NXT_CONF_MAP_PTR, 3801324Saxel.duch@nginx.com offsetof(nxt_http_route_match_conf_t, source), 3811324Saxel.duch@nginx.com }, 3821326Saxel.duch@nginx.com 3831326Saxel.duch@nginx.com { 3841326Saxel.duch@nginx.com nxt_string("destination"), 3851326Saxel.duch@nginx.com NXT_CONF_MAP_PTR, 3861326Saxel.duch@nginx.com offsetof(nxt_http_route_match_conf_t, destination), 3871326Saxel.duch@nginx.com }, 388964Sigor@sysoev.ru }; 389964Sigor@sysoev.ru 390964Sigor@sysoev.ru 391964Sigor@sysoev.ru static nxt_http_route_t * 392964Sigor@sysoev.ru nxt_http_route_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, 393964Sigor@sysoev.ru nxt_conf_value_t *cv) 394964Sigor@sysoev.ru { 395964Sigor@sysoev.ru size_t size; 396964Sigor@sysoev.ru uint32_t i, n; 397964Sigor@sysoev.ru nxt_conf_value_t *value; 398964Sigor@sysoev.ru nxt_http_route_t *route; 399964Sigor@sysoev.ru nxt_http_route_match_t *match, **m; 400964Sigor@sysoev.ru 401964Sigor@sysoev.ru n = nxt_conf_array_elements_count(cv); 402964Sigor@sysoev.ru size = sizeof(nxt_http_route_t) + n * sizeof(nxt_http_route_match_t *); 403964Sigor@sysoev.ru 404964Sigor@sysoev.ru route = nxt_mp_alloc(tmcf->router_conf->mem_pool, size); 405964Sigor@sysoev.ru if (nxt_slow_path(route == NULL)) { 406964Sigor@sysoev.ru return NULL; 407964Sigor@sysoev.ru } 408964Sigor@sysoev.ru 409964Sigor@sysoev.ru route->items = n; 410964Sigor@sysoev.ru m = &route->match[0]; 411964Sigor@sysoev.ru 412964Sigor@sysoev.ru for (i = 0; i < n; i++) { 413964Sigor@sysoev.ru value = nxt_conf_get_array_element(cv, i); 414964Sigor@sysoev.ru 415964Sigor@sysoev.ru match = nxt_http_route_match_create(task, tmcf, value); 416964Sigor@sysoev.ru if (match == NULL) { 417964Sigor@sysoev.ru return NULL; 418964Sigor@sysoev.ru } 419964Sigor@sysoev.ru 420964Sigor@sysoev.ru *m++ = match; 421964Sigor@sysoev.ru } 422964Sigor@sysoev.ru 423964Sigor@sysoev.ru return route; 424964Sigor@sysoev.ru } 425964Sigor@sysoev.ru 426964Sigor@sysoev.ru 427964Sigor@sysoev.ru static nxt_http_route_match_t * 428964Sigor@sysoev.ru nxt_http_route_match_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, 429964Sigor@sysoev.ru nxt_conf_value_t *cv) 430964Sigor@sysoev.ru { 431964Sigor@sysoev.ru size_t size; 432964Sigor@sysoev.ru uint32_t n; 4331059Sigor@sysoev.ru nxt_mp_t *mp; 434964Sigor@sysoev.ru nxt_int_t ret; 4351378Svbart@nginx.com nxt_conf_value_t *match_conf, *action_conf; 4361059Sigor@sysoev.ru nxt_http_route_test_t *test; 4371059Sigor@sysoev.ru nxt_http_route_rule_t *rule; 4381059Sigor@sysoev.ru nxt_http_route_table_t *table; 439964Sigor@sysoev.ru nxt_http_route_match_t *match; 4401324Saxel.duch@nginx.com nxt_http_route_addr_rule_t *addr_rule; 441964Sigor@sysoev.ru nxt_http_route_match_conf_t mtcf; 442964Sigor@sysoev.ru 443964Sigor@sysoev.ru static nxt_str_t match_path = nxt_string("/match"); 4441378Svbart@nginx.com static nxt_str_t action_path = nxt_string("/action"); 445964Sigor@sysoev.ru 446964Sigor@sysoev.ru match_conf = nxt_conf_get_path(cv, &match_path); 447964Sigor@sysoev.ru 448964Sigor@sysoev.ru n = (match_conf != NULL) ? nxt_conf_object_members_count(match_conf) : 0; 4491859So.canty@f5.com size = sizeof(nxt_http_route_match_t) + n * sizeof(nxt_http_route_test_t *); 450964Sigor@sysoev.ru 4511059Sigor@sysoev.ru mp = tmcf->router_conf->mem_pool; 4521059Sigor@sysoev.ru 4531059Sigor@sysoev.ru match = nxt_mp_alloc(mp, size); 454964Sigor@sysoev.ru if (nxt_slow_path(match == NULL)) { 455964Sigor@sysoev.ru return NULL; 456964Sigor@sysoev.ru } 457964Sigor@sysoev.ru 458964Sigor@sysoev.ru match->items = n; 459964Sigor@sysoev.ru 4601378Svbart@nginx.com action_conf = nxt_conf_get_path(cv, &action_path); 4611378Svbart@nginx.com if (nxt_slow_path(action_conf == NULL)) { 4621378Svbart@nginx.com return NULL; 4631378Svbart@nginx.com } 4641378Svbart@nginx.com 465*1903Sz.hong@f5.com ret = nxt_http_action_init(task, tmcf, action_conf, &match->action); 4661264Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 467964Sigor@sysoev.ru return NULL; 468964Sigor@sysoev.ru } 469964Sigor@sysoev.ru 470964Sigor@sysoev.ru if (n == 0) { 471964Sigor@sysoev.ru return match; 472964Sigor@sysoev.ru } 473964Sigor@sysoev.ru 474964Sigor@sysoev.ru nxt_memzero(&mtcf, sizeof(mtcf)); 475964Sigor@sysoev.ru 476964Sigor@sysoev.ru ret = nxt_conf_map_object(tmcf->mem_pool, 477964Sigor@sysoev.ru match_conf, nxt_http_route_match_conf, 478964Sigor@sysoev.ru nxt_nitems(nxt_http_route_match_conf), &mtcf); 479964Sigor@sysoev.ru if (ret != NXT_OK) { 480964Sigor@sysoev.ru return NULL; 481964Sigor@sysoev.ru } 482964Sigor@sysoev.ru 4831059Sigor@sysoev.ru test = &match->test[0]; 484964Sigor@sysoev.ru 4851110Saxel.duch@nginx.com if (mtcf.scheme != NULL) { 4861110Saxel.duch@nginx.com rule = nxt_http_route_rule_create(task, mp, mtcf.scheme, 1, 4871474Saxel.duch@nginx.com NXT_HTTP_ROUTE_PATTERN_NOCASE, 4881474Saxel.duch@nginx.com NXT_HTTP_ROUTE_ENCODING_NONE); 4891110Saxel.duch@nginx.com if (rule == NULL) { 4901110Saxel.duch@nginx.com return NULL; 4911110Saxel.duch@nginx.com } 4921110Saxel.duch@nginx.com 4931110Saxel.duch@nginx.com rule->object = NXT_HTTP_ROUTE_SCHEME; 4941110Saxel.duch@nginx.com test->rule = rule; 4951110Saxel.duch@nginx.com test++; 4961110Saxel.duch@nginx.com } 4971110Saxel.duch@nginx.com 498964Sigor@sysoev.ru if (mtcf.host != NULL) { 4991059Sigor@sysoev.ru rule = nxt_http_route_rule_create(task, mp, mtcf.host, 1, 5001474Saxel.duch@nginx.com NXT_HTTP_ROUTE_PATTERN_LOWCASE, 5011474Saxel.duch@nginx.com NXT_HTTP_ROUTE_ENCODING_NONE); 502964Sigor@sysoev.ru if (rule == NULL) { 503964Sigor@sysoev.ru return NULL; 504964Sigor@sysoev.ru } 505964Sigor@sysoev.ru 5061059Sigor@sysoev.ru rule->u.offset = offsetof(nxt_http_request_t, host); 507964Sigor@sysoev.ru rule->object = NXT_HTTP_ROUTE_STRING; 5081059Sigor@sysoev.ru test->rule = rule; 5091059Sigor@sysoev.ru test++; 510964Sigor@sysoev.ru } 511964Sigor@sysoev.ru 512964Sigor@sysoev.ru if (mtcf.uri != NULL) { 5131059Sigor@sysoev.ru rule = nxt_http_route_rule_create(task, mp, mtcf.uri, 1, 5141474Saxel.duch@nginx.com NXT_HTTP_ROUTE_PATTERN_NOCASE, 5151474Saxel.duch@nginx.com NXT_HTTP_ROUTE_ENCODING_URI); 516964Sigor@sysoev.ru if (rule == NULL) { 517964Sigor@sysoev.ru return NULL; 518964Sigor@sysoev.ru } 519964Sigor@sysoev.ru 5201059Sigor@sysoev.ru rule->u.offset = offsetof(nxt_http_request_t, path); 521964Sigor@sysoev.ru rule->object = NXT_HTTP_ROUTE_STRING_PTR; 5221059Sigor@sysoev.ru test->rule = rule; 5231059Sigor@sysoev.ru test++; 524964Sigor@sysoev.ru } 525964Sigor@sysoev.ru 526964Sigor@sysoev.ru if (mtcf.method != NULL) { 5271059Sigor@sysoev.ru rule = nxt_http_route_rule_create(task, mp, mtcf.method, 1, 5281474Saxel.duch@nginx.com NXT_HTTP_ROUTE_PATTERN_UPCASE, 5291474Saxel.duch@nginx.com NXT_HTTP_ROUTE_ENCODING_NONE); 530964Sigor@sysoev.ru if (rule == NULL) { 531964Sigor@sysoev.ru return NULL; 532964Sigor@sysoev.ru } 533964Sigor@sysoev.ru 5341059Sigor@sysoev.ru rule->u.offset = offsetof(nxt_http_request_t, method); 535964Sigor@sysoev.ru rule->object = NXT_HTTP_ROUTE_STRING_PTR; 5361059Sigor@sysoev.ru test->rule = rule; 5371059Sigor@sysoev.ru test++; 5381059Sigor@sysoev.ru } 5391059Sigor@sysoev.ru 5401059Sigor@sysoev.ru if (mtcf.headers != NULL) { 5411061Sigor@sysoev.ru table = nxt_http_route_table_create(task, mp, mtcf.headers, 5421474Saxel.duch@nginx.com NXT_HTTP_ROUTE_HEADER, 0, 5431474Saxel.duch@nginx.com NXT_HTTP_ROUTE_ENCODING_NONE); 5441061Sigor@sysoev.ru if (table == NULL) { 5451061Sigor@sysoev.ru return NULL; 5461061Sigor@sysoev.ru } 5471061Sigor@sysoev.ru 5481061Sigor@sysoev.ru test->table = table; 5491061Sigor@sysoev.ru test++; 5501061Sigor@sysoev.ru } 5511061Sigor@sysoev.ru 5521061Sigor@sysoev.ru if (mtcf.arguments != NULL) { 5531061Sigor@sysoev.ru table = nxt_http_route_table_create(task, mp, mtcf.arguments, 5541474Saxel.duch@nginx.com NXT_HTTP_ROUTE_ARGUMENT, 1, 5551474Saxel.duch@nginx.com NXT_HTTP_ROUTE_ENCODING_URI_PLUS); 5561059Sigor@sysoev.ru if (table == NULL) { 5571059Sigor@sysoev.ru return NULL; 5581059Sigor@sysoev.ru } 5591059Sigor@sysoev.ru 5601059Sigor@sysoev.ru test->table = table; 5611059Sigor@sysoev.ru test++; 562964Sigor@sysoev.ru } 563964Sigor@sysoev.ru 5641062Sigor@sysoev.ru if (mtcf.cookies != NULL) { 5651062Sigor@sysoev.ru table = nxt_http_route_table_create(task, mp, mtcf.cookies, 5661474Saxel.duch@nginx.com NXT_HTTP_ROUTE_COOKIE, 1, 5671474Saxel.duch@nginx.com NXT_HTTP_ROUTE_ENCODING_NONE); 5681062Sigor@sysoev.ru if (table == NULL) { 5691062Sigor@sysoev.ru return NULL; 5701062Sigor@sysoev.ru } 5711062Sigor@sysoev.ru 5721062Sigor@sysoev.ru test->table = table; 5731062Sigor@sysoev.ru test++; 5741062Sigor@sysoev.ru } 5751062Sigor@sysoev.ru 5761324Saxel.duch@nginx.com if (mtcf.source != NULL) { 5771324Saxel.duch@nginx.com addr_rule = nxt_http_route_addr_rule_create(task, mp, mtcf.source); 5781324Saxel.duch@nginx.com if (addr_rule == NULL) { 5791324Saxel.duch@nginx.com return NULL; 5801324Saxel.duch@nginx.com } 5811324Saxel.duch@nginx.com 5821324Saxel.duch@nginx.com addr_rule->object = NXT_HTTP_ROUTE_SOURCE; 5831324Saxel.duch@nginx.com test->addr_rule = addr_rule; 5841324Saxel.duch@nginx.com test++; 5851324Saxel.duch@nginx.com } 5861324Saxel.duch@nginx.com 5871326Saxel.duch@nginx.com if (mtcf.destination != NULL) { 5881326Saxel.duch@nginx.com addr_rule = nxt_http_route_addr_rule_create(task, mp, mtcf.destination); 5891326Saxel.duch@nginx.com if (addr_rule == NULL) { 5901326Saxel.duch@nginx.com return NULL; 5911326Saxel.duch@nginx.com } 5921326Saxel.duch@nginx.com 5931326Saxel.duch@nginx.com addr_rule->object = NXT_HTTP_ROUTE_DESTINATION; 5941326Saxel.duch@nginx.com test->addr_rule = addr_rule; 5951326Saxel.duch@nginx.com test++; 5961326Saxel.duch@nginx.com } 5971326Saxel.duch@nginx.com 598964Sigor@sysoev.ru return match; 599964Sigor@sysoev.ru } 600964Sigor@sysoev.ru 601964Sigor@sysoev.ru 6021264Sigor@sysoev.ru static nxt_conf_map_t nxt_http_route_action_conf[] = { 6031264Sigor@sysoev.ru { 6041264Sigor@sysoev.ru nxt_string("pass"), 6051264Sigor@sysoev.ru NXT_CONF_MAP_PTR, 606*1903Sz.hong@f5.com offsetof(nxt_http_action_conf_t, pass) 6071264Sigor@sysoev.ru }, 6081264Sigor@sysoev.ru { 6091429Svbart@nginx.com nxt_string("return"), 6101429Svbart@nginx.com NXT_CONF_MAP_PTR, 611*1903Sz.hong@f5.com offsetof(nxt_http_action_conf_t, ret) 6121429Svbart@nginx.com }, 6131429Svbart@nginx.com { 6141432Svbart@nginx.com nxt_string("location"), 6151432Svbart@nginx.com NXT_CONF_MAP_STR, 616*1903Sz.hong@f5.com offsetof(nxt_http_action_conf_t, location) 6171432Svbart@nginx.com }, 6181432Svbart@nginx.com { 6191854Sz.hong@f5.com nxt_string("proxy"), 6201854Sz.hong@f5.com NXT_CONF_MAP_PTR, 621*1903Sz.hong@f5.com offsetof(nxt_http_action_conf_t, proxy) 6221854Sz.hong@f5.com }, 6231854Sz.hong@f5.com { 6241264Sigor@sysoev.ru nxt_string("share"), 6251264Sigor@sysoev.ru NXT_CONF_MAP_PTR, 626*1903Sz.hong@f5.com offsetof(nxt_http_action_conf_t, share) 6271264Sigor@sysoev.ru }, 6281270Sigor@sysoev.ru { 6291855Sz.hong@f5.com nxt_string("chroot"), 6301855Sz.hong@f5.com NXT_CONF_MAP_STR, 631*1903Sz.hong@f5.com offsetof(nxt_http_action_conf_t, chroot) 6321855Sz.hong@f5.com }, 6331855Sz.hong@f5.com { 6341855Sz.hong@f5.com nxt_string("follow_symlinks"), 6351855Sz.hong@f5.com NXT_CONF_MAP_PTR, 636*1903Sz.hong@f5.com offsetof(nxt_http_action_conf_t, follow_symlinks) 6371855Sz.hong@f5.com }, 6381855Sz.hong@f5.com { 6391855Sz.hong@f5.com nxt_string("traverse_mounts"), 6401855Sz.hong@f5.com NXT_CONF_MAP_PTR, 641*1903Sz.hong@f5.com offsetof(nxt_http_action_conf_t, traverse_mounts) 6421855Sz.hong@f5.com }, 6431855Sz.hong@f5.com { 6441859So.canty@f5.com nxt_string("types"), 6451859So.canty@f5.com NXT_CONF_MAP_PTR, 646*1903Sz.hong@f5.com offsetof(nxt_http_action_conf_t, types) 6471859So.canty@f5.com }, 6481859So.canty@f5.com { 6491378Svbart@nginx.com nxt_string("fallback"), 6501378Svbart@nginx.com NXT_CONF_MAP_PTR, 651*1903Sz.hong@f5.com offsetof(nxt_http_action_conf_t, fallback) 6521378Svbart@nginx.com }, 6531264Sigor@sysoev.ru }; 6541264Sigor@sysoev.ru 6551264Sigor@sysoev.ru 6561264Sigor@sysoev.ru static nxt_int_t 657*1903Sz.hong@f5.com nxt_http_action_init(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, 6581859So.canty@f5.com nxt_conf_value_t *cv, nxt_http_action_t *action) 6591264Sigor@sysoev.ru { 6601855Sz.hong@f5.com #if (NXT_HAVE_OPENAT2) 661*1903Sz.hong@f5.com u_char *p; 662*1903Sz.hong@f5.com uint8_t slash; 663*1903Sz.hong@f5.com nxt_str_t *chroot; 6641855Sz.hong@f5.com #endif 665*1903Sz.hong@f5.com nxt_mp_t *mp; 666*1903Sz.hong@f5.com nxt_int_t ret; 667*1903Sz.hong@f5.com nxt_str_t name, *string; 668*1903Sz.hong@f5.com nxt_conf_value_t *conf; 669*1903Sz.hong@f5.com nxt_http_route_rule_t *rule; 670*1903Sz.hong@f5.com nxt_http_action_conf_t acf; 671*1903Sz.hong@f5.com 672*1903Sz.hong@f5.com nxt_memzero(&acf, sizeof(acf)); 6731264Sigor@sysoev.ru 6741378Svbart@nginx.com ret = nxt_conf_map_object(tmcf->mem_pool, cv, nxt_http_route_action_conf, 675*1903Sz.hong@f5.com nxt_nitems(nxt_http_route_action_conf), &acf); 6761264Sigor@sysoev.ru if (ret != NXT_OK) { 6771264Sigor@sysoev.ru return ret; 6781264Sigor@sysoev.ru } 6791264Sigor@sysoev.ru 6801428Svbart@nginx.com nxt_memzero(action, sizeof(nxt_http_action_t)); 6811428Svbart@nginx.com 6821432Svbart@nginx.com mp = tmcf->router_conf->mem_pool; 6831432Svbart@nginx.com 684*1903Sz.hong@f5.com if (acf.ret != NULL) { 685*1903Sz.hong@f5.com return nxt_http_return_init(mp, action, &acf); 6861429Svbart@nginx.com } 6871429Svbart@nginx.com 688*1903Sz.hong@f5.com if (acf.share != NULL) { 689*1903Sz.hong@f5.com conf = acf.share; 690*1903Sz.hong@f5.com 691*1903Sz.hong@f5.com } else if (acf.proxy != NULL) { 692*1903Sz.hong@f5.com conf = acf.proxy; 6931854Sz.hong@f5.com 6941854Sz.hong@f5.com } else { 695*1903Sz.hong@f5.com conf = acf.pass; 6961264Sigor@sysoev.ru } 6971264Sigor@sysoev.ru 6981264Sigor@sysoev.ru nxt_conf_get_string(conf, &name); 6991264Sigor@sysoev.ru 7001378Svbart@nginx.com string = nxt_str_dup(mp, &action->name, &name); 7011264Sigor@sysoev.ru if (nxt_slow_path(string == NULL)) { 7021264Sigor@sysoev.ru return NXT_ERROR; 7031264Sigor@sysoev.ru } 7041264Sigor@sysoev.ru 705*1903Sz.hong@f5.com if (acf.share != NULL) { 7061854Sz.hong@f5.com action->handler = nxt_http_static_handler; 7071854Sz.hong@f5.com 7081855Sz.hong@f5.com #if (NXT_HAVE_OPENAT2) 709*1903Sz.hong@f5.com string = &acf.chroot; 7101855Sz.hong@f5.com chroot = &action->u.share.chroot; 7111855Sz.hong@f5.com 7121855Sz.hong@f5.com if (string->length > 0) { 7131855Sz.hong@f5.com action->u.share.resolve |= RESOLVE_IN_ROOT; 7141855Sz.hong@f5.com 7151855Sz.hong@f5.com slash = (string->start[string->length - 1] != '/'); 7161855Sz.hong@f5.com 7171855Sz.hong@f5.com chroot->length = string->length + (slash ? 1 : 0); 7181855Sz.hong@f5.com 7191855Sz.hong@f5.com chroot->start = nxt_mp_alloc(mp, chroot->length + 1); 7201855Sz.hong@f5.com if (nxt_slow_path(chroot->start == NULL)) { 7211855Sz.hong@f5.com return NXT_ERROR; 7221855Sz.hong@f5.com } 7231855Sz.hong@f5.com 7241855Sz.hong@f5.com p = nxt_cpymem(chroot->start, string->start, string->length); 7251855Sz.hong@f5.com 7261855Sz.hong@f5.com if (slash) { 7271855Sz.hong@f5.com *p++ = '/'; 7281855Sz.hong@f5.com } 7291855Sz.hong@f5.com 7301855Sz.hong@f5.com *p = '\0'; 7311855Sz.hong@f5.com } 7321855Sz.hong@f5.com 733*1903Sz.hong@f5.com if (acf.follow_symlinks != NULL 734*1903Sz.hong@f5.com && !nxt_conf_get_boolean(acf.follow_symlinks)) 7351855Sz.hong@f5.com { 7361855Sz.hong@f5.com action->u.share.resolve |= RESOLVE_NO_SYMLINKS; 7371855Sz.hong@f5.com } 7381855Sz.hong@f5.com 739*1903Sz.hong@f5.com if (acf.traverse_mounts != NULL 740*1903Sz.hong@f5.com && !nxt_conf_get_boolean(acf.traverse_mounts)) 7411855Sz.hong@f5.com { 7421855Sz.hong@f5.com action->u.share.resolve |= RESOLVE_NO_XDEV; 7431855Sz.hong@f5.com } 7441855Sz.hong@f5.com #endif 7451855Sz.hong@f5.com 746*1903Sz.hong@f5.com if (acf.types != NULL) { 747*1903Sz.hong@f5.com rule = nxt_http_route_rule_create(task, mp, acf.types, 0, 7481859So.canty@f5.com NXT_HTTP_ROUTE_PATTERN_LOWCASE, 7491859So.canty@f5.com NXT_HTTP_ROUTE_ENCODING_NONE); 7501859So.canty@f5.com if (nxt_slow_path(rule == NULL)) { 7511859So.canty@f5.com return NXT_ERROR; 7521859So.canty@f5.com } 7531859So.canty@f5.com 7541859So.canty@f5.com action->u.share.types = rule; 7551859So.canty@f5.com } 7561859So.canty@f5.com 757*1903Sz.hong@f5.com if (acf.fallback != NULL) { 7581854Sz.hong@f5.com action->u.share.fallback = nxt_mp_alloc(mp, 7591854Sz.hong@f5.com sizeof(nxt_http_action_t)); 7601854Sz.hong@f5.com if (nxt_slow_path(action->u.share.fallback == NULL)) { 7611854Sz.hong@f5.com return NXT_ERROR; 7621854Sz.hong@f5.com } 7631854Sz.hong@f5.com 764*1903Sz.hong@f5.com return nxt_http_action_init(task, tmcf, acf.fallback, 765*1903Sz.hong@f5.com action->u.share.fallback); 7661378Svbart@nginx.com } 7671378Svbart@nginx.com 7681854Sz.hong@f5.com return NXT_OK; 7691378Svbart@nginx.com } 7701378Svbart@nginx.com 771*1903Sz.hong@f5.com if (acf.proxy != NULL) { 7721378Svbart@nginx.com return nxt_http_proxy_create(mp, action); 7731270Sigor@sysoev.ru } 7741270Sigor@sysoev.ru 7751264Sigor@sysoev.ru return NXT_OK; 7761264Sigor@sysoev.ru } 7771264Sigor@sysoev.ru 7781264Sigor@sysoev.ru 7791059Sigor@sysoev.ru static nxt_http_route_table_t * 7801059Sigor@sysoev.ru nxt_http_route_table_create(nxt_task_t *task, nxt_mp_t *mp, 7811061Sigor@sysoev.ru nxt_conf_value_t *table_cv, nxt_http_route_object_t object, 7821474Saxel.duch@nginx.com nxt_bool_t case_sensitive, nxt_http_route_encoding_t encoding) 7831059Sigor@sysoev.ru { 7841059Sigor@sysoev.ru size_t size; 7851059Sigor@sysoev.ru uint32_t i, n; 7861059Sigor@sysoev.ru nxt_bool_t array; 7871059Sigor@sysoev.ru nxt_conf_value_t *ruleset_cv; 7881059Sigor@sysoev.ru nxt_http_route_table_t *table; 7891059Sigor@sysoev.ru nxt_http_route_ruleset_t *ruleset; 7901059Sigor@sysoev.ru 7911059Sigor@sysoev.ru array = (nxt_conf_type(table_cv) == NXT_CONF_ARRAY); 7921059Sigor@sysoev.ru n = array ? nxt_conf_array_elements_count(table_cv) : 1; 7931059Sigor@sysoev.ru size = sizeof(nxt_http_route_table_t) 7941059Sigor@sysoev.ru + n * sizeof(nxt_http_route_ruleset_t *); 7951059Sigor@sysoev.ru 7961059Sigor@sysoev.ru table = nxt_mp_alloc(mp, size); 7971059Sigor@sysoev.ru if (nxt_slow_path(table == NULL)) { 7981059Sigor@sysoev.ru return NULL; 7991059Sigor@sysoev.ru } 8001059Sigor@sysoev.ru 8011059Sigor@sysoev.ru table->items = n; 8021059Sigor@sysoev.ru table->object = NXT_HTTP_ROUTE_TABLE; 8031059Sigor@sysoev.ru 8041059Sigor@sysoev.ru if (!array) { 8051474Saxel.duch@nginx.com ruleset = nxt_http_route_ruleset_create(task, mp, table_cv, object, 8061474Saxel.duch@nginx.com case_sensitive, encoding); 8071059Sigor@sysoev.ru if (nxt_slow_path(ruleset == NULL)) { 8081059Sigor@sysoev.ru return NULL; 8091059Sigor@sysoev.ru } 8101059Sigor@sysoev.ru 8111059Sigor@sysoev.ru table->ruleset[0] = ruleset; 8121059Sigor@sysoev.ru 8131059Sigor@sysoev.ru return table; 8141059Sigor@sysoev.ru } 8151059Sigor@sysoev.ru 8161059Sigor@sysoev.ru for (i = 0; i < n; i++) { 8171059Sigor@sysoev.ru ruleset_cv = nxt_conf_get_array_element(table_cv, i); 8181059Sigor@sysoev.ru 8191474Saxel.duch@nginx.com ruleset = nxt_http_route_ruleset_create(task, mp, ruleset_cv, object, 8201474Saxel.duch@nginx.com case_sensitive, encoding); 8211059Sigor@sysoev.ru if (nxt_slow_path(ruleset == NULL)) { 8221059Sigor@sysoev.ru return NULL; 8231059Sigor@sysoev.ru } 8241059Sigor@sysoev.ru 8251059Sigor@sysoev.ru table->ruleset[i] = ruleset; 8261059Sigor@sysoev.ru } 8271059Sigor@sysoev.ru 8281059Sigor@sysoev.ru return table; 8291059Sigor@sysoev.ru } 8301059Sigor@sysoev.ru 8311059Sigor@sysoev.ru 8321059Sigor@sysoev.ru static nxt_http_route_ruleset_t * 8331059Sigor@sysoev.ru nxt_http_route_ruleset_create(nxt_task_t *task, nxt_mp_t *mp, 8341061Sigor@sysoev.ru nxt_conf_value_t *ruleset_cv, nxt_http_route_object_t object, 8351474Saxel.duch@nginx.com nxt_bool_t case_sensitive, nxt_http_route_encoding_t encoding) 8361059Sigor@sysoev.ru { 8371059Sigor@sysoev.ru size_t size; 8381059Sigor@sysoev.ru uint32_t i, n, next; 8391059Sigor@sysoev.ru nxt_str_t name; 8401059Sigor@sysoev.ru nxt_conf_value_t *rule_cv; 8411059Sigor@sysoev.ru nxt_http_route_rule_t *rule; 8421059Sigor@sysoev.ru nxt_http_route_ruleset_t *ruleset; 8431059Sigor@sysoev.ru 8441059Sigor@sysoev.ru n = nxt_conf_object_members_count(ruleset_cv); 8451059Sigor@sysoev.ru size = sizeof(nxt_http_route_ruleset_t) 8461059Sigor@sysoev.ru + n * sizeof(nxt_http_route_rule_t *); 8471059Sigor@sysoev.ru 8481059Sigor@sysoev.ru ruleset = nxt_mp_alloc(mp, size); 8491059Sigor@sysoev.ru if (nxt_slow_path(ruleset == NULL)) { 8501059Sigor@sysoev.ru return NULL; 8511059Sigor@sysoev.ru } 8521059Sigor@sysoev.ru 8531059Sigor@sysoev.ru ruleset->items = n; 8541059Sigor@sysoev.ru 8551059Sigor@sysoev.ru next = 0; 8561059Sigor@sysoev.ru 8571785Svbart@nginx.com /* 8581785Svbart@nginx.com * A workaround for GCC 10 with -flto -O2 flags that warns about "name" 8591785Svbart@nginx.com * may be uninitialized in nxt_http_route_rule_name_create(). 8601785Svbart@nginx.com */ 8611785Svbart@nginx.com nxt_str_null(&name); 8621785Svbart@nginx.com 8631059Sigor@sysoev.ru for (i = 0; i < n; i++) { 8641059Sigor@sysoev.ru rule_cv = nxt_conf_next_object_member(ruleset_cv, &name, &next); 8651059Sigor@sysoev.ru 8661061Sigor@sysoev.ru rule = nxt_http_route_rule_name_create(task, mp, rule_cv, &name, 8671474Saxel.duch@nginx.com case_sensitive, encoding); 8681059Sigor@sysoev.ru if (nxt_slow_path(rule == NULL)) { 8691059Sigor@sysoev.ru return NULL; 8701059Sigor@sysoev.ru } 8711059Sigor@sysoev.ru 8721061Sigor@sysoev.ru rule->object = object; 8731059Sigor@sysoev.ru ruleset->rule[i] = rule; 8741059Sigor@sysoev.ru } 8751059Sigor@sysoev.ru 8761059Sigor@sysoev.ru return ruleset; 8771059Sigor@sysoev.ru } 8781059Sigor@sysoev.ru 8791059Sigor@sysoev.ru 880964Sigor@sysoev.ru static nxt_http_route_rule_t * 8811061Sigor@sysoev.ru nxt_http_route_rule_name_create(nxt_task_t *task, nxt_mp_t *mp, 8821474Saxel.duch@nginx.com nxt_conf_value_t *rule_cv, nxt_str_t *name, nxt_bool_t case_sensitive, 8831474Saxel.duch@nginx.com nxt_http_route_encoding_t encoding) 8841059Sigor@sysoev.ru { 8851474Saxel.duch@nginx.com u_char c, *p, *src, *start, *end, plus; 8861474Saxel.duch@nginx.com uint8_t d0, d1; 8871059Sigor@sysoev.ru uint32_t hash; 8881059Sigor@sysoev.ru nxt_uint_t i; 8891059Sigor@sysoev.ru nxt_http_route_rule_t *rule; 8901059Sigor@sysoev.ru 8911061Sigor@sysoev.ru rule = nxt_http_route_rule_create(task, mp, rule_cv, case_sensitive, 8921474Saxel.duch@nginx.com NXT_HTTP_ROUTE_PATTERN_NOCASE, 8931474Saxel.duch@nginx.com encoding); 8941059Sigor@sysoev.ru if (nxt_slow_path(rule == NULL)) { 8951059Sigor@sysoev.ru return NULL; 8961059Sigor@sysoev.ru } 8971059Sigor@sysoev.ru 8981059Sigor@sysoev.ru rule->u.name.length = name->length; 8991059Sigor@sysoev.ru 9001059Sigor@sysoev.ru p = nxt_mp_nget(mp, name->length); 9011059Sigor@sysoev.ru if (nxt_slow_path(p == NULL)) { 9021059Sigor@sysoev.ru return NULL; 9031059Sigor@sysoev.ru } 9041059Sigor@sysoev.ru 9051474Saxel.duch@nginx.com hash = NXT_HTTP_FIELD_HASH_INIT; 9061059Sigor@sysoev.ru rule->u.name.start = p; 9071059Sigor@sysoev.ru 9081474Saxel.duch@nginx.com if (encoding == NXT_HTTP_ROUTE_ENCODING_NONE) { 9091474Saxel.duch@nginx.com for (i = 0; i < name->length; i++) { 9101474Saxel.duch@nginx.com c = name->start[i]; 9111474Saxel.duch@nginx.com *p++ = c; 9121474Saxel.duch@nginx.com 9131474Saxel.duch@nginx.com c = case_sensitive ? c : nxt_lowcase(c); 9141474Saxel.duch@nginx.com hash = nxt_http_field_hash_char(hash, c); 9151474Saxel.duch@nginx.com } 9161474Saxel.duch@nginx.com 9171474Saxel.duch@nginx.com goto end; 9181474Saxel.duch@nginx.com } 9191474Saxel.duch@nginx.com 9201474Saxel.duch@nginx.com plus = (encoding == NXT_HTTP_ROUTE_ENCODING_URI_PLUS) ? ' ' : '+'; 9211474Saxel.duch@nginx.com 9221474Saxel.duch@nginx.com start = name->start; 9231474Saxel.duch@nginx.com end = start + name->length; 9241474Saxel.duch@nginx.com 9251474Saxel.duch@nginx.com for (src = start; src < end; src++) { 9261474Saxel.duch@nginx.com c = *src; 9271474Saxel.duch@nginx.com 9281474Saxel.duch@nginx.com switch (c) { 9291474Saxel.duch@nginx.com case '%': 9301474Saxel.duch@nginx.com if (nxt_slow_path(end - src <= 2)) { 9311474Saxel.duch@nginx.com return NULL; 9321474Saxel.duch@nginx.com } 9331474Saxel.duch@nginx.com 9341474Saxel.duch@nginx.com d0 = nxt_hex2int[src[1]]; 9351474Saxel.duch@nginx.com d1 = nxt_hex2int[src[2]]; 9361474Saxel.duch@nginx.com src += 2; 9371474Saxel.duch@nginx.com 9381474Saxel.duch@nginx.com if (nxt_slow_path((d0 | d1) >= 16)) { 9391474Saxel.duch@nginx.com return NULL; 9401474Saxel.duch@nginx.com } 9411474Saxel.duch@nginx.com 9421474Saxel.duch@nginx.com c = (d0 << 4) + d1; 9431474Saxel.duch@nginx.com *p++ = c; 9441474Saxel.duch@nginx.com break; 9451474Saxel.duch@nginx.com 9461474Saxel.duch@nginx.com case '+': 9471474Saxel.duch@nginx.com c = plus; 9481474Saxel.duch@nginx.com *p++ = c; 9491474Saxel.duch@nginx.com break; 9501474Saxel.duch@nginx.com 9511474Saxel.duch@nginx.com default: 9521474Saxel.duch@nginx.com *p++ = c; 9531474Saxel.duch@nginx.com break; 9541474Saxel.duch@nginx.com } 9551059Sigor@sysoev.ru 9561079Sigor@sysoev.ru c = case_sensitive ? c : nxt_lowcase(c); 9571059Sigor@sysoev.ru hash = nxt_http_field_hash_char(hash, c); 9581059Sigor@sysoev.ru } 9591059Sigor@sysoev.ru 9601474Saxel.duch@nginx.com rule->u.name.length = p - rule->u.name.start; 9611474Saxel.duch@nginx.com 9621474Saxel.duch@nginx.com end: 9631474Saxel.duch@nginx.com 9641059Sigor@sysoev.ru rule->u.name.hash = nxt_http_field_hash_end(hash) & 0xFFFF; 9651059Sigor@sysoev.ru 9661059Sigor@sysoev.ru return rule; 9671059Sigor@sysoev.ru } 9681059Sigor@sysoev.ru 9691059Sigor@sysoev.ru 9701059Sigor@sysoev.ru static nxt_http_route_rule_t * 9711059Sigor@sysoev.ru nxt_http_route_rule_create(nxt_task_t *task, nxt_mp_t *mp, 972964Sigor@sysoev.ru nxt_conf_value_t *cv, nxt_bool_t case_sensitive, 9731474Saxel.duch@nginx.com nxt_http_route_pattern_case_t pattern_case, 9741474Saxel.duch@nginx.com nxt_http_route_encoding_t encoding) 975964Sigor@sysoev.ru { 976964Sigor@sysoev.ru size_t size; 977964Sigor@sysoev.ru uint32_t i, n; 978964Sigor@sysoev.ru nxt_int_t ret; 979964Sigor@sysoev.ru nxt_bool_t string; 980964Sigor@sysoev.ru nxt_conf_value_t *value; 981964Sigor@sysoev.ru nxt_http_route_rule_t *rule; 982964Sigor@sysoev.ru nxt_http_route_pattern_t *pattern; 983964Sigor@sysoev.ru 984964Sigor@sysoev.ru string = (nxt_conf_type(cv) != NXT_CONF_ARRAY); 985964Sigor@sysoev.ru n = string ? 1 : nxt_conf_array_elements_count(cv); 986964Sigor@sysoev.ru size = sizeof(nxt_http_route_rule_t) + n * sizeof(nxt_http_route_pattern_t); 987964Sigor@sysoev.ru 988964Sigor@sysoev.ru rule = nxt_mp_alloc(mp, size); 989964Sigor@sysoev.ru if (nxt_slow_path(rule == NULL)) { 990964Sigor@sysoev.ru return NULL; 991964Sigor@sysoev.ru } 992964Sigor@sysoev.ru 993964Sigor@sysoev.ru rule->items = n; 994964Sigor@sysoev.ru 995964Sigor@sysoev.ru pattern = &rule->pattern[0]; 996964Sigor@sysoev.ru 997964Sigor@sysoev.ru if (string) { 998964Sigor@sysoev.ru pattern[0].case_sensitive = case_sensitive; 999964Sigor@sysoev.ru ret = nxt_http_route_pattern_create(task, mp, cv, &pattern[0], 10001474Saxel.duch@nginx.com pattern_case, encoding); 1001964Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 1002964Sigor@sysoev.ru return NULL; 1003964Sigor@sysoev.ru } 1004964Sigor@sysoev.ru 1005964Sigor@sysoev.ru return rule; 1006964Sigor@sysoev.ru } 1007964Sigor@sysoev.ru 1008964Sigor@sysoev.ru nxt_conf_array_qsort(cv, nxt_http_pattern_compare); 1009964Sigor@sysoev.ru 1010964Sigor@sysoev.ru for (i = 0; i < n; i++) { 1011964Sigor@sysoev.ru pattern[i].case_sensitive = case_sensitive; 1012964Sigor@sysoev.ru value = nxt_conf_get_array_element(cv, i); 1013964Sigor@sysoev.ru 1014964Sigor@sysoev.ru ret = nxt_http_route_pattern_create(task, mp, value, &pattern[i], 10151474Saxel.duch@nginx.com pattern_case, encoding); 1016964Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 1017964Sigor@sysoev.ru return NULL; 1018964Sigor@sysoev.ru } 1019964Sigor@sysoev.ru } 1020964Sigor@sysoev.ru 1021964Sigor@sysoev.ru return rule; 1022964Sigor@sysoev.ru } 1023964Sigor@sysoev.ru 1024964Sigor@sysoev.ru 10251324Saxel.duch@nginx.com static nxt_http_route_addr_rule_t * 10261324Saxel.duch@nginx.com nxt_http_route_addr_rule_create(nxt_task_t *task, nxt_mp_t *mp, 10271324Saxel.duch@nginx.com nxt_conf_value_t *cv) 10281324Saxel.duch@nginx.com { 10291324Saxel.duch@nginx.com size_t size; 10301324Saxel.duch@nginx.com uint32_t i, n; 10311324Saxel.duch@nginx.com nxt_bool_t array; 10321324Saxel.duch@nginx.com nxt_conf_value_t *value; 10331324Saxel.duch@nginx.com nxt_http_route_addr_rule_t *addr_rule; 10341324Saxel.duch@nginx.com nxt_http_route_addr_pattern_t *pattern; 10351324Saxel.duch@nginx.com 10361324Saxel.duch@nginx.com array = (nxt_conf_type(cv) == NXT_CONF_ARRAY); 10371324Saxel.duch@nginx.com n = array ? nxt_conf_array_elements_count(cv) : 1; 10381324Saxel.duch@nginx.com 10391324Saxel.duch@nginx.com size = sizeof(nxt_http_route_addr_rule_t) 10401324Saxel.duch@nginx.com + n * sizeof(nxt_http_route_addr_pattern_t); 10411324Saxel.duch@nginx.com 10421324Saxel.duch@nginx.com addr_rule = nxt_mp_alloc(mp, size); 10431324Saxel.duch@nginx.com if (nxt_slow_path(addr_rule == NULL)) { 10441324Saxel.duch@nginx.com return NULL; 10451324Saxel.duch@nginx.com } 10461324Saxel.duch@nginx.com 10471324Saxel.duch@nginx.com addr_rule->items = n; 10481324Saxel.duch@nginx.com 10491324Saxel.duch@nginx.com if (!array) { 10501324Saxel.duch@nginx.com pattern = &addr_rule->addr_pattern[0]; 10511324Saxel.duch@nginx.com 10521324Saxel.duch@nginx.com if (nxt_http_route_addr_pattern_parse(mp, pattern, cv) != NXT_OK) { 10531324Saxel.duch@nginx.com return NULL; 10541324Saxel.duch@nginx.com } 10551324Saxel.duch@nginx.com 10561324Saxel.duch@nginx.com return addr_rule; 10571324Saxel.duch@nginx.com } 10581324Saxel.duch@nginx.com 10591324Saxel.duch@nginx.com for (i = 0; i < n; i++) { 10601324Saxel.duch@nginx.com pattern = &addr_rule->addr_pattern[i]; 10611324Saxel.duch@nginx.com value = nxt_conf_get_array_element(cv, i); 10621324Saxel.duch@nginx.com 10631324Saxel.duch@nginx.com if (nxt_http_route_addr_pattern_parse(mp, pattern, value) != NXT_OK) { 10641324Saxel.duch@nginx.com return NULL; 10651324Saxel.duch@nginx.com } 10661324Saxel.duch@nginx.com } 10671324Saxel.duch@nginx.com 10681390Saxel.duch@nginx.com if (n > 1) { 10691390Saxel.duch@nginx.com nxt_qsort(addr_rule->addr_pattern, addr_rule->items, 10701390Saxel.duch@nginx.com sizeof(nxt_http_route_addr_pattern_t), 10711390Saxel.duch@nginx.com nxt_http_addr_pattern_compare); 10721390Saxel.duch@nginx.com } 10731390Saxel.duch@nginx.com 10741324Saxel.duch@nginx.com return addr_rule; 10751324Saxel.duch@nginx.com } 10761324Saxel.duch@nginx.com 10771324Saxel.duch@nginx.com 1078964Sigor@sysoev.ru static int 1079964Sigor@sysoev.ru nxt_http_pattern_compare(const void *one, const void *two) 1080964Sigor@sysoev.ru { 1081964Sigor@sysoev.ru nxt_str_t test; 1082964Sigor@sysoev.ru nxt_bool_t negative1, negative2; 1083964Sigor@sysoev.ru nxt_conf_value_t *value; 1084964Sigor@sysoev.ru 1085964Sigor@sysoev.ru value = (nxt_conf_value_t *) one; 1086964Sigor@sysoev.ru nxt_conf_get_string(value, &test); 1087964Sigor@sysoev.ru negative1 = (test.length != 0 && test.start[0] == '!'); 1088964Sigor@sysoev.ru 1089964Sigor@sysoev.ru value = (nxt_conf_value_t *) two; 1090964Sigor@sysoev.ru nxt_conf_get_string(value, &test); 1091964Sigor@sysoev.ru negative2 = (test.length != 0 && test.start[0] == '!'); 1092964Sigor@sysoev.ru 1093964Sigor@sysoev.ru return (negative2 - negative1); 1094964Sigor@sysoev.ru } 1095964Sigor@sysoev.ru 1096964Sigor@sysoev.ru 10971390Saxel.duch@nginx.com static int 10981390Saxel.duch@nginx.com nxt_http_addr_pattern_compare(const void *one, const void *two) 10991390Saxel.duch@nginx.com { 11001390Saxel.duch@nginx.com const nxt_http_route_addr_pattern_t *p1, *p2; 11011390Saxel.duch@nginx.com 11021390Saxel.duch@nginx.com p1 = one; 11031390Saxel.duch@nginx.com p2 = two; 11041390Saxel.duch@nginx.com 11051390Saxel.duch@nginx.com return (p2->base.negative - p1->base.negative); 11061390Saxel.duch@nginx.com } 11071390Saxel.duch@nginx.com 11081390Saxel.duch@nginx.com 1109964Sigor@sysoev.ru static nxt_int_t 1110964Sigor@sysoev.ru nxt_http_route_pattern_create(nxt_task_t *task, nxt_mp_t *mp, 1111964Sigor@sysoev.ru nxt_conf_value_t *cv, nxt_http_route_pattern_t *pattern, 11121474Saxel.duch@nginx.com nxt_http_route_pattern_case_t pattern_case, 11131474Saxel.duch@nginx.com nxt_http_route_encoding_t encoding) 1114964Sigor@sysoev.ru { 11151508Saxel.duch@nginx.com u_char c, *p, *end; 11161508Saxel.duch@nginx.com nxt_str_t test, tmp; 11171508Saxel.duch@nginx.com nxt_int_t ret; 11181508Saxel.duch@nginx.com nxt_array_t *slices; 11191721Saxel.duch@nginx.com #if (NXT_HAVE_REGEX) 11201721Saxel.duch@nginx.com nxt_regex_t *re; 11211721Saxel.duch@nginx.com nxt_regex_err_t err; 11221721Saxel.duch@nginx.com #endif 11231508Saxel.duch@nginx.com nxt_http_route_pattern_type_t type; 11241508Saxel.duch@nginx.com nxt_http_route_pattern_slice_t *slice; 1125964Sigor@sysoev.ru 1126964Sigor@sysoev.ru type = NXT_HTTP_ROUTE_PATTERN_EXACT; 1127964Sigor@sysoev.ru 1128964Sigor@sysoev.ru nxt_conf_get_string(cv, &test); 1129964Sigor@sysoev.ru 11301721Saxel.duch@nginx.com pattern->u.pattern_slices = NULL; 1131964Sigor@sysoev.ru pattern->negative = 0; 1132964Sigor@sysoev.ru pattern->any = 1; 11331474Saxel.duch@nginx.com pattern->min_length = 0; 11341721Saxel.duch@nginx.com #if (NXT_HAVE_REGEX) 11351721Saxel.duch@nginx.com pattern->regex = 0; 11361721Saxel.duch@nginx.com #endif 1137964Sigor@sysoev.ru 11381508Saxel.duch@nginx.com if (test.length != 0 && test.start[0] == '!') { 11391508Saxel.duch@nginx.com test.start++; 11401508Saxel.duch@nginx.com test.length--; 11411508Saxel.duch@nginx.com 11421508Saxel.duch@nginx.com pattern->negative = 1; 11431508Saxel.duch@nginx.com pattern->any = 0; 11441508Saxel.duch@nginx.com } 11451508Saxel.duch@nginx.com 11461721Saxel.duch@nginx.com if (test.length > 0 && test.start[0] == '~') { 11471721Saxel.duch@nginx.com #if (NXT_HAVE_REGEX) 11481721Saxel.duch@nginx.com test.start++; 11491721Saxel.duch@nginx.com test.length--; 11501721Saxel.duch@nginx.com 11511721Saxel.duch@nginx.com re = nxt_regex_compile(mp, &test, &err); 11521721Saxel.duch@nginx.com if (nxt_slow_path(re == NULL)) { 11531721Saxel.duch@nginx.com if (err.offset < test.length) { 11541721Saxel.duch@nginx.com nxt_alert(task, "nxt_regex_compile(%V) failed: %s at offset %d", 11551721Saxel.duch@nginx.com &test, err.msg, (int) err.offset); 11561721Saxel.duch@nginx.com return NXT_ERROR; 11571721Saxel.duch@nginx.com } 11581721Saxel.duch@nginx.com 11591721Saxel.duch@nginx.com nxt_alert(task, "nxt_regex_compile(%V) failed %s", &test, err.msg); 11601721Saxel.duch@nginx.com 11611721Saxel.duch@nginx.com return NXT_ERROR; 11621721Saxel.duch@nginx.com } 11631721Saxel.duch@nginx.com 11641721Saxel.duch@nginx.com pattern->u.regex = re; 11651721Saxel.duch@nginx.com pattern->regex = 1; 11661721Saxel.duch@nginx.com 11671721Saxel.duch@nginx.com return NXT_OK; 11681721Saxel.duch@nginx.com 11691721Saxel.duch@nginx.com #else 11701721Saxel.duch@nginx.com return NXT_ERROR; 11711721Saxel.duch@nginx.com #endif 11721721Saxel.duch@nginx.com } 11731721Saxel.duch@nginx.com 11741721Saxel.duch@nginx.com slices = nxt_array_create(mp, 1, sizeof(nxt_http_route_pattern_slice_t)); 11751721Saxel.duch@nginx.com if (nxt_slow_path(slices == NULL)) { 11761721Saxel.duch@nginx.com return NXT_ERROR; 11771721Saxel.duch@nginx.com } 11781721Saxel.duch@nginx.com 11791721Saxel.duch@nginx.com pattern->u.pattern_slices = slices; 11801721Saxel.duch@nginx.com 11811508Saxel.duch@nginx.com if (test.length == 0) { 11821508Saxel.duch@nginx.com slice = nxt_array_add(slices); 11831508Saxel.duch@nginx.com if (nxt_slow_path(slice == NULL)) { 11841508Saxel.duch@nginx.com return NXT_ERROR; 1185964Sigor@sysoev.ru } 1186964Sigor@sysoev.ru 11871508Saxel.duch@nginx.com slice->type = NXT_HTTP_ROUTE_PATTERN_EXACT; 11881508Saxel.duch@nginx.com slice->start = NULL; 11891508Saxel.duch@nginx.com slice->length = 0; 11901508Saxel.duch@nginx.com 11911508Saxel.duch@nginx.com return NXT_OK; 11921508Saxel.duch@nginx.com } 11931508Saxel.duch@nginx.com 11941508Saxel.duch@nginx.com if (test.start[0] == '*') { 11951508Saxel.duch@nginx.com /* 'type' is no longer 'EXACT', assume 'END'. */ 11961508Saxel.duch@nginx.com type = NXT_HTTP_ROUTE_PATTERN_END; 11971508Saxel.duch@nginx.com test.start++; 11981508Saxel.duch@nginx.com test.length--; 11991508Saxel.duch@nginx.com } 12001508Saxel.duch@nginx.com 12011522Saxel.duch@nginx.com if (type == NXT_HTTP_ROUTE_PATTERN_EXACT) { 12021508Saxel.duch@nginx.com tmp.start = test.start; 12031508Saxel.duch@nginx.com 12041508Saxel.duch@nginx.com p = nxt_memchr(test.start, '*', test.length); 12051508Saxel.duch@nginx.com 12061508Saxel.duch@nginx.com if (p == NULL) { 12071508Saxel.duch@nginx.com /* No '*' found - EXACT pattern. */ 12081508Saxel.duch@nginx.com tmp.length = test.length; 12091508Saxel.duch@nginx.com type = NXT_HTTP_ROUTE_PATTERN_EXACT; 12101508Saxel.duch@nginx.com 12111508Saxel.duch@nginx.com test.start += test.length; 12121508Saxel.duch@nginx.com test.length = 0; 12131508Saxel.duch@nginx.com 12141508Saxel.duch@nginx.com } else { 12151508Saxel.duch@nginx.com /* '*' found - BEGIN pattern. */ 12161508Saxel.duch@nginx.com tmp.length = p - test.start; 12171508Saxel.duch@nginx.com type = NXT_HTTP_ROUTE_PATTERN_BEGIN; 12181508Saxel.duch@nginx.com 12191508Saxel.duch@nginx.com test.start = p + 1; 12201508Saxel.duch@nginx.com test.length -= tmp.length + 1; 12211508Saxel.duch@nginx.com } 12221508Saxel.duch@nginx.com 12231508Saxel.duch@nginx.com ret = nxt_http_route_pattern_slice(slices, &tmp, type, encoding, 12241508Saxel.duch@nginx.com pattern_case); 12251508Saxel.duch@nginx.com if (nxt_slow_path(ret != NXT_OK)) { 12261508Saxel.duch@nginx.com return ret; 12271508Saxel.duch@nginx.com } 12281508Saxel.duch@nginx.com 12291508Saxel.duch@nginx.com pattern->min_length += tmp.length; 12301508Saxel.duch@nginx.com } 12311508Saxel.duch@nginx.com 12321508Saxel.duch@nginx.com end = test.start + test.length; 12331508Saxel.duch@nginx.com 12341508Saxel.duch@nginx.com if (test.length != 0 && end[-1] != '*') { 12351508Saxel.duch@nginx.com p = end - 1; 12361508Saxel.duch@nginx.com 12371508Saxel.duch@nginx.com while (p != test.start) { 12381508Saxel.duch@nginx.com c = *p--; 12391508Saxel.duch@nginx.com 12401508Saxel.duch@nginx.com if (c == '*') { 12411508Saxel.duch@nginx.com p += 2; 12421508Saxel.duch@nginx.com break; 12431474Saxel.duch@nginx.com } 1244964Sigor@sysoev.ru } 12451508Saxel.duch@nginx.com 12461508Saxel.duch@nginx.com tmp.start = p; 12471508Saxel.duch@nginx.com tmp.length = end - p; 12481508Saxel.duch@nginx.com 12491508Saxel.duch@nginx.com test.length -= tmp.length; 12501508Saxel.duch@nginx.com end = p; 12511508Saxel.duch@nginx.com 12521508Saxel.duch@nginx.com ret = nxt_http_route_pattern_slice(slices, &tmp, 12531508Saxel.duch@nginx.com NXT_HTTP_ROUTE_PATTERN_END, 12541508Saxel.duch@nginx.com encoding, pattern_case); 12551508Saxel.duch@nginx.com if (nxt_slow_path(ret != NXT_OK)) { 12561508Saxel.duch@nginx.com return ret; 12571508Saxel.duch@nginx.com } 12581508Saxel.duch@nginx.com 12591508Saxel.duch@nginx.com pattern->min_length += tmp.length; 1260964Sigor@sysoev.ru } 1261964Sigor@sysoev.ru 12621508Saxel.duch@nginx.com tmp.start = test.start; 12631508Saxel.duch@nginx.com tmp.length = 0; 12641508Saxel.duch@nginx.com 12651508Saxel.duch@nginx.com p = tmp.start; 12661508Saxel.duch@nginx.com 12671508Saxel.duch@nginx.com while (p != end) { 12681508Saxel.duch@nginx.com c = *p++; 12691508Saxel.duch@nginx.com 12701508Saxel.duch@nginx.com if (c != '*') { 12711508Saxel.duch@nginx.com tmp.length++; 12721508Saxel.duch@nginx.com continue; 12731508Saxel.duch@nginx.com } 12741508Saxel.duch@nginx.com 12751508Saxel.duch@nginx.com if (tmp.length == 0) { 12761508Saxel.duch@nginx.com tmp.start = p; 12771508Saxel.duch@nginx.com continue; 12781508Saxel.duch@nginx.com } 12791508Saxel.duch@nginx.com 12801508Saxel.duch@nginx.com ret = nxt_http_route_pattern_slice(slices, &tmp, 12811508Saxel.duch@nginx.com NXT_HTTP_ROUTE_PATTERN_SUBSTRING, 12821508Saxel.duch@nginx.com encoding, pattern_case); 12831508Saxel.duch@nginx.com if (nxt_slow_path(ret != NXT_OK)) { 12841508Saxel.duch@nginx.com return ret; 12851508Saxel.duch@nginx.com } 12861508Saxel.duch@nginx.com 12871508Saxel.duch@nginx.com pattern->min_length += tmp.length; 12881508Saxel.duch@nginx.com 12891508Saxel.duch@nginx.com tmp.start = p; 12901508Saxel.duch@nginx.com tmp.length = 0; 1291964Sigor@sysoev.ru } 1292964Sigor@sysoev.ru 12931508Saxel.duch@nginx.com if (tmp.length != 0) { 12941508Saxel.duch@nginx.com ret = nxt_http_route_pattern_slice(slices, &tmp, 12951508Saxel.duch@nginx.com NXT_HTTP_ROUTE_PATTERN_SUBSTRING, 12961508Saxel.duch@nginx.com encoding, pattern_case); 12971508Saxel.duch@nginx.com if (nxt_slow_path(ret != NXT_OK)) { 12981508Saxel.duch@nginx.com return ret; 12991508Saxel.duch@nginx.com } 13001508Saxel.duch@nginx.com 13011508Saxel.duch@nginx.com pattern->min_length += tmp.length; 13021508Saxel.duch@nginx.com } 13031032Sigor@sysoev.ru 13041474Saxel.duch@nginx.com return NXT_OK; 13051474Saxel.duch@nginx.com } 13061474Saxel.duch@nginx.com 13071474Saxel.duch@nginx.com 13081474Saxel.duch@nginx.com static nxt_int_t 13091474Saxel.duch@nginx.com nxt_http_route_decode_str(nxt_str_t *str, nxt_http_route_encoding_t encoding) 13101474Saxel.duch@nginx.com { 13111474Saxel.duch@nginx.com u_char *start, *end; 13121474Saxel.duch@nginx.com 13131474Saxel.duch@nginx.com switch (encoding) { 13141474Saxel.duch@nginx.com case NXT_HTTP_ROUTE_ENCODING_NONE: 13151474Saxel.duch@nginx.com break; 13161474Saxel.duch@nginx.com 13171474Saxel.duch@nginx.com case NXT_HTTP_ROUTE_ENCODING_URI: 13181474Saxel.duch@nginx.com start = str->start; 13191474Saxel.duch@nginx.com 13201474Saxel.duch@nginx.com end = nxt_decode_uri(start, start, str->length); 13211474Saxel.duch@nginx.com if (nxt_slow_path(end == NULL)) { 13221032Sigor@sysoev.ru return NXT_ERROR; 13231032Sigor@sysoev.ru } 13241032Sigor@sysoev.ru 13251474Saxel.duch@nginx.com str->length = end - start; 13261474Saxel.duch@nginx.com break; 13271474Saxel.duch@nginx.com 13281474Saxel.duch@nginx.com case NXT_HTTP_ROUTE_ENCODING_URI_PLUS: 13291474Saxel.duch@nginx.com start = str->start; 13301474Saxel.duch@nginx.com 13311474Saxel.duch@nginx.com end = nxt_decode_uri_plus(start, start, str->length); 13321474Saxel.duch@nginx.com if (nxt_slow_path(end == NULL)) { 13331474Saxel.duch@nginx.com return NXT_ERROR; 13341474Saxel.duch@nginx.com } 13351474Saxel.duch@nginx.com 13361474Saxel.duch@nginx.com str->length = end - start; 13371474Saxel.duch@nginx.com break; 13381474Saxel.duch@nginx.com 13391474Saxel.duch@nginx.com default: 13401474Saxel.duch@nginx.com nxt_unreachable(); 13411032Sigor@sysoev.ru } 13421032Sigor@sysoev.ru 13431032Sigor@sysoev.ru return NXT_OK; 13441032Sigor@sysoev.ru } 13451032Sigor@sysoev.ru 13461032Sigor@sysoev.ru 13471508Saxel.duch@nginx.com static nxt_int_t 13481508Saxel.duch@nginx.com nxt_http_route_pattern_slice(nxt_array_t *slices, 13491508Saxel.duch@nginx.com nxt_str_t *test, 13501508Saxel.duch@nginx.com nxt_http_route_pattern_type_t type, 13511508Saxel.duch@nginx.com nxt_http_route_encoding_t encoding, 13521032Sigor@sysoev.ru nxt_http_route_pattern_case_t pattern_case) 13531032Sigor@sysoev.ru { 13541508Saxel.duch@nginx.com u_char *start; 13551508Saxel.duch@nginx.com nxt_int_t ret; 13561508Saxel.duch@nginx.com nxt_http_route_pattern_slice_t *slice; 13571508Saxel.duch@nginx.com 13581508Saxel.duch@nginx.com ret = nxt_http_route_decode_str(test, encoding); 13591508Saxel.duch@nginx.com if (nxt_slow_path(ret != NXT_OK)) { 13601508Saxel.duch@nginx.com return ret; 13611508Saxel.duch@nginx.com } 13621508Saxel.duch@nginx.com 13631508Saxel.duch@nginx.com start = nxt_mp_nget(slices->mem_pool, test->length); 13641032Sigor@sysoev.ru if (nxt_slow_path(start == NULL)) { 13651508Saxel.duch@nginx.com return NXT_ERROR; 13661032Sigor@sysoev.ru } 1367964Sigor@sysoev.ru 1368964Sigor@sysoev.ru switch (pattern_case) { 1369964Sigor@sysoev.ru 1370964Sigor@sysoev.ru case NXT_HTTP_ROUTE_PATTERN_UPCASE: 13711032Sigor@sysoev.ru nxt_memcpy_upcase(start, test->start, test->length); 1372964Sigor@sysoev.ru break; 1373964Sigor@sysoev.ru 1374964Sigor@sysoev.ru case NXT_HTTP_ROUTE_PATTERN_LOWCASE: 13751032Sigor@sysoev.ru nxt_memcpy_lowcase(start, test->start, test->length); 1376964Sigor@sysoev.ru break; 1377964Sigor@sysoev.ru 1378964Sigor@sysoev.ru case NXT_HTTP_ROUTE_PATTERN_NOCASE: 13791032Sigor@sysoev.ru nxt_memcpy(start, test->start, test->length); 1380964Sigor@sysoev.ru break; 1381964Sigor@sysoev.ru } 1382964Sigor@sysoev.ru 13831508Saxel.duch@nginx.com slice = nxt_array_add(slices); 13841564Svbart@nginx.com if (nxt_slow_path(slice == NULL)) { 13851508Saxel.duch@nginx.com return NXT_ERROR; 13861508Saxel.duch@nginx.com } 13871508Saxel.duch@nginx.com 13881508Saxel.duch@nginx.com slice->type = type; 13891508Saxel.duch@nginx.com slice->start = start; 13901508Saxel.duch@nginx.com slice->length = test->length; 13911508Saxel.duch@nginx.com 13921508Saxel.duch@nginx.com return NXT_OK; 1393964Sigor@sysoev.ru } 1394964Sigor@sysoev.ru 1395964Sigor@sysoev.ru 13961472Svbart@nginx.com nxt_int_t 1397964Sigor@sysoev.ru nxt_http_routes_resolve(nxt_task_t *task, nxt_router_temp_conf_t *tmcf) 1398964Sigor@sysoev.ru { 13991472Svbart@nginx.com nxt_int_t ret; 14001033Svbart@nginx.com nxt_http_route_t **route, **end; 1401964Sigor@sysoev.ru nxt_http_routes_t *routes; 1402964Sigor@sysoev.ru 1403964Sigor@sysoev.ru routes = tmcf->router_conf->routes; 14041059Sigor@sysoev.ru 1405964Sigor@sysoev.ru if (routes != NULL) { 1406964Sigor@sysoev.ru route = &routes->route[0]; 14071033Svbart@nginx.com end = route + routes->items; 1408964Sigor@sysoev.ru 14091033Svbart@nginx.com while (route < end) { 14101472Svbart@nginx.com ret = nxt_http_route_resolve(task, tmcf, *route); 14111472Svbart@nginx.com if (nxt_slow_path(ret != NXT_OK)) { 14121472Svbart@nginx.com return NXT_ERROR; 14131472Svbart@nginx.com } 1414964Sigor@sysoev.ru 1415964Sigor@sysoev.ru route++; 1416964Sigor@sysoev.ru } 1417964Sigor@sysoev.ru } 14181472Svbart@nginx.com 14191472Svbart@nginx.com return NXT_OK; 1420964Sigor@sysoev.ru } 1421964Sigor@sysoev.ru 1422964Sigor@sysoev.ru 14231472Svbart@nginx.com static nxt_int_t 1424964Sigor@sysoev.ru nxt_http_route_resolve(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, 1425964Sigor@sysoev.ru nxt_http_route_t *route) 1426964Sigor@sysoev.ru { 14271472Svbart@nginx.com nxt_int_t ret; 14281033Svbart@nginx.com nxt_http_route_match_t **match, **end; 1429964Sigor@sysoev.ru 1430964Sigor@sysoev.ru match = &route->match[0]; 14311033Svbart@nginx.com end = match + route->items; 1432964Sigor@sysoev.ru 14331033Svbart@nginx.com while (match < end) { 14341472Svbart@nginx.com ret = nxt_http_action_resolve(task, tmcf, &(*match)->action); 14351472Svbart@nginx.com if (nxt_slow_path(ret != NXT_OK)) { 14361472Svbart@nginx.com return NXT_ERROR; 14371472Svbart@nginx.com } 1438964Sigor@sysoev.ru 1439964Sigor@sysoev.ru match++; 1440964Sigor@sysoev.ru } 14411472Svbart@nginx.com 14421472Svbart@nginx.com return NXT_OK; 1443964Sigor@sysoev.ru } 1444964Sigor@sysoev.ru 1445964Sigor@sysoev.ru 14461472Svbart@nginx.com static nxt_int_t 14471264Sigor@sysoev.ru nxt_http_action_resolve(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, 14481264Sigor@sysoev.ru nxt_http_action_t *action) 1449964Sigor@sysoev.ru { 14501563Svbart@nginx.com nxt_var_t *var; 14511563Svbart@nginx.com nxt_int_t ret; 1452964Sigor@sysoev.ru 14531378Svbart@nginx.com if (action->handler != NULL) { 14541378Svbart@nginx.com if (action->handler == nxt_http_static_handler 14551854Sz.hong@f5.com && action->u.share.fallback != NULL) 14561378Svbart@nginx.com { 14571854Sz.hong@f5.com return nxt_http_action_resolve(task, tmcf, 14581854Sz.hong@f5.com action->u.share.fallback); 14591378Svbart@nginx.com } 14601378Svbart@nginx.com 14611472Svbart@nginx.com return NXT_OK; 14621378Svbart@nginx.com } 14631378Svbart@nginx.com 14641563Svbart@nginx.com if (nxt_is_var(&action->name)) { 14651563Svbart@nginx.com var = nxt_var_compile(&action->name, tmcf->router_conf->mem_pool); 14661563Svbart@nginx.com if (nxt_slow_path(var == NULL)) { 14671563Svbart@nginx.com return NXT_ERROR; 14681563Svbart@nginx.com } 14691563Svbart@nginx.com 14701563Svbart@nginx.com action->u.var = var; 14711563Svbart@nginx.com action->handler = nxt_http_action_pass_var; 14721563Svbart@nginx.com return NXT_OK; 14731563Svbart@nginx.com } 14741563Svbart@nginx.com 14751563Svbart@nginx.com ret = nxt_http_pass_find(task, tmcf->mem_pool, tmcf->router_conf, action); 14761472Svbart@nginx.com if (nxt_slow_path(ret != NXT_OK)) { 14771472Svbart@nginx.com return NXT_ERROR; 14781472Svbart@nginx.com } 14791472Svbart@nginx.com 14801563Svbart@nginx.com return NXT_OK; 14811563Svbart@nginx.com } 14821563Svbart@nginx.com 14831563Svbart@nginx.com 14841563Svbart@nginx.com static nxt_http_action_t * 14851563Svbart@nginx.com nxt_http_action_pass_var(nxt_task_t *task, nxt_http_request_t *r, 14861563Svbart@nginx.com nxt_http_action_t *action) 14871563Svbart@nginx.com { 14881563Svbart@nginx.com nxt_var_t *var; 14891563Svbart@nginx.com nxt_int_t ret; 14901563Svbart@nginx.com 14911563Svbart@nginx.com ret = nxt_var_query_init(&r->var_query, r, r->mem_pool); 14921563Svbart@nginx.com if (nxt_slow_path(ret != NXT_OK)) { 14931563Svbart@nginx.com goto fail; 14941563Svbart@nginx.com } 14951563Svbart@nginx.com 14961563Svbart@nginx.com var = action->u.var; 14971563Svbart@nginx.com 14981563Svbart@nginx.com action = nxt_mp_get(r->mem_pool, sizeof(nxt_http_action_t)); 14991563Svbart@nginx.com if (nxt_slow_path(action == NULL)) { 15001563Svbart@nginx.com goto fail; 15011563Svbart@nginx.com } 15021563Svbart@nginx.com 15031563Svbart@nginx.com nxt_var_query(task, r->var_query, var, &action->name); 15041563Svbart@nginx.com nxt_var_query_resolve(task, r->var_query, action, 15051563Svbart@nginx.com nxt_http_action_pass_var_ready, 15061563Svbart@nginx.com nxt_http_action_pass_var_error); 15071563Svbart@nginx.com return NULL; 15081563Svbart@nginx.com 15091563Svbart@nginx.com fail: 15101563Svbart@nginx.com 15111563Svbart@nginx.com nxt_http_request_error(task, r, NXT_HTTP_INTERNAL_SERVER_ERROR); 15121563Svbart@nginx.com return NULL; 15131563Svbart@nginx.com } 15141563Svbart@nginx.com 15151563Svbart@nginx.com 15161563Svbart@nginx.com static void 15171563Svbart@nginx.com nxt_http_action_pass_var_ready(nxt_task_t *task, void *obj, void *data) 15181563Svbart@nginx.com { 15191563Svbart@nginx.com nxt_int_t ret; 15201563Svbart@nginx.com nxt_router_conf_t *rtcf; 15211563Svbart@nginx.com nxt_http_action_t *action; 15221563Svbart@nginx.com nxt_http_status_t status; 15231563Svbart@nginx.com nxt_http_request_t *r; 15241563Svbart@nginx.com 15251563Svbart@nginx.com r = obj; 15261563Svbart@nginx.com action = data; 15271563Svbart@nginx.com rtcf = r->conf->socket_conf->router_conf; 15281563Svbart@nginx.com 15291563Svbart@nginx.com nxt_debug(task, "http pass lookup: %V", &action->name); 15301563Svbart@nginx.com 15311563Svbart@nginx.com ret = nxt_http_pass_find(task, r->mem_pool, rtcf, action); 15321563Svbart@nginx.com 15331563Svbart@nginx.com if (ret != NXT_OK) { 15341563Svbart@nginx.com status = (ret == NXT_DECLINED) ? NXT_HTTP_NOT_FOUND 15351563Svbart@nginx.com : NXT_HTTP_INTERNAL_SERVER_ERROR; 15361563Svbart@nginx.com 15371563Svbart@nginx.com nxt_http_request_error(task, r, status); 15381563Svbart@nginx.com return; 15391563Svbart@nginx.com } 15401563Svbart@nginx.com 15411563Svbart@nginx.com nxt_http_request_action(task, r, action); 15421563Svbart@nginx.com } 15431563Svbart@nginx.com 15441563Svbart@nginx.com 15451563Svbart@nginx.com static void 15461563Svbart@nginx.com nxt_http_action_pass_var_error(nxt_task_t *task, void *obj, void *data) 15471563Svbart@nginx.com { 15481563Svbart@nginx.com nxt_http_request_t *r; 15491563Svbart@nginx.com 15501563Svbart@nginx.com r = obj; 15511563Svbart@nginx.com 15521563Svbart@nginx.com nxt_http_request_error(task, r, NXT_HTTP_INTERNAL_SERVER_ERROR); 15531563Svbart@nginx.com } 15541563Svbart@nginx.com 15551563Svbart@nginx.com 15561563Svbart@nginx.com static nxt_int_t 15571563Svbart@nginx.com nxt_http_pass_find(nxt_task_t *task, nxt_mp_t *mp, nxt_router_conf_t *rtcf, 15581563Svbart@nginx.com nxt_http_action_t *action) 15591563Svbart@nginx.com { 15601563Svbart@nginx.com nxt_str_t *targets; 15611563Svbart@nginx.com nxt_int_t ret; 15621563Svbart@nginx.com nxt_uint_t i; 15631563Svbart@nginx.com nxt_str_t segments[3]; 15641563Svbart@nginx.com 15651563Svbart@nginx.com ret = nxt_http_pass_segments(mp, &action->name, segments, 3); 15661563Svbart@nginx.com if (nxt_slow_path(ret != NXT_OK)) { 15671563Svbart@nginx.com return ret; 15681563Svbart@nginx.com } 15691563Svbart@nginx.com 15701472Svbart@nginx.com if (nxt_str_eq(&segments[0], "applications", 12)) { 15711563Svbart@nginx.com ret = nxt_router_listener_application(rtcf, &segments[1], action); 15721563Svbart@nginx.com 15731563Svbart@nginx.com if (ret != NXT_OK) { 15741563Svbart@nginx.com return ret; 15751563Svbart@nginx.com } 1576964Sigor@sysoev.ru 15771473Svbart@nginx.com if (segments[2].length != 0) { 15781854Sz.hong@f5.com targets = action->u.app.application->targets; 15791473Svbart@nginx.com 15801473Svbart@nginx.com for (i = 0; !nxt_strstr_eq(&segments[2], &targets[i]); i++); 15811473Svbart@nginx.com 15821854Sz.hong@f5.com action->u.app.target = i; 15831473Svbart@nginx.com 15841473Svbart@nginx.com } else { 15851854Sz.hong@f5.com action->u.app.target = 0; 15861473Svbart@nginx.com } 15871473Svbart@nginx.com 15881563Svbart@nginx.com return NXT_OK; 15891472Svbart@nginx.com } 15901472Svbart@nginx.com 15911563Svbart@nginx.com if (segments[2].length == 0) { 15921563Svbart@nginx.com if (nxt_str_eq(&segments[0], "upstreams", 9)) { 15931563Svbart@nginx.com return nxt_upstream_find(rtcf->upstreams, &segments[1], action); 15941563Svbart@nginx.com } 15951563Svbart@nginx.com 15961563Svbart@nginx.com if (nxt_str_eq(&segments[0], "routes", 6)) { 15971563Svbart@nginx.com return nxt_http_route_find(rtcf->routes, &segments[1], action); 15981563Svbart@nginx.com } 15991563Svbart@nginx.com } 16001563Svbart@nginx.com 16011563Svbart@nginx.com return NXT_DECLINED; 16021472Svbart@nginx.com } 16031472Svbart@nginx.com 16041472Svbart@nginx.com 16051472Svbart@nginx.com nxt_int_t 16061472Svbart@nginx.com nxt_http_pass_segments(nxt_mp_t *mp, nxt_str_t *pass, nxt_str_t *segments, 16071472Svbart@nginx.com nxt_uint_t n) 16081472Svbart@nginx.com { 16091472Svbart@nginx.com u_char *p; 16101472Svbart@nginx.com nxt_str_t rest; 16111472Svbart@nginx.com 16121472Svbart@nginx.com if (nxt_slow_path(nxt_str_dup(mp, &rest, pass) == NULL)) { 16131472Svbart@nginx.com return NXT_ERROR; 16141472Svbart@nginx.com } 16151472Svbart@nginx.com 16161472Svbart@nginx.com nxt_memzero(segments, n * sizeof(nxt_str_t)); 16171472Svbart@nginx.com 16181472Svbart@nginx.com do { 16191472Svbart@nginx.com p = nxt_memchr(rest.start, '/', rest.length); 16201472Svbart@nginx.com 16211472Svbart@nginx.com if (p != NULL) { 16221472Svbart@nginx.com n--; 16231472Svbart@nginx.com 16241472Svbart@nginx.com if (n == 0) { 16251472Svbart@nginx.com return NXT_DECLINED; 16261472Svbart@nginx.com } 16271472Svbart@nginx.com 16281472Svbart@nginx.com segments->length = p - rest.start; 16291472Svbart@nginx.com segments->start = rest.start; 16301472Svbart@nginx.com 16311472Svbart@nginx.com rest.length -= segments->length + 1; 16321472Svbart@nginx.com rest.start = p + 1; 16331472Svbart@nginx.com 16341472Svbart@nginx.com } else { 16351472Svbart@nginx.com n = 0; 16361472Svbart@nginx.com *segments = rest; 1637964Sigor@sysoev.ru } 1638964Sigor@sysoev.ru 16391472Svbart@nginx.com if (segments->length == 0) { 16401472Svbart@nginx.com return NXT_DECLINED; 16411472Svbart@nginx.com } 16421472Svbart@nginx.com 16431472Svbart@nginx.com p = nxt_decode_uri(segments->start, segments->start, segments->length); 16441472Svbart@nginx.com if (p == NULL) { 16451472Svbart@nginx.com return NXT_DECLINED; 16461472Svbart@nginx.com } 16471472Svbart@nginx.com 16481472Svbart@nginx.com segments->length = p - segments->start; 16491472Svbart@nginx.com segments++; 16501472Svbart@nginx.com 16511472Svbart@nginx.com } while (n); 16521472Svbart@nginx.com 16531472Svbart@nginx.com return NXT_OK; 1654964Sigor@sysoev.ru } 1655964Sigor@sysoev.ru 1656964Sigor@sysoev.ru 16571563Svbart@nginx.com static nxt_int_t 16581392Sigor@sysoev.ru nxt_http_route_find(nxt_http_routes_t *routes, nxt_str_t *name, 16591392Sigor@sysoev.ru nxt_http_action_t *action) 1660964Sigor@sysoev.ru { 16611033Svbart@nginx.com nxt_http_route_t **route, **end; 1662964Sigor@sysoev.ru 1663964Sigor@sysoev.ru route = &routes->route[0]; 16641033Svbart@nginx.com end = route + routes->items; 1665964Sigor@sysoev.ru 16661058Sigor@sysoev.ru while (route < end) { 1667964Sigor@sysoev.ru if (nxt_strstr_eq(&(*route)->name, name)) { 16681392Sigor@sysoev.ru action->u.route = *route; 16691392Sigor@sysoev.ru action->handler = nxt_http_route_handler; 16701392Sigor@sysoev.ru 16711563Svbart@nginx.com return NXT_OK; 1672964Sigor@sysoev.ru } 1673964Sigor@sysoev.ru 1674964Sigor@sysoev.ru route++; 16751058Sigor@sysoev.ru } 16761563Svbart@nginx.com 16771563Svbart@nginx.com return NXT_DECLINED; 1678964Sigor@sysoev.ru } 1679964Sigor@sysoev.ru 1680964Sigor@sysoev.ru 16811264Sigor@sysoev.ru nxt_http_action_t * 16821264Sigor@sysoev.ru nxt_http_action_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, 1683964Sigor@sysoev.ru nxt_str_t *name) 1684964Sigor@sysoev.ru { 16851597Shongzhidao@gmail.com nxt_int_t ret; 16861264Sigor@sysoev.ru nxt_http_action_t *action; 1687964Sigor@sysoev.ru 16881264Sigor@sysoev.ru action = nxt_mp_alloc(tmcf->router_conf->mem_pool, 16891264Sigor@sysoev.ru sizeof(nxt_http_action_t)); 16901264Sigor@sysoev.ru if (nxt_slow_path(action == NULL)) { 1691964Sigor@sysoev.ru return NULL; 1692964Sigor@sysoev.ru } 1693964Sigor@sysoev.ru 16941264Sigor@sysoev.ru action->name = *name; 16951270Sigor@sysoev.ru action->handler = NULL; 1696964Sigor@sysoev.ru 16971597Shongzhidao@gmail.com ret = nxt_http_action_resolve(task, tmcf, action); 16981597Shongzhidao@gmail.com if (nxt_slow_path(ret != NXT_OK)) { 16991597Shongzhidao@gmail.com return NULL; 17001597Shongzhidao@gmail.com } 1701964Sigor@sysoev.ru 17021264Sigor@sysoev.ru return action; 1703964Sigor@sysoev.ru } 1704964Sigor@sysoev.ru 1705964Sigor@sysoev.ru 1706964Sigor@sysoev.ru /* COMPATIBILITY: listener application. */ 1707964Sigor@sysoev.ru 17081264Sigor@sysoev.ru nxt_http_action_t * 17091563Svbart@nginx.com nxt_http_pass_application(nxt_task_t *task, nxt_router_conf_t *rtcf, 1710964Sigor@sysoev.ru nxt_str_t *name) 1711964Sigor@sysoev.ru { 17121264Sigor@sysoev.ru nxt_http_action_t *action; 1713964Sigor@sysoev.ru 17141563Svbart@nginx.com action = nxt_mp_alloc(rtcf->mem_pool, sizeof(nxt_http_action_t)); 17151264Sigor@sysoev.ru if (nxt_slow_path(action == NULL)) { 1716964Sigor@sysoev.ru return NULL; 1717964Sigor@sysoev.ru } 1718964Sigor@sysoev.ru 17191264Sigor@sysoev.ru action->name = *name; 1720964Sigor@sysoev.ru 17211563Svbart@nginx.com (void) nxt_router_listener_application(rtcf, name, action); 1722964Sigor@sysoev.ru 17231854Sz.hong@f5.com action->u.app.target = 0; 17241473Svbart@nginx.com 17251264Sigor@sysoev.ru return action; 1726964Sigor@sysoev.ru } 1727964Sigor@sysoev.ru 1728964Sigor@sysoev.ru 17291264Sigor@sysoev.ru static nxt_http_action_t * 17301264Sigor@sysoev.ru nxt_http_route_handler(nxt_task_t *task, nxt_http_request_t *r, 17311264Sigor@sysoev.ru nxt_http_action_t *start) 1732964Sigor@sysoev.ru { 1733964Sigor@sysoev.ru nxt_http_route_t *route; 17341264Sigor@sysoev.ru nxt_http_action_t *action; 17351033Svbart@nginx.com nxt_http_route_match_t **match, **end; 1736964Sigor@sysoev.ru 1737964Sigor@sysoev.ru route = start->u.route; 1738964Sigor@sysoev.ru match = &route->match[0]; 17391033Svbart@nginx.com end = match + route->items; 1740964Sigor@sysoev.ru 17411033Svbart@nginx.com while (match < end) { 17421326Saxel.duch@nginx.com action = nxt_http_route_match(task, r, *match); 17431264Sigor@sysoev.ru if (action != NULL) { 17441264Sigor@sysoev.ru return action; 1745964Sigor@sysoev.ru } 1746964Sigor@sysoev.ru 1747964Sigor@sysoev.ru match++; 1748964Sigor@sysoev.ru } 1749964Sigor@sysoev.ru 1750964Sigor@sysoev.ru nxt_http_request_error(task, r, NXT_HTTP_NOT_FOUND); 1751964Sigor@sysoev.ru 1752964Sigor@sysoev.ru return NULL; 1753964Sigor@sysoev.ru } 1754964Sigor@sysoev.ru 1755964Sigor@sysoev.ru 17561264Sigor@sysoev.ru static nxt_http_action_t * 17571326Saxel.duch@nginx.com nxt_http_route_match(nxt_task_t *task, nxt_http_request_t *r, 17581326Saxel.duch@nginx.com nxt_http_route_match_t *match) 1759964Sigor@sysoev.ru { 17601060Sigor@sysoev.ru nxt_int_t ret; 17611059Sigor@sysoev.ru nxt_http_route_test_t *test, *end; 17621059Sigor@sysoev.ru 17631059Sigor@sysoev.ru test = &match->test[0]; 17641059Sigor@sysoev.ru end = test + match->items; 1765964Sigor@sysoev.ru 17661059Sigor@sysoev.ru while (test < end) { 17671324Saxel.duch@nginx.com switch (test->rule->object) { 17681324Saxel.duch@nginx.com case NXT_HTTP_ROUTE_TABLE: 17691324Saxel.duch@nginx.com ret = nxt_http_route_table(r, test->table); 17701324Saxel.duch@nginx.com break; 17711324Saxel.duch@nginx.com case NXT_HTTP_ROUTE_SOURCE: 17721324Saxel.duch@nginx.com ret = nxt_http_route_addr_rule(r, test->addr_rule, r->remote); 17731324Saxel.duch@nginx.com break; 17741326Saxel.duch@nginx.com case NXT_HTTP_ROUTE_DESTINATION: 17751326Saxel.duch@nginx.com if (r->local == NULL && nxt_fast_path(r->proto.any != NULL)) { 17761326Saxel.duch@nginx.com nxt_http_proto[r->protocol].local_addr(task, r); 17771326Saxel.duch@nginx.com } 17781326Saxel.duch@nginx.com 17791326Saxel.duch@nginx.com ret = nxt_http_route_addr_rule(r, test->addr_rule, r->local); 17801326Saxel.duch@nginx.com break; 17811324Saxel.duch@nginx.com default: 17821059Sigor@sysoev.ru ret = nxt_http_route_rule(r, test->rule); 17831324Saxel.duch@nginx.com break; 17841059Sigor@sysoev.ru } 17851059Sigor@sysoev.ru 17861060Sigor@sysoev.ru if (ret <= 0) { 17871264Sigor@sysoev.ru /* 0 => NULL, -1 => NXT_HTTP_ACTION_ERROR. */ 17881264Sigor@sysoev.ru return (nxt_http_action_t *) (intptr_t) ret; 1789964Sigor@sysoev.ru } 1790964Sigor@sysoev.ru 17911059Sigor@sysoev.ru test++; 1792964Sigor@sysoev.ru } 1793964Sigor@sysoev.ru 17941264Sigor@sysoev.ru return &match->action; 1795964Sigor@sysoev.ru } 1796964Sigor@sysoev.ru 1797964Sigor@sysoev.ru 17981060Sigor@sysoev.ru static nxt_int_t 17991059Sigor@sysoev.ru nxt_http_route_table(nxt_http_request_t *r, nxt_http_route_table_t *table) 1800964Sigor@sysoev.ru { 18011060Sigor@sysoev.ru nxt_int_t ret; 18021059Sigor@sysoev.ru nxt_http_route_ruleset_t **ruleset, **end; 18031059Sigor@sysoev.ru 18041059Sigor@sysoev.ru ret = 1; 18051059Sigor@sysoev.ru ruleset = &table->ruleset[0]; 18061059Sigor@sysoev.ru end = ruleset + table->items; 18071059Sigor@sysoev.ru 18081059Sigor@sysoev.ru while (ruleset < end) { 18091059Sigor@sysoev.ru ret = nxt_http_route_ruleset(r, *ruleset); 18101059Sigor@sysoev.ru 18111060Sigor@sysoev.ru if (ret != 0) { 18121059Sigor@sysoev.ru return ret; 18131059Sigor@sysoev.ru } 1814964Sigor@sysoev.ru 18151059Sigor@sysoev.ru ruleset++; 18161059Sigor@sysoev.ru } 18171059Sigor@sysoev.ru 18181059Sigor@sysoev.ru return ret; 18191059Sigor@sysoev.ru } 18201059Sigor@sysoev.ru 1821964Sigor@sysoev.ru 18221060Sigor@sysoev.ru static nxt_int_t 18231059Sigor@sysoev.ru nxt_http_route_ruleset(nxt_http_request_t *r, nxt_http_route_ruleset_t *ruleset) 18241059Sigor@sysoev.ru { 18251060Sigor@sysoev.ru nxt_int_t ret; 18261059Sigor@sysoev.ru nxt_http_route_rule_t **rule, **end; 1827964Sigor@sysoev.ru 18281059Sigor@sysoev.ru rule = &ruleset->rule[0]; 18291059Sigor@sysoev.ru end = rule + ruleset->items; 1830964Sigor@sysoev.ru 18311059Sigor@sysoev.ru while (rule < end) { 18321060Sigor@sysoev.ru ret = nxt_http_route_rule(r, *rule); 18331060Sigor@sysoev.ru 18341060Sigor@sysoev.ru if (ret <= 0) { 18351060Sigor@sysoev.ru return ret; 1836964Sigor@sysoev.ru } 1837964Sigor@sysoev.ru 18381059Sigor@sysoev.ru rule++; 18391059Sigor@sysoev.ru } 18401059Sigor@sysoev.ru 18411059Sigor@sysoev.ru return 1; 18421059Sigor@sysoev.ru } 18431059Sigor@sysoev.ru 1844964Sigor@sysoev.ru 18451060Sigor@sysoev.ru static nxt_int_t 18461059Sigor@sysoev.ru nxt_http_route_rule(nxt_http_request_t *r, nxt_http_route_rule_t *rule) 18471059Sigor@sysoev.ru { 18481059Sigor@sysoev.ru void *p, **pp; 18491059Sigor@sysoev.ru u_char *start; 18501059Sigor@sysoev.ru size_t length; 18511059Sigor@sysoev.ru nxt_str_t *s; 18521059Sigor@sysoev.ru 18531059Sigor@sysoev.ru switch (rule->object) { 18541059Sigor@sysoev.ru 18551059Sigor@sysoev.ru case NXT_HTTP_ROUTE_HEADER: 18561059Sigor@sysoev.ru return nxt_http_route_header(r, rule); 1857964Sigor@sysoev.ru 18581059Sigor@sysoev.ru case NXT_HTTP_ROUTE_ARGUMENT: 18591061Sigor@sysoev.ru return nxt_http_route_arguments(r, rule); 1860964Sigor@sysoev.ru 18611059Sigor@sysoev.ru case NXT_HTTP_ROUTE_COOKIE: 18621062Sigor@sysoev.ru return nxt_http_route_cookies(r, rule); 18631059Sigor@sysoev.ru 18641110Saxel.duch@nginx.com case NXT_HTTP_ROUTE_SCHEME: 18651110Saxel.duch@nginx.com return nxt_http_route_scheme(r, rule); 18661110Saxel.duch@nginx.com 18671059Sigor@sysoev.ru default: 18681059Sigor@sysoev.ru break; 18691059Sigor@sysoev.ru } 1870964Sigor@sysoev.ru 18711059Sigor@sysoev.ru p = nxt_pointer_to(r, rule->u.offset); 18721059Sigor@sysoev.ru 18731059Sigor@sysoev.ru if (rule->object == NXT_HTTP_ROUTE_STRING) { 18741059Sigor@sysoev.ru s = p; 1875964Sigor@sysoev.ru 18761059Sigor@sysoev.ru } else { 18771059Sigor@sysoev.ru /* NXT_HTTP_ROUTE_STRING_PTR */ 18781059Sigor@sysoev.ru pp = p; 18791059Sigor@sysoev.ru s = *pp; 1880964Sigor@sysoev.ru 18811059Sigor@sysoev.ru if (s == NULL) { 1882964Sigor@sysoev.ru return 0; 1883964Sigor@sysoev.ru } 1884964Sigor@sysoev.ru } 1885964Sigor@sysoev.ru 18861059Sigor@sysoev.ru length = s->length; 18871059Sigor@sysoev.ru start = s->start; 18881059Sigor@sysoev.ru 18891059Sigor@sysoev.ru return nxt_http_route_test_rule(r, rule, start, length); 18901059Sigor@sysoev.ru } 18911059Sigor@sysoev.ru 18921059Sigor@sysoev.ru 18931060Sigor@sysoev.ru static nxt_int_t 18941324Saxel.duch@nginx.com nxt_http_route_addr_pattern_match(nxt_http_route_addr_pattern_t *p, 18951324Saxel.duch@nginx.com nxt_sockaddr_t *sa) 18961324Saxel.duch@nginx.com { 18971324Saxel.duch@nginx.com #if (NXT_INET6) 18981324Saxel.duch@nginx.com uint32_t i; 18991324Saxel.duch@nginx.com #endif 19001324Saxel.duch@nginx.com in_port_t in_port; 19011324Saxel.duch@nginx.com nxt_int_t match; 19021324Saxel.duch@nginx.com struct sockaddr_in *sin; 19031324Saxel.duch@nginx.com #if (NXT_INET6) 19041324Saxel.duch@nginx.com struct sockaddr_in6 *sin6; 19051324Saxel.duch@nginx.com #endif 19061324Saxel.duch@nginx.com nxt_http_route_addr_base_t *base; 19071324Saxel.duch@nginx.com 19081324Saxel.duch@nginx.com base = &p->base; 19091324Saxel.duch@nginx.com 19101324Saxel.duch@nginx.com switch (sa->u.sockaddr.sa_family) { 19111324Saxel.duch@nginx.com 19121324Saxel.duch@nginx.com case AF_INET: 19131324Saxel.duch@nginx.com 19141324Saxel.duch@nginx.com match = (base->addr_family == AF_INET 19151324Saxel.duch@nginx.com || base->addr_family == AF_UNSPEC); 19161324Saxel.duch@nginx.com if (!match) { 19171324Saxel.duch@nginx.com break; 19181324Saxel.duch@nginx.com } 19191324Saxel.duch@nginx.com 19201324Saxel.duch@nginx.com sin = &sa->u.sockaddr_in; 19211324Saxel.duch@nginx.com in_port = ntohs(sin->sin_port); 19221324Saxel.duch@nginx.com 19231324Saxel.duch@nginx.com match = (in_port >= base->port.start && in_port <= base->port.end); 19241324Saxel.duch@nginx.com if (!match) { 19251324Saxel.duch@nginx.com break; 19261324Saxel.duch@nginx.com } 19271324Saxel.duch@nginx.com 19281324Saxel.duch@nginx.com switch (base->match_type) { 19291324Saxel.duch@nginx.com 19301324Saxel.duch@nginx.com case NXT_HTTP_ROUTE_ADDR_ANY: 19311324Saxel.duch@nginx.com break; 19321324Saxel.duch@nginx.com 19331324Saxel.duch@nginx.com case NXT_HTTP_ROUTE_ADDR_EXACT: 19341324Saxel.duch@nginx.com match = (nxt_memcmp(&sin->sin_addr, &p->addr.v4.start, 19351324Saxel.duch@nginx.com sizeof(struct in_addr)) 19361324Saxel.duch@nginx.com == 0); 19371324Saxel.duch@nginx.com break; 19381324Saxel.duch@nginx.com 19391324Saxel.duch@nginx.com case NXT_HTTP_ROUTE_ADDR_RANGE: 19401324Saxel.duch@nginx.com match = (nxt_memcmp(&sin->sin_addr, &p->addr.v4.start, 19411324Saxel.duch@nginx.com sizeof(struct in_addr)) >= 0 19421324Saxel.duch@nginx.com && nxt_memcmp(&sin->sin_addr, &p->addr.v4.end, 19431324Saxel.duch@nginx.com sizeof(struct in_addr)) <= 0); 19441324Saxel.duch@nginx.com break; 19451324Saxel.duch@nginx.com 19461324Saxel.duch@nginx.com case NXT_HTTP_ROUTE_ADDR_CIDR: 19471324Saxel.duch@nginx.com match = ((sin->sin_addr.s_addr & p->addr.v4.end) 19481324Saxel.duch@nginx.com == p->addr.v4.start); 19491324Saxel.duch@nginx.com break; 19501324Saxel.duch@nginx.com 19511324Saxel.duch@nginx.com default: 19521324Saxel.duch@nginx.com nxt_unreachable(); 19531324Saxel.duch@nginx.com } 19541324Saxel.duch@nginx.com 19551324Saxel.duch@nginx.com break; 19561324Saxel.duch@nginx.com 19571324Saxel.duch@nginx.com #if (NXT_INET6) 19581324Saxel.duch@nginx.com case AF_INET6: 19591324Saxel.duch@nginx.com 19601324Saxel.duch@nginx.com match = (base->addr_family == AF_INET6 19611324Saxel.duch@nginx.com || base->addr_family == AF_UNSPEC); 19621324Saxel.duch@nginx.com if (!match) { 19631324Saxel.duch@nginx.com break; 19641324Saxel.duch@nginx.com } 19651324Saxel.duch@nginx.com 19661324Saxel.duch@nginx.com sin6 = &sa->u.sockaddr_in6; 19671324Saxel.duch@nginx.com in_port = ntohs(sin6->sin6_port); 19681324Saxel.duch@nginx.com 19691324Saxel.duch@nginx.com match = (in_port >= base->port.start && in_port <= base->port.end); 19701324Saxel.duch@nginx.com if (!match) { 19711324Saxel.duch@nginx.com break; 19721324Saxel.duch@nginx.com } 19731324Saxel.duch@nginx.com 19741324Saxel.duch@nginx.com switch (base->match_type) { 19751324Saxel.duch@nginx.com 19761324Saxel.duch@nginx.com case NXT_HTTP_ROUTE_ADDR_ANY: 19771324Saxel.duch@nginx.com break; 19781324Saxel.duch@nginx.com 19791324Saxel.duch@nginx.com case NXT_HTTP_ROUTE_ADDR_EXACT: 19801324Saxel.duch@nginx.com match = (nxt_memcmp(&sin6->sin6_addr, &p->addr.v6.start, 19811324Saxel.duch@nginx.com sizeof(struct in6_addr)) 19821324Saxel.duch@nginx.com == 0); 19831324Saxel.duch@nginx.com break; 19841324Saxel.duch@nginx.com 19851324Saxel.duch@nginx.com case NXT_HTTP_ROUTE_ADDR_RANGE: 19861324Saxel.duch@nginx.com match = (nxt_memcmp(&sin6->sin6_addr, &p->addr.v6.start, 19871324Saxel.duch@nginx.com sizeof(struct in6_addr)) >= 0 19881324Saxel.duch@nginx.com && nxt_memcmp(&sin6->sin6_addr, &p->addr.v6.end, 19891324Saxel.duch@nginx.com sizeof(struct in6_addr)) <= 0); 19901324Saxel.duch@nginx.com break; 19911324Saxel.duch@nginx.com 19921324Saxel.duch@nginx.com case NXT_HTTP_ROUTE_ADDR_CIDR: 19931324Saxel.duch@nginx.com for (i = 0; i < 16; i++) { 19941324Saxel.duch@nginx.com match = ((sin6->sin6_addr.s6_addr[i] 19951324Saxel.duch@nginx.com & p->addr.v6.end.s6_addr[i]) 19961324Saxel.duch@nginx.com == p->addr.v6.start.s6_addr[i]); 19971324Saxel.duch@nginx.com 19981324Saxel.duch@nginx.com if (!match) { 19991324Saxel.duch@nginx.com break; 20001324Saxel.duch@nginx.com } 20011324Saxel.duch@nginx.com } 20021324Saxel.duch@nginx.com 20031324Saxel.duch@nginx.com break; 20041324Saxel.duch@nginx.com 20051324Saxel.duch@nginx.com default: 20061324Saxel.duch@nginx.com nxt_unreachable(); 20071324Saxel.duch@nginx.com } 20081324Saxel.duch@nginx.com 20091324Saxel.duch@nginx.com break; 20101324Saxel.duch@nginx.com #endif 20111324Saxel.duch@nginx.com 20121324Saxel.duch@nginx.com default: 20131324Saxel.duch@nginx.com match = 0; 20141324Saxel.duch@nginx.com break; 20151324Saxel.duch@nginx.com } 20161324Saxel.duch@nginx.com 20171324Saxel.duch@nginx.com return match ^ base->negative; 20181324Saxel.duch@nginx.com } 20191324Saxel.duch@nginx.com 20201324Saxel.duch@nginx.com 20211324Saxel.duch@nginx.com static nxt_int_t 20221324Saxel.duch@nginx.com nxt_http_route_addr_rule(nxt_http_request_t *r, 20231324Saxel.duch@nginx.com nxt_http_route_addr_rule_t *addr_rule, nxt_sockaddr_t *sa) 20241324Saxel.duch@nginx.com { 20251390Saxel.duch@nginx.com uint32_t n; 20261390Saxel.duch@nginx.com nxt_bool_t matches; 20271324Saxel.duch@nginx.com nxt_http_route_addr_pattern_t *p; 20281324Saxel.duch@nginx.com 20291324Saxel.duch@nginx.com n = addr_rule->items; 20301390Saxel.duch@nginx.com p = &addr_rule->addr_pattern[0] - 1; 20311324Saxel.duch@nginx.com 20321390Saxel.duch@nginx.com do { 20331390Saxel.duch@nginx.com p++; 20341390Saxel.duch@nginx.com n--; 20351390Saxel.duch@nginx.com 20361390Saxel.duch@nginx.com matches = nxt_http_route_addr_pattern_match(p, sa); 20371390Saxel.duch@nginx.com 20381390Saxel.duch@nginx.com if (p->base.negative) { 20391390Saxel.duch@nginx.com if (matches) { 20401390Saxel.duch@nginx.com continue; 20411390Saxel.duch@nginx.com } 20421390Saxel.duch@nginx.com 20431390Saxel.duch@nginx.com return 0; 20441390Saxel.duch@nginx.com } 20451390Saxel.duch@nginx.com 20461390Saxel.duch@nginx.com if (matches) { 20471324Saxel.duch@nginx.com return 1; 20481324Saxel.duch@nginx.com } 20491324Saxel.duch@nginx.com 20501390Saxel.duch@nginx.com } while (n > 0); 20511390Saxel.duch@nginx.com 20521390Saxel.duch@nginx.com return p->base.negative; 20531324Saxel.duch@nginx.com } 20541324Saxel.duch@nginx.com 20551324Saxel.duch@nginx.com 20561324Saxel.duch@nginx.com static nxt_int_t 20571059Sigor@sysoev.ru nxt_http_route_header(nxt_http_request_t *r, nxt_http_route_rule_t *rule) 20581059Sigor@sysoev.ru { 20591060Sigor@sysoev.ru nxt_int_t ret; 20601059Sigor@sysoev.ru nxt_http_field_t *f; 20611059Sigor@sysoev.ru 20621059Sigor@sysoev.ru ret = 0; 20631059Sigor@sysoev.ru 20641059Sigor@sysoev.ru nxt_list_each(f, r->fields) { 20651059Sigor@sysoev.ru 20661059Sigor@sysoev.ru if (rule->u.name.hash != f->hash 20671059Sigor@sysoev.ru || rule->u.name.length != f->name_length 20681059Sigor@sysoev.ru || nxt_strncasecmp(rule->u.name.start, f->name, f->name_length) 20691059Sigor@sysoev.ru != 0) 20701059Sigor@sysoev.ru { 20711059Sigor@sysoev.ru continue; 20721059Sigor@sysoev.ru } 20731059Sigor@sysoev.ru 20741059Sigor@sysoev.ru ret = nxt_http_route_test_rule(r, rule, f->value, f->value_length); 20751721Saxel.duch@nginx.com if (nxt_slow_path(ret == NXT_ERROR)) { 20761721Saxel.duch@nginx.com return NXT_ERROR; 20771721Saxel.duch@nginx.com } 20781059Sigor@sysoev.ru 20791060Sigor@sysoev.ru if (ret == 0) { 20801059Sigor@sysoev.ru return ret; 20811059Sigor@sysoev.ru } 20821059Sigor@sysoev.ru 20831059Sigor@sysoev.ru } nxt_list_loop; 20841059Sigor@sysoev.ru 20851059Sigor@sysoev.ru return ret; 20861059Sigor@sysoev.ru } 20871059Sigor@sysoev.ru 20881059Sigor@sysoev.ru 20891060Sigor@sysoev.ru static nxt_int_t 20901061Sigor@sysoev.ru nxt_http_route_arguments(nxt_http_request_t *r, nxt_http_route_rule_t *rule) 20911061Sigor@sysoev.ru { 20921061Sigor@sysoev.ru nxt_array_t *arguments; 20931061Sigor@sysoev.ru 20941061Sigor@sysoev.ru if (r->args == NULL) { 20951061Sigor@sysoev.ru return 0; 20961061Sigor@sysoev.ru } 20971061Sigor@sysoev.ru 20981061Sigor@sysoev.ru arguments = nxt_http_route_arguments_parse(r); 20991061Sigor@sysoev.ru if (nxt_slow_path(arguments == NULL)) { 21001061Sigor@sysoev.ru return -1; 21011061Sigor@sysoev.ru } 21021061Sigor@sysoev.ru 21031061Sigor@sysoev.ru return nxt_http_route_test_argument(r, rule, arguments); 21041061Sigor@sysoev.ru } 21051061Sigor@sysoev.ru 21061061Sigor@sysoev.ru 21071061Sigor@sysoev.ru static nxt_array_t * 21081061Sigor@sysoev.ru nxt_http_route_arguments_parse(nxt_http_request_t *r) 21091061Sigor@sysoev.ru { 21101061Sigor@sysoev.ru size_t name_length; 21111474Saxel.duch@nginx.com u_char c, *p, *dst, *dst_start, *start, *end, *name; 21121474Saxel.duch@nginx.com uint8_t d0, d1; 21131061Sigor@sysoev.ru uint32_t hash; 21141061Sigor@sysoev.ru nxt_bool_t valid; 21151061Sigor@sysoev.ru nxt_array_t *args; 21161061Sigor@sysoev.ru nxt_http_name_value_t *nv; 21171061Sigor@sysoev.ru 21181061Sigor@sysoev.ru if (r->arguments != NULL) { 21191061Sigor@sysoev.ru return r->arguments; 21201061Sigor@sysoev.ru } 21211061Sigor@sysoev.ru 21221061Sigor@sysoev.ru args = nxt_array_create(r->mem_pool, 2, sizeof(nxt_http_name_value_t)); 21231061Sigor@sysoev.ru if (nxt_slow_path(args == NULL)) { 21241061Sigor@sysoev.ru return NULL; 21251061Sigor@sysoev.ru } 21261061Sigor@sysoev.ru 21271061Sigor@sysoev.ru hash = NXT_HTTP_FIELD_HASH_INIT; 21281061Sigor@sysoev.ru valid = 1; 21291061Sigor@sysoev.ru name = NULL; 21301061Sigor@sysoev.ru name_length = 0; 21311061Sigor@sysoev.ru 21321474Saxel.duch@nginx.com dst_start = nxt_mp_nget(r->mem_pool, r->args->length); 21331474Saxel.duch@nginx.com if (nxt_slow_path(dst_start == NULL)) { 21341474Saxel.duch@nginx.com return NULL; 21351474Saxel.duch@nginx.com } 21361474Saxel.duch@nginx.com 21371061Sigor@sysoev.ru start = r->args->start; 21381061Sigor@sysoev.ru end = start + r->args->length; 21391061Sigor@sysoev.ru 21401474Saxel.duch@nginx.com for (p = start, dst = dst_start; p < end; p++, dst++) { 21411061Sigor@sysoev.ru c = *p; 21421474Saxel.duch@nginx.com *dst = c; 21431474Saxel.duch@nginx.com 21441474Saxel.duch@nginx.com switch (c) { 21451474Saxel.duch@nginx.com case '=': 21461474Saxel.duch@nginx.com if (name != NULL) { 21471474Saxel.duch@nginx.com break; 21481474Saxel.duch@nginx.com } 21491474Saxel.duch@nginx.com 21501474Saxel.duch@nginx.com name_length = dst - dst_start; 21511061Sigor@sysoev.ru valid = (name_length != 0); 21521474Saxel.duch@nginx.com name = dst_start; 21531474Saxel.duch@nginx.com dst_start = dst + 1; 21541474Saxel.duch@nginx.com 21551474Saxel.duch@nginx.com continue; 21561474Saxel.duch@nginx.com 21571474Saxel.duch@nginx.com case '&': 21581061Sigor@sysoev.ru if (valid) { 21591061Sigor@sysoev.ru nv = nxt_http_route_argument(args, name, name_length, hash, 21601474Saxel.duch@nginx.com dst_start, dst); 21611061Sigor@sysoev.ru if (nxt_slow_path(nv == NULL)) { 21621061Sigor@sysoev.ru return NULL; 21631061Sigor@sysoev.ru } 21641061Sigor@sysoev.ru } 21651061Sigor@sysoev.ru 21661061Sigor@sysoev.ru hash = NXT_HTTP_FIELD_HASH_INIT; 21671474Saxel.duch@nginx.com name_length = 0; 21681061Sigor@sysoev.ru valid = 1; 21691061Sigor@sysoev.ru name = NULL; 21701474Saxel.duch@nginx.com dst_start = dst + 1; 21711474Saxel.duch@nginx.com 21721474Saxel.duch@nginx.com continue; 21731474Saxel.duch@nginx.com 21741474Saxel.duch@nginx.com case '+': 21751474Saxel.duch@nginx.com c = ' '; 21761474Saxel.duch@nginx.com *dst = ' '; 21771474Saxel.duch@nginx.com 21781474Saxel.duch@nginx.com break; 21791474Saxel.duch@nginx.com 21801474Saxel.duch@nginx.com case '%': 21811474Saxel.duch@nginx.com if (nxt_slow_path(end - p <= 2)) { 21821474Saxel.duch@nginx.com break; 21831474Saxel.duch@nginx.com } 21841474Saxel.duch@nginx.com 21851474Saxel.duch@nginx.com d0 = nxt_hex2int[p[1]]; 21861474Saxel.duch@nginx.com d1 = nxt_hex2int[p[2]]; 21871474Saxel.duch@nginx.com 21881474Saxel.duch@nginx.com if (nxt_slow_path((d0 | d1) >= 16)) { 21891474Saxel.duch@nginx.com break; 21901474Saxel.duch@nginx.com } 21911474Saxel.duch@nginx.com 21921474Saxel.duch@nginx.com p += 2; 21931474Saxel.duch@nginx.com c = (d0 << 4) + d1; 21941474Saxel.duch@nginx.com *dst = c; 21951474Saxel.duch@nginx.com 21961474Saxel.duch@nginx.com break; 21971474Saxel.duch@nginx.com } 21981474Saxel.duch@nginx.com 21991474Saxel.duch@nginx.com if (name == NULL) { 22001061Sigor@sysoev.ru hash = nxt_http_field_hash_char(hash, c); 22011061Sigor@sysoev.ru } 22021061Sigor@sysoev.ru } 22031061Sigor@sysoev.ru 22041061Sigor@sysoev.ru if (valid) { 22051474Saxel.duch@nginx.com nv = nxt_http_route_argument(args, name, name_length, hash, dst_start, 22061474Saxel.duch@nginx.com dst); 22071061Sigor@sysoev.ru if (nxt_slow_path(nv == NULL)) { 22081061Sigor@sysoev.ru return NULL; 22091061Sigor@sysoev.ru } 22101061Sigor@sysoev.ru } 22111061Sigor@sysoev.ru 22121061Sigor@sysoev.ru r->arguments = args; 22131061Sigor@sysoev.ru 22141061Sigor@sysoev.ru return args; 22151061Sigor@sysoev.ru } 22161061Sigor@sysoev.ru 22171061Sigor@sysoev.ru 22181061Sigor@sysoev.ru static nxt_http_name_value_t * 22191061Sigor@sysoev.ru nxt_http_route_argument(nxt_array_t *array, u_char *name, size_t name_length, 22201061Sigor@sysoev.ru uint32_t hash, u_char *start, u_char *end) 22211061Sigor@sysoev.ru { 22221061Sigor@sysoev.ru size_t length; 22231061Sigor@sysoev.ru nxt_http_name_value_t *nv; 22241061Sigor@sysoev.ru 22251061Sigor@sysoev.ru nv = nxt_array_add(array); 22261061Sigor@sysoev.ru if (nxt_slow_path(nv == NULL)) { 22271061Sigor@sysoev.ru return NULL; 22281061Sigor@sysoev.ru } 22291061Sigor@sysoev.ru 22301061Sigor@sysoev.ru nv->hash = nxt_http_field_hash_end(hash) & 0xFFFF; 22311061Sigor@sysoev.ru 22321061Sigor@sysoev.ru length = end - start; 22331061Sigor@sysoev.ru 22341061Sigor@sysoev.ru if (name == NULL) { 22351061Sigor@sysoev.ru name_length = length; 22361061Sigor@sysoev.ru name = start; 22371061Sigor@sysoev.ru length = 0; 22381061Sigor@sysoev.ru } 22391061Sigor@sysoev.ru 22401061Sigor@sysoev.ru nv->name_length = name_length; 22411061Sigor@sysoev.ru nv->value_length = length; 22421061Sigor@sysoev.ru nv->name = name; 22431061Sigor@sysoev.ru nv->value = start; 22441061Sigor@sysoev.ru 22451061Sigor@sysoev.ru return nv; 22461061Sigor@sysoev.ru } 22471061Sigor@sysoev.ru 22481061Sigor@sysoev.ru 22491061Sigor@sysoev.ru static nxt_int_t 22501061Sigor@sysoev.ru nxt_http_route_test_argument(nxt_http_request_t *r, 22511061Sigor@sysoev.ru nxt_http_route_rule_t *rule, nxt_array_t *array) 22521061Sigor@sysoev.ru { 22531721Saxel.duch@nginx.com nxt_int_t ret; 22541061Sigor@sysoev.ru nxt_http_name_value_t *nv, *end; 22551061Sigor@sysoev.ru 22561061Sigor@sysoev.ru ret = 0; 22571061Sigor@sysoev.ru 22581061Sigor@sysoev.ru nv = array->elts; 22591061Sigor@sysoev.ru end = nv + array->nelts; 22601061Sigor@sysoev.ru 22611061Sigor@sysoev.ru while (nv < end) { 22621061Sigor@sysoev.ru 22631061Sigor@sysoev.ru if (rule->u.name.hash == nv->hash 22641061Sigor@sysoev.ru && rule->u.name.length == nv->name_length 22651061Sigor@sysoev.ru && nxt_memcmp(rule->u.name.start, nv->name, nv->name_length) == 0) 22661061Sigor@sysoev.ru { 22671061Sigor@sysoev.ru ret = nxt_http_route_test_rule(r, rule, nv->value, 22681061Sigor@sysoev.ru nv->value_length); 22691721Saxel.duch@nginx.com if (nxt_slow_path(ret == NXT_ERROR)) { 22701721Saxel.duch@nginx.com return NXT_ERROR; 22711721Saxel.duch@nginx.com } 22721721Saxel.duch@nginx.com 22731061Sigor@sysoev.ru if (ret == 0) { 22741061Sigor@sysoev.ru break; 22751061Sigor@sysoev.ru } 22761061Sigor@sysoev.ru } 22771061Sigor@sysoev.ru 22781061Sigor@sysoev.ru nv++; 22791061Sigor@sysoev.ru } 22801061Sigor@sysoev.ru 22811061Sigor@sysoev.ru return ret; 22821061Sigor@sysoev.ru } 22831061Sigor@sysoev.ru 22841061Sigor@sysoev.ru 22851061Sigor@sysoev.ru static nxt_int_t 22861110Saxel.duch@nginx.com nxt_http_route_scheme(nxt_http_request_t *r, nxt_http_route_rule_t *rule) 22871110Saxel.duch@nginx.com { 22881508Saxel.duch@nginx.com nxt_bool_t tls, https; 22891508Saxel.duch@nginx.com nxt_http_route_pattern_slice_t *pattern_slice; 22901508Saxel.duch@nginx.com 22911721Saxel.duch@nginx.com pattern_slice = rule->pattern[0].u.pattern_slices->elts; 22921508Saxel.duch@nginx.com https = (pattern_slice->length == nxt_length("https")); 22931110Saxel.duch@nginx.com tls = (r->tls != NULL); 22941110Saxel.duch@nginx.com 22951110Saxel.duch@nginx.com return (tls == https); 22961110Saxel.duch@nginx.com } 22971110Saxel.duch@nginx.com 22981110Saxel.duch@nginx.com 22991110Saxel.duch@nginx.com static nxt_int_t 23001062Sigor@sysoev.ru nxt_http_route_cookies(nxt_http_request_t *r, nxt_http_route_rule_t *rule) 23011062Sigor@sysoev.ru { 23021062Sigor@sysoev.ru nxt_array_t *cookies; 23031062Sigor@sysoev.ru 23041062Sigor@sysoev.ru cookies = nxt_http_route_cookies_parse(r); 23051062Sigor@sysoev.ru if (nxt_slow_path(cookies == NULL)) { 23061062Sigor@sysoev.ru return -1; 23071062Sigor@sysoev.ru } 23081062Sigor@sysoev.ru 23091062Sigor@sysoev.ru return nxt_http_route_test_cookie(r, rule, cookies); 23101062Sigor@sysoev.ru } 23111062Sigor@sysoev.ru 23121062Sigor@sysoev.ru 23131062Sigor@sysoev.ru static nxt_array_t * 23141062Sigor@sysoev.ru nxt_http_route_cookies_parse(nxt_http_request_t *r) 23151062Sigor@sysoev.ru { 23161062Sigor@sysoev.ru nxt_int_t ret; 23171062Sigor@sysoev.ru nxt_array_t *cookies; 23181062Sigor@sysoev.ru nxt_http_field_t *f; 23191062Sigor@sysoev.ru 23201062Sigor@sysoev.ru if (r->cookies != NULL) { 23211062Sigor@sysoev.ru return r->cookies; 23221062Sigor@sysoev.ru } 23231062Sigor@sysoev.ru 23241062Sigor@sysoev.ru cookies = nxt_array_create(r->mem_pool, 2, sizeof(nxt_http_name_value_t)); 23251062Sigor@sysoev.ru if (nxt_slow_path(cookies == NULL)) { 23261062Sigor@sysoev.ru return NULL; 23271062Sigor@sysoev.ru } 23281062Sigor@sysoev.ru 23291062Sigor@sysoev.ru nxt_list_each(f, r->fields) { 23301062Sigor@sysoev.ru 23311522Saxel.duch@nginx.com if (f->hash != NXT_COOKIE_HASH 23321062Sigor@sysoev.ru || f->name_length != 6 23331062Sigor@sysoev.ru || nxt_strncasecmp(f->name, (u_char *) "Cookie", 6) != 0) 23341062Sigor@sysoev.ru { 23351062Sigor@sysoev.ru continue; 23361062Sigor@sysoev.ru } 23371062Sigor@sysoev.ru 23381062Sigor@sysoev.ru ret = nxt_http_route_cookie_parse(cookies, f->value, 23391062Sigor@sysoev.ru f->value + f->value_length); 23401062Sigor@sysoev.ru if (ret != NXT_OK) { 23411062Sigor@sysoev.ru return NULL; 23421062Sigor@sysoev.ru } 23431062Sigor@sysoev.ru 23441062Sigor@sysoev.ru } nxt_list_loop; 23451062Sigor@sysoev.ru 23461062Sigor@sysoev.ru r->cookies = cookies; 23471062Sigor@sysoev.ru 23481062Sigor@sysoev.ru return cookies; 23491062Sigor@sysoev.ru } 23501062Sigor@sysoev.ru 23511062Sigor@sysoev.ru 23521062Sigor@sysoev.ru static nxt_int_t 23531062Sigor@sysoev.ru nxt_http_route_cookie_parse(nxt_array_t *cookies, u_char *start, u_char *end) 23541062Sigor@sysoev.ru { 23551062Sigor@sysoev.ru size_t name_length; 23561062Sigor@sysoev.ru u_char c, *p, *name; 23571062Sigor@sysoev.ru nxt_http_name_value_t *nv; 23581062Sigor@sysoev.ru 23591062Sigor@sysoev.ru name = NULL; 23601062Sigor@sysoev.ru name_length = 0; 23611062Sigor@sysoev.ru 23621062Sigor@sysoev.ru for (p = start; p < end; p++) { 23631062Sigor@sysoev.ru c = *p; 23641062Sigor@sysoev.ru 23651062Sigor@sysoev.ru if (c == '=') { 23661062Sigor@sysoev.ru while (start[0] == ' ') { start++; } 23671062Sigor@sysoev.ru 23681062Sigor@sysoev.ru name_length = p - start; 23691062Sigor@sysoev.ru 23701062Sigor@sysoev.ru if (name_length != 0) { 23711062Sigor@sysoev.ru name = start; 23721062Sigor@sysoev.ru } 23731062Sigor@sysoev.ru 23741062Sigor@sysoev.ru start = p + 1; 23751062Sigor@sysoev.ru 23761062Sigor@sysoev.ru } else if (c == ';') { 23771062Sigor@sysoev.ru if (name != NULL) { 23781062Sigor@sysoev.ru nv = nxt_http_route_cookie(cookies, name, name_length, 23791062Sigor@sysoev.ru start, p); 23801062Sigor@sysoev.ru if (nxt_slow_path(nv == NULL)) { 23811062Sigor@sysoev.ru return NXT_ERROR; 23821062Sigor@sysoev.ru } 23831062Sigor@sysoev.ru } 23841062Sigor@sysoev.ru 23851062Sigor@sysoev.ru name = NULL; 23861062Sigor@sysoev.ru start = p + 1; 23871062Sigor@sysoev.ru } 23881062Sigor@sysoev.ru } 23891062Sigor@sysoev.ru 23901062Sigor@sysoev.ru if (name != NULL) { 23911062Sigor@sysoev.ru nv = nxt_http_route_cookie(cookies, name, name_length, start, p); 23921062Sigor@sysoev.ru if (nxt_slow_path(nv == NULL)) { 23931062Sigor@sysoev.ru return NXT_ERROR; 23941062Sigor@sysoev.ru } 23951062Sigor@sysoev.ru } 23961062Sigor@sysoev.ru 23971062Sigor@sysoev.ru return NXT_OK; 23981062Sigor@sysoev.ru } 23991062Sigor@sysoev.ru 24001062Sigor@sysoev.ru 24011062Sigor@sysoev.ru static nxt_http_name_value_t * 24021062Sigor@sysoev.ru nxt_http_route_cookie(nxt_array_t *array, u_char *name, size_t name_length, 24031062Sigor@sysoev.ru u_char *start, u_char *end) 24041062Sigor@sysoev.ru { 24051062Sigor@sysoev.ru u_char c, *p; 24061062Sigor@sysoev.ru uint32_t hash; 24071062Sigor@sysoev.ru nxt_http_name_value_t *nv; 24081062Sigor@sysoev.ru 24091062Sigor@sysoev.ru nv = nxt_array_add(array); 24101062Sigor@sysoev.ru if (nxt_slow_path(nv == NULL)) { 24111062Sigor@sysoev.ru return NULL; 24121062Sigor@sysoev.ru } 24131062Sigor@sysoev.ru 24141062Sigor@sysoev.ru nv->name_length = name_length; 24151062Sigor@sysoev.ru nv->name = name; 24161062Sigor@sysoev.ru 24171062Sigor@sysoev.ru hash = NXT_HTTP_FIELD_HASH_INIT; 24181062Sigor@sysoev.ru 24191062Sigor@sysoev.ru for (p = name; p < name + name_length; p++) { 24201062Sigor@sysoev.ru c = *p; 24211062Sigor@sysoev.ru hash = nxt_http_field_hash_char(hash, c); 24221062Sigor@sysoev.ru } 24231062Sigor@sysoev.ru 24241062Sigor@sysoev.ru nv->hash = nxt_http_field_hash_end(hash) & 0xFFFF; 24251062Sigor@sysoev.ru 24261062Sigor@sysoev.ru while (start < end && end[-1] == ' ') { end--; } 24271062Sigor@sysoev.ru 24281062Sigor@sysoev.ru nv->value_length = end - start; 24291062Sigor@sysoev.ru nv->value = start; 24301062Sigor@sysoev.ru 24311062Sigor@sysoev.ru return nv; 24321062Sigor@sysoev.ru } 24331062Sigor@sysoev.ru 24341062Sigor@sysoev.ru 24351062Sigor@sysoev.ru static nxt_int_t 24361062Sigor@sysoev.ru nxt_http_route_test_cookie(nxt_http_request_t *r, 24371062Sigor@sysoev.ru nxt_http_route_rule_t *rule, nxt_array_t *array) 24381062Sigor@sysoev.ru { 24391721Saxel.duch@nginx.com nxt_int_t ret; 24401062Sigor@sysoev.ru nxt_http_name_value_t *nv, *end; 24411062Sigor@sysoev.ru 24421062Sigor@sysoev.ru ret = 0; 24431062Sigor@sysoev.ru 24441062Sigor@sysoev.ru nv = array->elts; 24451062Sigor@sysoev.ru end = nv + array->nelts; 24461062Sigor@sysoev.ru 24471062Sigor@sysoev.ru while (nv < end) { 24481062Sigor@sysoev.ru 24491062Sigor@sysoev.ru if (rule->u.name.hash == nv->hash 24501062Sigor@sysoev.ru && rule->u.name.length == nv->name_length 24511079Sigor@sysoev.ru && nxt_memcmp(rule->u.name.start, nv->name, nv->name_length) == 0) 24521062Sigor@sysoev.ru { 24531062Sigor@sysoev.ru ret = nxt_http_route_test_rule(r, rule, nv->value, 24541062Sigor@sysoev.ru nv->value_length); 24551721Saxel.duch@nginx.com if (nxt_slow_path(ret == NXT_ERROR)) { 24561721Saxel.duch@nginx.com return NXT_ERROR; 24571721Saxel.duch@nginx.com } 24581721Saxel.duch@nginx.com 24591062Sigor@sysoev.ru if (ret == 0) { 24601062Sigor@sysoev.ru break; 24611062Sigor@sysoev.ru } 24621062Sigor@sysoev.ru } 24631062Sigor@sysoev.ru 24641062Sigor@sysoev.ru nv++; 24651062Sigor@sysoev.ru } 24661062Sigor@sysoev.ru 24671062Sigor@sysoev.ru return ret; 24681062Sigor@sysoev.ru } 24691062Sigor@sysoev.ru 24701062Sigor@sysoev.ru 24711859So.canty@f5.com nxt_int_t 24721059Sigor@sysoev.ru nxt_http_route_test_rule(nxt_http_request_t *r, nxt_http_route_rule_t *rule, 24731059Sigor@sysoev.ru u_char *start, size_t length) 24741059Sigor@sysoev.ru { 24751060Sigor@sysoev.ru nxt_int_t ret; 24761059Sigor@sysoev.ru nxt_http_route_pattern_t *pattern, *end; 24771059Sigor@sysoev.ru 24781057Sigor@sysoev.ru ret = 1; 2479964Sigor@sysoev.ru pattern = &rule->pattern[0]; 24801033Svbart@nginx.com end = pattern + rule->items; 2481964Sigor@sysoev.ru 24821057Sigor@sysoev.ru while (pattern < end) { 2483964Sigor@sysoev.ru ret = nxt_http_route_pattern(r, pattern, start, length); 24841721Saxel.duch@nginx.com if (nxt_slow_path(ret == NXT_ERROR)) { 24851721Saxel.duch@nginx.com return NXT_ERROR; 24861721Saxel.duch@nginx.com } 2487964Sigor@sysoev.ru 24881060Sigor@sysoev.ru /* nxt_http_route_pattern() returns either 1 or 0. */ 2489964Sigor@sysoev.ru ret ^= pattern->negative; 2490964Sigor@sysoev.ru 2491964Sigor@sysoev.ru if (pattern->any == ret) { 2492964Sigor@sysoev.ru return ret; 2493964Sigor@sysoev.ru } 2494964Sigor@sysoev.ru 2495964Sigor@sysoev.ru pattern++; 24961057Sigor@sysoev.ru } 2497964Sigor@sysoev.ru 2498964Sigor@sysoev.ru return ret; 2499964Sigor@sysoev.ru } 2500964Sigor@sysoev.ru 2501964Sigor@sysoev.ru 25021060Sigor@sysoev.ru static nxt_int_t 2503964Sigor@sysoev.ru nxt_http_route_pattern(nxt_http_request_t *r, nxt_http_route_pattern_t *pattern, 2504964Sigor@sysoev.ru u_char *start, size_t length) 2505964Sigor@sysoev.ru { 25061508Saxel.duch@nginx.com u_char *p, *end, *test; 25071508Saxel.duch@nginx.com size_t test_length; 25081508Saxel.duch@nginx.com uint32_t i; 25091508Saxel.duch@nginx.com nxt_array_t *pattern_slices; 25101508Saxel.duch@nginx.com nxt_http_route_pattern_slice_t *pattern_slice; 2511964Sigor@sysoev.ru 25121721Saxel.duch@nginx.com #if (NXT_HAVE_REGEX) 25131721Saxel.duch@nginx.com if (pattern->regex) { 25141721Saxel.duch@nginx.com if (r->regex_match == NULL) { 25151721Saxel.duch@nginx.com r->regex_match = nxt_regex_match_create(r->mem_pool, 0); 25161721Saxel.duch@nginx.com if (nxt_slow_path(r->regex_match == NULL)) { 25171721Saxel.duch@nginx.com return NXT_ERROR; 25181721Saxel.duch@nginx.com } 25191721Saxel.duch@nginx.com } 25201721Saxel.duch@nginx.com 25211721Saxel.duch@nginx.com return nxt_regex_match(pattern->u.regex, start, length, r->regex_match); 25221721Saxel.duch@nginx.com } 25231721Saxel.duch@nginx.com #endif 25241721Saxel.duch@nginx.com 2525964Sigor@sysoev.ru if (length < pattern->min_length) { 2526964Sigor@sysoev.ru return 0; 2527964Sigor@sysoev.ru } 2528964Sigor@sysoev.ru 25291721Saxel.duch@nginx.com nxt_assert(pattern->u.pattern_slices != NULL); 25301721Saxel.duch@nginx.com 25311721Saxel.duch@nginx.com pattern_slices = pattern->u.pattern_slices; 25321508Saxel.duch@nginx.com pattern_slice = pattern_slices->elts; 25331510Saxel.duch@nginx.com end = start + length; 25341508Saxel.duch@nginx.com 25351508Saxel.duch@nginx.com for (i = 0; i < pattern_slices->nelts; i++, pattern_slice++) { 25361508Saxel.duch@nginx.com test = pattern_slice->start; 25371508Saxel.duch@nginx.com test_length = pattern_slice->length; 25381508Saxel.duch@nginx.com 25391508Saxel.duch@nginx.com switch (pattern_slice->type) { 25401508Saxel.duch@nginx.com case NXT_HTTP_ROUTE_PATTERN_EXACT: 25411508Saxel.duch@nginx.com return ((length == pattern->min_length) && 25421508Saxel.duch@nginx.com nxt_http_route_memcmp(start, test, test_length, 25431508Saxel.duch@nginx.com pattern->case_sensitive)); 25441508Saxel.duch@nginx.com 25451508Saxel.duch@nginx.com case NXT_HTTP_ROUTE_PATTERN_BEGIN: 25461508Saxel.duch@nginx.com if (nxt_http_route_memcmp(start, test, test_length, 25471508Saxel.duch@nginx.com pattern->case_sensitive)) 25481508Saxel.duch@nginx.com { 25491510Saxel.duch@nginx.com start += test_length; 25501508Saxel.duch@nginx.com break; 25511508Saxel.duch@nginx.com } 25521508Saxel.duch@nginx.com 2553964Sigor@sysoev.ru return 0; 25541508Saxel.duch@nginx.com 25551508Saxel.duch@nginx.com case NXT_HTTP_ROUTE_PATTERN_END: 25561510Saxel.duch@nginx.com p = end - test_length; 25571508Saxel.duch@nginx.com 25581508Saxel.duch@nginx.com if (nxt_http_route_memcmp(p, test, test_length, 25591508Saxel.duch@nginx.com pattern->case_sensitive)) 25601508Saxel.duch@nginx.com { 25611510Saxel.duch@nginx.com end = p; 25621508Saxel.duch@nginx.com break; 25631508Saxel.duch@nginx.com } 25641508Saxel.duch@nginx.com 25651508Saxel.duch@nginx.com return 0; 25661508Saxel.duch@nginx.com 25671508Saxel.duch@nginx.com case NXT_HTTP_ROUTE_PATTERN_SUBSTRING: 25681508Saxel.duch@nginx.com if (pattern->case_sensitive) { 25691508Saxel.duch@nginx.com p = nxt_memstrn(start, end, (char *) test, test_length); 25701508Saxel.duch@nginx.com 25711508Saxel.duch@nginx.com } else { 25721508Saxel.duch@nginx.com p = nxt_memcasestrn(start, end, (char *) test, test_length); 25731508Saxel.duch@nginx.com } 25741508Saxel.duch@nginx.com 25751508Saxel.duch@nginx.com if (p == NULL) { 25761508Saxel.duch@nginx.com return 0; 25771508Saxel.duch@nginx.com } 25781510Saxel.duch@nginx.com 25791510Saxel.duch@nginx.com start = p + test_length; 25801032Sigor@sysoev.ru } 2581964Sigor@sysoev.ru } 2582964Sigor@sysoev.ru 25831508Saxel.duch@nginx.com return 1; 25841032Sigor@sysoev.ru } 25851032Sigor@sysoev.ru 25861032Sigor@sysoev.ru 25871060Sigor@sysoev.ru static nxt_int_t 25881032Sigor@sysoev.ru nxt_http_route_memcmp(u_char *start, u_char *test, size_t test_length, 25891032Sigor@sysoev.ru nxt_bool_t case_sensitive) 25901032Sigor@sysoev.ru { 25911032Sigor@sysoev.ru nxt_int_t n; 25921032Sigor@sysoev.ru 25931032Sigor@sysoev.ru if (case_sensitive) { 25941032Sigor@sysoev.ru n = nxt_memcmp(start, test, test_length); 25951032Sigor@sysoev.ru 25961032Sigor@sysoev.ru } else { 25971032Sigor@sysoev.ru n = nxt_memcasecmp(start, test, test_length); 2598964Sigor@sysoev.ru } 2599964Sigor@sysoev.ru 26001032Sigor@sysoev.ru return (n == 0); 2601964Sigor@sysoev.ru } 2602